1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use crate::{ 6 crypto::{Cryptographer, EcKeyComponents, LocalKeyPair, RemotePublicKey}, 7 error::*, 8 }; 9 use hkdf::Hkdf; 10 use lazy_static::lazy_static; 11 use openssl::{ 12 bn::{BigNum, BigNumContext}, 13 derive::Deriver, 14 ec::{EcGroup, EcKey, EcPoint, PointConversionForm}, 15 nid::Nid, 16 pkey::{PKey, Private, Public}, 17 rand::rand_bytes, 18 symm::{Cipher, Crypter, Mode}, 19 }; 20 use sha2::Sha256; 21 use std::{any::Any, fmt}; 22 23 lazy_static! { 24 static ref GROUP_P256: EcGroup = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); 25 } 26 const AES_GCM_TAG_LENGTH: usize = 16; 27 28 #[derive(Clone, Debug)] 29 pub struct OpenSSLRemotePublicKey { 30 raw_pub_key: Vec<u8>, 31 } 32 33 impl OpenSSLRemotePublicKey { from_raw(raw: &[u8]) -> Result<Self>34 fn from_raw(raw: &[u8]) -> Result<Self> { 35 Ok(OpenSSLRemotePublicKey { 36 raw_pub_key: raw.to_vec(), 37 }) 38 } 39 to_pkey(&self) -> Result<PKey<Public>>40 fn to_pkey(&self) -> Result<PKey<Public>> { 41 let mut bn_ctx = BigNumContext::new()?; 42 let point = EcPoint::from_bytes(&GROUP_P256, &self.raw_pub_key, &mut bn_ctx)?; 43 let ec = EcKey::from_public_key(&GROUP_P256, &point)?; 44 PKey::from_ec_key(ec).map_err(std::convert::Into::into) 45 } 46 } 47 48 impl RemotePublicKey for OpenSSLRemotePublicKey { as_raw(&self) -> Result<Vec<u8>>49 fn as_raw(&self) -> Result<Vec<u8>> { 50 Ok(self.raw_pub_key.to_vec()) 51 } as_any(&self) -> &dyn Any52 fn as_any(&self) -> &dyn Any { 53 self 54 } 55 } 56 57 #[derive(Clone)] 58 pub struct OpenSSLLocalKeyPair { 59 ec_key: EcKey<Private>, 60 } 61 62 impl fmt::Debug for OpenSSLLocalKeyPair { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 64 write!( 65 f, 66 "{:?}", 67 base64::encode_config(&self.ec_key.private_key().to_vec(), base64::URL_SAFE) 68 ) 69 } 70 } 71 72 impl OpenSSLLocalKeyPair { 73 /// Generate a random local key pair using OpenSSL `ECKey::generate`. generate_random() -> Result<Self>74 fn generate_random() -> Result<Self> { 75 let ec_key = EcKey::generate(&GROUP_P256)?; 76 Ok(OpenSSLLocalKeyPair { ec_key }) 77 } 78 to_pkey(&self) -> Result<PKey<Private>>79 fn to_pkey(&self) -> Result<PKey<Private>> { 80 PKey::from_ec_key(self.ec_key.clone()).map_err(std::convert::Into::into) 81 } 82 from_raw_components(components: &EcKeyComponents) -> Result<Self>83 fn from_raw_components(components: &EcKeyComponents) -> Result<Self> { 84 let d = BigNum::from_slice(&components.private_key())?; 85 let mut bn_ctx = BigNumContext::new()?; 86 let ec_point = EcPoint::from_bytes(&GROUP_P256, &components.public_key(), &mut bn_ctx)?; 87 let mut x = BigNum::new()?; 88 let mut y = BigNum::new()?; 89 ec_point.affine_coordinates_gfp(&GROUP_P256, &mut x, &mut y, &mut bn_ctx)?; 90 let public_key = EcKey::from_public_key_affine_coordinates(&GROUP_P256, &x, &y)?; 91 let private_key = EcKey::from_private_components(&GROUP_P256, &d, public_key.public_key())?; 92 Ok(Self { 93 ec_key: private_key, 94 }) 95 } 96 } 97 98 impl LocalKeyPair for OpenSSLLocalKeyPair { 99 /// Export the public key component in the binary uncompressed point representation 100 /// using OpenSSL `PointConversionForm::UNCOMPRESSED`. pub_as_raw(&self) -> Result<Vec<u8>>101 fn pub_as_raw(&self) -> Result<Vec<u8>> { 102 let pub_key_point = self.ec_key.public_key(); 103 let mut bn_ctx = BigNumContext::new()?; 104 let uncompressed = 105 pub_key_point.to_bytes(&GROUP_P256, PointConversionForm::UNCOMPRESSED, &mut bn_ctx)?; 106 Ok(uncompressed) 107 } 108 raw_components(&self) -> Result<EcKeyComponents>109 fn raw_components(&self) -> Result<EcKeyComponents> { 110 let private_key = self.ec_key.private_key(); 111 Ok(EcKeyComponents::new( 112 private_key.to_vec(), 113 self.pub_as_raw()?, 114 )) 115 } 116 as_any(&self) -> &dyn Any117 fn as_any(&self) -> &dyn Any { 118 self 119 } 120 } 121 122 impl From<EcKey<Private>> for OpenSSLLocalKeyPair { from(key: EcKey<Private>) -> OpenSSLLocalKeyPair123 fn from(key: EcKey<Private>) -> OpenSSLLocalKeyPair { 124 OpenSSLLocalKeyPair { ec_key: key } 125 } 126 } 127 128 pub struct OpensslCryptographer; 129 impl Cryptographer for OpensslCryptographer { generate_ephemeral_keypair(&self) -> Result<Box<dyn LocalKeyPair>>130 fn generate_ephemeral_keypair(&self) -> Result<Box<dyn LocalKeyPair>> { 131 Ok(Box::new(OpenSSLLocalKeyPair::generate_random()?)) 132 } 133 import_key_pair(&self, components: &EcKeyComponents) -> Result<Box<dyn LocalKeyPair>>134 fn import_key_pair(&self, components: &EcKeyComponents) -> Result<Box<dyn LocalKeyPair>> { 135 Ok(Box::new(OpenSSLLocalKeyPair::from_raw_components( 136 components, 137 )?)) 138 } 139 import_public_key(&self, raw: &[u8]) -> Result<Box<dyn RemotePublicKey>>140 fn import_public_key(&self, raw: &[u8]) -> Result<Box<dyn RemotePublicKey>> { 141 Ok(Box::new(OpenSSLRemotePublicKey::from_raw(raw)?)) 142 } 143 compute_ecdh_secret( &self, remote: &dyn RemotePublicKey, local: &dyn LocalKeyPair, ) -> Result<Vec<u8>>144 fn compute_ecdh_secret( 145 &self, 146 remote: &dyn RemotePublicKey, 147 local: &dyn LocalKeyPair, 148 ) -> Result<Vec<u8>> { 149 let local_any = local.as_any(); 150 let local = local_any.downcast_ref::<OpenSSLLocalKeyPair>().unwrap(); 151 let private = local.to_pkey()?; 152 let remote_any = remote.as_any(); 153 let remote = remote_any.downcast_ref::<OpenSSLRemotePublicKey>().unwrap(); 154 let public = remote.to_pkey()?; 155 let mut deriver = Deriver::new(&private)?; 156 deriver.set_peer(&public)?; 157 let shared_key = deriver.derive_to_vec()?; 158 Ok(shared_key) 159 } 160 hkdf_sha256(&self, salt: &[u8], secret: &[u8], info: &[u8], len: usize) -> Result<Vec<u8>>161 fn hkdf_sha256(&self, salt: &[u8], secret: &[u8], info: &[u8], len: usize) -> Result<Vec<u8>> { 162 let hk = Hkdf::<Sha256>::extract(Some(&salt[..]), &secret); 163 let mut okm = vec![0u8; len]; 164 hk.expand(&info, &mut okm).unwrap(); 165 Ok(okm) 166 } 167 aes_gcm_128_encrypt(&self, key: &[u8], iv: &[u8], data: &[u8]) -> Result<Vec<u8>>168 fn aes_gcm_128_encrypt(&self, key: &[u8], iv: &[u8], data: &[u8]) -> Result<Vec<u8>> { 169 let cipher = Cipher::aes_128_gcm(); 170 let mut c = Crypter::new(cipher, Mode::Encrypt, key, Some(iv))?; 171 let mut out = vec![0u8; data.len() + cipher.block_size()]; 172 let count = c.update(data, &mut out)?; 173 let rest = c.finalize(&mut out[count..])?; 174 let mut tag = vec![0u8; AES_GCM_TAG_LENGTH]; 175 c.get_tag(&mut tag)?; 176 out.truncate(count + rest); 177 out.append(&mut tag); 178 Ok(out) 179 } 180 aes_gcm_128_decrypt( &self, key: &[u8], iv: &[u8], ciphertext_and_tag: &[u8], ) -> Result<Vec<u8>>181 fn aes_gcm_128_decrypt( 182 &self, 183 key: &[u8], 184 iv: &[u8], 185 ciphertext_and_tag: &[u8], 186 ) -> Result<Vec<u8>> { 187 let block_len = ciphertext_and_tag.len() - AES_GCM_TAG_LENGTH; 188 let ciphertext = &ciphertext_and_tag[0..block_len]; 189 let tag = &ciphertext_and_tag[block_len..]; 190 let cipher = Cipher::aes_128_gcm(); 191 let mut c = Crypter::new(cipher, Mode::Decrypt, key, Some(iv))?; 192 let mut out = vec![0u8; ciphertext.len() + cipher.block_size()]; 193 let count = c.update(ciphertext, &mut out)?; 194 c.set_tag(tag)?; 195 let rest = c.finalize(&mut out[count..])?; 196 out.truncate(count + rest); 197 Ok(out) 198 } 199 random_bytes(&self, dest: &mut [u8]) -> Result<()>200 fn random_bytes(&self, dest: &mut [u8]) -> Result<()> { 201 Ok(rand_bytes(dest)?) 202 } 203 } 204