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::hil::public_key_crypto::keys::SetKeyBySliceClient;
13use kernel::utilities::cells::{OptionalCell, TakeCell};
14use kernel::ErrorCode;
15
16enum State {
17    Verifying,
18    ChangingKey(&'static mut [u8; 64]),
19}
20
21pub struct EcdsaP256SignatureVerifier<'a> {
22    verified: Cell<bool>,
23    client: OptionalCell<&'a dyn hil::public_key_crypto::signature::ClientVerify<32, 64>>,
24    client_key_set: OptionalCell<&'a dyn hil::public_key_crypto::keys::SetKeyBySliceClient<64>>,
25    verifying_key: TakeCell<'static, [u8; 64]>,
26    hash_storage: TakeCell<'static, [u8; 32]>,
27    signature_storage: TakeCell<'static, [u8; 64]>,
28    deferred_call: kernel::deferred_call::DeferredCall,
29    state: OptionalCell<State>,
30}
31
32impl EcdsaP256SignatureVerifier<'_> {
33    pub fn new(verifying_key: &'static mut [u8; 64]) -> Self {
34        Self {
35            verified: Cell::new(false),
36            client: OptionalCell::empty(),
37            client_key_set: OptionalCell::empty(),
38            verifying_key: TakeCell::new(verifying_key),
39            hash_storage: TakeCell::empty(),
40            signature_storage: TakeCell::empty(),
41            deferred_call: kernel::deferred_call::DeferredCall::new(),
42            state: OptionalCell::empty(),
43        }
44    }
45}
46
47impl<'a> hil::public_key_crypto::signature::SignatureVerify<'a, 32, 64>
48    for EcdsaP256SignatureVerifier<'a>
49{
50    fn set_verify_client(
51        &self,
52        client: &'a dyn hil::public_key_crypto::signature::ClientVerify<32, 64>,
53    ) {
54        self.client.replace(client);
55    }
56
57    fn verify(
58        &self,
59        hash: &'static mut [u8; 32],
60        signature: &'static mut [u8; 64],
61    ) -> Result<
62        (),
63        (
64            kernel::ErrorCode,
65            &'static mut [u8; 32],
66            &'static mut [u8; 64],
67        ),
68    > {
69        if self.verifying_key.is_some() {
70            if let Ok(sig) = ecdsa::Signature::from_slice(signature) {
71                self.verifying_key
72                    .map(|vkey| {
73                        let vkey: &[u8; 64] = vkey;
74                        let ep = p256::EncodedPoint::from_untagged_bytes(vkey.into());
75                        let key = ecdsa::VerifyingKey::from_encoded_point(&ep);
76                        key.map(|ecdsa_key| {
77                            self.verified
78                                .set(ecdsa_key.verify_prehash(hash, &sig).is_ok());
79                            self.hash_storage.replace(hash);
80                            self.signature_storage.replace(signature);
81                            self.state.set(State::Verifying);
82                            self.deferred_call.set();
83                            Ok(())
84                        })
85                        .unwrap()
86                    })
87                    .unwrap()
88            } else {
89                Err((kernel::ErrorCode::INVAL, hash, signature))
90            }
91        } else {
92            Err((kernel::ErrorCode::FAIL, hash, signature))
93        }
94    }
95}
96
97impl<'a> hil::public_key_crypto::keys::SetKeyBySlice<'a, 64> for EcdsaP256SignatureVerifier<'a> {
98    fn set_key(
99        &self,
100        key: &'static mut [u8; 64],
101    ) -> Result<(), (ErrorCode, &'static mut [u8; 64])> {
102        // Just wait for the deferred call to make the change so we can keep
103        // both the old and the new key in the meantime.
104        self.state.set(State::ChangingKey(key));
105        self.deferred_call.set();
106        Ok(())
107    }
108
109    fn set_client(&self, client: &'a dyn SetKeyBySliceClient<64>) {
110        self.client_key_set.replace(client);
111    }
112}
113
114impl kernel::deferred_call::DeferredCallClient for EcdsaP256SignatureVerifier<'_> {
115    fn handle_deferred_call(&self) {
116        if let Some(s) = self.state.take() {
117            match s {
118                State::Verifying => {
119                    self.client.map(|client| {
120                        if let Some(h) = self.hash_storage.take() {
121                            if let Some(s) = self.signature_storage.take() {
122                                client.verification_done(Ok(self.verified.get()), h, s);
123                            }
124                        }
125                    });
126                }
127                State::ChangingKey(key) => {
128                    self.verifying_key.map(|vkey| {
129                        vkey.copy_from_slice(key);
130                    });
131
132                    self.client_key_set.map(|client| {
133                        client.set_key_done(key, Ok(()));
134                    });
135                }
136            }
137        }
138    }
139
140    fn register(&'static self) {
141        self.deferred_call.register(self);
142    }
143}