mundane/public/mod.rs
1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Public key cryptography.
6
7pub mod ec;
8pub mod ed25519;
9pub mod rsa;
10
11use boringssl::{CHeapWrapper, CStackWrapper};
12use public::inner::BoringDerKey;
13use util::Sealed;
14use Error;
15
16/// The public component of a public/private key pair.
17pub trait PublicKey: Sealed + Sized {
18 /// The type of the private component.
19 type Private: PrivateKey<Public = Self>;
20
21 /// Verifies a message with this public key.
22 ///
23 /// `is_valid` verifies that a message was signed by the private key
24 /// corresponding to this public key. It is equivalent to
25 /// `signature.is_valid(self, message)`.
26 #[must_use]
27 fn is_valid<S: Signature<PrivateKey = Self::Private>>(
28 &self,
29 message: &[u8],
30 signature: &S,
31 ) -> bool {
32 signature.is_valid(self, message)
33 }
34}
35
36/// The private component of a public/private key pair.
37pub trait PrivateKey: Sealed + Sized {
38 /// The type of the public component.
39 type Public: PublicKey<Private = Self>;
40
41 /// Gets the public key corresponding to this private key.
42 #[must_use]
43 fn public(&self) -> Self::Public;
44
45 /// Signs a message with this private key.
46 ///
47 /// `sign` signs a message with this key using the signature scheme `S`. It
48 /// is equivalent to `S::sign(self, message)`.
49 #[must_use]
50 fn sign<S: Signature<PrivateKey = Self>>(&self, message: &[u8]) -> Result<S, Error> {
51 S::sign(self, message)
52 }
53}
54
55/// A public key which can be encoded as a DER object.
56pub trait DerPublicKey: PublicKey + self::inner::DerKey {
57 /// Marshals a public key in DER format.
58 ///
59 /// `marshal_to_der` marshals a public key as a DER-encoded
60 /// SubjectPublicKeyInfo structure as defined in [RFC 5280].
61 ///
62 /// [RFC 5280]: https://tools.ietf.org/html/rfc5280
63 #[must_use]
64 fn marshal_to_der(&self) -> Vec<u8> {
65 let mut evp_pkey = CHeapWrapper::default();
66 self.boring().pkey_assign(&mut evp_pkey);
67 // cbb_new can only fail due to OOM
68 let mut cbb = CStackWrapper::cbb_new(64).unwrap();
69 evp_pkey.evp_marshal_public_key(&mut cbb).expect("failed to marshal public key");
70 cbb.cbb_with_data(<[u8]>::to_vec)
71 }
72
73 /// Parses a public key in DER format.
74 ///
75 /// `parse_from_der` parses a public key from a DER-encoded
76 /// SubjectPublicKeyInfo structure as defined in [RFC 5280].
77 ///
78 /// # Elliptic Curve Keys
79 ///
80 /// For Elliptic Curve keys ([`EcPubKey`]), the curve itself is validated.
81 /// If the curve is not known ahead of time, and any curve must be supported
82 /// at runtime, use the [`EcPubKeyAnyCurve::parse_from_der`] function.
83 ///
84 /// [RFC 5280]: https://tools.ietf.org/html/rfc5280
85 /// [`EcPubKey`]: ::public::ec::EcPubKey
86 /// [`EcPubKeyAnyCurve::parse_from_der`]: ::public::ec::EcPubKeyAnyCurve::parse_from_der
87 #[must_use]
88 fn parse_from_der(bytes: &[u8]) -> Result<Self, Error> {
89 CStackWrapper::cbs_with_temp_buffer(bytes, |cbs| {
90 let mut evp_pkey = CHeapWrapper::evp_parse_public_key(cbs)?;
91 // NOTE: For EC, panics if evp_pkey doesn't have its group set. This is
92 // OK because EVP_parse_public_key guarantees that the returned key has
93 // its group set.
94 let key = Self::Boring::pkey_get(&mut evp_pkey)?;
95 if cbs.cbs_len() > 0 {
96 return Err(Error::new("malformed DER input".to_string()));
97 }
98 Ok(Self::from_boring(key))
99 })
100 }
101}
102
103/// A private key which can be encoded as a DER object.
104pub trait DerPrivateKey: PrivateKey + self::inner::DerKey {
105 /// Marshals a private key in DER format.
106 ///
107 /// `marshal_to_der` marshal a private key as a DER-encoded structure. The
108 /// exact structure encoded depends on the type of key:
109 /// - For an EC key, it is an ECPrivateKey structure as defined in [RFC
110 /// 5915].
111 /// - For an RSA key, it is an RSAPrivateKey structure as defined in [RFC
112 /// 3447].
113 ///
114 /// [RFC 5915]: https://tools.ietf.org/html/rfc5915
115 /// [RFC 3447]: https://tools.ietf.org/html/rfc3447
116 #[must_use]
117 fn marshal_to_der(&self) -> Vec<u8> {
118 // cbb_new can only fail due to OOM
119 let mut cbb = CStackWrapper::cbb_new(64).unwrap();
120 self.boring().marshal_private_key(&mut cbb).expect("failed to marshal private key");
121 cbb.cbb_with_data(<[u8]>::to_vec)
122 }
123
124 /// Parses a private key in DER format.
125 ///
126 /// `parse_from_der` parses a private key from a DER-encoded format. The
127 /// exact structure expected depends on the type of key:
128 /// - For an EC key, it is an ECPrivateKey structure as defined in [RFC
129 /// 5915].
130 /// - For an RSA key, it is an RSAPrivateKey structure as defined in [RFC
131 /// 3447].
132 ///
133 /// # Elliptic Curve Keys
134 ///
135 /// For Elliptic Curve keys ([`EcPrivKey`]), the curve itself is validated. If
136 /// the curve is not known ahead of time, and any curve must be supported at
137 /// runtime, use the [`EcPrivKeyAnyCurve::parse_from_der`] function.
138 ///
139 /// [RFC 5915]: https://tools.ietf.org/html/rfc5915
140 /// [RFC 3447]: https://tools.ietf.org/html/rfc3447
141 /// [`EcPrivKey`]: ::public::ec::EcPrivKey
142 /// [`EcPrivKeyAnyCurve::parse_from_der`]: ::public::ec::EcPrivKeyAnyCurve::parse_from_der
143 #[must_use]
144 fn parse_from_der(bytes: &[u8]) -> Result<Self, Error> {
145 CStackWrapper::cbs_with_temp_buffer(bytes, |cbs| {
146 let key = Self::Boring::parse_private_key(cbs)?;
147 if cbs.cbs_len() > 0 {
148 return Err(Error::new("malformed DER input".to_string()));
149 }
150 Ok(Self::from_boring(key))
151 })
152 }
153}
154
155/// A cryptographic signature generated by a private key.
156pub trait Signature: Sealed + Sized {
157 /// The private key type used to generate this signature.
158 type PrivateKey: PrivateKey;
159
160 /// Sign a message.
161 ///
162 /// The input to this function is always a message, never a digest. If a
163 /// signature scheme calls for hashing a message and signing the hash
164 /// digest, `sign` is responsible for both hashing and signing.
165 #[must_use]
166 fn sign(key: &Self::PrivateKey, message: &[u8]) -> Result<Self, Error>;
167
168 /// Verify a signature.
169 ///
170 /// The input to this function is always a message, never a digest. If a
171 /// signature scheme calls for hashing a message and signing the hash
172 /// digest, `is_valid` is responsible for both hashing and verifying the
173 /// digest.
174 #[must_use]
175 fn is_valid(&self, key: &<Self::PrivateKey as PrivateKey>::Public, message: &[u8]) -> bool;
176}
177
178mod inner {
179 use boringssl::{self, CHeapWrapper, CStackWrapper};
180 use Error;
181
182 /// A wrapper around a BoringSSL key object.
183 pub trait BoringDerKey: Sized {
184 // evp_pkey_assign_xxx
185 fn pkey_assign(&self, pkey: &mut CHeapWrapper<boringssl::EVP_PKEY>);
186
187 // evp_pkey_get_xxx; panics if the key is an EC key and doesn't have a group set,
188 // and errors if pkey isn't the expected key type
189 fn pkey_get(pkey: &mut CHeapWrapper<boringssl::EVP_PKEY>) -> Result<Self, Error>;
190
191 // xxx_parse_private_key
192 fn parse_private_key(cbs: &mut CStackWrapper<boringssl::CBS>) -> Result<Self, Error>;
193
194 // xxx_marshal_private_key
195 fn marshal_private_key(&self, cbb: &mut CStackWrapper<boringssl::CBB>)
196 -> Result<(), Error>;
197 }
198
199 /// Properties shared by both public and private keys of a given type.
200 pub trait DerKey {
201 /// The underlying BoringSSL object wrapper type.
202 type Boring: BoringDerKey;
203
204 fn boring(&self) -> &Self::Boring;
205
206 fn from_boring(boring: Self::Boring) -> Self;
207 }
208}
209
210#[cfg(test)]
211mod testutil {
212 use super::*;
213
214 /// Smoke test a signature scheme.
215 ///
216 /// `sig_from_bytes` takes a byte slice and converts it into a signature. If
217 /// the byte slice is too long, it either truncate it or treats it as
218 /// invalid (it's up to the caller). If the byte slice is too short, it
219 /// fills in the remaining bytes with zeroes.
220 pub fn test_signature_smoke<S: Signature, F: Fn(&[u8]) -> S, G: Fn(&S) -> &[u8]>(
221 key: &S::PrivateKey,
222 sig_from_bytes: F,
223 bytes_from_sig: G,
224 ) {
225 // Sign the message, verify the signature, and return the signature.
226 // Also verify that, if the wrong signature is used, the signature fails
227 // to verify. Also verify that sig_from_bytes works.
228 fn sign_and_verify<S: Signature, F: Fn(&[u8]) -> S, G: Fn(&S) -> &[u8]>(
229 key: &S::PrivateKey,
230 message: &[u8],
231 sig_from_bytes: F,
232 bytes_from_sig: G,
233 ) -> S {
234 let sig = S::sign(key, message).unwrap();
235 assert!(sig.is_valid(&key.public(), message));
236 // Make sure the PrivateKey::sign and PublicKey::is_valid convenience
237 // functions also work.
238 let sig = key.sign::<S>(message).unwrap();
239 assert!(key.public().is_valid(message, &sig));
240 let sig2 = S::sign(&key, bytes_from_sig(&sig)).unwrap();
241 assert!(!sig2.is_valid(&key.public(), message));
242 // Make sure the PrivateKey::sign and PublicKey::is_valid convenience
243 // functions also work.
244 let sig2 = key.sign::<S>(bytes_from_sig(&sig)).unwrap();
245 assert!(!key.public().is_valid(message, &sig2));
246 sig_from_bytes(bytes_from_sig(&sig))
247 }
248
249 // Sign an empty message, and verify the signature. Use the signature as
250 // the next message to test, and repeat many times.
251 let mut msg = Vec::new();
252 for _ in 0..16 {
253 msg = bytes_from_sig(&sign_and_verify(key, &msg, &sig_from_bytes, &bytes_from_sig))
254 .to_vec();
255 }
256 }
257}