1use std::io::Read;
4use buffered_reader::BufferedReader;
5use crate::{
6 Result,
7 Error,
8 PublicKeyAlgorithm,
9 SymmetricAlgorithm,
10 HashAlgorithm,
11};
12use crate::types::Curve;
13use crate::crypto::{
14 mem::Protected,
15 mpi::{self, MPI, ProtectedMPI},
16};
17use crate::parse::{
18 PacketHeaderParser,
19 Cookie,
20};
21
22impl mpi::PublicKey {
23 pub fn parse<R: Read + Send + Sync>(algo: PublicKeyAlgorithm, reader: R) -> Result<Self>
29 {
30 let bio = buffered_reader::Generic::with_cookie(
31 reader, None, Cookie::default());
32 let mut php = PacketHeaderParser::new_naked(bio.into_boxed());
33 Self::_parse(algo, &mut php)
34 }
35
36 pub(crate) fn _parse(
42 algo: PublicKeyAlgorithm,
43 php: &mut PacketHeaderParser<'_>)
44 -> Result<Self>
45 {
46 use crate::PublicKeyAlgorithm::*;
47
48 #[allow(deprecated)]
49 match algo {
50 RSAEncryptSign | RSAEncrypt | RSASign => {
51 let n = MPI::parse("rsa_public_n_len", "rsa_public_n", php)?;
52 let e = MPI::parse("rsa_public_e_len", "rsa_public_e", php)?;
53
54 Ok(mpi::PublicKey::RSA { e, n })
55 }
56
57 DSA => {
58 let p = MPI::parse("dsa_public_p_len", "dsa_public_p", php)?;
59 let q = MPI::parse("dsa_public_q_len", "dsa_public_q", php)?;
60 let g = MPI::parse("dsa_public_g_len", "dsa_public_g", php)?;
61 let y = MPI::parse("dsa_public_y_len", "dsa_public_y", php)?;
62
63 Ok(mpi::PublicKey::DSA {
64 p,
65 q,
66 g,
67 y,
68 })
69 }
70
71 ElGamalEncrypt | ElGamalEncryptSign => {
72 let p = MPI::parse("elgamal_public_p_len", "elgamal_public_p",
73 php)?;
74 let g = MPI::parse("elgamal_public_g_len", "elgamal_public_g",
75 php)?;
76 let y = MPI::parse("elgamal_public_y_len", "elgamal_public_y",
77 php)?;
78
79 Ok(mpi::PublicKey::ElGamal {
80 p,
81 g,
82 y,
83 })
84 }
85
86 EdDSA => {
87 let curve_len = php.parse_u8("curve_len")? as usize;
88 let curve = php.parse_bytes("curve", curve_len)?;
89 let q = MPI::parse("eddsa_public_len", "eddsa_public", php)?;
90
91 Ok(mpi::PublicKey::EdDSA {
92 curve: Curve::from_oid(&curve),
93 q
94 })
95 }
96
97 ECDSA => {
98 let curve_len = php.parse_u8("curve_len")? as usize;
99 let curve = php.parse_bytes("curve", curve_len)?;
100 let q = MPI::parse("ecdsa_public_len", "ecdsa_public", php)?;
101
102 Ok(mpi::PublicKey::ECDSA {
103 curve: Curve::from_oid(&curve),
104 q
105 })
106 }
107
108 ECDH => {
109 let curve_len = php.parse_u8("curve_len")? as usize;
110 let curve = php.parse_bytes("curve", curve_len)?;
111 let q = MPI::parse("ecdh_public_len", "ecdh_public", php)?;
112 let kdf_len = php.parse_u8("kdf_len")?;
113
114 if kdf_len != 3 {
115 return Err(Error::MalformedPacket(
116 "wrong kdf length".into()).into());
117 }
118
119 let reserved = php.parse_u8("kdf_reserved")?;
120 if reserved != 1 {
121 return Err(Error::MalformedPacket(
122 format!("Reserved kdf field must be 0x01, \
123 got 0x{:x}", reserved)).into());
124 }
125 let hash: HashAlgorithm = php.parse_u8("kdf_hash")?.into();
126 let sym: SymmetricAlgorithm = php.parse_u8("kek_symm")?.into();
127
128 Ok(mpi::PublicKey::ECDH {
129 curve: Curve::from_oid(&curve),
130 q,
131 hash,
132 sym
133 })
134 }
135
136 X25519 => {
137 let mut u = [0; 32];
138 php.parse_bytes_into("x25519_public", &mut u)?;
139 Ok(mpi::PublicKey::X25519 { u })
140 },
141
142 X448 => {
143 let mut u = [0; 56];
144 php.parse_bytes_into("x448_public", &mut u)?;
145 Ok(mpi::PublicKey::X448 { u: Box::new(u) })
146 },
147
148 Ed25519 => {
149 let mut a = [0; 32];
150 php.parse_bytes_into("ed25519_public", &mut a)?;
151 Ok(mpi::PublicKey::Ed25519 { a })
152 },
153
154 Ed448 => {
155 let mut a = [0; 57];
156 php.parse_bytes_into("ed448_public", &mut a)?;
157 Ok(mpi::PublicKey::Ed448 { a: Box::new(a) })
158 },
159
160 MLDSA65_Ed25519 => Ok(mpi::PublicKey::MLDSA65_Ed25519 {
161 eddsa: {
162 let mut a = Box::new([0; 32]);
163 php.parse_bytes_into("ed25519_public", &mut a[..])?;
164 a
165 },
166 mldsa: {
167 let mut a = Box::new([0; 1952]);
168 php.parse_bytes_into("mldsa65_public", &mut a[..])?;
169 a
170 },
171 }),
172
173 MLDSA87_Ed448 => Ok(mpi::PublicKey::MLDSA87_Ed448 {
174 eddsa: {
175 let mut a = Box::new([0; 57]);
176 php.parse_bytes_into("ed448_public", &mut a[..])?;
177 a
178 },
179 mldsa: {
180 let mut a = Box::new([0; 2592]);
181 php.parse_bytes_into("mldsa87_public", &mut a[..])?;
182 a
183 },
184 }),
185
186 SLHDSA128s => Ok(mpi::PublicKey::SLHDSA128s {
187 public: {
188 let mut a = [0; 32];
189 php.parse_bytes_into("public", &mut a[..])?;
190 a
191 },
192 }),
193
194 SLHDSA128f => Ok(mpi::PublicKey::SLHDSA128f {
195 public: {
196 let mut a = [0; 32];
197 php.parse_bytes_into("public", &mut a[..])?;
198 a
199 },
200 }),
201
202 SLHDSA256s => Ok(mpi::PublicKey::SLHDSA256s {
203 public: {
204 let mut a = Box::new([0; 64]);
205 php.parse_bytes_into("public", &mut a[..])?;
206 a
207 },
208 }),
209
210 MLKEM768_X25519 => {
211 let mut ecdh = Box::new([0; 32]);
212 php.parse_bytes_into("x25519_public", ecdh.as_mut())?;
213 let mut mlkem = Box::new([0; 1184]);
214 php.parse_bytes_into("mlkem768_public", mlkem.as_mut())?;
215 Ok(mpi::PublicKey::MLKEM768_X25519 { ecdh, mlkem })
216 },
217
218 MLKEM1024_X448 => {
219 let mut ecdh = Box::new([0; 56]);
220 php.parse_bytes_into("x448_public", ecdh.as_mut())?;
221 let mut mlkem = Box::new([0; 1568]);
222 php.parse_bytes_into("mlkem1024_public", mlkem.as_mut())?;
223 Ok(mpi::PublicKey::MLKEM1024_X448 { ecdh, mlkem })
224 },
225
226 Unknown(_) | Private(_) => {
227 let mut mpis = Vec::new();
228 while let Ok(mpi) = MPI::parse("unknown_len",
229 "unknown", php) {
230 mpis.push(mpi);
231 }
232 let rest = php.parse_bytes_eof("rest")?;
233
234 Ok(mpi::PublicKey::Unknown {
235 mpis: mpis.into_boxed_slice(),
236 rest: rest.into_boxed_slice(),
237 })
238 }
239 }
240 }
241}
242
243impl mpi::SecretKeyMaterial {
244 #[deprecated(
248 since = "1.14.0",
249 note = "Leaks secrets into the heap, use [`SecretKeyMaterial::from_bytes_with_checksum`]")]
250 pub fn parse_with_checksum<R: Read + Send + Sync>(algo: PublicKeyAlgorithm,
251 reader: R,
252 checksum: mpi::SecretKeyChecksum)
253 -> Result<Self> {
254 let bio = buffered_reader::Generic::with_cookie(
255 reader, None, Cookie::default());
256 let mut php = PacketHeaderParser::new_naked(bio.into_boxed());
257 Self::_parse(algo, &mut php, Some(checksum))
258 }
259
260 pub fn from_bytes_with_checksum(algo: PublicKeyAlgorithm,
264 bytes: &[u8],
265 checksum: mpi::SecretKeyChecksum)
266 -> Result<Self> {
267 let bio = buffered_reader::Memory::with_cookie(
268 bytes, Cookie::default());
269 let mut php = PacketHeaderParser::new_naked(bio.into_boxed());
270 Self::_parse(algo, &mut php, Some(checksum))
271 }
272
273 #[deprecated(
279 since = "1.14.0",
280 note = "Leaks secrets into the heap, use [`SecretKeyMaterial::from_bytes`]")]
281 pub fn parse<R: Read + Send + Sync>(algo: PublicKeyAlgorithm, reader: R) -> Result<Self>
282 {
283 let bio = buffered_reader::Generic::with_cookie(
284 reader, None, Cookie::default());
285 let mut php = PacketHeaderParser::new_naked(bio.into_boxed());
286 Self::_parse(algo, &mut php, None)
287 }
288
289 pub fn from_bytes(algo: PublicKeyAlgorithm, buf: &[u8]) -> Result<Self> {
295 let bio = buffered_reader::Memory::with_cookie(
296 buf, Cookie::default());
297 let mut php = PacketHeaderParser::new_naked(bio.into_boxed());
298 Self::_parse(algo, &mut php, None)
299 }
300
301 pub(crate) fn _parse(
307 algo: PublicKeyAlgorithm,
308 php: &mut PacketHeaderParser<'_>,
309 checksum: Option<mpi::SecretKeyChecksum>,
310 )
311 -> Result<Self>
312 {
313 use crate::PublicKeyAlgorithm::*;
314
315 let mpis_start = php.reader.total_out();
319
320 #[allow(deprecated)]
321 let mpis: Result<Self> = match algo {
322 RSAEncryptSign | RSAEncrypt | RSASign => {
323 Ok(mpi::SecretKeyMaterial::RSA {
324 d: ProtectedMPI::parse(
325 "rsa_secret_d_len", "rsa_secret_d", php)?,
326 p: ProtectedMPI::parse(
327 "rsa_secret_p_len", "rsa_secret_p", php)?,
328 q: ProtectedMPI::parse(
329 "rsa_secret_q_len", "rsa_secret_q", php)?,
330 u: ProtectedMPI::parse(
331 "rsa_secret_u_len", "rsa_secret_u", php)?,
332 })
333 }
334
335 DSA => {
336 Ok(mpi::SecretKeyMaterial::DSA {
337 x: ProtectedMPI::parse(
338 "dsa_secret_len", "dsa_secret", php)?,
339 })
340 }
341
342 ElGamalEncrypt | ElGamalEncryptSign => {
343 Ok(mpi::SecretKeyMaterial::ElGamal {
344 x: ProtectedMPI::parse(
345 "elgamal_secret_len", "elgamal_secret", php)?,
346 })
347 }
348
349 EdDSA => {
350 Ok(mpi::SecretKeyMaterial::EdDSA {
351 scalar: ProtectedMPI::parse(
352 "eddsa_secret_len", "eddsa_secret", php)?,
353 })
354 }
355
356 ECDSA => {
357 Ok(mpi::SecretKeyMaterial::ECDSA {
358 scalar: ProtectedMPI::parse(
359 "ecdsa_secret_len", "ecdsa_secret", php)?,
360 })
361 }
362
363 ECDH => {
364 Ok(mpi::SecretKeyMaterial::ECDH {
365 scalar: ProtectedMPI::parse(
366 "ecdh_secret_len", "ecdh_secret", php)?,
367 })
368 }
369
370 X25519 => {
371 let mut x: Protected = vec![0; 32].into();
372 php.parse_bytes_into("x25519_secret", &mut x)?;
373 Ok(mpi::SecretKeyMaterial::X25519 { x })
374 },
375
376 X448 => {
377 let mut x: Protected = vec![0; 56].into();
378 php.parse_bytes_into("x448_secret", &mut x)?;
379 Ok(mpi::SecretKeyMaterial::X448 { x })
380 },
381
382 Ed25519 => {
383 let mut x: Protected = vec![0; 32].into();
384 php.parse_bytes_into("ed25519_secret", &mut x)?;
385 Ok(mpi::SecretKeyMaterial::Ed25519 { x })
386 },
387
388 Ed448 => {
389 let mut x: Protected = vec![0; 57].into();
390 php.parse_bytes_into("ed448_secret", &mut x)?;
391 Ok(mpi::SecretKeyMaterial::Ed448 { x })
392 },
393
394 MLDSA65_Ed25519 => {
395 let mut eddsa: Protected = vec![0; 32].into();
396 php.parse_bytes_into("ed25519_secret", &mut eddsa)?;
397 let mut mldsa: Protected = vec![0; 32].into();
398 php.parse_bytes_into("mldsa_secret", &mut mldsa)?;
399 Ok(mpi::SecretKeyMaterial::MLDSA65_Ed25519 { eddsa, mldsa })
400 },
401
402 MLDSA87_Ed448 => {
403 let mut eddsa: Protected = vec![0; 57].into();
404 php.parse_bytes_into("ed448_secret", &mut eddsa)?;
405 let mut mldsa: Protected = vec![0; 32].into();
406 php.parse_bytes_into("mldsa_secret", &mut mldsa)?;
407 Ok(mpi::SecretKeyMaterial::MLDSA87_Ed448 { eddsa, mldsa })
408 },
409
410 SLHDSA128s => Ok(mpi::SecretKeyMaterial::SLHDSA128s {
411 secret: {
412 let mut a: Protected = vec![0; 64].into();
413 php.parse_bytes_into("secret", &mut a[..])?;
414 a
415 },
416 }),
417
418 SLHDSA128f => Ok(mpi::SecretKeyMaterial::SLHDSA128f {
419 secret: {
420 let mut a: Protected = vec![0; 64].into();
421 php.parse_bytes_into("secret", &mut a[..])?;
422 a
423 },
424 }),
425
426 SLHDSA256s => Ok(mpi::SecretKeyMaterial::SLHDSA256s {
427 secret: {
428 let mut a: Protected = vec![0; 128].into();
429 php.parse_bytes_into("secret", &mut a[..])?;
430 a
431 },
432 }),
433
434 MLKEM768_X25519 => {
435 let mut ecdh: Protected = vec![0; 32].into();
436 php.parse_bytes_into("x25519_secret", &mut ecdh)?;
437 let mut mlkem: Protected = vec![0; 64].into();
438 php.parse_bytes_into("mlkem_secret", &mut mlkem)?;
439 Ok(mpi::SecretKeyMaterial::MLKEM768_X25519 { ecdh, mlkem })
440 },
441
442 MLKEM1024_X448 => {
443 let mut ecdh: Protected = vec![0; 56].into();
444 php.parse_bytes_into("x448_secret", &mut ecdh)?;
445 let mut mlkem: Protected = vec![0; 64].into();
446 php.parse_bytes_into("mlkem_secret", &mut mlkem)?;
447 Ok(mpi::SecretKeyMaterial::MLKEM1024_X448 { ecdh, mlkem })
448 },
449
450 Unknown(_) | Private(_) => {
451 let mut mpis = Vec::new();
452 while let Ok(mpi) = ProtectedMPI::parse("unknown_len",
453 "unknown", php) {
454 mpis.push(mpi);
455 }
456 let rest = php.parse_bytes_eof("rest")?;
457
458 Ok(mpi::SecretKeyMaterial::Unknown {
459 mpis: mpis.into_boxed_slice(),
460 rest: rest.into(),
461 })
462 }
463 };
464 let mpis = mpis?;
465
466 if let Some(checksum) = checksum {
467 let mpis_len = php.reader.total_out() - mpis_start;
472
473 let their_chksum = php.parse_bytes("checksum", checksum.len())?;
478
479 let total_out = php.reader.total_out();
481
482 php.reader.rewind();
484 php.reader.consume(mpis_start);
485 let data = &php.reader.data_consume_hard(mpis_len)?[..mpis_len];
486
487 let good = match checksum {
488 mpi::SecretKeyChecksum::SHA1 => {
489 let mut hsh = HashAlgorithm::SHA1.context().unwrap()
491 .for_digest();
492 hsh.update(data);
493 let mut our_chksum = [0u8; 20];
494 let _ = hsh.digest(&mut our_chksum);
495
496 our_chksum == their_chksum[..]
497 },
498
499 mpi::SecretKeyChecksum::Sum16 => {
500 let our_chksum = data.iter()
502 .fold(0u16, |acc, v| acc.wrapping_add(*v as u16))
503 .to_be_bytes();
504
505 our_chksum == their_chksum[..]
506 },
507 };
508
509 php.reader.consume(checksum.len());
512
513 debug_assert_eq!(total_out, php.reader.total_out());
515
516 if good {
517 Ok(mpis)
518 } else {
519 Err(Error::MalformedMPI("checksum wrong".to_string()).into())
520 }
521 } else {
522 Ok(mpis)
523 }
524 }
525}
526
527impl mpi::Ciphertext {
528 pub fn parse<R: Read + Send + Sync>(algo: PublicKeyAlgorithm, reader: R) -> Result<Self>
535 {
536 let bio = buffered_reader::Generic::with_cookie(
537 reader, None, Cookie::default());
538 let mut php = PacketHeaderParser::new_naked(bio.into_boxed());
539 Self::_parse(algo, &mut php)
540 }
541
542 pub(crate) fn _parse(
549 algo: PublicKeyAlgorithm,
550 php: &mut PacketHeaderParser<'_>)
551 -> Result<Self> {
552 use crate::PublicKeyAlgorithm::*;
553
554 #[allow(deprecated)]
555 match algo {
556 RSAEncryptSign | RSAEncrypt => {
557 let c = MPI::parse("rsa_ciphertxt_len", "rsa_ciphertxt",
558 php)?;
559
560 Ok(mpi::Ciphertext::RSA {
561 c,
562 })
563 }
564
565 ElGamalEncrypt | ElGamalEncryptSign => {
566 let e = MPI::parse("elgamal_e_len", "elgamal_e", php)?;
567 let c = MPI::parse("elgamal_c_len", "elgamal_c", php)?;
568
569 Ok(mpi::Ciphertext::ElGamal {
570 e,
571 c,
572 })
573 }
574
575 ECDH => {
576 let e = MPI::parse("ecdh_e_len", "ecdh_e", php)?;
577 let key_len = php.parse_u8("ecdh_esk_len")? as usize;
578 let key = Vec::from(&php.parse_bytes("ecdh_esk", key_len)?
579 [..key_len]);
580
581 Ok(mpi::Ciphertext::ECDH {
582 e, key: key.into_boxed_slice()
583 })
584 }
585
586 X25519 => {
587 let mut e = [0; 32];
588 php.parse_bytes_into("x25519_e", &mut e)?;
589 let key_len = php.parse_u8("x25519_esk_len")? as usize;
590 let key = Vec::from(&php.parse_bytes("x25519_esk", key_len)?
591 [..key_len]);
592 Ok(mpi::Ciphertext::X25519 { e: Box::new(e), key: key.into() })
593 },
594
595 X448 => {
596 let mut e = [0; 56];
597 php.parse_bytes_into("x448_e", &mut e)?;
598 let key_len = php.parse_u8("x448_esk_len")? as usize;
599 let key = Vec::from(&php.parse_bytes("x448_esk", key_len)?
600 [..key_len]);
601 Ok(mpi::Ciphertext::X448 { e: Box::new(e), key: key.into() })
602 },
603
604 MLKEM768_X25519 => {
605 let mut ecdh = Box::new([0; 32]);
606 php.parse_bytes_into("x25519_ciphertext", ecdh.as_mut())?;
607 let mut mlkem = Box::new([0; 1088]);
608 php.parse_bytes_into("mlkem768_ciphertext", mlkem.as_mut())?;
609 let esk_len = php.parse_u8("esk_len")? as usize;
610 let esk = Vec::from(&php.parse_bytes("esk", esk_len)?
611 [..esk_len]).into();
612 Ok(mpi::Ciphertext::MLKEM768_X25519 { ecdh, mlkem, esk })
613 },
614
615 MLKEM1024_X448 => {
616 let mut ecdh = Box::new([0; 56]);
617 php.parse_bytes_into("x448_ciphertext", ecdh.as_mut())?;
618 let mut mlkem = Box::new([0; 1568]);
619 php.parse_bytes_into("mlkem1024_ciphertext", mlkem.as_mut())?;
620 let esk_len = php.parse_u8("esk_len")? as usize;
621 let esk = Vec::from(&php.parse_bytes("esk", esk_len)?
622 [..esk_len]).into();
623 Ok(mpi::Ciphertext::MLKEM1024_X448 { ecdh, mlkem, esk })
624 },
625
626 Unknown(_) | Private(_) => {
627 let mut mpis = Vec::new();
628 while let Ok(mpi) = MPI::parse("unknown_len",
629 "unknown", php) {
630 mpis.push(mpi);
631 }
632 let rest = php.parse_bytes_eof("rest")?;
633
634 Ok(mpi::Ciphertext::Unknown {
635 mpis: mpis.into_boxed_slice(),
636 rest: rest.into_boxed_slice(),
637 })
638 }
639
640 RSASign | DSA | EdDSA | ECDSA | Ed25519 | Ed448
641 | MLDSA65_Ed25519 | MLDSA87_Ed448
642 | SLHDSA128s | SLHDSA128f | SLHDSA256s
643 => Err(Error::InvalidArgument(
644 format!("not an encryption algorithm: {:?}", algo)).into()),
645 }
646 }
647}
648
649impl mpi::Signature {
650 pub fn parse<R: Read + Send + Sync>(algo: PublicKeyAlgorithm, reader: R) -> Result<Self>
657 {
658 let bio = buffered_reader::Generic::with_cookie(
659 reader, None, Cookie::default());
660 let mut php = PacketHeaderParser::new_naked(bio.into_boxed());
661 Self::_parse(algo, &mut php)
662 }
663
664 pub(crate) fn _parse(
671 algo: PublicKeyAlgorithm,
672 php: &mut PacketHeaderParser<'_>)
673 -> Result<Self> {
674 use crate::PublicKeyAlgorithm::*;
675
676 #[allow(deprecated)]
677 match algo {
678 RSAEncryptSign | RSASign => {
679 let s = MPI::parse("rsa_signature_len", "rsa_signature", php)?;
680
681 Ok(mpi::Signature::RSA {
682 s,
683 })
684 }
685
686 DSA => {
687 let r = MPI::parse("dsa_sig_r_len", "dsa_sig_r",
688 php)?;
689 let s = MPI::parse("dsa_sig_s_len", "dsa_sig_s",
690 php)?;
691
692 Ok(mpi::Signature::DSA {
693 r,
694 s,
695 })
696 }
697
698 ElGamalEncryptSign => {
699 let r = MPI::parse("elgamal_sig_r_len",
700 "elgamal_sig_r", php)?;
701 let s = MPI::parse("elgamal_sig_s_len",
702 "elgamal_sig_s", php)?;
703
704 Ok(mpi::Signature::ElGamal {
705 r,
706 s,
707 })
708 }
709
710 EdDSA => {
711 let r = MPI::parse("eddsa_sig_r_len", "eddsa_sig_r",
712 php)?;
713 let s = MPI::parse("eddsa_sig_s_len", "eddsa_sig_s",
714 php)?;
715
716 Ok(mpi::Signature::EdDSA {
717 r,
718 s,
719 })
720 }
721
722 ECDSA => {
723 let r = MPI::parse("ecdsa_sig_r_len", "ecdsa_sig_r",
724 php)?;
725 let s = MPI::parse("ecdsa_sig_s_len", "ecdsa_sig_s",
726 php)?;
727
728 Ok(mpi::Signature::ECDSA {
729 r,
730 s,
731 })
732 }
733
734 Ed25519 => {
735 let mut s = [0; 64];
736 php.parse_bytes_into("ed25519_sig", &mut s)?;
737 Ok(mpi::Signature::Ed25519 { s: Box::new(s) })
738 },
739
740 Ed448 => {
741 let mut s = [0; 114];
742 php.parse_bytes_into("ed448_sig", &mut s)?;
743 Ok(mpi::Signature::Ed448 { s: Box::new(s) })
744 },
745
746 MLDSA65_Ed25519 => Ok(mpi::Signature::MLDSA65_Ed25519 {
747 eddsa: {
748 let mut s = Box::new([0; 64]);
749 php.parse_bytes_into("ed25519_sig", &mut s[..])?;
750 s
751 },
752 mldsa: {
753 let mut s = Box::new([0; 3309]);
754 php.parse_bytes_into("mldsa65_sig", &mut s[..])?;
755 s
756 },
757 }),
758
759 MLDSA87_Ed448 => Ok(mpi::Signature::MLDSA87_Ed448 {
760 eddsa: {
761 let mut s = Box::new([0; 114]);
762 php.parse_bytes_into("ed448_sig", &mut s[..])?;
763 s
764 },
765 mldsa: {
766 let mut s = Box::new([0; 4627]);
767 php.parse_bytes_into("mldsa87_sig", &mut s[..])?;
768 s
769 },
770 }),
771
772 SLHDSA128s => Ok(mpi::Signature::SLHDSA128s {
773 sig: {
774 let mut a = Box::new([0; 7856]);
775 php.parse_bytes_into("sig", &mut a[..])?;
776 a
777 },
778 }),
779
780 SLHDSA128f => Ok(mpi::Signature::SLHDSA128f {
781 sig: {
782 let mut a = Box::new([0; 17088]);
783 php.parse_bytes_into("sig", &mut a[..])?;
784 a
785 },
786 }),
787
788 SLHDSA256s => Ok(mpi::Signature::SLHDSA256s {
789 sig: {
790 let mut a = Box::new([0; 29792]);
791 php.parse_bytes_into("sig", &mut a[..])?;
792 a
793 },
794 }),
795
796 Unknown(_) | Private(_) => {
797 let mut mpis = Vec::new();
798 while let Ok(mpi) = MPI::parse("unknown_len",
799 "unknown", php) {
800 mpis.push(mpi);
801 }
802 let rest = php.parse_bytes_eof("rest")?;
803
804 Ok(mpi::Signature::Unknown {
805 mpis: mpis.into_boxed_slice(),
806 rest: rest.into_boxed_slice(),
807 })
808 }
809
810 RSAEncrypt | ElGamalEncrypt | ECDH | X25519 | X448
811 | MLKEM768_X25519
812 | MLKEM1024_X448
813 => Err(Error::InvalidArgument(
814 format!("not a signature algorithm: {:?}", algo)).into()),
815 }
816 }
817}
818
819#[test]
820fn mpis_parse_test() {
821 use std::io::Cursor;
822 use super::Parse;
823 use crate::PublicKeyAlgorithm::*;
824 use crate::serialize::MarshalInto;
825
826 {
828 let buf = Cursor::new("\x00\x01\x01\x00\x02\x02");
829 let mpis = mpi::PublicKey::parse(RSAEncryptSign, buf).unwrap();
830
831 match &mpis {
833 &mpi::PublicKey::RSA{ ref n, ref e } => {
834 assert_eq!(n.bits(), 1);
835 assert_eq!(n.value()[0], 1);
836 assert_eq!(n.value().len(), 1);
837 assert_eq!(e.bits(), 2);
838 assert_eq!(e.value()[0], 2);
839 assert_eq!(e.value().len(), 1);
840 }
841
842 _ => assert!(false),
843 }
844 }
845
846 {
848 let buf = Cursor::new("\x00\x02\x02");
849 let mpis = mpi::Ciphertext::parse(RSAEncryptSign, buf).unwrap();
850
851 assert_eq!(mpis.serialized_len(), 3);
852 }
853
854 let mpi = MPI::from_bytes(b"\x00\x09\x01\xff").unwrap();
856 assert_eq!(mpi.value().len(), 2);
857 assert_eq!(mpi.bits(), 9);
858 assert_eq!(mpi.value()[0], 1);
859 assert_eq!(mpi.value()[1], 0xff);
860
861 assert!(MPI::from_bytes(b"\x00\x02\x01").is_err());
864}