1use nettle::{
8 curve25519,
9 curve448,
10 dsa,
11 ecc,
12 ecdh,
13 ecdsa,
14 ed25519,
15 ed448,
16 rsa,
17 random::Yarrow,
18};
19
20use crate::{Error, Result};
21
22use crate::packet::{key, Key};
23use crate::crypto::asymmetric::KeyPair;
24use crate::crypto::backend::interface::Asymmetric;
25use crate::crypto::mpi::{self, MPI, ProtectedMPI, PublicKey};
26use crate::crypto::{
27 SessionKey,
28 mem::Protected,
29};
30use crate::types::{Curve, HashAlgorithm};
31
32impl Asymmetric for super::Backend {
33 fn supports_algo(algo: PublicKeyAlgorithm) -> bool {
34 use PublicKeyAlgorithm::*;
35 #[allow(deprecated)]
36 match algo {
37 X25519 | Ed25519 |
38 RSAEncryptSign | RSAEncrypt | RSASign | DSA | ECDH | ECDSA | EdDSA
39 => true,
40 X448 | Ed448
41 => curve448::IS_SUPPORTED,
42 ElGamalEncrypt | ElGamalEncryptSign | Private(_) | Unknown(_)
43 => false,
44 }
45 }
46
47 fn supports_curve(curve: &Curve) -> bool {
48 use Curve::*;
49 match curve {
50 NistP256 | NistP384 | NistP521 | Ed25519 | Cv25519
51 => true,
52 BrainpoolP256 | BrainpoolP384 | BrainpoolP512 | Unknown(_)
53 => false,
54 }
55 }
56
57 fn x25519_generate_key() -> Result<(Protected, [u8; 32])> {
58 debug_assert_eq!(curve25519::CURVE25519_SIZE, 32);
59 let mut rng = Yarrow::default();
60 let secret = curve25519::private_key(&mut rng);
61 let mut public = [0; 32];
62 curve25519::mul_g(&mut public, &secret)?;
63 Ok((secret.into(), public))
64 }
65
66 fn x25519_derive_public(secret: &Protected) -> Result<[u8; 32]> {
67 debug_assert_eq!(curve25519::CURVE25519_SIZE, 32);
68 let mut public = [0; 32];
69 curve25519::mul_g(&mut public, secret)?;
70 Ok(public)
71 }
72
73 fn x25519_shared_point(secret: &Protected, public: &[u8; 32])
74 -> Result<Protected> {
75 debug_assert_eq!(curve25519::CURVE25519_SIZE, 32);
76 let mut s: Protected = vec![0; 32].into();
77 curve25519::mul(&mut s, secret, public)?;
78 Ok(s)
79 }
80
81 fn x448_generate_key() -> Result<(Protected, [u8; 56])> {
82 debug_assert_eq!(curve448::CURVE448_SIZE, 56);
83 if ! curve448::IS_SUPPORTED {
84 return Err(Error::UnsupportedPublicKeyAlgorithm(
85 PublicKeyAlgorithm::Ed448).into());
86 }
87 let mut rng = Yarrow::default();
88 let secret = curve448::private_key(&mut rng);
89 let mut public = [0; 56];
90 curve448::mul_g(&mut public, &secret)?;
91 Ok((secret.into(), public))
92 }
93
94 fn x448_derive_public(secret: &Protected) -> Result<[u8; 56]> {
95 debug_assert_eq!(curve448::CURVE448_SIZE, 56);
96 if ! curve448::IS_SUPPORTED {
97 return Err(Error::UnsupportedPublicKeyAlgorithm(
98 PublicKeyAlgorithm::Ed448).into());
99 }
100 let mut public = [0; 56];
101 curve448::mul_g(&mut public, secret)?;
102 Ok(public)
103 }
104
105 fn x448_shared_point(secret: &Protected, public: &[u8; 56])
106 -> Result<Protected> {
107 debug_assert_eq!(curve448::CURVE448_SIZE, 56);
108 if ! curve448::IS_SUPPORTED {
109 return Err(Error::UnsupportedPublicKeyAlgorithm(
110 PublicKeyAlgorithm::Ed448).into());
111 }
112 let mut s: Protected = vec![0; 56].into();
113 curve448::mul(&mut s, secret, public)?;
114 Ok(s)
115 }
116
117 fn ed25519_generate_key() -> Result<(Protected, [u8; 32])> {
118 debug_assert_eq!(ed25519::ED25519_KEY_SIZE, 32);
119 let mut rng = Yarrow::default();
120 let mut public = [0; 32];
121 let secret: Protected =
122 ed25519::private_key(&mut rng).into();
123 ed25519::public_key(&mut public, &secret)?;
124 Ok((secret, public))
125 }
126
127 fn ed25519_derive_public(secret: &Protected) -> Result<[u8; 32]> {
128 debug_assert_eq!(ed25519::ED25519_KEY_SIZE, 32);
129 let mut public = [0; 32];
130 ed25519::public_key(&mut public, secret)?;
131 Ok(public)
132 }
133
134 fn ed25519_sign(secret: &Protected, public: &[u8; 32], digest: &[u8])
135 -> Result<[u8; 64]> {
136 debug_assert_eq!(ed25519::ED25519_KEY_SIZE, 32);
137 debug_assert_eq!(ed25519::ED25519_SIGNATURE_SIZE, 64);
138 let mut sig = [0u8; 64];
139 ed25519::sign(public, secret, digest, &mut sig)?;
140 Ok(sig)
141 }
142
143 fn ed25519_verify(public: &[u8; 32], digest: &[u8], signature: &[u8; 64])
144 -> Result<bool> {
145 debug_assert_eq!(ed25519::ED25519_KEY_SIZE, 32);
146 debug_assert_eq!(ed25519::ED25519_SIGNATURE_SIZE, 64);
147 Ok(ed25519::verify(public, digest, signature)?)
148 }
149
150 fn ed448_generate_key() -> Result<(Protected, [u8; 57])> {
151 debug_assert_eq!(ed448::ED448_KEY_SIZE, 57);
152 let mut rng = Yarrow::default();
153 let mut public = [0; 57];
154 let secret: Protected =
155 ed448::private_key(&mut rng).into();
156 ed448::public_key(&mut public, &secret)?;
157 Ok((secret, public))
158 }
159
160 fn ed448_derive_public(secret: &Protected) -> Result<[u8; 57]> {
161 debug_assert_eq!(ed448::ED448_KEY_SIZE, 57);
162 let mut public = [0; 57];
163 ed448::public_key(&mut public, secret)?;
164 Ok(public)
165 }
166
167 fn ed448_sign(secret: &Protected, public: &[u8; 57], digest: &[u8])
168 -> Result<[u8; 114]> {
169 debug_assert_eq!(ed448::ED448_KEY_SIZE, 57);
170 debug_assert_eq!(ed448::ED448_SIGNATURE_SIZE, 114);
171 let mut sig = [0u8; 114];
172 ed448::sign(public, secret, digest, &mut sig)?;
173 Ok(sig)
174 }
175
176 fn ed448_verify(public: &[u8; 57], digest: &[u8], signature: &[u8; 114])
177 -> Result<bool> {
178 debug_assert_eq!(ed448::ED448_KEY_SIZE, 57);
179 debug_assert_eq!(ed448::ED448_SIGNATURE_SIZE, 114);
180 Ok(ed448::verify(public, digest, signature)?)
181 }
182
183 fn dsa_generate_key(p_bits: usize)
184 -> Result<(MPI, MPI, MPI, MPI, ProtectedMPI)>
185 {
186 let mut rng = Yarrow::default();
187 let q_bits = if p_bits <= 1024 { 160 } else { 256 };
188 let params = dsa::Params::generate(&mut rng, p_bits, q_bits)?;
189 let (p, q) = params.primes();
190 let g = params.g();
191 let (y, x) = dsa::generate_keypair(¶ms, &mut rng);
192 Ok((p.into(), q.into(), g.into(), y.as_bytes().into(),
193 x.as_bytes().into()))
194 }
195
196 fn dsa_sign(x: &ProtectedMPI,
197 p: &MPI, q: &MPI, g: &MPI, _y: &MPI,
198 digest: &[u8])
199 -> Result<(MPI, MPI)>
200 {
201 let mut rng = Yarrow::default();
202 let params = dsa::Params::new(p.value(), q.value(), g.value());
203 let secret = dsa::PrivateKey::new(x.value());
204
205 let sig = dsa::sign(¶ms, &secret, digest, &mut rng)?;
206
207 Ok((MPI::new(&sig.r()), MPI::new(&sig.s())))
208 }
209
210 fn dsa_verify(p: &MPI, q: &MPI, g: &MPI, y: &MPI,
211 digest: &[u8],
212 r: &MPI, s: &MPI)
213 -> Result<bool>
214 {
215 let key = dsa::PublicKey::new(y.value());
216 let params = dsa::Params::new(p.value(), q.value(), g.value());
217 let signature = dsa::Signature::new(r.value(), s.value());
218 Ok(dsa::verify(¶ms, &key, digest, &signature))
219 }
220}
221
222impl KeyPair {
223 pub(crate) fn sign_backend(&self,
224 secret: &mpi::SecretKeyMaterial,
225 hash_algo: HashAlgorithm,
226 digest: &[u8])
227 -> Result<mpi::Signature>
228 {
229 use crate::PublicKeyAlgorithm::*;
230
231 let mut rng = Yarrow::default();
232
233 #[allow(deprecated)]
234 match (self.public().pk_algo(), self.public().mpis(), secret)
235 {
236 (RSASign,
237 &PublicKey::RSA { ref e, ref n },
238 &mpi::SecretKeyMaterial::RSA { ref p, ref q, ref d, .. }) |
239 (RSAEncryptSign,
240 &PublicKey::RSA { ref e, ref n },
241 &mpi::SecretKeyMaterial::RSA { ref p, ref q, ref d, .. }) => {
242 let public = rsa::PublicKey::new(n.value(), e.value())?;
243 let secret = rsa::PrivateKey::new(d.value(), p.value(),
244 q.value(), Option::None)?;
245
246 let mut sig = vec![0u8; n.value().len()];
248
249 rsa::sign_digest_pkcs1(&public, &secret, digest,
256 hash_algo.oid()?,
257 &mut rng, &mut sig)?;
258
259 Ok(mpi::Signature::RSA {
260 s: MPI::new(&sig),
261 })
262 },
263
264 (ECDSA,
265 &PublicKey::ECDSA { ref curve, .. },
266 &mpi::SecretKeyMaterial::ECDSA { ref scalar }) => {
267 let secret = match curve {
268 Curve::NistP256 =>
269 ecc::Scalar::new::<ecc::Secp256r1>(
270 scalar.value())?,
271 Curve::NistP384 =>
272 ecc::Scalar::new::<ecc::Secp384r1>(
273 scalar.value())?,
274 Curve::NistP521 =>
275 ecc::Scalar::new::<ecc::Secp521r1>(
276 scalar.value())?,
277 _ =>
278 return Err(
279 Error::UnsupportedEllipticCurve(curve.clone())
280 .into()),
281 };
282
283 let sig = ecdsa::sign(&secret, digest, &mut rng);
284
285 Ok(mpi::Signature::ECDSA {
286 r: MPI::new(&sig.r()),
287 s: MPI::new(&sig.s()),
288 })
289 },
290
291 (pk_algo, _, _) => Err(Error::InvalidOperation(format!(
292 "unsupported combination of algorithm {:?}, key {:?}, \
293 and secret key {:?}",
294 pk_algo, self.public(), self.secret())).into()),
295 }
296 }
297}
298
299impl KeyPair {
300 pub(crate) fn decrypt_backend(&self, secret: &mpi::SecretKeyMaterial, ciphertext: &mpi::Ciphertext,
301 plaintext_len: Option<usize>)
302 -> Result<SessionKey>
303 {
304 use crate::PublicKeyAlgorithm::*;
305
306 Ok(match (self.public().mpis(), secret, ciphertext) {
307 (PublicKey::RSA{ ref e, ref n },
308 mpi::SecretKeyMaterial::RSA{ ref p, ref q, ref d, .. },
309 mpi::Ciphertext::RSA{ ref c }) => {
310 let public = rsa::PublicKey::new(n.value(), e.value())?;
311 let secret = rsa::PrivateKey::new(d.value(), p.value(),
312 q.value(), Option::None)?;
313 let mut rand = Yarrow::default();
314 if let Some(l) = plaintext_len {
315 let mut plaintext: SessionKey = vec![0; l].into();
316 rsa::decrypt_pkcs1(&public, &secret, &mut rand,
317 c.value(), plaintext.as_mut())?;
318 plaintext
319 } else {
320 rsa::decrypt_pkcs1_insecure(&public, &secret,
321 &mut rand, c.value())?
322 .into()
323 }
324 }
325
326 (PublicKey::ElGamal{ .. },
327 mpi::SecretKeyMaterial::ElGamal{ .. },
328 mpi::Ciphertext::ElGamal{ .. }) => {
329 #[allow(deprecated)]
330 return Err(
331 Error::UnsupportedPublicKeyAlgorithm(ElGamalEncrypt).into());
332 },
333
334 (PublicKey::ECDH{ .. },
335 mpi::SecretKeyMaterial::ECDH { .. },
336 mpi::Ciphertext::ECDH { .. }) =>
337 crate::crypto::ecdh::decrypt(self.public(), secret, ciphertext,
338 plaintext_len)?,
339
340 (public, secret, ciphertext) =>
341 return Err(Error::InvalidOperation(format!(
342 "unsupported combination of key pair {:?}/{:?} \
343 and ciphertext {:?}",
344 public, secret, ciphertext)).into()),
345 })
346 }
347}
348
349
350impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
351 pub(crate) fn encrypt_backend(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
353 use crate::PublicKeyAlgorithm::*;
354
355 #[allow(deprecated)]
356 match self.pk_algo() {
357 RSAEncryptSign | RSAEncrypt => {
358 match self.mpis() {
360 mpi::PublicKey::RSA { e, n } => {
361 let ciphertext_len = n.value().len();
363 if data.len() + 11 > ciphertext_len {
364 return Err(Error::InvalidArgument(
365 "Plaintext data too large".into()).into());
366 }
367
368 let mut esk = vec![0u8; ciphertext_len];
369 let mut rng = Yarrow::default();
370 let pk = rsa::PublicKey::new(n.value(), e.value())?;
371 rsa::encrypt_pkcs1(&pk, &mut rng, data,
372 &mut esk)?;
373 Ok(mpi::Ciphertext::RSA {
374 c: MPI::new(&esk),
375 })
376 },
377 pk => {
378 Err(Error::MalformedPacket(
379 format!(
380 "Key: Expected RSA public key, got {:?}",
381 pk)).into())
382 },
383 }
384 },
385
386 ECDH => crate::crypto::ecdh::encrypt(self.parts_as_public(),
387 data),
388
389 RSASign | DSA | ECDSA | EdDSA | Ed25519 | Ed448 =>
390 Err(Error::InvalidOperation(
391 format!("{} is not an encryption algorithm", self.pk_algo())
392 ).into()),
393
394 X25519 | X448 | ElGamalEncrypt | ElGamalEncryptSign |
397 Private(_) | Unknown(_) =>
398 Err(Error::UnsupportedPublicKeyAlgorithm(self.pk_algo()).into()),
399 }
400 }
401
402 pub(crate) fn verify_backend(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
404 digest: &[u8]) -> Result<()>
405 {
406 use crate::crypto::mpi::Signature;
407
408 let ok = match (self.mpis(), sig) {
409 (PublicKey::RSA { e, n }, Signature::RSA { s }) => {
410 let key = rsa::PublicKey::new(n.value(), e.value())?;
411
412 rsa::verify_digest_pkcs1(&key, digest, hash_algo.oid()?,
419 s.value())?
420 },
421 (PublicKey::ECDSA { curve, q }, Signature::ECDSA { s, r }) =>
422 {
423 let (x, y) = q.decode_point(curve)?;
424 let key = match curve {
425 Curve::NistP256 => ecc::Point::new::<ecc::Secp256r1>(x, y)?,
426 Curve::NistP384 => ecc::Point::new::<ecc::Secp384r1>(x, y)?,
427 Curve::NistP521 => ecc::Point::new::<ecc::Secp521r1>(x, y)?,
428 _ => return Err(
429 Error::UnsupportedEllipticCurve(curve.clone()).into()),
430 };
431
432 let signature = dsa::Signature::new(r.value(), s.value());
433 ecdsa::verify(&key, digest, &signature)
434 },
435 _ => return Err(Error::MalformedPacket(format!(
436 "unsupported combination of key {} and signature {:?}.",
437 self.pk_algo(), sig)).into()),
438 };
439
440 if ok {
441 Ok(())
442 } else {
443 Err(Error::ManipulatedMessage.into())
444 }
445 }
446}
447
448use std::time::SystemTime;
449use crate::packet::key::{Key4, SecretParts};
450use crate::types::PublicKeyAlgorithm;
451
452impl<R> Key4<SecretParts, R>
453 where R: key::KeyRole,
454{
455 pub fn import_secret_rsa<T>(d: &[u8], p: &[u8], q: &[u8], ctime: T)
461 -> Result<Self> where T: Into<Option<SystemTime>>
462 {
463 let sec = rsa::PrivateKey::new(d, p, q, None)?;
464 let key = sec.public_key()?;
465 let (a, b, c) = sec.as_rfc4880();
466
467 Self::with_secret(
468 ctime.into().unwrap_or_else(crate::now),
469 PublicKeyAlgorithm::RSAEncryptSign,
470 mpi::PublicKey::RSA {
471 e: mpi::MPI::new(&key.e()[..]),
472 n: mpi::MPI::new(&key.n()[..]),
473 },
474 mpi::SecretKeyMaterial::RSA {
475 d: d.into(),
476 p: a.into(),
477 q: b.into(),
478 u: c.into(),
479 }.into())
480 }
481
482 pub fn generate_rsa(bits: usize) -> Result<Self> {
484 let mut rng = Yarrow::default();
485
486 let (public, private) = rsa::generate_keypair(&mut rng, bits as u32)?;
487 let (p, q, u) = private.as_rfc4880();
488 let public_mpis = PublicKey::RSA {
489 e: MPI::new(&*public.e()),
490 n: MPI::new(&*public.n()),
491 };
492 let private_mpis = mpi::SecretKeyMaterial::RSA {
493 d: private.d().into(),
494 p: p.into(),
495 q: q.into(),
496 u: u.into(),
497 };
498
499 Self::with_secret(
500 crate::now(),
501 PublicKeyAlgorithm::RSAEncryptSign,
502 public_mpis,
503 private_mpis.into())
504 }
505
506 pub(crate) fn generate_ecc_backend(for_signing: bool, curve: Curve)
513 -> Result<(PublicKeyAlgorithm,
514 mpi::PublicKey,
515 mpi::SecretKeyMaterial)>
516 {
517 let mut rng = Yarrow::default();
518
519 match (curve.clone(), for_signing) {
520 (Curve::Ed25519, true) =>
521 unreachable!("handled in Key4::generate_ecc"),
522
523 (Curve::Cv25519, false) =>
524 unreachable!("handled in Key4::generate_ecc"),
525
526 (Curve::NistP256, true) | (Curve::NistP384, true)
527 | (Curve::NistP521, true) => {
528 let (public, private, field_sz) = match curve {
529 Curve::NistP256 => {
530 let (pu, sec) =
531 ecdsa::generate_keypair::<ecc::Secp256r1, _>(&mut rng)?;
532 (pu, sec, 256)
533 }
534 Curve::NistP384 => {
535 let (pu, sec) =
536 ecdsa::generate_keypair::<ecc::Secp384r1, _>(&mut rng)?;
537 (pu, sec, 384)
538 }
539 Curve::NistP521 => {
540 let (pu, sec) =
541 ecdsa::generate_keypair::<ecc::Secp521r1, _>(&mut rng)?;
542 (pu, sec, 521)
543 }
544 _ => unreachable!(),
545 };
546 let (pub_x, pub_y) = public.as_bytes();
547 let public_mpis = mpi::PublicKey::ECDSA{
548 curve,
549 q: MPI::new_point(&pub_x, &pub_y, field_sz),
550 };
551 let private_mpis = mpi::SecretKeyMaterial::ECDSA{
552 scalar: private.as_bytes().into(),
553 };
554
555 Ok((PublicKeyAlgorithm::ECDSA, public_mpis, private_mpis))
556 }
557
558 (Curve::NistP256, false) | (Curve::NistP384, false)
559 | (Curve::NistP521, false) => {
560 let (private, field_sz) = match curve {
561 Curve::NistP256 => {
562 let pv =
563 ecc::Scalar::new_random::<ecc::Secp256r1, _>(&mut rng);
564
565 (pv, 256)
566 }
567 Curve::NistP384 => {
568 let pv =
569 ecc::Scalar::new_random::<ecc::Secp384r1, _>(&mut rng);
570
571 (pv, 384)
572 }
573 Curve::NistP521 => {
574 let pv =
575 ecc::Scalar::new_random::<ecc::Secp521r1, _>(&mut rng);
576
577 (pv, 521)
578 }
579 _ => unreachable!(),
580 };
581 let public = ecdh::point_mul_g(&private);
582 let (pub_x, pub_y) = public.as_bytes();
583 let public_mpis = mpi::PublicKey::ECDH{
584 q: MPI::new_point(&pub_x, &pub_y, field_sz),
585 hash:
586 crate::crypto::ecdh::default_ecdh_kdf_hash(&curve),
587 sym:
588 crate::crypto::ecdh::default_ecdh_kek_cipher(&curve),
589 curve,
590 };
591 let private_mpis = mpi::SecretKeyMaterial::ECDH{
592 scalar: private.as_bytes().into(),
593 };
594
595 Ok((PublicKeyAlgorithm::ECDH, public_mpis, private_mpis))
596 }
597
598 _ => Err(Error::UnsupportedEllipticCurve(curve).into()),
599 }
600 }
601}