1use std::{
30 collections::{BTreeMap, BTreeSet, HashMap},
31 io::{self, Cursor, Write},
32 time::SystemTime,
33};
34
35use sequoia_openpgp as openpgp;
36use openpgp::{
37 armor,
38 cert::prelude::*,
39 parse::{
40 Cookie,
41 Parse,
42 PacketParser,
43 PacketParserResult,
44 buffered_reader::*,
45 stream::*,
46 },
47 packet::prelude::*,
48 policy::{
49 NullPolicy,
50 StandardPolicy,
51 },
52 serialize::{
53 Serialize,
54 stream::{*, padding::Padder},
55 },
56 types::*,
57};
58
59use openpgp::{
60 Cert,
61 KeyID,
62};
63use openpgp::crypto::{self, SessionKey};
64use openpgp::packet::{key, Key, PKESK, SKESK};
65use openpgp::policy::Policy;
66
67pub use sop::{self, SOP};
69
70use sop::{
71 *,
72 errors::*,
73 ops::{
74 ArmorLabel,
75 EncryptAs,
76 InlineSignAs,
77 SignAs,
78 SignatureMode,
79 Verification,
80 },
81 plumbing::PasswordsAreHumanReadable,
82};
83
84#[macro_use]
85mod macros;
86mod version;
87
88pub struct Certs<'s> {
90 sop: &'s SQOP<'s>,
91 certs: Vec<openpgp::Cert>,
92 source_name: Option<String>,
93}
94
95impl<'s> sop::plumbing::SopRef<'s, SQOP<'s>> for Certs<'s> {
96 fn sop(&self) -> &'s SQOP<'s> {
97 self.sop
98 }
99}
100
101impl<'s> sop::Load<'s, SQOP<'s>> for Certs<'s> {
102 fn from_reader(sop: &'s SQOP, source: &mut (dyn io::Read + Send + Sync),
103 source_name: Option<String>)
104 -> Result<Self>
105 where
106 Self: Sized,
107 {
108 let sop_error = |e| sop.sop_error(e);
109
110 Ok(Certs {
111 sop,
112 certs: CertParser::from_reader(source).map_err(sop_error)?
113 .collect::<openpgp::Result<Vec<openpgp::Cert>>>()
114 .map_err(sop_error)?,
115 source_name,
116 })
117 }
118
119 fn source_name(&self) -> Option<&str> {
120 self.source_name.as_ref().map(|s| s.as_str())
121 }
122}
123
124impl sop::Save for Certs<'_> {
125 fn to_writer(&self, armored: bool, sink: &mut (dyn io::Write + Send + Sync))
126 -> Result<()>
127 {
128 let sop_error = |e| self.sop.sop_error(e);
129
130 if self.certs.len() == 1 {
131 let cert = &self.certs[0];
132 if armored {
133 cert.armored().serialize(sink).map_err(sop_error)?;
134 } else {
135 cert.serialize(sink).map_err(sop_error)?;
136 }
137 } else {
138 if armored {
139 let mut armorer =
140 armor::Writer::new(sink, armor::Kind::PublicKey)?;
141 for cert in &self.certs {
142 cert.serialize(&mut armorer).map_err(sop_error)?;
143 }
144 armorer.finalize()?;
145 } else {
146 for cert in &self.certs {
147 cert.serialize(sink).map_err(sop_error)?;
148 }
149 }
150 }
151 Ok(())
152 }
153}
154
155pub struct Keys<'s> {
157 sop: &'s SQOP<'s>,
158 keys: Vec<openpgp::Cert>,
159 source_name: Option<String>,
160}
161
162impl<'s> sop::plumbing::SopRef<'s, SQOP<'s>> for Keys<'s> {
163 fn sop(&self) -> &'s SQOP<'s> {
164 self.sop
165 }
166}
167
168impl<'s> sop::Load<'s, SQOP<'s>> for Keys<'s> {
169 fn from_reader(sop: &'s SQOP, source: &mut (dyn io::Read + Send + Sync),
170 source_name: Option<String>)
171 -> Result<Self>
172 where
173 Self: Sized,
174 {
175 let sop_error = |e| sop.sop_error(e);
176
177 Ok(Keys {
178 sop,
179 keys: CertParser::from_reader(source).map_err(sop_error)?
180 .collect::<openpgp::Result<Vec<openpgp::Cert>>>()
181 .map_err(sop_error)?,
182 source_name,
183 })
184 }
185
186 fn source_name(&self) -> Option<&str> {
187 self.source_name.as_ref().map(|s| s.as_str())
188 }
189}
190
191impl sop::Save for Keys<'_> {
192 fn to_writer(&self, armored: bool, sink: &mut (dyn io::Write + Send + Sync))
193 -> Result<()>
194 {
195 let sop_error = |e| self.sop.sop_error(e);
196
197 if self.keys.len() == 1 {
198 let key = &self.keys[0];
199 if armored {
200 key.as_tsk().armored().serialize(sink).map_err(sop_error)?;
201 } else {
202 key.as_tsk().serialize(sink).map_err(sop_error)?;
203 }
204 } else {
205 if armored {
206 let mut armorer =
207 armor::Writer::new(sink, armor::Kind::SecretKey)?;
208 for key in &self.keys {
209 key.as_tsk().serialize(&mut armorer).map_err(sop_error)?;
210 }
211 armorer.finalize()?;
212 } else {
213 for key in &self.keys {
214 key.as_tsk().serialize(sink).map_err(sop_error)?;
215 }
216 }
217 }
218 Ok(())
219 }
220}
221
222pub struct Sigs<'s> {
224 sop: &'s SQOP<'s>,
225 data: Vec<u8>,
226 source_name: Option<String>,
227}
228
229impl<'s> sop::plumbing::SopRef<'s, SQOP<'s>> for Sigs<'s> {
230 fn sop(&self) -> &'s SQOP<'s> {
231 self.sop
232 }
233}
234
235impl<'s> sop::Load<'s, SQOP<'s>> for Sigs<'s> {
236 fn from_reader(sop: &'s SQOP, source: &mut (dyn io::Read + Send + Sync),
237 source_name: Option<String>)
238 -> Result<Self>
239 where
240 Self: Sized,
241 {
242 let mut data = vec![];
243 source.read_to_end(&mut data)?;
244 Ok(Sigs {
245 sop,
246 data,
247 source_name,
248 })
249 }
250
251 fn source_name(&self) -> Option<&str> {
252 self.source_name.as_ref().map(|s| s.as_str())
253 }
254}
255
256impl sop::Save for Sigs<'_> {
257 fn to_writer(&self, armored: bool, sink: &mut (dyn io::Write + Send + Sync))
258 -> Result<()>
259 {
260 if armored && self.data.starts_with(
262 b"-----BEGIN PGP PUBLIC KEY BLOCK-----")
263 {
264 sink.write_all(&self.data)?;
265 return Ok(());
266 }
267
268 if armored {
269 self.sop.armor()?
270 .data(&mut Cursor::new(&self.data))?
271 .to_writer(sink)?;
272 } else {
273 self.sop.dearmor()?
274 .data(&mut Cursor::new(&self.data))?
275 .to_writer(sink)?;
276 }
277 Ok(())
278 }
279}
280
281pub struct SQOP<'s> {
285 policy: &'s dyn openpgp::policy::Policy,
286 debug: bool,
287}
288
289impl Default for SQOP<'_> {
290 fn default() -> Self {
291 const P: &StandardPolicy = &StandardPolicy::new();
292 Self::with_policy(P)
293 }
294}
295
296impl<'s> SQOP<'s> {
297 pub fn with_policy(policy: &'s dyn Policy) -> Self {
304 SQOP {
305 policy,
306 debug: false,
307 }
308 }
309
310 fn sop_error(&self, e: anyhow::Error) -> Error {
313 sop_error(self, e)
314 }
315}
316
317impl<'s> sop::SOP<'s> for SQOP<'s> {
318 type Keys = Keys<'s>;
319 type Certs = Certs<'s>;
320 type Sigs = Sigs<'s>;
321
322 fn debug(&mut self, enable: bool) {
323 self.debug = enable;
324 }
325 fn version(&self) -> Result<Box<dyn sop::ops::Version>> {
326 Ok(Box::new(version::Version::default()))
327 }
328 fn sopv_version(&'s self) -> Result<&'static str> {
329 Ok("1.0")
330 }
331 fn generate_key(&'s self)
332 -> Result<Box<dyn sop::ops::GenerateKey<SQOP, Keys> + 's>>
333 {
334 GenerateKey::new(self)
335 }
336 fn change_key_password(&'s self)
337 -> Result<Box<dyn sop::ops::ChangeKeyPassword<SQOP, Keys> + 's>>
338 {
339 ChangeKeyPassword::new(self)
340 }
341 fn revoke_key(&'s self)
342 -> Result<Box<dyn sop::ops::RevokeKey<SQOP<'s>, Certs, Keys> + 's>>
343 {
344 RevokeKey::new(self)
345 }
346 fn extract_cert(&'s self)
347 -> Result<Box<dyn sop::ops::ExtractCert<SQOP, Certs, Keys> + 's>>
348 {
349 ExtractCert::new(self)
350 }
351 fn update_key(&'s self)
352 -> Result<Box<dyn sop::ops::UpdateKey<Self, Self::Certs, Self::Keys> + 's>>
353 {
354 Err(Error::NotImplemented)
355 }
356 fn merge_certs(&'s self)
357 -> Result<Box<dyn sop::ops::MergeCerts<Self, Self::Certs> + 's>>
358 {
359 MergeCerts::new(self)
360 }
361 fn certify_userid(&'s self)
362 -> Result<Box<dyn sop::ops::CertifyUserID<Self, Self::Certs, Self::Keys> + 's>>
363 {
364 CertifyUserID::new(self)
365 }
366 fn validate_userid(&'s self)
367 -> Result<Box<dyn sop::ops::ValidateUserID<Self, Self::Certs> + 's>>
368 {
369 ValidateUserID::new(self)
370 }
371 fn sign(&'s self)
372 -> Result<Box<dyn sop::ops::Sign<SQOP, Keys, Sigs> + 's>>
373 {
374 Sign::new(self)
375 }
376 fn verify(&'s self)
377 -> Result<Box<dyn sop::ops::Verify<SQOP, Certs, Sigs> + 's>>
378 {
379 Verify::new(self)
380 }
381 fn encrypt(&'s self)
382 -> Result<Box<dyn sop::ops::Encrypt<SQOP, Certs, Keys> + 's>> {
383 Encrypt::new(self)
384 }
385 fn decrypt(&'s self)
386 -> Result<Box<dyn sop::ops::Decrypt<SQOP, Certs, Keys> + 's>> {
387 Decrypt::new(self)
388 }
389 fn armor(&'s self) -> Result<Box<dyn sop::ops::Armor + 's>> {
390 Armor::new(self)
391 }
392 fn dearmor(&'s self) -> Result<Box<dyn sop::ops::Dearmor + 's>> {
393 Dearmor::new(self)
394 }
395 fn inline_detach(&'s self)
396 -> Result<Box<dyn sop::ops::InlineDetach<Sigs> + 's>>
397 {
398 InlineDetach::new(self)
399 }
400 fn inline_verify(&'s self)
401 -> Result<Box<dyn sop::ops::InlineVerify<SQOP, Certs> + 's>>
402 {
403 InlineVerify::new(self)
404 }
405 fn inline_sign(&'s self)
406 -> Result<Box<dyn sop::ops::InlineSign<SQOP, Keys> + 's>>
407 {
408 InlineSign::new(self)
409 }
410}
411
412struct GenerateKey<'s> {
413 #[allow(dead_code)]
414 sqop: &'s SQOP<'s>,
415 profile: &'static str,
416 signing_only: bool,
417 with_key_password: Option<Password>,
418 userids: Vec<String>,
419}
420
421impl<'s> GenerateKey<'s> {
422 const PROFILE_RFC9580: &'static str = "rfc9580";
423 const PROFILE_EDDSA: &'static str = "draft-koch-eddsa-for-openpgp-00";
424 const PROFILE_RFC4880: &'static str = "rfc4880";
425 const PROFILE_RFC9980: &'static str = "rfc9980";
426 const PROFILES: &'static [(&'static str, &'static str)] = &[
427 (Self::PROFILE_RFC9580, "use Ed25519/X25519"),
428 (Self::PROFILE_EDDSA, "use EdDSA & ECDH over Cv25519"),
429 (Self::PROFILE_RFC4880, "use RSA with 3072 bit keys"),
430 (Self::PROFILE_RFC9980, "use MLDSA65+Ed25519 & MLKEM768+X25519"),
431 ];
432
433 fn normalize_profile(profile: &str) -> Result<&'static str> {
434 match profile {
435 Self::PROFILE_RFC9580 => Ok(Self::PROFILE_RFC9580),
436 Self::PROFILE_EDDSA => Ok(Self::PROFILE_EDDSA),
437 Self::PROFILE_RFC4880 => Ok(Self::PROFILE_RFC4880),
438 Self::PROFILE_RFC9980 => Ok(Self::PROFILE_RFC9980),
439
440 "default" => Ok(match openpgp::Profile::default() {
442 openpgp::Profile::RFC4880 => Self::PROFILE_EDDSA,
443 openpgp::Profile::RFC9580 => Self::PROFILE_RFC9580,
444 _ => Self::PROFILE_RFC9580,
445 }),
446 "security" => Ok(Self::PROFILE_RFC9980),
447 "performance" => Ok(Self::PROFILE_RFC9580),
448 "compatibility" => Ok(Self::PROFILE_RFC4880),
449
450 _ => Err(Error::UnsupportedProfile),
451 }
452 }
453
454 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::GenerateKey<'s, SQOP<'s>, Keys<'s>> + 's>> {
455 Ok(Box::new(GenerateKey {
456 sqop,
457 profile: Self::normalize_profile("default")?,
458 signing_only: false,
459 with_key_password: Default::default(),
460 userids: Default::default(),
461 }))
462 }
463}
464
465impl<'s> sop::ops::GenerateKey<'s, SQOP<'s>, Keys<'s>> for GenerateKey<'s> {
466 fn list_profiles(&self) -> Vec<(String, String)> {
467 list_profiles(Self::PROFILES, &Self::normalize_profile)
468 }
469
470 fn profile(mut self: Box<Self>, profile: &str)
471 -> Result<Box<dyn sop::ops::GenerateKey<'s, SQOP<'s>, Keys<'s>> + 's>> {
472 self.profile = Self::normalize_profile(profile)?;
473 Ok(self)
474 }
475
476 fn signing_only(mut self: Box<Self>) -> Box<dyn sop::ops::GenerateKey<'s, SQOP<'s>, Keys<'s>> + 's> {
477 self.signing_only = true;
478 self
479 }
480
481 fn with_key_password(mut self: Box<Self>, password: Password)
482 -> Result<Box<dyn sop::ops::GenerateKey<'s, SQOP<'s>, Keys<'s>> + 's>> {
483 self.with_key_password = Some(password);
484 Ok(self)
485 }
486
487 fn userid(mut self: Box<Self>, userid: &str)
488 -> Box<dyn sop::ops::GenerateKey<'s, SQOP<'s>, Keys<'s>> + 's> {
489 self.userids.push(userid.into());
490 self
491 }
492
493 fn generate(self: Box<Self>) -> Result<Keys<'s>> {
494 let sop_error = |e| self.sqop.sop_error(e);
495
496 let mut builder = CertBuilder::new();
497 builder = builder.add_signing_subkey();
498 if ! self.signing_only {
499 builder = builder.add_subkey(
500 KeyFlags::empty()
501 .set_storage_encryption()
502 .set_transport_encryption(),
503 None,
504 None);
505 }
506
507 builder = builder.set_profile(match self.profile {
508 Self::PROFILE_RFC9580 => openpgp::Profile::RFC9580,
509 Self::PROFILE_EDDSA => openpgp::Profile::RFC4880,
510 Self::PROFILE_RFC4880 => openpgp::Profile::RFC4880,
511 Self::PROFILE_RFC9980 => openpgp::Profile::RFC9580,
512 _ => return Err(Error::UnsupportedProfile),
513 }).map_err(sop_error)?;
514
515 builder = builder.set_cipher_suite(match self.profile {
516 Self::PROFILE_RFC9580 => CipherSuite::Cv25519,
517 Self::PROFILE_EDDSA => CipherSuite::Cv25519,
518 Self::PROFILE_RFC4880 => CipherSuite::RSA3k,
519 Self::PROFILE_RFC9980 => CipherSuite::MLDSA65_Ed25519,
520 _ => return Err(Error::UnsupportedProfile),
521 });
522
523 for u in self.userids {
524 builder = builder.add_userid(u);
525 }
526 if let Some(p) = self.with_key_password {
527 builder = builder.set_password(Some(p.normalized().into()));
528 }
529 let (key, _) = builder.generate().map_err(sop_error)?;
530
531 Ok(Keys {
532 sop: self.sqop,
533 keys: vec![key],
534 source_name: None,
535 })
536 }
537}
538
539struct ChangeKeyPassword<'s> {
540 #[allow(dead_code)]
541 sqop: &'s SQOP<'s>,
542 new_password: Option<openpgp::crypto::Password>,
543 old_password: Vec<openpgp::crypto::Password>,
544}
545
546impl<'s> ChangeKeyPassword<'s> {
547 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::ChangeKeyPassword<'s, SQOP<'s>, Keys<'s>> + 's>> {
548 Ok(Box::new(ChangeKeyPassword {
549 sqop,
550 new_password: None,
551 old_password: vec![],
552 }))
553 }
554}
555
556impl<'s> sop::ops::ChangeKeyPassword<'s, SQOP<'s>, Keys<'s>> for ChangeKeyPassword<'s> {
557 fn new_key_password(mut self: Box<Self>, password: Password)
558 -> Result<Box<dyn sop::ops::ChangeKeyPassword<'s, SQOP<'s>, Keys<'s>> + 's>> {
559 self.new_password = Some(password.normalized().into());
560 Ok(self)
561 }
562
563 fn old_key_password(mut self: Box<Self>, password: Password)
564 -> Result<Box<dyn sop::ops::ChangeKeyPassword<'s, SQOP<'s>, Keys<'s>> + 's>> {
565 for p in password.variants() {
566 self.old_password.push(p.into());
567 }
568 Ok(self)
569 }
570
571 fn keys(self: Box<Self>, keys: &Keys) -> Result<Keys<'s>> {
572 let sop_error = |e| self.sqop.sop_error(e);
573
574 let mut result = vec![];
575
576 for key in keys.keys.clone() {
577 let fp = key.fingerprint();
578
579 let mut key_packets =
582 key.keys().unencrypted_secret()
583 .map(|ka| ka.key().clone())
584 .collect::<Vec<_>>();
585
586 for locked_key in key.keys().secret()
588 .filter(|ka| ka.key().secret().is_encrypted())
589 .map(|ka| ka.key())
590 {
591 let mut unlocked = false;
592
593 for p in &self.old_password {
594 if let Ok(k) = locked_key.clone().decrypt_secret(p) {
595 key_packets.push(k);
596 unlocked = true;
597 break;
598 }
599 }
600
601 if ! unlocked {
602 return Err(Error::KeyIsProtected);
603 }
604 }
605
606 if let Some(p) = &self.new_password {
608 for k in std::mem::take(&mut key_packets) {
609 key_packets.push(k.encrypt_secret(&p).map_err(sop_error)?);
610 }
611 }
612
613 let (key, _changed) =
615 key.insert_packets(
616 key_packets.into_iter().map(|k| -> openpgp::Packet {
617 if k.fingerprint() == fp {
618 k.role_into_primary().into()
619 } else {
620 k.role_into_subordinate().into()
621 }
622 }))
623 .map_err(sop_error)?;
624
625 result.push(key);
626 }
627
628 Ok(Keys {
629 sop: self.sqop,
630 keys: result,
631 source_name: None,
632 })
633 }
634}
635
636struct RevokeKey<'s> {
637 #[allow(dead_code)]
638 sqop: &'s SQOP<'s>,
639 key_password: Vec<openpgp::crypto::Password>,
640}
641
642impl<'s> RevokeKey<'s> {
643 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::RevokeKey<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
644 Ok(Box::new(RevokeKey {
645 sqop,
646 key_password: vec![],
647 }))
648 }
649}
650
651impl<'s> sop::ops::RevokeKey<'s, SQOP<'s>, Certs<'s>, Keys<'s>> for RevokeKey<'s> {
652 fn with_key_password(mut self: Box<Self>, password: Password)
653 -> Result<Box<dyn sop::ops::RevokeKey<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
654 for p in password.variants() {
655 self.key_password.push(p.into());
656 }
657 Ok(self)
658 }
659
660 fn keys(self: Box<Self>, keys: &Keys) -> Result<Certs<'s>> {
661 let sop_error = |e| self.sqop.sop_error(e);
662
663 let mut results = vec![];
664 for key in &keys.keys {
665 let mut primary = match key.primary_key().key().parts_as_secret() {
667 Ok(p) => p.clone(),
668 Err(_) => return Err(Error::BadData),
669 };
670
671 if primary.secret().is_encrypted() {
673 let mut unlocked = false;
674
675 for p in &self.key_password {
676 if let Ok(k) = primary.clone().decrypt_secret(p) {
677 primary = k;
678 unlocked = true;
679 break;
680 }
681 }
682
683 if ! unlocked {
684 return Err(Error::KeyIsProtected);
685 }
686 }
687 let mut signer = primary.into_keypair().map_err(sop_error)?;
688
689 let revocation = key.revoke(&mut signer,
691 ReasonForRevocation::Unspecified,
692 b"unspecified").map_err(sop_error)?;
693 results.push(key.clone().insert_packets(
694 std::iter::once(openpgp::Packet::from(revocation)))
695 .map(|(cert, _changed)| cert)
696 .map_err(sop_error)?
697 .strip_secret_key_material());
698 }
699
700 Ok(Certs {
701 sop: self.sqop,
702 certs: results,
703 source_name: None,
704 })
705 }
706}
707
708struct ExtractCert<'s> {
709 #[allow(dead_code)]
710 sqop: &'s SQOP<'s>,
711}
712
713impl<'s> ExtractCert<'s> {
714 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::ExtractCert<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
715 Ok(Box::new(ExtractCert {
716 sqop,
717 }))
718 }
719}
720
721impl<'s> sop::ops::ExtractCert<'s, SQOP<'s>, Certs<'s>, Keys<'s>> for ExtractCert<'s> {
722 fn keys(self: Box<Self>, keys: &Keys) -> Result<Certs<'s>> {
723 Ok(Certs {
724 sop: self.sqop,
725 certs: keys.keys.iter()
726 .map(|c| c.clone().strip_secret_key_material())
727 .collect::<Vec<_>>(),
728 source_name: None,
729 })
730 }
731}
732
733struct MergeCerts<'s> {
734 #[allow(dead_code)]
735 sqop: &'s SQOP<'s>,
736 updates: BTreeMap<openpgp::Fingerprint, openpgp::Cert>,
737}
738
739impl<'s> MergeCerts<'s> {
740 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::MergeCerts<'s, SQOP<'s>, Certs<'s>> + 's>> {
741 Ok(Box::new(MergeCerts {
742 sqop,
743 updates: Default::default(),
744 }))
745 }
746
747 fn merge_internal(&mut self, updates: &Certs) -> Result<()> {
748 let sop_error = |e| self.sqop.sop_error(e);
749
750 use std::collections::btree_map::Entry;
751
752 for cert in updates.certs.iter().cloned() {
753 match self.updates.entry(cert.fingerprint()) {
754 Entry::Occupied(e) => {
755 let e = e.into_mut();
756 *e = e.clone().merge_public(cert).map_err(sop_error)?;
757 },
758 Entry::Vacant(e) => {
759 e.insert(cert);
760 },
761 }
762 }
763
764 Ok(())
765 }
766}
767
768impl<'s> sop::ops::MergeCerts<'s, SQOP<'s>, Certs<'s>> for MergeCerts<'s> {
769 fn merge_updates(mut self: Box<Self>, updates: &Certs)
770 -> Result<Box<dyn sop::ops::MergeCerts<'s, SQOP<'s>, Certs<'s>> + 's>> {
771 self.merge_internal(updates)?;
772 Ok(self)
773 }
774
775 fn merge(mut self: Box<Self>, certs: &Certs) -> Result<Certs<'s>> {
776 let fps: BTreeSet<_> =
777 certs.certs.iter().map(openpgp::Cert::fingerprint).collect();
778 self.merge_internal(certs)?;
779
780 Ok(Certs {
781 sop: self.sqop,
782 certs: fps.iter()
783 .map(|fp| self.updates.get(fp).expect("have ingested certs").clone())
784 .collect(),
785 source_name: None,
786 })
787 }
788}
789
790struct CertifyUserID<'s> {
791 #[allow(dead_code)]
792 sqop: &'s SQOP<'s>,
793 userids: Vec<String>,
794 with_key_password: Vec<Password>,
795 no_require_self_sig: bool,
796 certifiers: Vec<openpgp::Cert>,
797}
798
799impl<'s> CertifyUserID<'s> {
800 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::CertifyUserID<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
801 Ok(Box::new(CertifyUserID {
802 sqop,
803 userids: Default::default(),
804 with_key_password: Default::default(),
805 no_require_self_sig: false,
806 certifiers: Default::default(),
807 }))
808 }
809}
810
811impl<'s> sop::ops::CertifyUserID<'s, SQOP<'s>, Certs<'s>, Keys<'s>> for CertifyUserID<'s> {
812 fn userid(mut self: Box<Self>, userid: String)
813 -> Box<dyn sop::ops::CertifyUserID<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's> {
814 self.userids.push(userid);
815 self
816 }
817
818 fn with_key_password(mut self: Box<Self>, password: Password)
819 -> Result<Box<dyn sop::ops::CertifyUserID<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
820 self.with_key_password.push(password);
821 Ok(self)
822 }
823
824 fn no_require_self_sig(mut self: Box<Self>)
825 -> Box<dyn sop::ops::CertifyUserID<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's> {
826 self.no_require_self_sig = true;
827 self
828 }
829
830 fn keys(mut self: Box<Self>, keys: &Keys)
831 -> Result<Box<dyn sop::ops::CertifyUserID<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
832 for key in &keys.keys {
833 self.certifiers.push(key.clone());
834 }
835 Ok(self)
836 }
837
838 fn certify(self: Box<Self>, certs: &Certs)-> Result<Certs<'s>> {
839 let sop_error = |e| self.sqop.sop_error(e);
840
841 if self.certifiers.is_empty() {
842 return Err(Error::MissingArg);
843 }
844
845 let mut certifiers = Vec::with_capacity(self.certifiers.len());
846 for cert in &self.certifiers {
847 let vcert =
848 cert.with_policy(self.sqop.policy, None)
849 .map_err(|e| {
851 sop_error(e);
852 Error::KeyCannotSign
853 })?;
854
855 if let RevocationStatus::Revoked(_) = vcert.revocation_status() {
856 return Err(Error::KeyCannotSign);
858 }
859
860 let mut one = false;
861 for ka in vcert.keys()
862 .supported()
863 .secret()
864 .alive()
865 .revoked(false)
866 .for_certification()
867 {
868 let mut key = ka.key().clone();
869 if key.secret().is_encrypted() {
870 for p in self.with_key_password.iter()
871 .flat_map(|p| p.variants())
872 {
873 if key.secret_mut()
874 .decrypt_in_place(ka.key(), &p.into()).is_ok()
875 {
876 break;
877 }
878 }
879 }
880 if ! key.secret().is_encrypted() {
881 one = true;
882 certifiers.push(key.into_keypair().map_err(sop_error)?);
884 break;
885 }
886 }
887
888 if ! one {
889 return Err(Error::KeyIsProtected);
890 }
891 }
892
893 let mut outputs = Vec::new();
894 for cert in &certs.certs {
895 let mut acc = Vec::<openpgp::Packet>::new();
896
897 for new_userid in &self.userids {
898 if ! self.no_require_self_sig
899 && ! cert.userids().any(|u| u.userid().value() == new_userid.as_bytes())
900 {
901 return Err(Error::UnspecifiedFailure);
903 }
904
905 let uid = openpgp::packet::UserID::from(new_userid.as_str());
906 acc.push(uid.clone().into());
907 for certifier in &mut certifiers {
908 let sig = uid.bind(certifier, cert,
909 SignatureBuilder::new(
910 SignatureType::PositiveCertification))
911 .map_err(sop_error)?;
912 acc.push(sig.into());
913 }
914 }
915
916 outputs.push(cert.clone().insert_packets(acc)
917 .map_err(sop_error)?.0);
918 }
919
920 Ok(Certs {
921 sop: self.sqop,
922 certs: outputs,
923 source_name: None,
924 })
925 }
926}
927
928struct ValidateUserID<'s> {
929 #[allow(dead_code)]
930 sqop: &'s SQOP<'s>,
931 trust_roots: Vec<openpgp::Cert>,
932 target_certs: Vec<openpgp::Cert>,
933 validate_at: Option<SystemTime>,
934}
935
936impl<'s> ValidateUserID<'s> {
937 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::ValidateUserID<'s, SQOP<'s>, Certs<'s>> + 's>> {
938 Ok(Box::new(ValidateUserID {
939 sqop,
940 trust_roots: Default::default(),
941 target_certs: Default::default(),
942 validate_at: Default::default(),
943 }))
944 }
945
946 fn authenticate(&self, userid: &str, email: bool) -> Result<()> {
947 let sop_error = |e| self.sqop.sop_error(e);
948
949 tracer!(self.sqop.debug, "ValidateUserID::authenticate");
950 use sequoia_wot::{FULLY_TRUSTED, Network};
951
952 t!("authenticating {} {:?}",
953 if email { "email" } else { "user ID" }, userid);
954
955 let roots: Vec<_> =
956 self.trust_roots.iter().map(openpgp::Cert::fingerprint).collect();
957 t!("using trust roots {:?}", roots);
958
959 let n = Network::from_cert_refs(
960 self.trust_roots.iter().chain(self.target_certs.iter()),
961 self.sqop.policy,
962 self.validate_at.clone(),
963 &roots[..])
964 .map_err(sop_error)?;
965
966 if ! email {
967 let uid = openpgp::packet::UserID::from(userid);
969
970 for cert in &self.target_certs {
971 t!("considering {}", cert.fingerprint());
972
973 let paths =
974 n.authenticate(&uid, cert.fingerprint(), FULLY_TRUSTED);
975 t!("authenticate({:?}, {}) => {}",
976 cert.fingerprint(), userid, paths.amount());
977
978 if paths.amount() < FULLY_TRUSTED {
979 return Err(Error::CertUseridNoMatch);
980 }
981 }
982 } else {
983 for cert in &self.target_certs {
985 t!("considering {}", cert.fingerprint());
986
987 let mut one = false;
988 for uid in cert.userids()
989 .filter(|u| u.userid().email().ok().flatten()
990 .map(|email| email == userid)
991 .unwrap_or(false))
992 {
993 let paths =
994 n.authenticate(uid.userid(), cert.fingerprint(),
995 FULLY_TRUSTED);
996 t!("authenticate({}, {:?}) => {}",
997 cert.fingerprint(), userid, paths.amount());
998
999 if paths.amount() >= FULLY_TRUSTED {
1000 one = true;
1001 break;
1002 }
1003 }
1004
1005 if ! one {
1006 return Err(Error::CertUseridNoMatch);
1007 }
1008 }
1009 }
1010
1011 Ok(())
1012 }
1013}
1014
1015impl<'s> sop::ops::ValidateUserID<'s, SQOP<'s>, Certs<'s>> for ValidateUserID<'s> {
1016 fn trust_roots(mut self: Box<Self>, certs: &Certs)
1017 -> Result<Box<dyn sop::ops::ValidateUserID<'s, SQOP<'s>, Certs<'s>> + 's>> {
1018 for cert in &certs.certs {
1019 self.trust_roots.push(cert.clone());
1020 }
1021 Ok(self)
1022 }
1023
1024 fn target_certs(mut self: Box<Self>, certs: &Certs)
1025 -> Result<Box<dyn sop::ops::ValidateUserID<'s, SQOP<'s>, Certs<'s>> + 's>> {
1026 for cert in &certs.certs {
1027 self.target_certs.push(cert.clone());
1028 }
1029 Ok(self)
1030 }
1031
1032 fn validate_at(mut self: Box<Self>, at: SystemTime)
1033 -> Result<Box<dyn sop::ops::ValidateUserID<'s, SQOP<'s>, Certs<'s>> + 's>> {
1034 self.validate_at = Some(at);
1035 Ok(self)
1036 }
1037
1038 fn userid(self: Box<Self>, userid: &str) -> Result<()> {
1039 self.authenticate(userid, false)
1040 }
1041
1042 fn email(self: Box<Self>, address: &str) -> Result<()> {
1043 self.authenticate(address, true)
1044 }
1045}
1046
1047struct Sign<'s> {
1048 sqop: &'s SQOP<'s>,
1049 mode: SignAs,
1050 hash_algos: Vec<HashAlgorithm>,
1051 with_key_password: Vec<Password>,
1052 signers: Vec<openpgp::Cert>,
1053}
1054
1055impl<'s> Sign<'s> {
1056 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::Sign<'s, SQOP<'s>, Keys<'s>, Sigs<'s>> + 's>> {
1057 Ok(Box::new(Self::unboxed(sqop)))
1058 }
1059
1060 fn unboxed(sqop: &'s SQOP) -> Sign<'s> {
1061 Sign {
1062 sqop,
1063 mode: Default::default(),
1064 hash_algos: [
1065 HashAlgorithm::SHA512,
1066 HashAlgorithm::SHA384,
1067 HashAlgorithm::SHA256,
1068 HashAlgorithm::SHA224,
1069 ].iter().copied().filter(|h| h.is_supported()).collect(),
1070 with_key_password: Default::default(),
1071 signers: Default::default(),
1072 }
1073 }
1074}
1075
1076impl Sign<'_> {
1077 fn add_signing_keys(&mut self, keys: &Keys) -> Result<()> {
1078 for key in &keys.keys {
1079 self.add_signing_cert(key)?;
1080 }
1081 Ok(())
1082 }
1083
1084 fn add_signing_cert(&mut self, cert: &Cert) -> Result<()> {
1085 let vcert =
1086 cert.with_policy(self.sqop.policy, None)
1087 .map_err(|e| {
1088 self.sqop.sop_error(e);
1089 Error::KeyCannotSign
1090 })?;
1091
1092 if let RevocationStatus::Revoked(_) = vcert.revocation_status() {
1093 return Err(Error::KeyCannotSign);
1094 }
1095
1096 if let Some(p) = vcert.preferred_hash_algorithms() {
1097 self.hash_algos.retain(|a| p.contains(a));
1098 }
1099
1100 if vcert.keys()
1101 .supported()
1102 .secret()
1103 .alive()
1104 .revoked(false)
1105 .for_signing()
1106 .next().is_none()
1107 {
1108 return Err(Error::KeyCannotSign);
1109 }
1110
1111 self.signers.push(cert.clone());
1112 Ok(())
1113 }
1114
1115 fn make_signers(&self) -> Result<Vec<openpgp::crypto::KeyPair>> {
1117 let sop_error = |e| self.sqop.sop_error(e);
1118
1119 let mut signers = Vec::with_capacity(self.signers.len());
1120 for cert in &self.signers {
1121 let vcert =
1122 cert.with_policy(self.sqop.policy, None)
1123 .map_err(|e| {
1124 sop_error(e);
1125 Error::KeyCannotSign
1126 })?;
1127
1128 let mut one = false;
1129 for skb in vcert.keys()
1130 .supported()
1131 .secret()
1132 .alive()
1133 .revoked(false)
1134 .for_signing()
1135 {
1136 let mut key = skb.key().clone();
1137
1138 if key.secret().is_encrypted() {
1139 for p in self.with_key_password.iter()
1140 .flat_map(|p| p.variants())
1141 {
1142 if key.secret_mut().decrypt_in_place(skb.key(), &p.into())
1143 .is_ok()
1144 {
1145 break;
1146 }
1147 }
1148 }
1149 if ! key.secret().is_encrypted() {
1150 one = true;
1151 signers.push(key.into_keypair().map_err(sop_error)?);
1153 break;
1154 }
1155 }
1156
1157 if ! one {
1158 return Err(Error::KeyIsProtected);
1159 }
1160 }
1161
1162 Ok(signers)
1163 }
1164}
1165
1166impl<'s> sop::ops::Sign<'s, SQOP<'s>, Keys<'s>, Sigs<'s>> for Sign<'s> {
1167 fn mode(mut self: Box<Self>, mode: SignAs)
1168 -> Box<dyn sop::ops::Sign<'s, SQOP<'s>, Keys<'s>, Sigs<'s>> + 's> {
1169 self.mode = mode;
1170 self
1171 }
1172
1173 fn keys(mut self: Box<Self>, keys: &Keys)
1174 -> Result<Box<dyn sop::ops::Sign<'s, SQOP<'s>, Keys<'s>, Sigs<'s>> + 's>> {
1175 self.add_signing_keys(keys)?;
1176 Ok(self)
1177 }
1178
1179 fn with_key_password(mut self: Box<Self>, password: Password)
1180 -> Result<Box<dyn sop::ops::Sign<'s, SQOP<'s>, Keys<'s>, Sigs<'s>> + 's>> {
1181 self.with_key_password.push(password);
1182 Ok(self)
1183 }
1184
1185 fn data(self: Box<Self>, data: &mut (dyn io::Read + Send + Sync))
1186 -> Result<(sop::ops::Micalg, Sigs<'s>)>
1187 {
1188 let sop_error = |e| self.sqop.sop_error(e);
1189
1190 if self.signers.is_empty() {
1191 return Err(Error::MissingArg);
1192 }
1193
1194 let mut buf = vec![];
1195 let message = Message::new(&mut buf);
1196 let mut signers = self.make_signers()?;
1197 let mut signer = Signer::with_template(
1198 message,
1199 signers.pop().expect("at least one"),
1200 signature::SignatureBuilder::new(into_sig_type(self.mode)))
1201 .map_err(sop_error)?
1202 .hash_algo(
1203 self.hash_algos.get(0).cloned().unwrap_or_default()
1204 ).map_err(sop_error)?
1205 .detached();
1206 for s in signers {
1207 signer = signer.add_signer(s).map_err(sop_error)?;
1208 }
1209 let mut message = signer.build().map_err(sop_error)?;
1210 io::copy(data, &mut message)?;
1211 message.finalize().map_err(sop_error)?;
1212
1213 Ok((u8::from(HashAlgorithm::default()).into(),
1214 Sigs::from_bytes(self.sqop, &buf)?))
1215 }
1216}
1217
1218struct Verify<'s> {
1219 sqop: &'s SQOP<'s>,
1220 verbose: bool,
1221 not_before: Option<SystemTime>,
1222 not_after: Option<SystemTime>,
1223 certs: CertBag,
1224}
1225
1226impl<'s> Verify<'s> {
1227 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::Verify<'s, SQOP<'s>, Certs<'s>, Sigs<'s>> + 's>> {
1228 Ok(Box::new(Self::unboxed(sqop)))
1229 }
1230
1231 fn unboxed(sqop: &'s SQOP) -> Verify<'s>
1232 where
1233 's: 's,
1234 {
1235 Verify {
1236 sqop,
1237 verbose: Default::default(),
1238 not_before: Default::default(),
1239 not_after: Default::default(),
1240 certs: Default::default(),
1241 }
1242 }
1243}
1244
1245impl<'s> sop::ops::Verify<'s, SQOP<'s>, Certs<'s>, Sigs<'s>> for Verify<'s> {
1246 fn not_before(mut self: Box<Self>, t: SystemTime)
1247 -> Box<dyn sop::ops::Verify<'s, SQOP<'s>, Certs<'s>, Sigs<'s>> + 's> {
1248 self.not_before = Some(t);
1249 self
1250 }
1251
1252 fn not_after(mut self: Box<Self>, t: SystemTime)
1253 -> Box<dyn sop::ops::Verify<'s, SQOP<'s>, Certs<'s>, Sigs<'s>> + 's> {
1254 self.not_after = Some(t);
1255 self
1256 }
1257
1258 fn certs(mut self: Box<Self>, cert: &Certs)
1259 -> Result<Box<dyn sop::ops::Verify<'s, SQOP<'s>, Certs<'s>, Sigs<'s>> + 's>> {
1260 self.certs.extend_from(cert);
1261 Ok(self)
1262 }
1263
1264 fn signatures<'sigs>(self: Box<Self>, signatures: &'sigs Sigs)
1265 -> Result<Box<dyn sop::ops::VerifySignatures<'sigs> + 'sigs>>
1266 where
1267 's: 'sigs,
1268 {
1269 Ok(Box::new(VerifySignatures {
1270 verify: *self,
1271 signatures: signatures,
1272 }))
1273 }
1274}
1275
1276struct VerifySignatures<'s, 'sigs> {
1277 verify: Verify<'s>,
1278 signatures: &'sigs Sigs<'s>,
1279}
1280
1281impl sop::ops::VerifySignatures<'_> for VerifySignatures<'_, '_> {
1282 fn data(self: Box<Self>, data: &mut (dyn io::Read + Send + Sync))
1283 -> Result<Vec<sop::ops::Verification>> {
1284 let sop_error = |e| self.verify.sqop.sop_error(e);
1285
1286 if self.verify.certs.is_empty() {
1287 return Err(Error::MissingArg);
1288 }
1289
1290 let helper = VHelper::new(
1291 if self.verify.verbose {
1292 Box::new(io::stderr())
1293 } else {
1294 Box::new(io::sink())
1295 },
1296 1,
1297 self.verify.not_before,
1298 self.verify.not_after,
1299 self.verify.certs);
1300 let mut v =
1301 DetachedVerifierBuilder::from_bytes(&self.signatures.data)
1302 .map_err(sop_error)?
1303 .with_policy(self.verify.sqop.policy, None, helper)
1304 .map_err(sop_error)?;
1305 v.verify_reader(data).map_err(sop_error)?;
1306 Ok(v.into_helper().verifications)
1307 }
1308}
1309
1310struct Encrypt<'s> {
1311 no_armor: bool,
1312 sign: Sign<'s>,
1313 profile: &'static str,
1314 mode: EncryptAs,
1315 symmetric_algos: Vec<SymmetricAlgorithm>,
1316 aead_algos: Vec<(SymmetricAlgorithm, AEADAlgorithm)>,
1317 recipients: Vec<(Features, Key<key::PublicParts, key::UnspecifiedRole>)>,
1318 passwords: Vec<Password>,
1319}
1320
1321impl<'s> Encrypt<'s> {
1322 const PROFILE_RFC9580: &'static str = "rfc9580";
1323 const PROFILE_RFC4880: &'static str = "rfc4880";
1324 const PROFILES: &'static [(&'static str, &'static str)] = &[
1325 (Self::PROFILE_RFC9580, "use SEIPDv2"),
1326 (Self::PROFILE_RFC4880, "use SEIPDv1"),
1327 ];
1328
1329 fn normalize_profile(profile: &str) -> Result<&'static str> {
1330 match profile {
1331 Self::PROFILE_RFC9580 => Ok(Self::PROFILE_RFC9580),
1332 Self::PROFILE_RFC4880 => Ok(Self::PROFILE_RFC4880),
1333
1334 "default" => Ok(match openpgp::Profile::default() {
1336 openpgp::Profile::RFC4880 => Self::PROFILE_RFC4880,
1337 openpgp::Profile::RFC9580 => Self::PROFILE_RFC9580,
1338 _ => Self::PROFILE_RFC9580,
1339 }),
1340 "security" => Ok(Self::PROFILE_RFC9580),
1341 "performance" => Ok(Self::PROFILE_RFC9580),
1342 "compatibility" => Ok(Self::PROFILE_RFC4880),
1343
1344 _ => Err(Error::UnsupportedProfile),
1345 }
1346 }
1347
1348 const SYMMETRIC_ALGOS: &'static [SymmetricAlgorithm] = &[
1349 SymmetricAlgorithm::AES256,
1350 SymmetricAlgorithm::AES192,
1351 SymmetricAlgorithm::AES128,
1352 SymmetricAlgorithm::Camellia256,
1353 SymmetricAlgorithm::Camellia192,
1354 SymmetricAlgorithm::Camellia128,
1355 SymmetricAlgorithm::Blowfish,
1356 SymmetricAlgorithm::Twofish,
1357 ];
1358
1359 const AEAD_ALGOS: &'static [AEADAlgorithm] = &[
1360 AEADAlgorithm::OCB,
1361 AEADAlgorithm::GCM,
1362 AEADAlgorithm::EAX,
1363 ];
1364
1365 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1366 Ok(Box::new(Encrypt {
1367 no_armor: false,
1368 sign: Sign::unboxed(sqop),
1369 profile: Self::normalize_profile("default")?,
1370 mode: Default::default(),
1371 symmetric_algos: Self::SYMMETRIC_ALGOS.iter().copied().filter(|&a| {
1372 a.is_supported() && sqop.policy.symmetric_algorithm(a).is_ok()
1373 }).collect(),
1374 aead_algos: Self::SYMMETRIC_ALGOS.iter().copied().filter(|&a| {
1375 a.is_supported() && sqop.policy.symmetric_algorithm(a).is_ok()
1376 }).flat_map(|s| Self::AEAD_ALGOS.iter().copied().filter(|&a| {
1377 a.is_supported() && sqop.policy.aead_algorithm(a).is_ok()
1378 }).map(move |a| (s, a))).collect(),
1379 recipients: Default::default(),
1380 passwords: Default::default(),
1381 }))
1382 }
1383
1384 fn add_cert(mut self: Box<Self>, cert: &Cert)
1385 -> Result<Box<Self>> {
1386 let vcert = cert.with_policy(self.sign.sqop.policy, None)
1387 .map_err(|e| {
1388 self.sign.sqop.sop_error(e);
1389 Error::CertCannotEncrypt
1390 })?;
1391
1392 if let RevocationStatus::Revoked(_) = vcert.revocation_status() {
1393 return Err(Error::CertCannotEncrypt);
1394 }
1395
1396 if let Some(p) = vcert.preferred_hash_algorithms() {
1399 self.sign.hash_algos.retain(|a| p.contains(a));
1400 }
1401 if let Some(p) = vcert.preferred_symmetric_algorithms() {
1402 self.symmetric_algos.retain(|a| p.contains(a));
1403 }
1404 if let Some(p) = vcert.preferred_aead_ciphersuites() {
1405 self.aead_algos.retain(|a| p.contains(a));
1406 }
1407
1408 if ! vcert.features().map(|f| f.supports_seipdv2())
1410 .unwrap_or_else(|| vcert.primary_key().key().version() == 6)
1411 {
1412 self.profile = Self::PROFILE_RFC4880;
1413 }
1414
1415 let mut one = false;
1416 for vka in vcert.keys()
1417 .supported()
1418 .alive()
1419 .revoked(false)
1420 .for_storage_encryption()
1421 .for_transport_encryption()
1422 {
1423 self.recipients.push(
1424 (vka.valid_cert().features().unwrap_or_else(Features::empty),
1425 vka.key().clone()));
1426 one = true;
1427 }
1428
1429 if one {
1430 Ok(self)
1431 } else {
1432 Err(Error::CertCannotEncrypt)
1433 }
1434 }
1435}
1436
1437impl<'s> sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> for Encrypt<'s> {
1438 fn no_armor(mut self: Box<Self>) -> Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's> {
1439 self.no_armor = true;
1440 self
1441 }
1442
1443 fn list_profiles(&self) -> Vec<(String, String)> {
1444 list_profiles(Self::PROFILES, &Self::normalize_profile)
1445 }
1446
1447 fn profile(mut self: Box<Self>, profile: &str)
1448 -> Result<Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1449 self.profile = Self::normalize_profile(profile)?;
1450 Ok(self)
1451 }
1452
1453 fn mode(mut self: Box<Self>, mode: EncryptAs) -> Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's> {
1454 self.sign.mode = mode.into();
1455 self.mode = mode;
1456 self
1457 }
1458
1459 fn sign_with_keys(mut self: Box<Self>,
1460 keys: &Keys)
1461 -> Result<Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1462 self.sign.add_signing_keys(keys)?;
1463 Ok(self)
1464 }
1465
1466 fn with_key_password(mut self: Box<Self>, password: Password)
1467 -> Result<Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1468 self.sign.with_key_password.push(password);
1469 Ok(self)
1470 }
1471
1472 fn with_password(mut self: Box<Self>, password: Password)
1473 -> Result<Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1474 self.passwords.push(password);
1475 Ok(self)
1476 }
1477
1478 fn with_certs(mut self: Box<Self>, certs: &Certs)
1479 -> Result<Box<dyn sop::ops::Encrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1480 for cert in &certs.certs {
1481 self = self.add_cert(cert)?;
1482 }
1483 Ok(self)
1484 }
1485
1486 fn plaintext<'d>(self: Box<Self>,
1487 plaintext: &'d mut (dyn io::Read + Send + Sync))
1488 -> Result<Box<dyn sop::ops::Ready<Option<sop::SessionKey>> + 'd>>
1489 where
1490 's: 'd
1491 {
1492 Ok(Box::new(EncryptReady {
1493 encrypt: *self,
1494 plaintext,
1495 }))
1496 }
1497}
1498
1499struct EncryptReady<'s> {
1500 encrypt: Encrypt<'s>,
1501 plaintext: &'s mut (dyn io::Read + Send + Sync),
1502}
1503
1504impl<'s> sop::ops::Ready<Option<sop::SessionKey>> for EncryptReady<'s> {
1505 fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
1506 -> Result<Option<sop::SessionKey>>
1507 {
1508 let sop_error = |e| self.encrypt.sign.sqop.sop_error(e);
1509
1510 if self.encrypt.recipients.is_empty()
1511 && self.encrypt.passwords.is_empty()
1512 {
1513 return Err(Error::MissingArg);
1514 }
1515
1516 let mut message = Message::new(sink);
1517 if ! self.encrypt.no_armor {
1518 message = Armorer::new(message).build().map_err(sop_error)?;
1519 }
1520
1521 let (cipher, aead_algo) = match self.encrypt.profile {
1525 Encrypt::PROFILE_RFC9580 => {
1526 let (c, a) = self.encrypt.aead_algos.get(0).cloned()
1527 .unwrap_or(
1528 (SymmetricAlgorithm::AES128, AEADAlgorithm::OCB));
1530 (c, Some(a))
1531 },
1532 Encrypt::PROFILE_RFC4880 => {
1533 (self.encrypt.symmetric_algos.get(0).cloned()
1534 .unwrap_or_default(),
1535 None)
1536 },
1537 _ => unreachable!("checked in Encrypt::profile"),
1538 };
1539
1540 let session_key =
1541 SessionKey::new(cipher.key_size().map_err(sop_error)?)
1542 .map_err(sop_error)?;
1543 let sop_session_key = sop::SessionKey::new(cipher, &session_key)?;
1544 let mut encryptor =
1545 Encryptor::with_session_key(message, cipher, session_key)
1546 .map_err(sop_error)?
1547 .add_recipients(
1548 self.encrypt.recipients.iter()
1549 .map(|(f, k)| Recipient::new(f.clone(), k.key_handle(), k)))
1550 .add_passwords(
1551 self.encrypt.passwords.into_iter()
1552 .map(|p| crypto::Password::from(p.normalized())))
1553 .symmetric_algo(cipher);
1554
1555 if let Some(a) = aead_algo {
1556 encryptor = encryptor.aead_algo(a);
1557 }
1558
1559 let mut message = encryptor
1560 .build().map_err(sop_error)?;
1561
1562 message = Padder::new(message).build().map_err(sop_error)?;
1564
1565 let mut signers = self.encrypt.sign.make_signers()?;
1567 if let Some(first) = signers.pop() {
1568 let mut signer = Signer::with_template(
1569 message, first,
1570 signature::SignatureBuilder::new(into_sig_type(self.encrypt.sign.mode)))
1571 .map_err(sop_error)?
1572 .hash_algo(
1573 self.encrypt.sign.hash_algos.get(0).cloned().unwrap_or_default())
1574 .map_err(sop_error)?;
1575 for s in signers {
1576 signer = signer.add_signer(s).map_err(sop_error)?;
1577 }
1578 message = signer.build().map_err(sop_error)?;
1579 }
1580
1581 let mut message = LiteralWriter::new(message)
1583 .build().map_err(sop_error)?;
1584 io::copy(self.plaintext, &mut message)?;
1585 message.finalize().map_err(sop_error)?;
1586 Ok(Some(sop_session_key))
1587 }
1588}
1589
1590struct Decrypt<'s> {
1591 verify: Verify<'s>,
1592 session_keys: Vec<sop::SessionKey>,
1593 passwords: Vec<Password>,
1594 keys: Vec<Cert>,
1595 with_key_password: Vec<Password>,
1596}
1597
1598impl<'s> Decrypt<'s> {
1599 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1600 Ok(Box::new(Decrypt {
1601 verify: Verify::unboxed(sqop),
1602 session_keys: Default::default(),
1603 passwords: Default::default(),
1604 keys: Default::default(),
1605 with_key_password: Default::default(),
1606 }))
1607 }
1608}
1609
1610impl<'s> sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> for Decrypt<'s> {
1611 fn verify_not_before(mut self: Box<Self>, t: SystemTime)
1612 -> Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's> {
1613 self.verify.not_before = Some(t);
1614 self
1615 }
1616
1617 fn verify_not_after(mut self: Box<Self>, t: SystemTime)
1618 -> Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's> {
1619 self.verify.not_after = Some(t);
1620 self
1621 }
1622
1623 fn verify_with_certs(mut self: Box<Self>,
1624 certs: &Certs)
1625 -> Result<Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1626 self.verify.certs.extend_from(certs);
1627 Ok(self)
1628 }
1629
1630 fn with_session_key(mut self: Box<Self>, sk: sop::SessionKey)
1631 -> Result<Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1632 self.session_keys.push(sk);
1633 Ok(self)
1634 }
1635
1636 fn with_password(mut self: Box<Self>, password: Password)
1637 -> Result<Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1638 self.passwords.push(password);
1639 Ok(self)
1640 }
1641
1642 fn with_keys(mut self: Box<Self>, keys: &Keys)
1643 -> Result<Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1644 for key in &keys.keys {
1645 self.keys.push(key.clone());
1646 }
1647 Ok(self)
1648 }
1649
1650 fn with_key_password(mut self: Box<Self>, password: Password)
1651 -> Result<Box<dyn sop::ops::Decrypt<'s, SQOP<'s>, Certs<'s>, Keys<'s>> + 's>> {
1652 self.with_key_password.push(password);
1653 Ok(self)
1654 }
1655
1656 fn ciphertext<'d>(self: Box<Self>,
1657 ciphertext: &'d mut (dyn io::Read + Send + Sync))
1658 -> Result<Box<dyn sop::ops::Ready<(Option<sop::SessionKey>,
1659 Vec<sop::ops::Verification>)> + 'd>>
1660 where
1661 's: 'd
1662 {
1663 Ok(Box::new(DecryptReady {
1664 decrypt: *self,
1665 ciphertext,
1666 }))
1667 }
1668}
1669
1670struct DecryptReady<'s> {
1671 decrypt: Decrypt<'s>,
1672 ciphertext: &'s mut (dyn io::Read + Send + Sync),
1673}
1674
1675impl<'s> sop::ops::Ready<(Option<sop::SessionKey>, Vec<sop::ops::Verification>)>
1676 for DecryptReady<'s>
1677{
1678 fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
1679 -> Result<(Option<sop::SessionKey>, Vec<sop::ops::Verification>)> {
1680
1681 let sop_error = |e| self.decrypt.verify.sqop.sop_error(e);
1682
1683 let vhelper = VHelper::new(
1684 if self.decrypt.verify.verbose {
1685 Box::new(io::stderr())
1686 } else {
1687 Box::new(io::sink())
1688 },
1689 0,
1690 self.decrypt.verify.not_before,
1691 self.decrypt.verify.not_after,
1692 self.decrypt.verify.certs);
1693 let helper = Helper::new(self.decrypt.verify.sqop.policy,
1694 vhelper,
1695 self.decrypt.session_keys,
1696 self.decrypt.passwords,
1697 self.decrypt.with_key_password,
1698 self.decrypt.keys);
1699 let mut d = DecryptorBuilder::from_reader(self.ciphertext)
1700 .map_err(sop_error)?
1701 .with_policy(self.decrypt.verify.sqop.policy, None, helper)
1702 .map_err(sop_error)?;
1703
1704 io::copy(&mut d, sink)?;
1705
1706 let helper = d.into_helper();
1707 Ok((helper.session_key, helper.vhelper.verifications))
1708 }
1709}
1710
1711struct Armor<'s> {
1712 sqop: &'s SQOP<'s>,
1713 label: ArmorLabel,
1714}
1715
1716impl<'s> Armor<'s> {
1717 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::Armor<'s> + 's>> {
1718 Ok(Box::new(Armor {
1719 sqop,
1720 label: Default::default(),
1721 }))
1722 }
1723
1724 fn dpi(&self, mut source: Box<dyn BufferedReader<Cookie> + 's>)
1728 -> Result<(Box<dyn BufferedReader<Cookie> + 's>,
1729 Option<armor::Kind>,
1730 openpgp::Profile)>
1731 {
1732 let sop_error = |e| self.sqop.sop_error(e);
1733
1734 let mut kind = None;
1736
1737 let mut profile = None;
1739
1740 let mut saw_sig_v4 = false;
1742 let mut saw_sig_v6 = false;
1743
1744 let mut saw_key_v4 = false;
1746 let mut saw_key_v6 = false;
1747
1748 source = Dup::with_cookie(source, Default::default()).into_boxed();
1749 {
1750 let mut ppr = PacketParser::from_buffered_reader(&mut source)
1751 .map_err(sop_error)?;
1752
1753 while let PacketParserResult::Some(pp) = ppr {
1754 if kind.is_none() {
1755 kind = Some(match &pp.packet {
1757 Packet::Signature(_) =>
1758 armor::Kind::Signature,
1759 Packet::SecretKey(_) =>
1760 armor::Kind::SecretKey,
1761 Packet::PublicKey(_) =>
1762 armor::Kind::PublicKey,
1763 Packet::PKESK(_) | Packet::SKESK(_)
1764 | Packet::OnePassSig(_) =>
1765 armor::Kind::Message,
1766 _ => return Err(Error::BadData),
1767 });
1768 }
1769
1770 match &pp.packet {
1774 Packet::SEIP(s) => {
1775 match s.version() {
1776 1 =>
1777 profile = Some(openpgp::Profile::RFC4880),
1778
1779 2 | _ =>
1780 profile = Some(openpgp::Profile::RFC9580),
1781 }
1782
1783 break;
1785 },
1786
1787 Packet::Literal(_) => {
1788 break;
1791 },
1792
1793 Packet::Signature(s) => {
1794 saw_sig_v4 |= s.version() == 3;
1795 saw_sig_v4 |= s.version() == 4;
1796 saw_sig_v6 |= s.version() == 6;
1797 },
1798 Packet::OnePassSig(s) => {
1799 saw_sig_v4 |= s.version() == 3;
1800 saw_sig_v6 |= s.version() == 6;
1801 },
1802
1803 Packet::SecretKey(k) => {
1804 saw_key_v4 |= k.version() == 4;
1805 saw_key_v6 |= k.version() == 6;
1806 },
1807 Packet::PublicKey(k) => {
1808 saw_key_v4 |= k.version() == 4;
1809 saw_key_v6 |= k.version() == 6;
1810 },
1811
1812 _ => (),
1813 }
1814
1815 ppr = pp.next().map_err(sop_error)?.1;
1816 }
1817 }
1818
1819 source = source.into_inner()
1822 .expect("the Dup to be popped off");
1823
1824 let profile = match profile {
1826 Some(p) => p,
1827 None => match (saw_sig_v4, saw_sig_v6, saw_key_v4, saw_key_v6) {
1828 (false, false, false, false) => openpgp::Profile::default(),
1829 (false, true, false, false) => openpgp::Profile::RFC9580,
1830 ( true, false, false, false) => openpgp::Profile::RFC4880,
1831 ( true, true, false, false) => openpgp::Profile::RFC4880,
1832 ( _, _, false, true) => openpgp::Profile::RFC9580,
1833 ( _, _, true, false) => openpgp::Profile::RFC4880,
1834 ( _, _, true, true) => openpgp::Profile::RFC4880,
1835 },
1836 };
1837
1838 Ok((source, kind, profile))
1839 }
1840}
1841
1842impl<'s> sop::ops::Armor<'s> for Armor<'s> {
1843 fn label(mut self: Box<Self>, label: ArmorLabel)
1844 -> Box<dyn sop::ops::Armor<'s> + 's> {
1845 self.label = label;
1846 self
1847 }
1848
1849 fn data<'d>(self: Box<Self>, data: &'d mut (dyn io::Read + Send + Sync))
1850 -> Result<Box<dyn sop::ops::Ready + 'd>>
1851 where
1852 's: 'd
1853 {
1854 Ok(Box::new(ArmorReady {
1855 armor: *self,
1856 data,
1857 }))
1858 }
1859}
1860
1861struct ArmorReady<'s> {
1862 armor: Armor<'s>,
1863 data: &'s mut (dyn io::Read + Send + Sync),
1864}
1865
1866impl<'s> sop::ops::Ready for ArmorReady<'s> {
1867 fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
1868 -> Result<()> {
1869 let _ = self.armor.sqop;
1870
1871 let mut source =
1872 Generic::with_cookie(self.data, None, Cookie::default())
1873 .into_boxed();
1874
1875 let armored =
1877 source.data(1)?.get(0).map(|b| b & 0x80 == 0).unwrap_or(false);
1878
1879 let mut headers: Vec<(String, String)> = vec![];
1881 if armored {
1882 let mut r = armor::Reader::from_buffered_reader(
1883 source, armor::ReaderMode::Tolerant(None))?;
1884 headers = r.headers()?.iter().cloned().collect();
1885 source = r.into_boxed();
1886 }
1887
1888 let (source_, guess, profile) = self.armor.dpi(source)?;
1890 source = source_;
1891
1892 let kind = match self.armor.label {
1893 ArmorLabel::Auto => guess.ok_or(Error::BadData)?,
1894 ArmorLabel::Sig => armor::Kind::Signature,
1895 ArmorLabel::Key => armor::Kind::SecretKey,
1896 ArmorLabel::Cert => armor::Kind::PublicKey,
1897 ArmorLabel::Message => armor::Kind::Message,
1898 };
1899
1900 let mut sink = armor::Writer::with_headers(sink, kind, headers)?;
1901 sink.set_profile(profile)?;
1902 source.copy(&mut sink)?;
1903 sink.finalize()?;
1904 Ok(())
1905 }
1906}
1907
1908struct Dearmor<'s> {
1909 sqop: &'s SQOP<'s>,
1910}
1911
1912impl<'s> Dearmor<'s> {
1913 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::Dearmor<'s> + 's>> {
1914 Ok(Box::new(Dearmor {
1915 sqop,
1916 }))
1917 }
1918}
1919
1920impl<'s> sop::ops::Dearmor<'s> for Dearmor<'s> {
1921 fn data<'d>(self: Box<Self>, data: &'d mut (dyn io::Read + Send + Sync))
1922 -> Result<Box<dyn sop::ops::Ready + 'd>>
1923 where
1924 's: 'd
1925 {
1926 Ok(Box::new(DearmorReady {
1927 dearmor: *self,
1928 data,
1929 }))
1930 }
1931}
1932
1933struct DearmorReady<'s> {
1934 dearmor: Dearmor<'s>,
1935 data: &'s mut (dyn io::Read + Send + Sync),
1936}
1937
1938impl sop::ops::Ready for DearmorReady<'_> {
1939 fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
1940 -> Result<()> {
1941 let _ = self.dearmor.sqop;
1942
1943 let mut source =
1946 Generic::with_cookie(self.data, None, Cookie::default())
1947 .into_boxed();
1948 let armored =
1949 source.data(1)?.get(0).map(|b| b & 0x80 == 0).unwrap_or(false);
1950
1951 if armored {
1952 let mut r = armor::Reader::from_buffered_reader(source, None)?;
1953 r.copy(sink)?;
1954 } else {
1955 source.copy(sink)?;
1956 }
1957 Ok(())
1958 }
1959}
1960
1961struct InlineDetach<'s> {
1962 sqop: &'s SQOP<'s>,
1963 no_armor: bool,
1964}
1965
1966impl<'s> InlineDetach<'s> {
1967 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::InlineDetach<'s, Sigs<'s>> + 's>> {
1968 Ok(Box::new(InlineDetach {
1969 sqop,
1970 no_armor: Default::default(),
1971 }))
1972 }
1973}
1974
1975impl<'s> sop::ops::InlineDetach<'s, Sigs<'s>> for InlineDetach<'s> {
1976 fn message<'d>(self: Box<Self>, data: &'d mut (dyn io::Read + Send + Sync))
1977 -> Result<Box<dyn sop::ops::Ready<Sigs<'s>> + 'd>>
1978 where
1979 's: 'd
1980 {
1981 Ok(Box::new(InlineDetachReady {
1982 inline_detach: *self,
1983 data,
1984 }))
1985 }
1986}
1987
1988struct InlineDetachReady<'s, 'd> {
1989 inline_detach: InlineDetach<'s>,
1990 data: &'d mut (dyn io::Read + Send + Sync),
1991}
1992
1993impl<'s> sop::ops::Ready<Sigs<'s>> for InlineDetachReady<'s, '_> {
1994 fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
1995 -> Result<Sigs<'s>> {
1996 let sop_error = |e| self.inline_detach.sqop.sop_error(e);
1997
1998 let _ = self.inline_detach.sqop;
1999
2000 let np = unsafe { NullPolicy::new() };
2001
2002 #[derive(Default)]
2005 struct NullHelper {
2006 sigs: Vec<Packet>,
2007 }
2008
2009 impl VerificationHelper for NullHelper {
2010 fn get_certs(&mut self, _: &[openpgp::KeyHandle])
2011 -> openpgp::Result<Vec<Cert>> {
2012 Ok(Default::default())
2013 }
2014
2015 fn check(&mut self, structure: MessageStructure)
2016 -> openpgp::Result<()> {
2017 for layer in structure {
2018 match layer {
2019 MessageLayer::SignatureGroup { results } => {
2020 for result in results {
2021 match result
2022 .expect_err("no certs given")
2023 {
2024 VerificationError::MalformedSignature {
2025 sig, ..
2026 } =>
2027 self.sigs.push(sig.clone().into()),
2028 VerificationError::MissingKey {
2029 sig, ..
2030 } =>
2031 self.sigs.push(sig.clone().into()),
2032 _ => unreachable!("no certs given"),
2033 }
2034 }
2035 },
2036 _ => (),
2037 }
2038 }
2039
2040 Ok(())
2041 }
2042 }
2043
2044 let mut verifier = VerifierBuilder::from_reader(self.data)
2045 .map_err(sop_error)?
2046 .with_policy(&np, None, NullHelper::default())
2047 .map_err(sop_error)?;
2048
2049 io::copy(&mut verifier, sink)?;
2050
2051 let mut signatures = Vec::new();
2053 let mut signature_sink = Message::new(&mut signatures);
2054 if ! self.inline_detach.no_armor {
2055 signature_sink = Armorer::new(signature_sink)
2056 .kind(armor::Kind::Signature)
2057 .build().map_err(sop_error)?;
2058 }
2059
2060 for sig in verifier.into_helper().sigs {
2061 sig.serialize(&mut signature_sink).map_err(sop_error)?;
2062 }
2063 signature_sink.finalize().map_err(sop_error)?;
2064
2065 Ok(Sigs {
2066 sop: self.inline_detach.sqop,
2067 data: signatures,
2068 source_name: None,
2069 })
2070 }
2071}
2072
2073struct InlineVerify<'s> {
2074 sqop: &'s SQOP<'s>,
2075 verbose: bool,
2076 not_before: Option<SystemTime>,
2077 not_after: Option<SystemTime>,
2078 certs: CertBag,
2079}
2080
2081impl<'s> InlineVerify<'s> {
2082 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::InlineVerify<'s, SQOP<'s>, Certs<'s>> + 's>> {
2083 Ok(Box::new(InlineVerify {
2084 sqop,
2085 verbose: Default::default(),
2086 not_before: Default::default(),
2087 not_after: Default::default(),
2088 certs: Default::default(),
2089 }))
2090 }
2091}
2092
2093impl<'s> sop::ops::InlineVerify<'s, SQOP<'s>, Certs<'s>> for InlineVerify<'s> {
2094 fn not_before(mut self: Box<Self>, t: SystemTime)
2095 -> Box<dyn sop::ops::InlineVerify<'s, SQOP<'s>, Certs<'s>> + 's> {
2096 self.not_before = Some(t);
2097 self
2098 }
2099
2100 fn not_after(mut self: Box<Self>, t: SystemTime)
2101 -> Box<dyn sop::ops::InlineVerify<'s, SQOP<'s>, Certs<'s>> + 's> {
2102 self.not_after = Some(t);
2103 self
2104 }
2105
2106 fn certs(mut self: Box<Self>, certs: &Certs)
2107 -> Result<Box<dyn sop::ops::InlineVerify<'s, SQOP<'s>, Certs<'s>> + 's>> {
2108 self.certs.extend_from(certs);
2109 Ok(self)
2110 }
2111
2112 fn message<'d>(self: Box<Self>, data: &'d mut (dyn io::Read + Send + Sync))
2113 -> Result<Box<dyn sop::ops::Ready<Vec<Verification>> + 'd>>
2114 where
2115 's: 'd
2116 {
2117 Ok(Box::new(InlineVerifyReady {
2118 inline_verify: *self,
2119 data,
2120 }))
2121 }
2122}
2123
2124struct InlineVerifyReady<'s> {
2125 inline_verify: InlineVerify<'s>,
2126 data: &'s mut (dyn io::Read + Send + Sync),
2127}
2128
2129impl<'s> sop::ops::Ready<Vec<Verification>> for InlineVerifyReady<'_> {
2130 fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
2131 -> Result<Vec<Verification>> {
2132 let sop_error = |e| self.inline_verify.sqop.sop_error(e);
2133
2134 let helper = VHelper::new(
2135 if self.inline_verify.verbose {
2136 Box::new(io::stderr())
2137 } else {
2138 Box::new(io::sink())
2139 },
2140 1,
2141 self.inline_verify.not_before,
2142 self.inline_verify.not_after,
2143 self.inline_verify.certs);
2144
2145 let mut verifier = VerifierBuilder::from_reader(self.data)
2146 .map_err(sop_error)?
2147 .with_policy(self.inline_verify.sqop.policy, None, helper)
2148 .map_err(sop_error)?;
2149
2150 io::copy(&mut verifier, sink)?;
2151
2152 Ok(verifier.into_helper().verifications)
2153 }
2154}
2155
2156struct InlineSign<'s> {
2157 no_armor: bool,
2158 sign: Sign<'s>,
2159 mode: InlineSignAs,
2160}
2161
2162impl<'s> InlineSign<'s> {
2163 fn new(sqop: &'s SQOP) -> Result<Box<dyn sop::ops::InlineSign<'s, SQOP<'s>, Keys<'s>> + 's>> {
2164 Ok(Box::new(InlineSign {
2165 no_armor: false,
2166 sign: Sign::unboxed(sqop),
2167 mode: Default::default(),
2168 }))
2169 }
2170}
2171
2172impl<'s> sop::ops::InlineSign<'s, SQOP<'s>, Keys<'s>> for InlineSign<'s> {
2173 fn no_armor(mut self: Box<Self>) -> Box<dyn sop::ops::InlineSign<'s, SQOP<'s>, Keys<'s>> + 's> {
2174 self.no_armor = true;
2175 self
2176 }
2177
2178 fn mode(mut self: Box<Self>, mode: InlineSignAs) -> Box<dyn sop::ops::InlineSign<'s, SQOP<'s>, Keys<'s>> + 's> {
2179 self.mode = mode;
2180 self
2181 }
2182
2183 fn keys(mut self: Box<Self>, keys: &Keys)
2184 -> Result<Box<dyn sop::ops::InlineSign<'s, SQOP<'s>, Keys<'s>> + 's>> {
2185 self.sign.add_signing_keys(keys)?;
2186 Ok(self)
2187 }
2188
2189 fn with_key_password(mut self: Box<Self>, password: Password)
2190 -> Result<Box<dyn sop::ops::InlineSign<'s, SQOP<'s>, Keys<'s>> + 's>> {
2191 self.sign.with_key_password.push(password);
2192 Ok(self)
2193 }
2194
2195 fn data<'d>(self: Box<Self>, data: &'d mut (dyn io::Read + Send + Sync))
2196 -> Result<Box<dyn sop::ops::Ready + 'd>>
2197 where
2198 's: 'd
2199 {
2200 if self.sign.signers.is_empty() {
2201 return Err(Error::MissingArg);
2202 }
2203
2204 if self.no_armor && matches!(self.mode, InlineSignAs::ClearSigned)
2205 {
2206 return Err(Error::IncompatibleOptions);
2207 }
2208
2209 Ok(Box::new(InlineSignReady {
2210 inline_sign: *self,
2211 data,
2212 }))
2213 }
2214}
2215
2216struct InlineSignReady<'s> {
2217 inline_sign: InlineSign<'s>,
2218 data: &'s mut (dyn io::Read + Send + Sync),
2219}
2220
2221impl<'s> sop::ops::Ready for InlineSignReady<'s> {
2222 fn to_writer(self: Box<Self>, sink: &mut (dyn io::Write + Send + Sync))
2223 -> Result<()>
2224 {
2225 let sop_error = |e| self.inline_sign.sign.sqop.sop_error(e);
2226
2227 let mut message = Message::new(sink);
2228 if ! (self.inline_sign.no_armor
2229 || matches!(self.inline_sign.mode, InlineSignAs::ClearSigned))
2230 {
2231 message =
2232 Armorer::new(message).build().map_err(sop_error)?;
2233 }
2234
2235 let mut signers = self.inline_sign.sign.make_signers()?;
2236 let mut signer = Signer::with_template(
2237 message,
2238 signers.pop().expect("at least one"),
2239 signature::SignatureBuilder::new(
2240 into_isig_type(self.inline_sign.mode)))
2241 .map_err(sop_error)?
2242 .hash_algo(
2243 self.inline_sign.sign.hash_algos.get(0).cloned()
2244 .unwrap_or_default()).map_err(sop_error)?;
2245
2246 for s in signers {
2247 signer = signer.add_signer(s).map_err(sop_error)?;
2248 }
2249
2250 if matches!(self.inline_sign.mode, InlineSignAs::ClearSigned) {
2251 signer = signer.cleartext();
2252 }
2253
2254 let mut message = signer.build().map_err(sop_error)?;
2255
2256 if ! matches!(self.inline_sign.mode, InlineSignAs::ClearSigned) {
2257 message = LiteralWriter::new(message).build().map_err(sop_error)?;
2258 }
2259
2260 io::copy(self.data, &mut message)?;
2261 message.finalize().map_err(sop_error)?;
2262 Ok(())
2263 }
2264}
2265
2266#[derive(Default)]
2268struct CertBag {
2269 certs: BTreeMap<openpgp::Fingerprint, (Cert, Vec<String>)>,
2270}
2271
2272impl CertBag {
2273 fn is_empty(&self) -> bool {
2274 self.certs.is_empty()
2275 }
2276
2277 fn insert(&mut self, cert: Cert, source_name: Option<&str>) {
2278 use std::collections::btree_map::Entry;
2279 match self.certs.entry(cert.fingerprint()) {
2280 Entry::Occupied(mut e) => {
2281 let e = e.get_mut();
2282 e.0 = e.0.clone().merge_public(cert)
2283 .expect("merging certs with the same fipr is infallible");
2284 if let Some(n) = source_name {
2285 e.1.push(n.into());
2286 }
2287 },
2288 Entry::Vacant(e) => {
2289 e.insert((cert,
2290 if let Some(n) = source_name {
2291 vec![n.into()]
2292 } else {
2293 vec![]
2294 }));
2295 },
2296 }
2297 }
2298
2299 fn extend_from(&mut self, certs: &Certs) {
2300 for cert in &certs.certs {
2301 self.insert(cert.clone(), certs.source_name());
2302 }
2303 }
2304}
2305
2306struct VHelper {
2307 verbose_out: Box<dyn io::Write>,
2308 verifications: Vec<Verification>,
2309 not_before: Option<SystemTime>,
2310 not_after: Option<SystemTime>,
2311
2312 good: usize,
2313 total: usize,
2314 threshold: usize,
2315
2316 keyring: CertBag,
2317}
2318
2319impl VHelper {
2320 fn new(verbose_out: Box<dyn io::Write>,
2321 threshold: usize,
2322 not_before: Option<SystemTime>,
2323 not_after: Option<SystemTime>,
2324 keyring: CertBag)
2325 -> Self
2326 {
2327 assert!(threshold <= 1);
2328 VHelper {
2329 verbose_out,
2330 verifications: Default::default(),
2331 not_before,
2332 not_after,
2333 good: 0,
2334 total: 0,
2335 threshold,
2336 keyring,
2337 }
2338 }
2339}
2340
2341impl VerificationHelper for VHelper {
2342 fn get_certs(&mut self, _: &[openpgp::KeyHandle])
2343 -> openpgp::Result<Vec<Cert>> {
2344 Ok(self.keyring.certs.values()
2345 .map(|(cert, _)| cert.clone())
2346 .collect())
2347 }
2348
2349 fn check(&mut self, structure: MessageStructure) -> openpgp::Result<()> {
2350 use self::VerificationError::*;
2351
2352 for layer in structure.into_iter() {
2353 match layer {
2354 MessageLayer::SignatureGroup { results } =>
2355 for result in results {
2356 self.total += 1;
2357 match result {
2358 Ok(GoodChecksum { sig, ka, .. }) => {
2359 let t = match sig.signature_creation_time() {
2360 Some(t) => t,
2361 None => {
2362 writeln!(self.verbose_out,
2363 "Malformed signature:")?;
2364 print_error_chain(&mut self.verbose_out, &anyhow::anyhow!(
2365 "no signature creation time"))?;
2366 continue;
2367 },
2368 };
2369
2370 if let Some(not_before) = self.not_before {
2371 if t < not_before {
2372 writeln!(self.verbose_out,
2373 "Signature by {:X} was created before \
2374 the --not-before date.",
2375 ka.key().fingerprint())?;
2376 continue;
2377 }
2378 }
2379
2380 if let Some(not_after) = self.not_after {
2381 if t > not_after {
2382 writeln!(self.verbose_out,
2383 "Signature by {:X} was created after \
2384 the --not-after date.",
2385 ka.key().fingerprint())?;
2386 continue;
2387 }
2388 }
2389 let mut v = Verification::new(
2390 t,
2391 ka.key().fingerprint(),
2392 ka.cert().fingerprint(),
2393 match sig.typ() {
2394 SignatureType::Text =>
2395 SignatureMode::Text,
2396 _ => SignatureMode::Binary,
2397 },
2398 None)?;
2399
2400 for n in self.keyring.certs.get(&ka.cert().fingerprint())
2401 .map(|(_, source_names)| source_names)
2402 .unwrap_or(&vec![])
2403 {
2404 v.add_signer(n);
2405 }
2406
2407 self.verifications.push(v);
2408 },
2409 Err(MalformedSignature { error, .. }) => {
2410 writeln!(self.verbose_out,
2411 "Signature is malformed:")?;
2412 print_error_chain(&mut self.verbose_out, &error)?;
2413 },
2414 Err(MissingKey { sig, .. }) => {
2415 let issuers = sig.get_issuers();
2416 writeln!(self.verbose_out,
2417 "Missing key {:X}, which is needed to \
2418 verify signature.",
2419 issuers.first().unwrap())?;
2420 },
2421 Err(UnboundKey { cert, error, .. }) => {
2422 writeln!(self.verbose_out,
2423 "Signing key on {:X} is not bound:",
2424 cert.fingerprint())?;
2425 print_error_chain(&mut self.verbose_out, &error)?;
2426 },
2427 Err(BadKey { ka, error, .. }) => {
2428 writeln!(self.verbose_out,
2429 "Signing key on {:X} is bad:",
2430 ka.cert().fingerprint())?;
2431 print_error_chain(&mut self.verbose_out, &error)?;
2432 },
2433 Err(BadSignature { error, .. }) => {
2434 writeln!(self.verbose_out,
2435 "Verifying signature:")?;
2436 print_error_chain(&mut self.verbose_out, &error)?;
2437 },
2438 Err(UnknownSignature { sig, .. }) => {
2439 writeln!(self.verbose_out,
2440 "Verifying signature:")?;
2441 print_error_chain(&mut self.verbose_out, sig.error())?;
2442 },
2443 Err(error) => {
2444 writeln!(self.verbose_out,
2445 "Verifying signature: {}", error)?;
2446 },
2447 }
2448 }
2449 MessageLayer::Compression { .. } => (),
2450 MessageLayer::Encryption { .. } => (),
2451 }
2452 }
2453
2454 self.good = self.verifications.len();
2455 if self.good >= self.threshold {
2456 Ok(())
2457 } else {
2458 Err(Error::NoSignature.into())
2459 }
2460 }
2461}
2462
2463struct Helper {
2464 vhelper: VHelper,
2465 session_keys: Vec<sop::SessionKey>,
2466 passwords: Vec<crypto::Password>,
2467 secret_keys:
2468 HashMap<KeyID, Key<key::SecretParts, key::UnspecifiedRole>>,
2469 with_key_password: Vec<Password>,
2470 identities: HashMap<KeyID, Cert>,
2471 session_key: Option<sop::SessionKey>,
2472}
2473
2474impl Helper {
2475 fn new(policy: &dyn Policy,
2476 vhelper: VHelper,
2477 session_keys: Vec<sop::SessionKey>,
2478 passwords: Vec<Password>,
2479 with_key_password: Vec<Password>,
2480 secrets: Vec<Cert>) -> Self
2481 {
2482 let mut secret_keys = HashMap::new();
2483 let mut identities: HashMap<KeyID, Cert> = HashMap::new();
2484 for tsk in secrets {
2485 for ka in tsk.keys().secret()
2486 .with_policy(policy, None)
2487 .supported()
2488 .for_transport_encryption().for_storage_encryption()
2489 {
2490 let id: KeyID = ka.key().fingerprint().into();
2491 secret_keys.insert(id.clone(), ka.key().clone().into());
2492 identities.insert(id.clone(), tsk.clone().strip_secret_key_material());
2493 }
2494 }
2495
2496 Helper {
2497 vhelper,
2498 session_keys: session_keys.into_iter().map(Into::into).collect(),
2499 passwords: passwords.into_iter()
2500 .flat_map(|p| p.variants().map(crypto::Password::from)
2501 .collect::<Vec<_>>()).collect(),
2502 secret_keys,
2503 with_key_password,
2504 identities,
2505 session_key: None,
2506 }
2507 }
2508
2509 fn try_decrypt(&self, pkesk: &PKESK,
2512 algo_hint: Option<SymmetricAlgorithm>,
2513 keypair: &mut dyn crypto::Decryptor,
2514 decrypt: &mut dyn FnMut(Option<SymmetricAlgorithm>, &SessionKey) -> bool)
2515 -> Option<(SymmetricAlgorithm,
2516 SessionKey,
2517 Option<Cert>)>
2518 {
2519 let keyid: KeyID = keypair.public().fingerprint().into();
2520 let (algo, sk) = pkesk.decrypt(keypair, algo_hint)
2521 .and_then(|(algo, sk)| {
2522 if decrypt(algo, &sk) { Some((algo, sk)) } else { None }
2523 })?;
2524
2525 Some((algo.or(algo_hint).unwrap(), sk,
2526 self.identities.get(&keyid).map(|cert| cert.clone())))
2527 }
2528
2529 fn dump_session_key(&mut self, algo: SymmetricAlgorithm, sk: &SessionKey)
2531 -> Result<()> {
2532 self.session_key = Some(sop::SessionKey::new(algo, sk)?);
2533 Ok(())
2534 }
2535}
2536
2537impl VerificationHelper for Helper {
2538 fn get_certs(&mut self, ids: &[openpgp::KeyHandle])
2539 -> openpgp::Result<Vec<Cert>> {
2540 self.vhelper.get_certs(ids)
2541 }
2542 fn check(&mut self, structure: MessageStructure)
2543 -> openpgp::Result<()> {
2544 self.vhelper.check(structure)
2545 }
2546}
2547
2548impl DecryptionHelper for Helper {
2549 fn decrypt(&mut self, pkesks: &[PKESK], skesks: &[SKESK],
2550 algo_hint: Option<SymmetricAlgorithm>,
2551 decrypt: &mut dyn FnMut(Option<SymmetricAlgorithm>, &SessionKey) -> bool)
2552 -> openpgp::Result<Option<Cert>>
2553 {
2554 let mut error = Error::CannotDecrypt;
2555
2556 while let Some(sk) = self.session_keys.pop() {
2558 let algo = SymmetricAlgorithm::from(sk.algorithm());
2559 let sk = SessionKey::from(sk.key());
2560 if decrypt(Some(algo), &sk) {
2561 self.dump_session_key(algo, &sk)?;
2562 return Ok(None);
2563 }
2564 }
2565
2566 for pkesk in pkesks {
2568 let keyid: KeyID = pkesk.recipient().into();
2569 if let Some(key) = self.secret_keys.get_mut(&keyid) {
2570 let key_ref = key.clone();
2571
2572 if key.secret().is_encrypted() {
2574 for p in self.with_key_password.iter()
2575 .flat_map(|p| p.variants())
2576 {
2577 if key.secret_mut().decrypt_in_place(&key_ref, &p.into())
2578 .is_ok()
2579 {
2580 break;
2581 }
2582 }
2583 }
2584
2585 if ! key.secret().is_encrypted() {
2586 if let Some((algo, sk, fp)) =
2587 key.clone().into_keypair().ok().and_then(|mut k| {
2588 self.try_decrypt(pkesk, algo_hint, &mut k, decrypt)
2589 })
2590 {
2591 self.dump_session_key(algo, &sk)?;
2592 return Ok(fp);
2593 }
2594 } else {
2595 error = Error::KeyIsProtected;
2599 }
2600 }
2601 }
2602
2603 for pkesk in pkesks.iter().filter(|p| KeyID::from(p.recipient()).is_wildcard()) {
2606 for mut key in std::mem::take(&mut self.secret_keys).into_values() {
2607 let key_ref = key.clone();
2608
2609 if key.secret().is_encrypted() {
2611 for p in self.with_key_password.iter()
2612 .flat_map(|p| p.variants())
2613 {
2614 if key.secret_mut().decrypt_in_place(&key_ref, &p.into())
2615 .is_ok()
2616 {
2617 break;
2618 }
2619 }
2620 }
2621
2622 if ! key.secret().is_encrypted() {
2623 if let Some((algo, sk, fp)) =
2624 key.clone().into_keypair().ok().and_then(|mut k| {
2625 self.try_decrypt(pkesk, algo_hint, &mut k, decrypt)
2626 })
2627 {
2628 self.dump_session_key(algo, &sk)?;
2629 return Ok(fp);
2630 }
2631 } else {
2632 error = Error::KeyIsProtected;
2635 }
2636 }
2637 }
2638
2639 if skesks.is_empty() {
2640 return Err(error.into());
2641 }
2642
2643 for password in self.passwords.iter() {
2645 for skesk in skesks {
2646 if let Some((algo, sk)) = skesk.decrypt(password).ok()
2647 .and_then(|(algo, sk)| {
2648 if decrypt(algo, &sk) {
2649 Some((algo, sk))
2650 } else {
2651 None
2652 }
2653 })
2654 {
2655 self.dump_session_key(algo.or(algo_hint).unwrap(), &sk)?;
2656 return Ok(None);
2657 }
2658 }
2659 }
2660
2661 Err(error.into())
2662 }
2663}
2664
2665fn into_sig_type(mode: sop::ops::SignAs) -> SignatureType {
2666 match mode {
2667 SignAs::Binary => SignatureType::Binary,
2668 SignAs::Text => SignatureType::Text,
2669 }
2670}
2671
2672fn into_isig_type(mode: sop::ops::InlineSignAs) -> SignatureType {
2673 match mode {
2674 InlineSignAs::Binary => SignatureType::Binary,
2675 InlineSignAs::Text => SignatureType::Text,
2676 InlineSignAs::ClearSigned => SignatureType::Text,
2677 }
2678}
2679
2680fn symbolic_profiles() -> impl Iterator<Item=&'static str> {
2682 [
2683 "default",
2684 "security",
2685 "performance",
2686 "compatibility",
2687 ].into_iter()
2688}
2689
2690fn list_profiles(profiles: &[(&str, &str)],
2692 normalize: &dyn Fn(&str) -> Result<&'static str>)
2693 -> Vec<(String, String)> {
2694 let mut p = profiles.iter()
2695 .map(|(p, d)| {
2696 let aliases = symbolic_profiles()
2698 .filter_map(|q| {
2699 if normalize(q)
2700 .map(|q| q == *p)
2701 .unwrap_or(false)
2702 {
2703 Some(q)
2704 } else {
2705 None
2706 }
2707 })
2708 .collect::<Vec<_>>();
2709
2710 let description = if aliases.is_empty() {
2711 d.to_string()
2712 } else {
2713 format!("{} (alias{}: {})",
2714 d,
2715 if aliases.len() > 1 { "es" } else { "" },
2716 aliases.join(", "))
2717 };
2718
2719 (p.to_string(), description)
2720 })
2721 .collect::<Vec<_>>();
2722
2723 if let Ok(default) = normalize("default") {
2725 p.sort_by_key(|(name, _)| name != default);
2726 assert_eq!(&p[0].0, default);
2727 }
2728
2729 p
2730}
2731
2732fn print_error_chain(sink: &mut dyn io::Write, err: &anyhow::Error)
2734 -> io::Result<()>
2735{
2736 writeln!(sink, " {}", err)?;
2737 for cause in err.chain().skip(1) {
2738 writeln!(sink, " because: {}", cause)?;
2739 }
2740 Ok(())
2741}
2742
2743fn sop_error(sqop: &SQOP, e: anyhow::Error) -> Error {
2748 tracer!(sqop.debug, "sop_error");
2749
2750 let e = match e.downcast::<Error>() {
2751 Ok(e) => return e,
2752 Err(e) => e,
2753 };
2754
2755 t!("mapping error: {}", e);
2756
2757 let e = match e.downcast::<io::Error>() {
2758 Ok(e) => return if e.kind() == io::ErrorKind::UnexpectedEof {
2759 Error::BadData
2760 } else {
2761 e.into()
2762 },
2763 Err(e) => e,
2764 };
2765
2766 if let Some(e) = e.downcast_ref::<openpgp::Error>() {
2767 use openpgp::Error::*;
2768 return match e {
2769 InvalidArgument(_) => Error::BadData,
2770 InvalidOperation(_) => Error::BadData,
2771 MalformedPacket(_) => Error::BadData,
2772 PacketTooLarge(_, _, _) => Error::BadData,
2773
2774 UnsupportedPacketType(_) => Error::BadData,
2775
2776 UnsupportedHashAlgorithm(_) => Error::UnsupportedAsymmetricAlgo,
2778 UnsupportedPublicKeyAlgorithm(_) => Error::UnsupportedAsymmetricAlgo,
2779 UnsupportedEllipticCurve(_) => Error::UnsupportedAsymmetricAlgo,
2780 UnsupportedSymmetricAlgorithm(_) => Error::UnsupportedAsymmetricAlgo,
2781 UnsupportedAEADAlgorithm(_) => Error::UnsupportedAsymmetricAlgo,
2782 UnsupportedCompressionAlgorithm(_) => Error::UnsupportedAsymmetricAlgo,
2783
2784 UnsupportedSignatureType(_) => Error::BadData,
2785 InvalidSessionKey(_) => Error::CannotDecrypt,
2786 MissingSessionKey(_) => Error::CannotDecrypt,
2787 MalformedMPI(_) => Error::BadData,
2788 BadSignature(_) => Error::BadData,
2789 MalformedMessage(_) => Error::BadData,
2790 MalformedCert(_) => Error::BadData,
2791 UnsupportedCert(_, _) => Error::BadData,
2792 Expired(_) => Error::BadData,
2793 NotYetLive(_) => Error::BadData,
2794 NoBindingSignature(_) => Error::BadData,
2795 InvalidKey(_) => Error::BadData,
2796 PolicyViolation(_, _) => Error::BadData,
2797 e => {
2798 t!("unknown Sequoia error");
2799 Error::BadData
2800 },
2801 };
2802 }
2803
2804 t!("untranslated error");
2805 Error::BadData
2806}
2807
2808#[cfg(test)]
2809mod tests {
2810 use std::io::Cursor;
2811 use super::*;
2812
2813 #[test]
2824 fn sop_examples() -> Result<()> {
2825 let sop = SQOP::default();
2826
2827 let alice_sec = sop.generate_key()?
2828 .userid("Alice Lovelace <alice@openpgp.example>")
2829 .generate()?;
2830 let alice_pgp = sop.extract_cert()?
2831 .keys(&alice_sec)?;
2832
2833 let bob_sec = sop.generate_key()?
2834 .userid("Bob Babbage <bob@openpgp.example>")
2835 .generate()?;
2836 let bob_pgp = sop.extract_cert()?
2837 .keys(&bob_sec)?;
2838
2839 let statement = b"Hello World :)";
2840 let mut data = Cursor::new(&statement);
2841 let (_micalg, signature) = sop.sign()?
2842 .mode(SignAs::Text)
2843 .keys(&alice_sec)?
2844 .data(&mut data)?;
2845
2846 let verifications = sop.verify()?
2847 .certs(&alice_pgp)?
2848 .signatures(&signature)?
2849 .data(&mut Cursor::new(&statement))?;
2850 assert_eq!(verifications.len(), 1);
2851
2852 let mut statement_cur = Cursor::new(&statement);
2853 let (_session_key, ciphertext) = sop.encrypt()?
2854 .sign_with_keys(&alice_sec)?
2855 .with_certs(&bob_pgp)?
2856 .plaintext(&mut statement_cur)?
2857 .to_vec()?;
2858
2859 let mut ciphertext_cur = Cursor::new(&ciphertext);
2860 let (_, plaintext) = sop.decrypt()?
2861 .with_keys(&bob_sec)?
2862 .ciphertext(&mut ciphertext_cur)?
2863 .to_vec()?;
2864 assert_eq!(&plaintext, statement);
2865
2866 Ok(())
2867 }
2868
2869 #[test]
2870 fn issue_29() -> Result<()> {
2871 let sop = SQOP::default();
2872
2873 let alice_sec = sop.generate_key()?
2874 .userid("Alice Lovelace <alice@openpgp.example>")
2875 .generate()?;
2876 let alice_pgp = sop.extract_cert()?
2877 .keys(&alice_sec)?;
2878
2879 let no_signature = b"\n";
2880 assert!(matches!(sop.inline_verify()?
2881 .certs(&alice_pgp)?
2882 .message(&mut Cursor::new(&no_signature))
2883 .and_then(|ready| ready.to_vec()),
2884 Err(sop::errors::Error::BadData)));
2885
2886 Ok(())
2887 }
2888
2889 #[test]
2890 fn test_pqc() -> Result<()> {
2891 if ! PublicKeyAlgorithm::MLDSA65_Ed25519.is_supported() {
2892 eprintln!("MLDSA65_Ed25519 is not supported, skipping.");
2893 return Ok(());
2894 }
2895
2896 let sop = SQOP::default();
2897
2898 let alice_sec = sop.generate_key()?
2899 .profile("rfc9980")?
2900 .userid("Alice Lovelace <alice@openpgp.example>")
2901 .generate()?;
2902 let alice_pgp = sop.extract_cert()?
2903 .keys(&alice_sec)?;
2904
2905 let statement = b"Hello World :)";
2906 let mut data = Cursor::new(&statement);
2907 let (_micalg, signature) = sop.sign()?
2908 .mode(SignAs::Text)
2909 .keys(&alice_sec)?
2910 .data(&mut data)?;
2911
2912 let verifications = sop.verify()?
2913 .certs(&alice_pgp)?
2914 .signatures(&signature)?
2915 .data(&mut Cursor::new(&statement))?;
2916 assert_eq!(verifications.len(), 1);
2917
2918 let mut statement_cur = Cursor::new(&statement);
2919 let (_session_key, ciphertext) = sop.encrypt()?
2920 .sign_with_keys(&alice_sec)?
2921 .with_certs(&alice_pgp)?
2922 .plaintext(&mut statement_cur)?
2923 .to_vec()?;
2924
2925 let mut ciphertext_cur = Cursor::new(&ciphertext);
2926 let (_, plaintext) = sop.decrypt()?
2927 .with_keys(&alice_sec)?
2928 .ciphertext(&mut ciphertext_cur)?
2929 .to_vec()?;
2930 assert_eq!(&plaintext, statement);
2931
2932 Ok(())
2933 }
2934}