1 /* Copyright (c) 2024, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 */ 15 16 //! Elliptic Curve Digital Signature Algorithm. 17 //! 18 //! The module implements ECDSA for the NIST curves P-256 and P-384. 19 //! 20 //! ``` 21 //! use bssl_crypto::{ecdsa, ec::P256}; 22 //! 23 //! let key = ecdsa::PrivateKey::<P256>::generate(); 24 //! // Publish your public key. 25 //! let public_key_bytes = key.to_der_subject_public_key_info(); 26 //! 27 //! // Sign and publish some message. 28 //! let signed_message = b"hello world"; 29 //! let mut sig = key.sign(signed_message); 30 //! 31 //! // Anyone with the public key can verify it. 32 //! let public_key = ecdsa::PublicKey::<P256>::from_der_subject_public_key_info( 33 //! public_key_bytes.as_ref()).unwrap(); 34 //! assert!(public_key.verify(signed_message, sig.as_slice()).is_ok()); 35 //! ``` 36 37 use crate::{ec, sealed, with_output_vec, Buffer, FfiSlice, InvalidSignatureError}; 38 use alloc::vec::Vec; 39 use core::marker::PhantomData; 40 41 /// An ECDSA public key over the given curve. 42 pub struct PublicKey<C: ec::Curve> { 43 point: ec::Point, 44 marker: PhantomData<C>, 45 } 46 47 impl<C: ec::Curve> PublicKey<C> { 48 /// Parse a public key in uncompressed X9.62 format. (This is the common 49 /// format for elliptic curve points beginning with an 0x04 byte.) from_x962_uncompressed(x962: &[u8]) -> Option<Self>50 pub fn from_x962_uncompressed(x962: &[u8]) -> Option<Self> { 51 let point = ec::Point::from_x962_uncompressed(C::group(sealed::Sealed), x962)?; 52 Some(Self { 53 point, 54 marker: PhantomData, 55 }) 56 } 57 58 /// Serialize this key as uncompressed X9.62 format. to_x962_uncompressed(&self) -> Buffer59 pub fn to_x962_uncompressed(&self) -> Buffer { 60 self.point.to_x962_uncompressed() 61 } 62 63 /// Parse a public key in SubjectPublicKeyInfo format. 64 /// (This is found in, e.g., X.509 certificates.) from_der_subject_public_key_info(spki: &[u8]) -> Option<Self>65 pub fn from_der_subject_public_key_info(spki: &[u8]) -> Option<Self> { 66 let point = ec::Point::from_der_subject_public_key_info(C::group(sealed::Sealed), spki)?; 67 Some(Self { 68 point, 69 marker: PhantomData, 70 }) 71 } 72 73 /// Serialize this key in SubjectPublicKeyInfo format. to_der_subject_public_key_info(&self) -> Buffer74 pub fn to_der_subject_public_key_info(&self) -> Buffer { 75 self.point.to_der_subject_public_key_info() 76 } 77 78 /// Verify `signature` as a valid signature of a digest of `signed_msg` 79 /// with this public key. SHA-256 will be used to produce the digest if the 80 /// curve of this public key is P-256. SHA-384 will be used to produce the 81 /// digest if the curve of this public key is P-384. verify(&self, signed_msg: &[u8], signature: &[u8]) -> Result<(), InvalidSignatureError>82 pub fn verify(&self, signed_msg: &[u8], signature: &[u8]) -> Result<(), InvalidSignatureError> { 83 let digest = C::hash(signed_msg); 84 let result = self.point.with_point_as_ec_key(|ec_key| unsafe { 85 // Safety: `ec_key` is valid per `with_point_as_ec_key`. 86 bssl_sys::ECDSA_verify( 87 /*type=*/ 0, 88 digest.as_slice().as_ffi_ptr(), 89 digest.len(), 90 signature.as_ffi_ptr(), 91 signature.len(), 92 ec_key, 93 ) 94 }); 95 if result == 1 { 96 Ok(()) 97 } else { 98 Err(InvalidSignatureError) 99 } 100 } 101 } 102 103 /// An ECDH private key over the given curve. 104 pub struct PrivateKey<C: ec::Curve> { 105 key: ec::Key, 106 marker: PhantomData<C>, 107 } 108 109 impl<C: ec::Curve> PrivateKey<C> { 110 /// Generate a random private key. generate() -> Self111 pub fn generate() -> Self { 112 Self { 113 key: ec::Key::generate(C::group(sealed::Sealed)), 114 marker: PhantomData, 115 } 116 } 117 118 /// Parse a `PrivateKey` from a zero-padded, big-endian representation of the secret scalar. from_big_endian(scalar: &[u8]) -> Option<Self>119 pub fn from_big_endian(scalar: &[u8]) -> Option<Self> { 120 let key = ec::Key::from_big_endian(C::group(sealed::Sealed), scalar)?; 121 Some(Self { 122 key, 123 marker: PhantomData, 124 }) 125 } 126 127 /// Return the private key as zero-padded, big-endian bytes. to_big_endian(&self) -> Buffer128 pub fn to_big_endian(&self) -> Buffer { 129 self.key.to_big_endian() 130 } 131 132 /// Parse an ECPrivateKey structure (from RFC 5915). The key must be on the 133 /// specified curve. from_der_ec_private_key(der: &[u8]) -> Option<Self>134 pub fn from_der_ec_private_key(der: &[u8]) -> Option<Self> { 135 let key = ec::Key::from_der_ec_private_key(C::group(sealed::Sealed), der)?; 136 Some(Self { 137 key, 138 marker: PhantomData, 139 }) 140 } 141 142 /// Serialize this private key as an ECPrivateKey structure (from RFC 5915). to_der_ec_private_key(&self) -> Buffer143 pub fn to_der_ec_private_key(&self) -> Buffer { 144 self.key.to_der_ec_private_key() 145 } 146 147 /// Parse a PrivateKeyInfo structure (from RFC 5208), commonly called 148 /// "PKCS#8 format". The key must be on the specified curve. from_der_private_key_info(der: &[u8]) -> Option<Self>149 pub fn from_der_private_key_info(der: &[u8]) -> Option<Self> { 150 let key = ec::Key::from_der_private_key_info(C::group(sealed::Sealed), der)?; 151 Some(Self { 152 key, 153 marker: PhantomData, 154 }) 155 } 156 157 /// Serialize this private key as a PrivateKeyInfo structure (from RFC 5208), 158 /// commonly called "PKCS#8 format". to_der_private_key_info(&self) -> Buffer159 pub fn to_der_private_key_info(&self) -> Buffer { 160 self.key.to_der_private_key_info() 161 } 162 163 /// Serialize the _public_ part of this key in uncompressed X9.62 format. to_x962_uncompressed(&self) -> Buffer164 pub fn to_x962_uncompressed(&self) -> Buffer { 165 self.key.to_x962_uncompressed() 166 } 167 168 /// Serialize this key in SubjectPublicKeyInfo format. to_der_subject_public_key_info(&self) -> Buffer169 pub fn to_der_subject_public_key_info(&self) -> Buffer { 170 self.key.to_der_subject_public_key_info() 171 } 172 173 /// Return the public key corresponding to this private key. to_public_key(&self) -> PublicKey<C>174 pub fn to_public_key(&self) -> PublicKey<C> { 175 PublicKey { 176 point: self.key.to_point(), 177 marker: PhantomData, 178 } 179 } 180 181 /// Sign a digest of `to_be_signed` using this key and return the signature. 182 /// SHA-256 will be used to produce the digest if the curve of this public 183 /// key is P-256. SHA-384 will be used to produce the digest if the curve 184 /// of this public key is P-384. sign(&self, to_be_signed: &[u8]) -> Vec<u8>185 pub fn sign(&self, to_be_signed: &[u8]) -> Vec<u8> { 186 // Safety: `self.key` is valid by construction. 187 let max_size = unsafe { bssl_sys::ECDSA_size(self.key.as_ffi_ptr()) }; 188 // No curve can be empty. 189 assert_ne!(max_size, 0); 190 191 let digest = C::hash(to_be_signed); 192 193 unsafe { 194 with_output_vec(max_size, |out_buf| { 195 let mut out_len: core::ffi::c_uint = 0; 196 // Safety: `out_buf` points to at least `max_size` bytes, 197 // as required. 198 let result = { 199 bssl_sys::ECDSA_sign( 200 /*type=*/ 0, 201 digest.as_slice().as_ffi_ptr(), 202 digest.len(), 203 out_buf, 204 &mut out_len, 205 self.key.as_ffi_ptr(), 206 ) 207 }; 208 // Signing should never fail unless we're out of memory, 209 // which this crate doesn't handle. 210 assert_eq!(result, 1); 211 let out_len = out_len as usize; 212 assert!(out_len <= max_size); 213 // Safety: `out_len` bytes have been written. 214 out_len 215 }) 216 } 217 } 218 } 219 220 #[cfg(test)] 221 mod test { 222 use super::*; 223 use crate::ec::{P256, P384}; 224 check_curve<C: ec::Curve>()225 fn check_curve<C: ec::Curve>() { 226 let signed_message = b"hello world"; 227 let key = PrivateKey::<C>::generate(); 228 let mut sig = key.sign(signed_message); 229 230 let public_key = PublicKey::<C>::from_der_subject_public_key_info( 231 key.to_der_subject_public_key_info().as_ref(), 232 ) 233 .unwrap(); 234 assert!(public_key.verify(signed_message, sig.as_slice()).is_ok()); 235 236 sig[10] ^= 1; 237 assert!(public_key.verify(signed_message, sig.as_slice()).is_err()); 238 } 239 240 #[test] p256()241 fn p256() { 242 check_curve::<P256>(); 243 } 244 245 #[test] p384()246 fn p384() { 247 check_curve::<P384>(); 248 } 249 } 250