ecdsa_sw/test/
p256.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Test the software implementation of ECDSA over the P256 curve by signing a
6//! hash and checking it against the expected signature value. Since the
7//! implementation of EcdsaP256SignatureSigner uses the deterministic nonce
8//! generation algorithm as detailed in RFC 6979, the signature output by
9//! this test will always be the same, meaning we can simply test it against
10//! a known correct value.
11
12use crate::p256_signer::EcdsaP256SignatureSigner;
13use capsules_core::test::capsule_test::{CapsuleTest, CapsuleTestClient, CapsuleTestError};
14use kernel::debug;
15use kernel::hil::public_key_crypto::signature;
16use kernel::hil::public_key_crypto::signature::SignatureSign;
17use kernel::utilities::cells::{OptionalCell, TakeCell};
18use kernel::ErrorCode;
19
20pub struct TestEcdsaP256Sign {
21    ecdsa: &'static EcdsaP256SignatureSigner<'static>,
22    hash: TakeCell<'static, [u8; 32]>,      // The hash to sign
23    signature: TakeCell<'static, [u8; 64]>, // The resulting signature
24    correct_signature: TakeCell<'static, [u8; 64]>, // The expected signature
25    client: OptionalCell<&'static dyn CapsuleTestClient>,
26}
27
28impl TestEcdsaP256Sign {
29    pub fn new(
30        ecdsa: &'static EcdsaP256SignatureSigner<'static>,
31        hash: &'static mut [u8; 32],
32        signature: &'static mut [u8; 64],
33        correct_signature: &'static mut [u8; 64],
34    ) -> Self {
35        TestEcdsaP256Sign {
36            ecdsa,
37            hash: TakeCell::new(hash),
38            signature: TakeCell::new(signature),
39            correct_signature: TakeCell::new(correct_signature),
40            client: OptionalCell::empty(),
41        }
42    }
43
44    pub fn run(&'static self) {
45        self.ecdsa.set_sign_client(self);
46        let hash = self.hash.take().unwrap();
47        let signature = self.signature.take().unwrap();
48        let r = self.ecdsa.sign(hash, signature);
49        if r.is_err() {
50            panic!("EcdsaP256SignTest: failed to sign: {:?}", r);
51        }
52    }
53}
54
55impl signature::ClientSign<32, 64> for TestEcdsaP256Sign {
56    fn signing_done(
57        &self,
58        result: Result<(), ErrorCode>,
59        _hash: &'static mut [u8; 32],
60        signature: &'static mut [u8; 64],
61    ) {
62        match result {
63            Ok(()) => {
64                let correct = self.correct_signature.take().unwrap();
65                let res = if signature == correct {
66                    debug!("EcdsaP256SignTest passed (signatures match)");
67                    Ok(())
68                } else {
69                    debug!("EcdsaP256SignTest failed (signatures don't match)");
70                    Err(CapsuleTestError::IncorrectResult)
71                };
72                self.client.map(|client| client.done(res));
73            }
74            Err(e) => {
75                panic!("EcdsaP256SignTest: signing failed: {:?}", e);
76            }
77        }
78    }
79}
80
81impl CapsuleTest for TestEcdsaP256Sign {
82    fn set_client(&self, client: &'static dyn CapsuleTestClient) {
83        self.client.set(client);
84    }
85}