]> git.proxmox.com Git - rustc.git/blob - src/vendor/openssl/src/pkey.rs
New upstream version 1.19.0+dfsg1
[rustc.git] / src / vendor / openssl / src / pkey.rs
1 use libc::{c_void, c_char, c_int, size_t};
2 use std::ptr;
3 use std::mem;
4 use std::ffi::CString;
5 use ffi;
6 use foreign_types::{ForeignType, ForeignTypeRef};
7
8 use {cvt, cvt_p};
9 use bio::MemBioSlice;
10 use dh::Dh;
11 use dsa::Dsa;
12 use ec::EcKey;
13 use rsa::{Rsa, Padding};
14 use error::ErrorStack;
15 use util::{CallbackState, invoke_passwd_cb, invoke_passwd_cb_old};
16
17 foreign_type! {
18 type CType = ffi::EVP_PKEY;
19 fn drop = ffi::EVP_PKEY_free;
20
21 pub struct PKey;
22 pub struct PKeyRef;
23 }
24
25 impl PKeyRef {
26 /// Returns a copy of the internal RSA key.
27 pub fn rsa(&self) -> Result<Rsa, ErrorStack> {
28 unsafe {
29 let rsa = try!(cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr())));
30 Ok(Rsa::from_ptr(rsa))
31 }
32 }
33
34 /// Returns a copy of the internal DSA key.
35 pub fn dsa(&self) -> Result<Dsa, ErrorStack> {
36 unsafe {
37 let dsa = try!(cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr())));
38 Ok(Dsa::from_ptr(dsa))
39 }
40 }
41
42 /// Returns a copy of the internal DH key.
43 pub fn dh(&self) -> Result<Dh, ErrorStack> {
44 unsafe {
45 let dh = try!(cvt_p(ffi::EVP_PKEY_get1_DH(self.as_ptr())));
46 Ok(Dh::from_ptr(dh))
47 }
48 }
49
50 /// Returns a copy of the internal elliptic curve key.
51 pub fn ec_key(&self) -> Result<EcKey, ErrorStack> {
52 unsafe {
53 let ec_key = try!(cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr())));
54 Ok(EcKey::from_ptr(ec_key))
55 }
56 }
57
58 public_key_to_pem!(ffi::PEM_write_bio_PUBKEY);
59 private_key_to_pem!(ffi::PEM_write_bio_PKCS8PrivateKey);
60
61 private_key_to_der!(ffi::i2d_PrivateKey);
62 public_key_to_der!(ffi::i2d_PUBKEY);
63
64 /// Returns the size of the key.
65 ///
66 /// This corresponds to the bit length of the modulus of an RSA key, and the bit length of the
67 /// group order for an elliptic curve key, for example.
68 pub fn bits(&self) -> u32 {
69 unsafe { ffi::EVP_PKEY_bits(self.as_ptr()) as u32 }
70 }
71
72 /// Compares the public component of this key with another.
73 pub fn public_eq(&self, other: &PKeyRef) -> bool {
74 unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 }
75 }
76 }
77
78 unsafe impl Send for PKey {}
79 unsafe impl Sync for PKey {}
80
81 impl PKey {
82 /// Creates a new `PKey` containing an RSA key.
83 pub fn from_rsa(rsa: Rsa) -> Result<PKey, ErrorStack> {
84 unsafe {
85 let evp = try!(cvt_p(ffi::EVP_PKEY_new()));
86 let pkey = PKey(evp);
87 try!(cvt(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_RSA, rsa.as_ptr() as *mut _)));
88 mem::forget(rsa);
89 Ok(pkey)
90 }
91 }
92
93 /// Creates a new `PKey` containing a DSA key.
94 pub fn from_dsa(dsa: Dsa) -> Result<PKey, ErrorStack> {
95 unsafe {
96 let evp = try!(cvt_p(ffi::EVP_PKEY_new()));
97 let pkey = PKey(evp);
98 try!(cvt(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_DSA, dsa.as_ptr() as *mut _)));
99 mem::forget(dsa);
100 Ok(pkey)
101 }
102 }
103
104 /// Creates a new `PKey` containing a Diffie-Hellman key.
105 pub fn from_dh(dh: Dh) -> Result<PKey, ErrorStack> {
106 unsafe {
107 let evp = try!(cvt_p(ffi::EVP_PKEY_new()));
108 let pkey = PKey(evp);
109 try!(cvt(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_DH, dh.as_ptr() as *mut _)));
110 mem::forget(dh);
111 Ok(pkey)
112 }
113 }
114
115 /// Creates a new `PKey` containing an elliptic curve key.
116 pub fn from_ec_key(ec_key: EcKey) -> Result<PKey, ErrorStack> {
117 unsafe {
118 let evp = try!(cvt_p(ffi::EVP_PKEY_new()));
119 let pkey = PKey(evp);
120 try!(cvt(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_EC, ec_key.as_ptr() as *mut _)));
121 mem::forget(ec_key);
122 Ok(pkey)
123 }
124 }
125
126 /// Creates a new `PKey` containing an HMAC key.
127 ///
128 /// # Note
129 /// To compute HMAC values, use the `sign` module.
130 pub fn hmac(key: &[u8]) -> Result<PKey, ErrorStack> {
131 unsafe {
132 assert!(key.len() <= c_int::max_value() as usize);
133 let key = try!(cvt_p(ffi::EVP_PKEY_new_mac_key(ffi::EVP_PKEY_HMAC,
134 ptr::null_mut(),
135 key.as_ptr() as *const _,
136 key.len() as c_int)));
137 Ok(PKey(key))
138 }
139 }
140
141 private_key_from_pem!(PKey, ffi::PEM_read_bio_PrivateKey);
142 public_key_from_pem!(PKey, ffi::PEM_read_bio_PUBKEY);
143 public_key_from_der!(PKey, ffi::d2i_PUBKEY);
144
145 /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password
146 /// if the key is encrpyted.
147 ///
148 /// The callback should copy the password into the provided buffer and return the number of
149 /// bytes written.
150 pub fn private_key_from_pkcs8_callback<F>(der: &[u8], callback: F) -> Result<PKey, ErrorStack>
151 where F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>
152 {
153 unsafe {
154 ffi::init();
155 let mut cb = CallbackState::new(callback);
156 let bio = try!(MemBioSlice::new(der));
157 cvt_p(ffi::d2i_PKCS8PrivateKey_bio(bio.as_ptr(),
158 ptr::null_mut(),
159 Some(invoke_passwd_cb::<F>),
160 &mut cb as *mut _ as *mut _))
161 .map(PKey)
162 }
163 }
164
165 /// Deserializes a DER-formatted PKCS#8 private key, using the supplied password if the key is
166 /// encrypted.
167 ///
168 /// # Panics
169 ///
170 /// Panics if `passphrase` contains an embedded null.
171 pub fn private_key_from_pkcs8_passphrase(der: &[u8],
172 passphrase: &[u8])
173 -> Result<PKey, ErrorStack> {
174 unsafe {
175 ffi::init();
176 let bio = try!(MemBioSlice::new(der));
177 let passphrase = CString::new(passphrase).unwrap();
178 cvt_p(ffi::d2i_PKCS8PrivateKey_bio(bio.as_ptr(),
179 ptr::null_mut(),
180 None,
181 passphrase.as_ptr() as *const _ as *mut _))
182 .map(PKey)
183 }
184 }
185
186 #[deprecated(since = "0.9.2", note = "use private_key_from_pem_callback")]
187 pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<PKey, ErrorStack>
188 where F: FnOnce(&mut [c_char]) -> usize
189 {
190 ffi::init();
191 let mut cb = CallbackState::new(pass_cb);
192 let mem_bio = try!(MemBioSlice::new(buf));
193 unsafe {
194 let evp = try!(cvt_p(ffi::PEM_read_bio_PrivateKey(mem_bio.as_ptr(),
195 ptr::null_mut(),
196 Some(invoke_passwd_cb_old::<F>),
197 &mut cb as *mut _ as *mut c_void)));
198 Ok(PKey::from_ptr(evp))
199 }
200 }
201 }
202
203 foreign_type! {
204 type CType = ffi::EVP_PKEY_CTX;
205 fn drop = ffi::EVP_PKEY_CTX_free;
206
207 pub struct PKeyCtx;
208 pub struct PKeyCtxRef;
209 }
210
211 unsafe impl Send for PKeyCtx {}
212 unsafe impl Sync for PKeyCtx {}
213
214 impl PKeyCtx {
215 pub fn from_pkey(pkey: &PKeyRef) -> Result<PKeyCtx, ErrorStack> {
216 unsafe {
217 let evp = try!(cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut())));
218 Ok(PKeyCtx(evp))
219 }
220 }
221 }
222
223 impl PKeyCtxRef {
224 pub fn set_rsa_padding(&mut self, pad: Padding) -> Result<(), ErrorStack> {
225 unsafe {
226 try!(cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(self.as_ptr(), pad.as_raw())));
227 }
228 Ok(())
229 }
230
231 pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
232 let mut pad: c_int = 0;
233 unsafe {
234 try!(cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad)));
235 };
236 Ok(Padding::from_raw(pad))
237 }
238
239 pub fn derive_init(&mut self) -> Result<(), ErrorStack> {
240 unsafe {
241 try!(cvt(ffi::EVP_PKEY_derive_init(self.as_ptr())));
242 }
243 Ok(())
244 }
245
246 pub fn derive_set_peer(&mut self, peer: &PKeyRef) -> Result<(), ErrorStack> {
247 unsafe {
248 try!(cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), peer.as_ptr())));
249 }
250 Ok(())
251 }
252
253 pub fn derive(&mut self) -> Result<Vec<u8>, ErrorStack> {
254 let mut len: size_t = 0;
255 unsafe { try!(cvt(ffi::EVP_PKEY_derive(self.as_ptr(), ptr::null_mut(), &mut len))); }
256
257 let mut key = vec![0u8; len];
258 unsafe { try!(cvt(ffi::EVP_PKEY_derive(self.as_ptr(), key.as_mut_ptr(), &mut len))); }
259 Ok(key)
260 }
261 }
262
263 #[cfg(test)]
264 mod tests {
265 use symm::Cipher;
266 use dh::Dh;
267 use dsa::Dsa;
268 use ec::{EcGroup, EcKey};
269 use rsa::Rsa;
270 use nid;
271
272 use super::*;
273
274 #[test]
275 fn test_to_password() {
276 let rsa = Rsa::generate(2048).unwrap();
277 let pkey = PKey::from_rsa(rsa).unwrap();
278 let pem = pkey.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar").unwrap();
279 PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
280 assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
281 }
282
283 #[test]
284 fn test_encrypted_pkcs8_passphrase() {
285 let key = include_bytes!("../test/pkcs8.der");
286 PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap();
287 }
288
289 #[test]
290 fn test_encrypted_pkcs8_callback() {
291 let mut password_queried = false;
292 let key = include_bytes!("../test/pkcs8.der");
293 PKey::private_key_from_pkcs8_callback(key, |password| {
294 password_queried = true;
295 password[..6].copy_from_slice(b"mypass");
296 Ok(6)
297 })
298 .unwrap();
299 assert!(password_queried);
300 }
301
302 #[test]
303 fn test_private_key_from_pem() {
304 let key = include_bytes!("../test/key.pem");
305 PKey::private_key_from_pem(key).unwrap();
306 }
307
308 #[test]
309 fn test_public_key_from_pem() {
310 let key = include_bytes!("../test/key.pem.pub");
311 PKey::public_key_from_pem(key).unwrap();
312 }
313
314 #[test]
315 fn test_public_key_from_der() {
316 let key = include_bytes!("../test/key.der.pub");
317 PKey::public_key_from_der(key).unwrap();
318 }
319
320 #[test]
321 fn test_pem() {
322 let key = include_bytes!("../test/key.pem");
323 let key = PKey::private_key_from_pem(key).unwrap();
324
325 let priv_key = key.private_key_to_pem().unwrap();
326 let pub_key = key.public_key_to_pem().unwrap();
327
328 // As a super-simple verification, just check that the buffers contain
329 // the `PRIVATE KEY` or `PUBLIC KEY` strings.
330 assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY"));
331 assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY"));
332 }
333
334 #[test]
335 fn test_rsa_accessor() {
336 let rsa = Rsa::generate(2048).unwrap();
337 let pkey = PKey::from_rsa(rsa).unwrap();
338 pkey.rsa().unwrap();
339 assert!(pkey.dsa().is_err());
340 }
341
342 #[test]
343 fn test_dsa_accessor() {
344 let dsa = Dsa::generate(2048).unwrap();
345 let pkey = PKey::from_dsa(dsa).unwrap();
346 pkey.dsa().unwrap();
347 assert!(pkey.rsa().is_err());
348 }
349
350 #[test]
351 fn test_dh_accessor() {
352 let dh = include_bytes!("../test/dhparams.pem");
353 let dh = Dh::from_pem(dh).unwrap();
354 let pkey = PKey::from_dh(dh).unwrap();
355 pkey.dh().unwrap();
356 assert!(pkey.rsa().is_err());
357 }
358
359 #[test]
360 fn test_ec_key_accessor() {
361 let ec_key = EcKey::from_curve_name(nid::X9_62_PRIME256V1).unwrap();
362 let pkey = PKey::from_ec_key(ec_key).unwrap();
363 pkey.ec_key().unwrap();
364 assert!(pkey.rsa().is_err());
365 }
366
367 #[test]
368 fn test_ec_key_derive() {
369 let group = EcGroup::from_curve_name(nid::X9_62_PRIME256V1).unwrap();
370 let ec_key = EcKey::generate(&group).unwrap();
371 let ec_key2 = EcKey::generate(&group).unwrap();
372 let pkey = PKey::from_ec_key(ec_key).unwrap();
373 let pkey2 = PKey::from_ec_key(ec_key2).unwrap();
374 let mut pkey_ctx = PKeyCtx::from_pkey(&pkey).unwrap();
375 pkey_ctx.derive_init().unwrap();
376 pkey_ctx.derive_set_peer(&pkey2).unwrap();
377 let shared = pkey_ctx.derive().unwrap();
378 assert!(!shared.is_empty());
379 }
380 }