1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use crate::RcRng;
16 use core::marker::PhantomData;
17 use crypto_provider::{
18     elliptic_curve::{EcdhProvider, EphemeralSecret},
19     p256::{PointCompression, P256},
20     tinyvec::ArrayVec,
21 };
22 use p256::{
23     elliptic_curve,
24     elliptic_curve::{
25         generic_array::GenericArray,
26         sec1::{FromEncodedPoint, ToEncodedPoint},
27     },
28 };
29 use rand::{RngCore, SeedableRng};
30 use rand_core::CryptoRng;
31 
32 /// Implementation of NIST-P256 using RustCrypto crates.
33 pub struct P256Ecdh<R> {
34     _marker: PhantomData<R>,
35 }
36 
37 impl<R: CryptoRng + SeedableRng + RngCore + Send> EcdhProvider<P256> for P256Ecdh<R> {
38     type PublicKey = P256PublicKey;
39     type EphemeralSecret = P256EphemeralSecret<R>;
40     type SharedSecret = [u8; 32];
41 }
42 
43 /// A NIST-P256 public key.
44 #[derive(Debug, PartialEq, Eq)]
45 pub struct P256PublicKey(p256::PublicKey);
46 impl crypto_provider::p256::P256PublicKey for P256PublicKey {
47     type Error = elliptic_curve::Error;
48 
from_sec1_bytes(bytes: &[u8]) -> Result<Self, Self::Error>49     fn from_sec1_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
50         p256::PublicKey::from_sec1_bytes(bytes).map(Self)
51     }
52 
to_sec1_bytes(&self, point_compression: PointCompression) -> ArrayVec<[u8; 65]>53     fn to_sec1_bytes(&self, point_compression: PointCompression) -> ArrayVec<[u8; 65]> {
54         let mut bytes = ArrayVec::<[u8; 65]>::new();
55         bytes.extend_from_slice(
56             self.0.to_encoded_point(point_compression == PointCompression::Compressed).as_bytes(),
57         );
58         bytes
59     }
60 
61     #[allow(clippy::expect_used)]
to_affine_coordinates(&self) -> Result<([u8; 32], [u8; 32]), Self::Error>62     fn to_affine_coordinates(&self) -> Result<([u8; 32], [u8; 32]), Self::Error> {
63         let p256_key = self.0.to_encoded_point(false);
64         let x: &[u8; 32] =
65             p256_key.x().expect("Generated key should not be on identity point").as_ref();
66         let y: &[u8; 32] =
67             p256_key.y().expect("Generated key should not be on identity point").as_ref();
68         Ok((*x, *y))
69     }
from_affine_coordinates(x: &[u8; 32], y: &[u8; 32]) -> Result<Self, Self::Error>70     fn from_affine_coordinates(x: &[u8; 32], y: &[u8; 32]) -> Result<Self, Self::Error> {
71         let key_option: Option<p256::PublicKey> =
72             p256::PublicKey::from_encoded_point(&p256::EncodedPoint::from_affine_coordinates(
73                 &GenericArray::clone_from_slice(x),
74                 &GenericArray::clone_from_slice(y),
75                 false,
76             ))
77             .into();
78         key_option.map(Self).ok_or(elliptic_curve::Error)
79     }
80 }
81 
82 /// Ephemeral secrect for use in a P256 Diffie-Hellman
83 pub struct P256EphemeralSecret<R: CryptoRng + SeedableRng + RngCore> {
84     secret: p256::ecdh::EphemeralSecret,
85     _marker: PhantomData<R>,
86 }
87 
88 impl<R: CryptoRng + SeedableRng + RngCore + Send> EphemeralSecret<P256> for P256EphemeralSecret<R> {
89     type Impl = P256Ecdh<R>;
90     type Error = sec1::Error;
91     type Rng = RcRng<R>;
92     type EncodedPublicKey = ArrayVec<[u8; 65]>;
93 
generate_random(rng: &mut Self::Rng) -> Self94     fn generate_random(rng: &mut Self::Rng) -> Self {
95         Self {
96             secret: p256::ecdh::EphemeralSecret::random(&mut rng.0),
97             _marker: Default::default(),
98         }
99     }
100 
public_key_bytes(&self) -> Self::EncodedPublicKey101     fn public_key_bytes(&self) -> Self::EncodedPublicKey {
102         let mut bytes = Self::EncodedPublicKey::new();
103         bytes.extend_from_slice(self.secret.public_key().to_encoded_point(false).as_bytes());
104         bytes
105     }
106 
diffie_hellman( self, other_pub: &P256PublicKey, ) -> Result<<Self::Impl as EcdhProvider<P256>>::SharedSecret, Self::Error>107     fn diffie_hellman(
108         self,
109         other_pub: &P256PublicKey,
110     ) -> Result<<Self::Impl as EcdhProvider<P256>>::SharedSecret, Self::Error> {
111         let shared_secret = p256::ecdh::EphemeralSecret::diffie_hellman(&self.secret, &other_pub.0);
112         let bytes: <Self::Impl as EcdhProvider<P256>>::SharedSecret =
113             (*shared_secret.raw_secret_bytes()).into();
114         Ok(bytes)
115     }
116 }
117 
118 #[cfg(test)]
119 impl<R: CryptoRng + SeedableRng + RngCore + Send>
120     crypto_provider_test::elliptic_curve::EphemeralSecretForTesting<P256>
121     for P256EphemeralSecret<R>
122 {
from_private_components( private_bytes: &[u8; 32], _public_key: &P256PublicKey, ) -> Result<Self, Self::Error>123     fn from_private_components(
124         private_bytes: &[u8; 32],
125         _public_key: &P256PublicKey,
126     ) -> Result<Self, Self::Error> {
127         Ok(Self {
128             secret: p256::ecdh::EphemeralSecret::random(&mut crate::testing::MockCryptoRng {
129                 values: private_bytes.iter(),
130             }),
131             _marker: Default::default(),
132         })
133     }
134 }
135 
136 #[cfg(test)]
137 mod tests {
138     use super::P256Ecdh;
139     use core::marker::PhantomData;
140     use crypto_provider_test::p256::*;
141     use rand::rngs::StdRng;
142 
143     #[apply(p256_test_cases)]
p256_tests(testcase: CryptoProviderTestCase<P256Ecdh<StdRng>>, _name: &str)144     fn p256_tests(testcase: CryptoProviderTestCase<P256Ecdh<StdRng>>, _name: &str) {
145         testcase(PhantomData::<P256Ecdh<StdRng>>)
146     }
147 }
148