ecdsa_sw/
p256_verifier.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 2025.
4
5//! ECDSA Signature Verifier for P256 signatures.
6
7use p256::ecdsa;
8use p256::ecdsa::signature::hazmat::PrehashVerifier;
9
10use core::cell::Cell;
11use kernel::hil;
12use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell};
13
14pub struct EcdsaP256SignatureVerifier<'a> {
15    verified: Cell<bool>,
16    client: OptionalCell<&'a dyn hil::public_key_crypto::signature::ClientVerify<32, 64>>,
17    verifying_key: MapCell<ecdsa::VerifyingKey>,
18    hash_storage: TakeCell<'static, [u8; 32]>,
19    signature_storage: TakeCell<'static, [u8; 64]>,
20    deferred_call: kernel::deferred_call::DeferredCall,
21}
22
23impl EcdsaP256SignatureVerifier<'_> {
24    pub fn new(verifying_key_bytes: &[u8; 64]) -> Self {
25        let ep = p256::EncodedPoint::from_untagged_bytes(verifying_key_bytes.into());
26        let key = ecdsa::VerifyingKey::from_encoded_point(&ep);
27
28        let verifying_key = key.map_or_else(|_e| MapCell::empty(), MapCell::new);
29
30        Self {
31            verified: Cell::new(false),
32            client: OptionalCell::empty(),
33            verifying_key,
34            hash_storage: TakeCell::empty(),
35            signature_storage: TakeCell::empty(),
36            deferred_call: kernel::deferred_call::DeferredCall::new(),
37        }
38    }
39}
40
41impl<'a> hil::public_key_crypto::signature::SignatureVerify<'a, 32, 64>
42    for EcdsaP256SignatureVerifier<'a>
43{
44    fn set_verify_client(
45        &self,
46        client: &'a dyn hil::public_key_crypto::signature::ClientVerify<32, 64>,
47    ) {
48        self.client.replace(client);
49    }
50
51    fn verify(
52        &self,
53        hash: &'static mut [u8; 32],
54        signature: &'static mut [u8; 64],
55    ) -> Result<
56        (),
57        (
58            kernel::ErrorCode,
59            &'static mut [u8; 32],
60            &'static mut [u8; 64],
61        ),
62    > {
63        if self.verifying_key.is_some() {
64            if let Ok(sig) = ecdsa::Signature::from_slice(signature) {
65                self.verifying_key
66                    .map(|vkey| {
67                        self.verified.set(vkey.verify_prehash(hash, &sig).is_ok());
68                        self.hash_storage.replace(hash);
69                        self.signature_storage.replace(signature);
70                        self.deferred_call.set();
71                        Ok(())
72                    })
73                    .unwrap()
74            } else {
75                Err((kernel::ErrorCode::INVAL, hash, signature))
76            }
77        } else {
78            Err((kernel::ErrorCode::FAIL, hash, signature))
79        }
80    }
81}
82
83impl kernel::deferred_call::DeferredCallClient for EcdsaP256SignatureVerifier<'_> {
84    fn handle_deferred_call(&self) {
85        self.client.map(|client| {
86            if let Some(h) = self.hash_storage.take() {
87                if let Some(s) = self.signature_storage.take() {
88                    client.verification_done(Ok(self.verified.get()), h, s);
89                }
90            }
91        });
92    }
93
94    fn register(&'static self) {
95        self.deferred_call.register(self);
96    }
97}