1use std::fmt;
18use std::cmp::Ordering;
19use std::io::Write;
20use std::borrow::Cow;
21
22#[cfg(test)]
23use quickcheck::{Arbitrary, Gen};
24
25use crate::fmt::hex;
26use crate::types::{
27 Curve,
28 HashAlgorithm,
29 PublicKeyAlgorithm,
30 SymmetricAlgorithm,
31};
32use crate::crypto::hash::{self, Hash};
33use crate::crypto::mem::{secure_cmp, Protected};
34use crate::serialize::Marshal;
35
36use crate::Error;
37use crate::Result;
38
39#[derive(Clone)]
41pub struct MPI {
42 value: Box<[u8]>,
44}
45assert_send_and_sync!(MPI);
46
47impl From<Vec<u8>> for MPI {
48 fn from(v: Vec<u8>) -> Self {
49 Self::new(&v)
56 }
57}
58
59impl From<Box<[u8]>> for MPI {
60 fn from(v: Box<[u8]>) -> Self {
61 Self::new(&v)
68 }
69}
70
71impl MPI {
72 fn trim_leading_zeros(v: &[u8]) -> &[u8] {
74 let offset = v.iter().take_while(|&&o| o == 0).count();
75 &v[offset..]
76 }
77
78 pub fn new(value: &[u8]) -> Self {
82 let value = Self::trim_leading_zeros(value).to_vec().into_boxed_slice();
83
84 MPI {
85 value,
86 }
87 }
88
89 pub fn new_point(x: &[u8], y: &[u8], field_bits: usize) -> Self {
98 Self::new_point_common(x, y, field_bits).into()
99 }
100
101 fn new_point_common(x: &[u8], y: &[u8], field_bits: usize) -> Vec<u8> {
103 let field_sz = if field_bits % 8 > 0 { 1 } else { 0 } + field_bits / 8;
104 let mut val = vec![0x0u8; 1 + 2 * field_sz];
105 let x_missing = field_sz - x.len();
106 let y_missing = field_sz - y.len();
107
108 val[0] = 0x4;
109 val[1 + x_missing..1 + field_sz].copy_from_slice(x);
110 val[1 + field_sz + y_missing..].copy_from_slice(y);
111 val
112 }
113
114 pub fn new_compressed_point(x: &[u8]) -> Self {
124 Self::new_compressed_point_common(x).into()
125 }
126
127 fn new_compressed_point_common(x: &[u8]) -> Vec<u8> {
129 let mut val = vec![0; 1 + x.len()];
130 val[0] = 0x40;
131 val[1..].copy_from_slice(x);
132 val
133 }
134
135 pub fn zero() -> Self {
137 Self::new(&[])
138 }
139
140 pub fn is_zero(&self) -> bool {
142 self.value().is_empty()
143 }
144
145 pub fn bits(&self) -> usize {
149 self.value.len() * 8
150 - self.value.get(0).map(|&b| b.leading_zeros() as usize)
151 .unwrap_or(0)
152 }
153
154 pub fn value(&self) -> &[u8] {
159 &self.value
160 }
161
162 pub fn value_padded(&self, to: usize) -> Result<Cow<[u8]>> {
168 crate::crypto::pad(self.value(), to)
169 }
170
171 pub fn decode_point(&self, curve: &Curve) -> Result<(&[u8], &[u8])> {
188 Self::decode_point_common(self.value(), curve)
189 }
190
191 fn decode_point_common<'a>(value: &'a [u8], curve: &Curve)
193 -> Result<(&'a [u8], &'a [u8])> {
194 const ED25519_KEY_SIZE: usize = 32;
195 const CURVE25519_SIZE: usize = 32;
196 use self::Curve::*;
197 match &curve {
198 Ed25519 | Cv25519 => {
199 assert_eq!(CURVE25519_SIZE, ED25519_KEY_SIZE);
200 if value.len() != 1 + CURVE25519_SIZE {
203 return Err(Error::MalformedMPI(
204 format!("Bad size of Curve25519 key: {} expected: {}",
205 value.len(),
206 1 + CURVE25519_SIZE
207 )
208 ).into());
209 }
210
211 if value.get(0).map(|&b| b != 0x40).unwrap_or(true) {
212 return Err(Error::MalformedMPI(
213 "Bad encoding of Curve25519 key".into()).into());
214 }
215
216 Ok((&value[1..], &[]))
217 },
218
219 NistP256
220 | NistP384
221 | NistP521
222 | BrainpoolP256
223 | BrainpoolP384
224 | BrainpoolP512
225 =>
226 {
227 let coordinate_length = curve.field_size()?;
229
230 let expected_length =
232 1 + (2 * coordinate_length);
235
236 if value.len() != expected_length {
237 return Err(Error::MalformedMPI(
238 format!("Invalid length of MPI: {} (expected {})",
239 value.len(), expected_length)).into());
240 }
241
242 if value.get(0).map(|&b| b != 0x04).unwrap_or(true) {
243 return Err(Error::MalformedMPI(
244 format!("Bad prefix: {:?} (expected Some(0x04))",
245 value.get(0))).into());
246 }
247
248 Ok((&value[1..1 + coordinate_length],
249 &value[1 + coordinate_length..]))
250 },
251
252 Unknown(_) =>
253 Err(Error::UnsupportedEllipticCurve(curve.clone()).into()),
254 }
255 }
256
257 fn secure_memcmp(&self, other: &Self) -> Ordering {
259 let cmp = unsafe {
260 if self.value.len() == other.value.len() {
261 ::memsec::memcmp(self.value.as_ptr(), other.value.as_ptr(),
262 other.value.len())
263 } else {
264 self.value.len() as i32 - other.value.len() as i32
265 }
266 };
267
268 match cmp {
269 0 => Ordering::Equal,
270 x if x < 0 => Ordering::Less,
271 _ => Ordering::Greater,
272 }
273 }
274}
275
276impl fmt::Debug for MPI {
277 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
278 f.write_fmt(format_args!(
279 "{} bits: {}", self.bits(),
280 crate::fmt::to_hex(&*self.value, true)))
281 }
282}
283
284impl Hash for MPI {
285 fn hash(&self, hash: &mut hash::Context) -> Result<()> {
286 let len = self.bits() as u16;
287
288 hash.update(&len.to_be_bytes());
289 hash.update(&self.value);
290 Ok(())
291 }
292}
293
294#[cfg(test)]
295impl Arbitrary for MPI {
296 fn arbitrary(g: &mut Gen) -> Self {
297 loop {
298 let buf = <Vec<u8>>::arbitrary(g);
299
300 if !buf.is_empty() && buf[0] != 0 {
301 break MPI::new(&buf);
302 }
303 }
304 }
305}
306
307impl PartialOrd for MPI {
308 fn partial_cmp(&self, other: &MPI) -> Option<Ordering> {
309 Some(self.cmp(other))
310 }
311}
312
313impl Ord for MPI {
314 fn cmp(&self, other: &MPI) -> Ordering {
315 self.secure_memcmp(other)
316 }
317}
318
319impl PartialEq for MPI {
320 fn eq(&self, other: &MPI) -> bool {
321 self.cmp(other) == Ordering::Equal
322 }
323}
324
325impl Eq for MPI {}
326
327impl std::hash::Hash for MPI {
328 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
329 self.value.hash(state);
330 }
331}
332
333#[derive(Clone)]
339pub struct ProtectedMPI {
340 value: Protected,
342}
343assert_send_and_sync!(ProtectedMPI);
344
345impl From<&[u8]> for ProtectedMPI {
346 fn from(m: &[u8]) -> Self {
347 let value = Protected::from(MPI::trim_leading_zeros(m));
348 ProtectedMPI {
349 value,
350 }
351 }
352}
353
354impl From<Vec<u8>> for ProtectedMPI {
355 fn from(m: Vec<u8>) -> Self {
356 let value = Protected::from(MPI::trim_leading_zeros(&m));
357 drop(Protected::from(m)); ProtectedMPI {
359 value,
360 }
361 }
362}
363
364impl From<Box<[u8]>> for ProtectedMPI {
365 fn from(m: Box<[u8]>) -> Self {
366 let value = Protected::from(MPI::trim_leading_zeros(&m));
367 drop(Protected::from(m)); ProtectedMPI {
369 value,
370 }
371 }
372}
373
374impl From<Protected> for ProtectedMPI {
375 fn from(m: Protected) -> Self {
376 let value = Protected::from(MPI::trim_leading_zeros(&m));
377 drop(m); ProtectedMPI {
379 value,
380 }
381 }
382}
383
384impl PartialOrd for ProtectedMPI {
385 fn partial_cmp(&self, other: &ProtectedMPI) -> Option<Ordering> {
386 Some(self.cmp(other))
387 }
388}
389
390impl Ord for ProtectedMPI {
391 fn cmp(&self, other: &ProtectedMPI) -> Ordering {
392 self.secure_memcmp(other)
393 }
394}
395
396impl PartialEq for ProtectedMPI {
397 fn eq(&self, other: &ProtectedMPI) -> bool {
398 self.cmp(other) == Ordering::Equal
399 }
400}
401
402impl Eq for ProtectedMPI {}
403
404impl std::hash::Hash for ProtectedMPI {
405 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
406 self.value.hash(state);
407 }
408}
409
410#[cfg(test)]
411impl Arbitrary for ProtectedMPI {
412 fn arbitrary(g: &mut Gen) -> Self {
413 loop {
414 let buf = <Vec<u8>>::arbitrary(g);
415
416 if ! buf.is_empty() && buf[0] != 0 {
417 break ProtectedMPI::from(buf);
418 }
419 }
420 }
421}
422
423impl ProtectedMPI {
424 pub fn new_point(x: &[u8], y: &[u8], field_bits: usize) -> Self {
433 MPI::new_point_common(x, y, field_bits).into()
434 }
435
436 pub fn new_compressed_point(x: &[u8]) -> Self {
446 MPI::new_compressed_point_common(x).into()
447 }
448
449 pub fn bits(&self) -> usize {
453 self.value.len() * 8
454 - self.value.get(0).map(|&b| b.leading_zeros() as usize)
455 .unwrap_or(0)
456 }
457
458 pub fn value(&self) -> &[u8] {
463 &self.value
464 }
465
466 pub fn value_padded(&self, to: usize) -> Protected {
473 let missing = to.saturating_sub(self.value.len());
474 let limit = self.value.len().min(to);
475 let mut v: Protected = vec![0; to].into();
476 v[missing..].copy_from_slice(&self.value()[..limit]);
477 v
478 }
479
480 pub fn decode_point(&self, curve: &Curve) -> Result<(&[u8], &[u8])> {
497 MPI::decode_point_common(self.value(), curve)
498 }
499
500 fn secure_memcmp(&self, other: &Self) -> Ordering {
502 (self.value.len() as i32).cmp(&(other.value.len() as i32))
503 .then(
504 self.value.cmp(&other.value))
506 }
507}
508
509impl fmt::Debug for ProtectedMPI {
510 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
511 if cfg!(debug_assertions) {
512 f.write_fmt(format_args!(
513 "{} bits: {}", self.bits(),
514 crate::fmt::to_hex(&*self.value, true)))
515 } else {
516 f.write_str("<Redacted>")
517 }
518 }
519}
520
521#[non_exhaustive]
528#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
529pub enum PublicKey {
530 RSA {
532 e: MPI,
534 n: MPI,
536 },
537
538 DSA {
540 p: MPI,
542 q: MPI,
544 g: MPI,
546 y: MPI,
548 },
549
550 ElGamal {
552 p: MPI,
554 g: MPI,
556 y: MPI,
558 },
559
560 EdDSA {
562 curve: Curve,
564 q: MPI,
566 },
567
568 ECDSA {
570 curve: Curve,
572 q: MPI,
574 },
575
576 ECDH {
578 curve: Curve,
580 q: MPI,
582 hash: HashAlgorithm,
584 sym: SymmetricAlgorithm,
586 },
587
588 X25519 {
590 u: [u8; 32],
592 },
593
594 X448 {
596 u: Box<[u8; 56]>,
598 },
599
600 Ed25519 {
602 a: [u8; 32],
604 },
605
606 Ed448 {
608 a: Box<[u8; 57]>,
610 },
611
612 Unknown {
614 mpis: Box<[MPI]>,
616 rest: Box<[u8]>,
618 },
619}
620assert_send_and_sync!(PublicKey);
621
622impl fmt::Debug for PublicKey {
623 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
624 match self {
625 PublicKey::RSA { e, n } =>
626 f.debug_struct("RSA")
627 .field("e", e)
628 .field("n", n)
629 .finish(),
630
631 PublicKey::DSA { p, q, g, y } =>
632 f.debug_struct("DSA")
633 .field("p", p)
634 .field("q", q)
635 .field("g", g)
636 .field("y", y)
637 .finish(),
638
639 PublicKey::ElGamal { p, g, y } =>
640 f.debug_struct("ElGamal")
641 .field("p", p)
642 .field("g", g)
643 .field("y", y)
644 .finish(),
645
646 PublicKey::EdDSA { curve, q } =>
647 f.debug_struct("EdDSA")
648 .field("curve", curve)
649 .field("q", q)
650 .finish(),
651
652 PublicKey::ECDSA { curve, q } =>
653 f.debug_struct("ECDSA")
654 .field("curve", curve)
655 .field("q", q)
656 .finish(),
657
658 PublicKey::ECDH { curve, q, hash, sym } =>
659 f.debug_struct("ECDH")
660 .field("curve", curve)
661 .field("q", q)
662 .field("hash", hash)
663 .field("sym", sym)
664 .finish(),
665
666 PublicKey::X25519 { u } =>
667 f.debug_struct("X25519")
668 .field("u", &hex::encode(u))
669 .finish(),
670
671 PublicKey::X448 { u } =>
672 f.debug_struct("X448")
673 .field("u", &hex::encode(u.as_ref()))
674 .finish(),
675
676 PublicKey::Ed25519 { a } =>
677 f.debug_struct("Ed25519")
678 .field("a", &hex::encode(a))
679 .finish(),
680
681 PublicKey::Ed448 { a } =>
682 f.debug_struct("Ed448")
683 .field("a", &hex::encode(a.as_ref()))
684 .finish(),
685
686 PublicKey::Unknown { mpis, rest } =>
687 f.debug_struct("Unknown")
688 .field("mpis", mpis)
689 .field("rest", &hex::encode(rest))
690 .finish(),
691 }
692 }
693}
694
695impl PublicKey {
696 pub fn bits(&self) -> Option<usize> {
707 use self::PublicKey::*;
708 match self {
709 RSA { ref n,.. } => Some(n.bits()),
710 DSA { ref p,.. } => Some(p.bits()),
711 ElGamal { ref p,.. } => Some(p.bits()),
712 EdDSA { ref curve,.. } => curve.bits().ok(),
713 ECDSA { ref curve,.. } => curve.bits().ok(),
714 ECDH { ref curve,.. } => curve.bits().ok(),
715 X25519 { .. } => Some(256),
716 X448 { .. } => Some(448),
717 Ed25519 { .. } => Some(256),
718 Ed448 { .. } => Some(456),
719 Unknown { .. } => None,
720 }
721 }
722
723 pub fn algo(&self) -> Option<PublicKeyAlgorithm> {
726 use self::PublicKey::*;
727 #[allow(deprecated)]
728 match self {
729 RSA { .. } => Some(PublicKeyAlgorithm::RSAEncryptSign),
730 DSA { .. } => Some(PublicKeyAlgorithm::DSA),
731 ElGamal { .. } => Some(PublicKeyAlgorithm::ElGamalEncrypt),
732 EdDSA { .. } => Some(PublicKeyAlgorithm::EdDSA),
733 ECDSA { .. } => Some(PublicKeyAlgorithm::ECDSA),
734 ECDH { .. } => Some(PublicKeyAlgorithm::ECDH),
735 X25519 { .. } => Some(PublicKeyAlgorithm::X25519),
736 X448 { .. } => Some(PublicKeyAlgorithm::X448),
737 Ed25519 { .. } => Some(PublicKeyAlgorithm::Ed25519),
738 Ed448 { .. } => Some(PublicKeyAlgorithm::Ed448),
739 Unknown { .. } => None,
740 }
741 }
742}
743
744impl Hash for PublicKey {
745 fn hash(&self, mut hash: &mut hash::Context) -> Result<()> {
746 self.serialize(&mut hash as &mut dyn Write)
747 }
748}
749
750#[cfg(test)]
751impl Arbitrary for PublicKey {
752 fn arbitrary(g: &mut Gen) -> Self {
753 use self::PublicKey::*;
754 use crate::arbitrary_helper::gen_arbitrary_from_range;
755
756 match gen_arbitrary_from_range(0..10, g) {
757 0 => RSA {
758 e: MPI::arbitrary(g),
759 n: MPI::arbitrary(g),
760 },
761
762 1 => DSA {
763 p: MPI::arbitrary(g),
764 q: MPI::arbitrary(g),
765 g: MPI::arbitrary(g),
766 y: MPI::arbitrary(g),
767 },
768
769 2 => ElGamal {
770 p: MPI::arbitrary(g),
771 g: MPI::arbitrary(g),
772 y: MPI::arbitrary(g),
773 },
774
775 3 => EdDSA {
776 curve: Curve::arbitrary(g),
777 q: MPI::arbitrary(g),
778 },
779
780 4 => ECDSA {
781 curve: Curve::arbitrary(g),
782 q: MPI::arbitrary(g),
783 },
784
785 5 => ECDH {
786 curve: Curve::arbitrary(g),
787 q: MPI::arbitrary(g),
788 hash: HashAlgorithm::arbitrary(g),
789 sym: SymmetricAlgorithm::arbitrary(g),
790 },
791
792 6 => X25519 { u: arbitrary(g) },
793 7 => X448 { u: Box::new(arbitrarize(g, [0; 56])) },
794 8 => Ed25519 { a: arbitrary(g) },
795 9 => Ed448 { a: Box::new(arbitrarize(g, [0; 57])) },
796
797 _ => unreachable!(),
798 }
799 }
800}
801
802#[cfg(test)]
803pub(crate) fn arbitrarize<T: AsMut<[u8]>>(g: &mut Gen, mut a: T) -> T
804{
805 a.as_mut().iter_mut().for_each(|p| *p = Arbitrary::arbitrary(g));
806 a
807}
808
809#[cfg(test)]
810pub(crate) fn arbitrary<T: Default + AsMut<[u8]>>(g: &mut Gen) -> T
811{
812 arbitrarize(g, Default::default())
813}
814
815
816#[non_exhaustive]
826#[allow(clippy::derived_hash_with_manual_eq)]
827#[derive(Clone, Hash)]
828pub enum SecretKeyMaterial {
829 RSA {
831 d: ProtectedMPI,
833 p: ProtectedMPI,
835 q: ProtectedMPI,
837 u: ProtectedMPI,
839 },
840
841 DSA {
843 x: ProtectedMPI,
845 },
846
847 ElGamal {
849 x: ProtectedMPI,
851 },
852
853 EdDSA {
855 scalar: ProtectedMPI,
857 },
858
859 ECDSA {
861 scalar: ProtectedMPI,
863 },
864
865 ECDH {
867 scalar: ProtectedMPI,
869 },
870
871 X25519 {
873 x: Protected,
875 },
876
877 X448 {
879 x: Protected,
881 },
882
883 Ed25519 {
885 x: Protected,
887 },
888
889 Ed448 {
891 x: Protected,
893 },
894
895 Unknown {
897 mpis: Box<[ProtectedMPI]>,
899 rest: Protected,
901 },
902}
903assert_send_and_sync!(SecretKeyMaterial);
904
905impl fmt::Debug for SecretKeyMaterial {
906 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
907 if cfg!(debug_assertions) {
908 match self {
909 SecretKeyMaterial::RSA { d, p, q, u } =>
910 f.debug_struct("RSA")
911 .field("d", d)
912 .field("p", p)
913 .field("q", q)
914 .field("u", u)
915 .finish(),
916
917 SecretKeyMaterial::DSA { x } =>
918 f.debug_struct("DSA")
919 .field("x", x)
920 .finish(),
921
922 SecretKeyMaterial::ElGamal { x } =>
923 f.debug_struct("ElGamal")
924 .field("x", x)
925 .finish(),
926
927 SecretKeyMaterial::EdDSA { scalar } =>
928 f.debug_struct("EdDSA")
929 .field("scalar", scalar)
930 .finish(),
931
932 SecretKeyMaterial::ECDSA { scalar } =>
933 f.debug_struct("ECDSA")
934 .field("scalar", scalar)
935 .finish(),
936
937 SecretKeyMaterial::ECDH { scalar } =>
938 f.debug_struct("ECDH")
939 .field("scalar", scalar)
940 .finish(),
941
942 SecretKeyMaterial::X25519 { x } =>
943 f.debug_struct("X25519")
944 .field("x", &hex::encode(x))
945 .finish(),
946
947 SecretKeyMaterial::X448 { x } =>
948 f.debug_struct("X448")
949 .field("x", &hex::encode(x))
950 .finish(),
951
952 SecretKeyMaterial::Ed25519 { x } =>
953 f.debug_struct("Ed25519")
954 .field("x", &hex::encode(x))
955 .finish(),
956
957 SecretKeyMaterial::Ed448 { x } =>
958 f.debug_struct("Ed448")
959 .field("x", &hex::encode(x))
960 .finish(),
961
962 SecretKeyMaterial::Unknown{ mpis, rest } =>
963 f.debug_struct("Unknown")
964 .field("mpis", mpis)
965 .field("rest", &hex::encode(rest))
966 .finish(),
967 }
968 } else {
969 match self {
970 SecretKeyMaterial::RSA{ .. } =>
971 f.write_str("RSA { <Redacted> }"),
972 SecretKeyMaterial::DSA{ .. } =>
973 f.write_str("DSA { <Redacted> }"),
974 SecretKeyMaterial::ElGamal{ .. } =>
975 f.write_str("ElGamal { <Redacted> }"),
976 SecretKeyMaterial::EdDSA{ .. } =>
977 f.write_str("EdDSA { <Redacted> }"),
978 SecretKeyMaterial::ECDSA{ .. } =>
979 f.write_str("ECDSA { <Redacted> }"),
980 SecretKeyMaterial::ECDH{ .. } =>
981 f.write_str("ECDH { <Redacted> }"),
982 SecretKeyMaterial::X25519 { .. } =>
983 f.write_str("X25519 { <Redacted> }"),
984 SecretKeyMaterial::X448 { .. } =>
985 f.write_str("X448 { <Redacted> }"),
986 SecretKeyMaterial::Ed25519 { .. } =>
987 f.write_str("Ed25519 { <Redacted> }"),
988 SecretKeyMaterial::Ed448 { .. } =>
989 f.write_str("Ed448 { <Redacted> }"),
990 SecretKeyMaterial::Unknown{ .. } =>
991 f.write_str("Unknown { <Redacted> }"),
992 }
993 }
994 }
995}
996
997impl PartialOrd for SecretKeyMaterial {
998 fn partial_cmp(&self, other: &SecretKeyMaterial) -> Option<Ordering> {
999 Some(self.cmp(other))
1000 }
1001}
1002
1003impl Ord for SecretKeyMaterial {
1004 fn cmp(&self, other: &Self) -> Ordering {
1005 use std::iter;
1006
1007 fn discriminant(sk: &SecretKeyMaterial) -> usize {
1008 match sk {
1009 SecretKeyMaterial::RSA{ .. } => 0,
1010 SecretKeyMaterial::DSA{ .. } => 1,
1011 SecretKeyMaterial::ElGamal{ .. } => 2,
1012 SecretKeyMaterial::EdDSA{ .. } => 3,
1013 SecretKeyMaterial::ECDSA{ .. } => 4,
1014 SecretKeyMaterial::ECDH{ .. } => 5,
1015 SecretKeyMaterial::X25519 { .. } => 6,
1016 SecretKeyMaterial::X448 { .. } => 7,
1017 SecretKeyMaterial::Ed25519 { .. } => 8,
1018 SecretKeyMaterial::Ed448 { .. } => 9,
1019 SecretKeyMaterial::Unknown { .. } => 10,
1020 }
1021 }
1022
1023 let ret = match (self, other) {
1024 (&SecretKeyMaterial::RSA{ d: ref d1, p: ref p1, q: ref q1, u: ref u1 }
1025 ,&SecretKeyMaterial::RSA{ d: ref d2, p: ref p2, q: ref q2, u: ref u2 }) => {
1026 let o1 = d1.cmp(d2);
1027 let o2 = p1.cmp(p2);
1028 let o3 = q1.cmp(q2);
1029 let o4 = u1.cmp(u2);
1030
1031 if o1 != Ordering::Equal { return o1; }
1032 if o2 != Ordering::Equal { return o2; }
1033 if o3 != Ordering::Equal { return o3; }
1034 o4
1035 }
1036 (&SecretKeyMaterial::DSA{ x: ref x1 }
1037 ,&SecretKeyMaterial::DSA{ x: ref x2 }) => {
1038 x1.cmp(x2)
1039 }
1040 (&SecretKeyMaterial::ElGamal{ x: ref x1 }
1041 ,&SecretKeyMaterial::ElGamal{ x: ref x2 }) => {
1042 x1.cmp(x2)
1043 }
1044 (&SecretKeyMaterial::EdDSA{ scalar: ref scalar1 }
1045 ,&SecretKeyMaterial::EdDSA{ scalar: ref scalar2 }) => {
1046 scalar1.cmp(scalar2)
1047 }
1048 (&SecretKeyMaterial::ECDSA{ scalar: ref scalar1 }
1049 ,&SecretKeyMaterial::ECDSA{ scalar: ref scalar2 }) => {
1050 scalar1.cmp(scalar2)
1051 }
1052 (&SecretKeyMaterial::ECDH{ scalar: ref scalar1 }
1053 ,&SecretKeyMaterial::ECDH{ scalar: ref scalar2 }) => {
1054 scalar1.cmp(scalar2)
1055 }
1056 (SecretKeyMaterial::X25519 { x: x0 },
1057 SecretKeyMaterial::X25519 { x: x1 }) => x0.cmp(x1),
1058 (SecretKeyMaterial::X448 { x: x0 },
1059 SecretKeyMaterial::X448 { x: x1 }) => x0.cmp(x1),
1060 (SecretKeyMaterial::Ed25519 { x: x0 },
1061 SecretKeyMaterial::Ed25519 { x: x1 }) => x0.cmp(x1),
1062 (SecretKeyMaterial::Ed448 { x: x0 },
1063 SecretKeyMaterial::Ed448 { x: x1 }) => x0.cmp(x1),
1064
1065 (&SecretKeyMaterial::Unknown{ mpis: ref mpis1, rest: ref rest1 }
1066 ,&SecretKeyMaterial::Unknown{ mpis: ref mpis2, rest: ref rest2 }) => {
1067 let o1 = secure_cmp(rest1, rest2);
1068 let o2 = mpis1.len().cmp(&mpis2.len());
1069 let on = mpis1.iter().zip(mpis2.iter()).map(|(a,b)| {
1070 a.cmp(b)
1071 }).collect::<Vec<_>>();
1072
1073 iter::once(o1)
1074 .chain(iter::once(o2))
1075 .chain(on.iter().cloned())
1076 .fold(Ordering::Equal, |acc, x| acc.then(x))
1077 }
1078
1079 (a, b) => {
1080 let ret = discriminant(a).cmp(&discriminant(b));
1081
1082 assert!(ret != Ordering::Equal);
1083 ret
1084 }
1085 };
1086
1087 ret
1088 }
1089}
1090
1091impl PartialEq for SecretKeyMaterial {
1092 fn eq(&self, other: &Self) -> bool { self.cmp(other) == Ordering::Equal }
1093}
1094
1095impl Eq for SecretKeyMaterial {}
1096
1097impl SecretKeyMaterial {
1098 pub fn algo(&self) -> Option<PublicKeyAlgorithm> {
1101 use self::SecretKeyMaterial::*;
1102 #[allow(deprecated)]
1103 match self {
1104 RSA { .. } => Some(PublicKeyAlgorithm::RSAEncryptSign),
1105 DSA { .. } => Some(PublicKeyAlgorithm::DSA),
1106 ElGamal { .. } => Some(PublicKeyAlgorithm::ElGamalEncrypt),
1107 EdDSA { .. } => Some(PublicKeyAlgorithm::EdDSA),
1108 ECDSA { .. } => Some(PublicKeyAlgorithm::ECDSA),
1109 ECDH { .. } => Some(PublicKeyAlgorithm::ECDH),
1110 X25519 { .. } => Some(PublicKeyAlgorithm::X25519),
1111 X448 { .. } => Some(PublicKeyAlgorithm::X448),
1112 Ed25519 { .. } => Some(PublicKeyAlgorithm::Ed25519),
1113 Ed448 { .. } => Some(PublicKeyAlgorithm::Ed448),
1114 Unknown { .. } => None,
1115 }
1116 }
1117}
1118
1119impl Hash for SecretKeyMaterial {
1120 fn hash(&self, mut hash: &mut hash::Context) -> Result<()> {
1121 self.serialize(&mut hash as &mut dyn Write)
1122 }
1123}
1124
1125#[cfg(test)]
1126impl SecretKeyMaterial {
1127 pub(crate) fn arbitrary_for(g: &mut Gen, pk: PublicKeyAlgorithm) -> Result<Self> {
1128 use self::PublicKeyAlgorithm::*;
1129 #[allow(deprecated)]
1130 match pk {
1131 RSAEncryptSign | RSASign | RSAEncrypt => Ok(SecretKeyMaterial::RSA {
1132 d: ProtectedMPI::arbitrary(g),
1133 p: ProtectedMPI::arbitrary(g),
1134 q: ProtectedMPI::arbitrary(g),
1135 u: ProtectedMPI::arbitrary(g),
1136 }),
1137
1138 DSA => Ok(SecretKeyMaterial::DSA {
1139 x: ProtectedMPI::arbitrary(g),
1140 }),
1141
1142 ElGamalEncryptSign | ElGamalEncrypt => Ok(SecretKeyMaterial::ElGamal {
1143 x: ProtectedMPI::arbitrary(g),
1144 }),
1145
1146 EdDSA => Ok(SecretKeyMaterial::EdDSA {
1147 scalar: ProtectedMPI::arbitrary(g),
1148 }),
1149
1150 ECDSA => Ok(SecretKeyMaterial::ECDSA {
1151 scalar: ProtectedMPI::arbitrary(g),
1152 }),
1153
1154 ECDH => Ok(SecretKeyMaterial::ECDH {
1155 scalar: ProtectedMPI::arbitrary(g),
1156 }),
1157
1158 X25519 => Ok(SecretKeyMaterial::X25519 {
1159 x: arbitrarize(g, vec![0; 32]).into(),
1160 }),
1161 X448 => Ok(SecretKeyMaterial::X448 {
1162 x: arbitrarize(g, vec![0; 56]).into(),
1163 }),
1164 Ed25519 => Ok(SecretKeyMaterial::Ed25519 {
1165 x: arbitrarize(g, vec![0; 32]).into(),
1166 }),
1167 Ed448 => Ok(SecretKeyMaterial::Ed448 {
1168 x: arbitrarize(g, vec![0; 57]).into(),
1169 }),
1170
1171 Private(_) | Unknown(_) =>
1172 Err(Error::UnsupportedPublicKeyAlgorithm(pk).into()),
1173 }
1174 }
1175}
1176#[cfg(test)]
1177impl Arbitrary for SecretKeyMaterial {
1178 fn arbitrary(g: &mut Gen) -> Self {
1179 let pk = *g.choose(
1180 &crate::crypto::types::public_key_algorithm::PUBLIC_KEY_ALGORITHM_VARIANTS)
1181 .expect("not empty");
1182 Self::arbitrary_for(g, pk).expect("only known variants")
1183 }
1184}
1185
1186#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
1193pub enum SecretKeyChecksum {
1194 SHA1,
1196
1197 Sum16,
1199}
1200assert_send_and_sync!(SecretKeyChecksum);
1201
1202impl Default for SecretKeyChecksum {
1203 fn default() -> Self {
1204 SecretKeyChecksum::SHA1
1205 }
1206}
1207
1208impl SecretKeyChecksum {
1209 pub(crate) fn len(&self) -> usize {
1211 match self {
1212 SecretKeyChecksum::SHA1 => 20,
1213 SecretKeyChecksum::Sum16 => 2,
1214 }
1215 }
1216}
1217
1218#[non_exhaustive]
1225#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1226pub enum Ciphertext {
1227 RSA {
1229 c: MPI,
1231 },
1232
1233 ElGamal {
1235 e: MPI,
1237 c: MPI,
1239 },
1240
1241 ECDH {
1243 e: MPI,
1245 key: Box<[u8]>,
1247 },
1248
1249 X25519 {
1251 e: Box<[u8; 32]>,
1253 key: Box<[u8]>,
1255 },
1256
1257 X448 {
1259 e: Box<[u8; 56]>,
1261 key: Box<[u8]>,
1263 },
1264
1265 Unknown {
1267 mpis: Box<[MPI]>,
1269 rest: Box<[u8]>,
1271 },
1272}
1273assert_send_and_sync!(Ciphertext);
1274
1275impl fmt::Debug for Ciphertext {
1276 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1277 match self {
1278 Ciphertext::RSA { c } =>
1279 f.debug_struct("RSA")
1280 .field("c", c)
1281 .finish(),
1282
1283 Ciphertext::ElGamal { e, c } =>
1284 f.debug_struct("ElGamal")
1285 .field("e", e)
1286 .field("c", c)
1287 .finish(),
1288
1289 Ciphertext::ECDH { e, key } =>
1290 f.debug_struct("ECDH")
1291 .field("e", e)
1292 .field("key", &hex::encode(key))
1293 .finish(),
1294
1295 Ciphertext::X25519 { e, key } =>
1296 f.debug_struct("X25519")
1297 .field("e", &hex::encode(&e[..]))
1298 .field("key", &hex::encode(key))
1299 .finish(),
1300
1301 Ciphertext::X448 { e, key } =>
1302 f.debug_struct("X448")
1303 .field("e", &hex::encode(&e[..]))
1304 .field("key", &hex::encode(key))
1305 .finish(),
1306
1307 Ciphertext::Unknown { mpis, rest } =>
1308 f.debug_struct("Unknown")
1309 .field("mpis", mpis)
1310 .field("rest", &hex::encode(rest))
1311 .finish(),
1312 }
1313 }
1314}
1315
1316impl Ciphertext {
1317 pub fn pk_algo(&self) -> Option<PublicKeyAlgorithm> {
1320 use self::Ciphertext::*;
1321
1322 #[allow(deprecated)]
1326 match self {
1327 RSA { .. } => Some(PublicKeyAlgorithm::RSAEncryptSign),
1328 ElGamal { .. } => Some(PublicKeyAlgorithm::ElGamalEncrypt),
1329 ECDH { .. } => Some(PublicKeyAlgorithm::ECDH),
1330 X25519 { .. } => Some(PublicKeyAlgorithm::X25519),
1331 X448 { .. } => Some(PublicKeyAlgorithm::X448),
1332 Unknown { .. } => None,
1333 }
1334 }
1335}
1336
1337impl Hash for Ciphertext {
1338 fn hash(&self, mut hash: &mut hash::Context) -> Result<()> {
1339 self.serialize(&mut hash as &mut dyn Write)
1340 }
1341}
1342
1343#[cfg(test)]
1344impl Arbitrary for Ciphertext {
1345 fn arbitrary(g: &mut Gen) -> Self {
1346 use crate::arbitrary_helper::gen_arbitrary_from_range;
1347
1348 match gen_arbitrary_from_range(0..5, g) {
1349 0 => Ciphertext::RSA {
1350 c: MPI::arbitrary(g),
1351 },
1352
1353 1 => Ciphertext::ElGamal {
1354 e: MPI::arbitrary(g),
1355 c: MPI::arbitrary(g)
1356 },
1357
1358 2 => Ciphertext::ECDH {
1359 e: MPI::arbitrary(g),
1360 key: {
1361 let mut k = <Vec<u8>>::arbitrary(g);
1362 k.truncate(255);
1363 k.into_boxed_slice()
1364 },
1365 },
1366
1367 3 => Ciphertext::X25519 {
1368 e: Box::new(arbitrary(g)),
1369 key: {
1370 let mut k = <Vec<u8>>::arbitrary(g);
1371 k.truncate(255);
1372 k.into_boxed_slice()
1373 },
1374 },
1375
1376 4 => Ciphertext::X448 {
1377 e: Box::new(arbitrarize(g, [0; 56])),
1378 key: {
1379 let mut k = <Vec<u8>>::arbitrary(g);
1380 k.truncate(255);
1381 k.into_boxed_slice()
1382 },
1383 },
1384 _ => unreachable!(),
1385 }
1386 }
1387}
1388
1389#[non_exhaustive]
1396#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1397pub enum Signature {
1398 RSA {
1400 s: MPI,
1402 },
1403
1404 DSA {
1406 r: MPI,
1408 s: MPI,
1410 },
1411
1412 ElGamal {
1414 r: MPI,
1416 s: MPI,
1418 },
1419
1420 EdDSA {
1422 r: MPI,
1424 s: MPI,
1426 },
1427
1428 ECDSA {
1430 r: MPI,
1432 s: MPI,
1434 },
1435
1436 Ed25519 {
1438 s: Box<[u8; 64]>,
1440 },
1441
1442 Ed448 {
1444 s: Box<[u8; 114]>,
1446 },
1447
1448 Unknown {
1450 mpis: Box<[MPI]>,
1452 rest: Box<[u8]>,
1454 },
1455}
1456assert_send_and_sync!(Signature);
1457
1458impl fmt::Debug for Signature {
1459 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1460 match self {
1461 Signature::RSA { s } =>
1462 f.debug_struct("RSA")
1463 .field("s", s)
1464 .finish(),
1465
1466 Signature::DSA { r, s } =>
1467 f.debug_struct("DSA")
1468 .field("r", r)
1469 .field("s", s)
1470 .finish(),
1471
1472 Signature::ElGamal { r, s } =>
1473 f.debug_struct("ElGamal")
1474 .field("r", r)
1475 .field("s", s)
1476 .finish(),
1477
1478 Signature::EdDSA { r, s } =>
1479 f.debug_struct("EdDSA")
1480 .field("r", r)
1481 .field("s", s)
1482 .finish(),
1483
1484 Signature::ECDSA { r, s } =>
1485 f.debug_struct("ECDSA")
1486 .field("r", r)
1487 .field("s", s)
1488 .finish(),
1489
1490 Signature::Ed25519 { s } =>
1491 f.debug_struct("Ed25519")
1492 .field("s", &hex::encode(&s[..]))
1493 .finish(),
1494
1495 Signature::Ed448 { s } =>
1496 f.debug_struct("Ed448")
1497 .field("s", &hex::encode(&s[..]))
1498 .finish(),
1499
1500 Signature::Unknown { mpis, rest } =>
1501 f.debug_struct("Unknown")
1502 .field("mpis", mpis)
1503 .field("rest", &hex::encode(rest))
1504 .finish(),
1505 }
1506 }
1507}
1508
1509impl Hash for Signature {
1510 fn hash(&self, mut hash: &mut hash::Context) -> Result<()> {
1511 self.serialize(&mut hash as &mut dyn Write)
1512 }
1513}
1514
1515#[cfg(test)]
1516impl Arbitrary for Signature {
1517 fn arbitrary(g: &mut Gen) -> Self {
1518 use crate::arbitrary_helper::gen_arbitrary_from_range;
1519
1520 match gen_arbitrary_from_range(0..6, g) {
1521 0 => Signature::RSA {
1522 s: MPI::arbitrary(g),
1523 },
1524
1525 1 => Signature::DSA {
1526 r: MPI::arbitrary(g),
1527 s: MPI::arbitrary(g),
1528 },
1529
1530 2 => Signature::EdDSA {
1531 r: MPI::arbitrary(g),
1532 s: MPI::arbitrary(g),
1533 },
1534
1535 3 => Signature::ECDSA {
1536 r: MPI::arbitrary(g),
1537 s: MPI::arbitrary(g),
1538 },
1539
1540 4 => Signature::Ed25519 {
1541 s: Box::new(arbitrarize(g, [0; 64])),
1542 },
1543
1544 5 => Signature::Ed448 {
1545 s: Box::new(arbitrarize(g, [0; 114])),
1546 },
1547
1548 _ => unreachable!(),
1549 }
1550 }
1551}
1552
1553#[cfg(test)]
1554mod tests {
1555 use super::*;
1556 use crate::parse::Parse;
1557
1558 quickcheck! {
1559 fn mpi_roundtrip(mpi: MPI) -> bool {
1560 let mut buf = Vec::new();
1561 mpi.serialize(&mut buf).unwrap();
1562 MPI::from_bytes(&buf).unwrap() == mpi
1563 }
1564 }
1565
1566 quickcheck! {
1567 fn pk_roundtrip(pk: PublicKey) -> bool {
1568 use std::io::Cursor;
1569
1570 let mut buf = Vec::new();
1571 pk.serialize(&mut buf).unwrap();
1572 let cur = Cursor::new(buf);
1573 let pk_ = PublicKey::parse(pk.algo().unwrap(), cur).unwrap();
1574
1575 pk == pk_
1576 }
1577 }
1578
1579 #[test]
1580 fn pk_bits() {
1581 for (name, key_no, bits) in &[
1582 ("testy.pgp", 0, 2048),
1583 ("testy-new.pgp", 1, 256),
1584 ("dennis-simon-anton.pgp", 0, 2048),
1585 ("dsa2048-elgamal3072.pgp", 1, 3072),
1586 ("emmelie-dorothea-dina-samantha-awina-ed25519.pgp", 0, 256),
1587 ("erika-corinna-daniela-simone-antonia-nistp256.pgp", 0, 256),
1588 ("erika-corinna-daniela-simone-antonia-nistp384.pgp", 0, 384),
1589 ("erika-corinna-daniela-simone-antonia-nistp521.pgp", 0, 521),
1590 ] {
1591 let cert = crate::Cert::from_bytes(crate::tests::key(name)).unwrap();
1592 let ka = cert.keys().nth(*key_no).unwrap();
1593 assert_eq!(ka.key().mpis().bits().unwrap(), *bits,
1594 "Cert {}, key no {}", name, *key_no);
1595 }
1596 }
1597
1598 quickcheck! {
1599 fn sk_roundtrip(sk: SecretKeyMaterial) -> bool {
1600 let mut buf = Vec::new();
1601 sk.serialize(&mut buf).unwrap();
1602 let sk_ =
1603 SecretKeyMaterial::from_bytes(sk.algo().unwrap(),
1604 &buf).unwrap();
1605
1606 sk == sk_
1607 }
1608 }
1609
1610 quickcheck! {
1611 fn ct_roundtrip(ct: Ciphertext) -> bool {
1612 use std::io::Cursor;
1613
1614 let mut buf = Vec::new();
1615 ct.serialize(&mut buf).unwrap();
1616 let cur = Cursor::new(buf);
1617 let ct_ = Ciphertext::parse(ct.pk_algo().unwrap(), cur).unwrap();
1618
1619 ct == ct_
1620 }
1621 }
1622
1623 quickcheck! {
1624 fn signature_roundtrip(sig: Signature) -> bool {
1625 use std::io::Cursor;
1626 use crate::PublicKeyAlgorithm::*;
1627
1628 let mut buf = Vec::new();
1629 sig.serialize(&mut buf).unwrap();
1630 let cur = Cursor::new(buf);
1631
1632 #[allow(deprecated)]
1633 let sig_ = match &sig {
1634 Signature::RSA { .. } =>
1635 Signature::parse(RSAEncryptSign, cur).unwrap(),
1636 Signature::DSA { .. } =>
1637 Signature::parse(DSA, cur).unwrap(),
1638 Signature::ElGamal { .. } =>
1639 Signature::parse(ElGamalEncryptSign, cur).unwrap(),
1640 Signature::EdDSA { .. } =>
1641 Signature::parse(EdDSA, cur).unwrap(),
1642 Signature::ECDSA { .. } =>
1643 Signature::parse(ECDSA, cur).unwrap(),
1644 Signature::Ed25519 { .. } =>
1645 Signature::parse(Ed25519, cur).unwrap(),
1646 Signature::Ed448 { .. } =>
1647 Signature::parse(Ed448, cur).unwrap(),
1648
1649 Signature::Unknown { .. } => unreachable!(),
1650 };
1651
1652 sig == sig_
1653 }
1654 }
1655}