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 tinyvec::ArrayVec;
16 
17 use crate::elliptic_curve::{Curve, EcdhProvider, PublicKey};
18 use core::fmt::Debug;
19 
20 /// Marker type for P256 implementation. This is used by EcdhProvider as its type parameter.
21 #[derive(Debug, PartialEq, Eq)]
22 pub enum P256 {}
23 impl Curve for P256 {}
24 
25 /// Longest length for a sec-1 encoded P256 public key, which is the uncompressed format
26 /// `04 || X || Y` as defined in section 2.3.3 of the SECG SEC 1 ("Elliptic Curve Cryptography")
27 /// standard.
28 const P256_PUBLIC_KEY_MAX_LENGTH: usize = 65;
29 
30 /// Whether an elliptic curve point should be compressed or not.
31 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
32 pub enum PointCompression {
33     /// The elliptic curve point should be compressed (`02 || X` or `03 || X`),
34     /// as defined in section 2.3.3 of the SECG SEC 1 ("Elliptic Curve
35     /// Cryptography").
36     Compressed,
37     /// The elliptic curve point should be uncompressed (`04 || X || Y`), as
38     /// defined in section 2.3.3 of the SECG SEC 1 ("Elliptic Curve
39     /// Cryptography").
40     Uncompressed,
41 }
42 
43 /// Trait for a NIST-P256 public key.
44 pub trait P256PublicKey: Sized + PartialEq + Debug {
45     /// The error type associated with this implementation.
46     type Error: Debug;
47 
48     /// Creates a public key from the given sec1-encoded bytes, as described in section 2.3.4 of
49     /// the SECG SEC 1 ("Elliptic Curve Cryptography") standard.
from_sec1_bytes(bytes: &[u8]) -> Result<Self, Self::Error>50     fn from_sec1_bytes(bytes: &[u8]) -> Result<Self, Self::Error>;
51 
52     /// Serializes this key into sec1-encoded bytes, as described in section 2.3.3 of the SECG SEC 1
53     /// ("Elliptic Curve Cryptography") standard. Note that it is not necessarily true that
54     /// `from_sec1_bytes(bytes)?.to_sec1_bytes() == bytes` because of point compression. (But it is
55     /// always true that `from_sec1_bytes(key.to_sec1_bytes())? == key`).
to_sec1_bytes( &self, point_compression: PointCompression, ) -> ArrayVec<[u8; P256_PUBLIC_KEY_MAX_LENGTH]>56     fn to_sec1_bytes(
57         &self,
58         point_compression: PointCompression,
59     ) -> ArrayVec<[u8; P256_PUBLIC_KEY_MAX_LENGTH]>;
60 
61     /// Converts this public key's x and y coordinates on the elliptic curve to big endian octet
62     /// strings.
to_affine_coordinates(&self) -> Result<([u8; 32], [u8; 32]), Self::Error>63     fn to_affine_coordinates(&self) -> Result<([u8; 32], [u8; 32]), Self::Error>;
64 
65     /// Creates a public key from the X and Y coordinates on the elliptic curve.
from_affine_coordinates(x: &[u8; 32], y: &[u8; 32]) -> Result<Self, Self::Error>66     fn from_affine_coordinates(x: &[u8; 32], y: &[u8; 32]) -> Result<Self, Self::Error>;
67 }
68 
69 impl<P: P256PublicKey> PublicKey<P256> for P {
70     type Error = <Self as P256PublicKey>::Error;
71     type EncodedPublicKey = ArrayVec<[u8; P256_PUBLIC_KEY_MAX_LENGTH]>;
72 
from_bytes(bytes: &[u8]) -> Result<Self, Self::Error>73     fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
74         Self::from_sec1_bytes(bytes)
75     }
76 
to_bytes(&self) -> Self::EncodedPublicKey77     fn to_bytes(&self) -> Self::EncodedPublicKey {
78         Self::to_sec1_bytes(self, PointCompression::Uncompressed)
79     }
80 }
81 
82 /// Equivalent to EcdhProvider<P256, PublicKey: P256PublicKey> if associated type bounds are
83 /// supported.
84 pub trait P256EcdhProvider:
85     EcdhProvider<P256, PublicKey = <Self as P256EcdhProvider>::PublicKey>
86 {
87     /// Same as EcdhProvider::PublicKey.
88     type PublicKey: P256PublicKey;
89 }
90 
91 impl<E> P256EcdhProvider for E
92 where
93     E: EcdhProvider<P256>,
94     E::PublicKey: P256PublicKey,
95 {
96     type PublicKey = E::PublicKey;
97 }
98