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