1use std::env;
71use std::ffi::{
72 CString,
73};
74use std::fmt::Debug;
75use std::io::Read;
76use std::io::Write;
77use std::path::PathBuf;
78use std::sync::RwLock;
79use std::time::{
80 Duration,
81 SystemTime,
82 UNIX_EPOCH,
83};
84
85#[allow(unused_imports)]
86use anyhow::Context;
87
88use libc::{
89 c_char,
90 c_int,
91 c_uint,
92 c_void,
93 size_t,
94};
95
96use chrono::{
97 DateTime,
98 Utc,
99};
100
101use sequoia_openpgp as openpgp;
102use openpgp::armor;
103use openpgp::Cert;
104use openpgp::cert::prelude::*;
105use openpgp::Fingerprint;
106use openpgp::KeyID;
107use openpgp::packet::key::{
108 PublicParts,
109};
110use openpgp::packet::{
111 Packet,
112 Signature,
113 Tag,
114};
115use openpgp::parse::{
116 PacketParser,
117 PacketParserResult,
118 PacketParserBuilder,
119 Dearmor,
120};
121use openpgp::parse::Parse;
122use openpgp::policy::{
123 NullPolicy,
124 StandardPolicy,
125 Policy,
126};
127use openpgp::serialize::SerializeInto;
128use openpgp::types::RevocationStatus;
129
130use openpgp::parse::buffered_reader;
131
132#[macro_use] mod log;
133#[macro_use] mod ffi;
134#[macro_use] pub mod rpm;
135use rpm::{
136 Error,
137 ErrorCode,
138 PgpArmor,
139 PgpArmorError,
140 Result,
141};
142pub mod digest;
143
144lazy_static::lazy_static! {
145 static ref P: RwLock<StandardPolicy<'static>> = RwLock::new(StandardPolicy::new());
146}
147const NP: &NullPolicy = unsafe {
148 &NullPolicy::new()
149};
150
151lazy_static::lazy_static! {
154 static ref TRACE: bool = {
155 if let Ok(v) = env::var("RPM_TRACE") {
156 let v: isize = v.parse().unwrap_or(1);
157 v != 0
158 } else {
159 false
160 }
161 };
162}
163
164pub fn print_error_chain(err: &anyhow::Error) {
166 eprintln!(" {}", err);
167 err.chain().skip(1).for_each(|cause| eprintln!(" because: {}", cause));
168}
169
170fn error_chain(err: &anyhow::Error) -> Vec<String> {
185 let mut errs = std::iter::once(err.to_string())
186 .chain(err.chain().map(|source| source.to_string()))
187 .collect::<Vec<String>>();
188 errs.dedup();
189 errs
190}
191
192macro_rules! linter {
198 ($dollar:tt, $lints:ident) => {
199 macro_rules! add_lint {
207 ($err:expr, $msg:expr $dollar(, $args:expr)*) => {{
208 let err: Option<anyhow::Error> = $err;
209 let msg = format!("{}", format_args!($msg $dollar(, $args)*));
210 let err = if let Some(err) = err {
211 err.context(msg)
212 } else {
213 anyhow::anyhow!(msg)
214 };
215 $lints.push(err);
216 }};
217 }
218
219 macro_rules! return_err {
224 ($err:expr, $msg:expr $dollar(, $args:expr)*) => {{
225 add_lint!($err, $msg $dollar(, $args)*);
226 return Err(Error::Fail(
227 format!("{}", format_args!($msg $dollar(, $args)*))));
228 }};
229 }
230 }
231}
232
233const RPM_SEQUOIA_CONFIG_ENV: &'static str
236 = "RPM_SEQUOIA_CRYPTO_POLICY";
237const RPM_SEQUOIA_CONFIG: &[&str] = &[
238 "/etc/crypto-policies/back-ends/rpm-sequoia.config",
239 "/usr/share/crypto-policies/back-ends/rpm-sequoia.config",
240];
241
242ffi!(
243fn _rpmInitCrypto() -> Binary {
245 let mut p = openpgp::policy::StandardPolicy::new();
254 p.accept_packet_tag_version(openpgp::packet::Tag::Signature, 3);
255
256 let mut p = sequoia_policy_config::ConfiguredStandardPolicy
257 ::from_policy(p);
258
259 let rpm_sequoia_config = RPM_SEQUOIA_CONFIG
263 .iter()
264 .find(|path| {
265 PathBuf::from(path).exists()
266 })
267 .unwrap_or(&RPM_SEQUOIA_CONFIG[0]);
268
269 match p.parse_config(RPM_SEQUOIA_CONFIG_ENV,
270 rpm_sequoia_config)
271 {
272 Ok(false) => {
273 if let Err(err) = p.parse_default_config() {
275 print_error_chain(&err);
276 return Err(err.into());
277 }
278 }
279 Ok(true) => (),
280 Err(err) => {
281 print_error_chain(&err);
282 return Err(err.into());
283 }
284 }
285
286 *crate::P.write().unwrap() = p.build();
287
288 Ok(())
289});
290
291ffi!(
292fn _rpmFreeCrypto() -> Binary {
294 Ok(())
295});
296
297enum PgpDigParamsObj {
314 Cert(Cert),
315 Subkey(Cert, Fingerprint),
316 Signature(Signature),
317}
318
319pub struct PgpDigParams {
320 obj: PgpDigParamsObj,
321 signid: [u8; 8],
322 userid: Option<CString>,
323}
324
325impl PgpDigParams {
326 fn cert(&self) -> Option<&Cert> {
327 match &self.obj {
328 PgpDigParamsObj::Cert(cert) => Some(cert),
329 PgpDigParamsObj::Subkey(cert, _) => Some(cert),
330 PgpDigParamsObj::Signature(_) => None,
331 }
332 }
333
334 fn key(&self) -> Option<ErasedKeyAmalgamation<PublicParts>> {
335 match &self.obj {
336 PgpDigParamsObj::Cert(cert) => {
337 Some(cert.primary_key().into())
338 }
339 PgpDigParamsObj::Subkey(cert, fpr) => {
340 Some(cert.keys().subkeys()
341 .key_handle(fpr)
342 .next()
343 .expect("subkey missing")
344 .into())
345 }
346 PgpDigParamsObj::Signature(_) => None,
347 }
348 }
349
350 fn signature(&self) -> Option<&Signature> {
351 match &self.obj {
352 PgpDigParamsObj::Cert(_) => None,
353 PgpDigParamsObj::Subkey(_, _) => None,
354 PgpDigParamsObj::Signature(sig) => Some(sig),
355 }
356 }
357}
358
359ffi!(
360fn _pgpSignatureType(dig: *const PgpDigParams) -> c_int[-1] {
365 let dig = check_ptr!(dig);
366
367 dig.signature()
368 .ok_or_else(|| Error::Fail("Not a signature".into()))
369 .map(|sig| {
370 u8::from(sig.typ()).into()
371 })
372});
373
374ffi!(
375fn _pgpDigParamsFree(dig: Option<&mut PgpDigParams>) {
377 free!(dig);
378});
379
380ffi!(
381fn _pgpDigParamsCmp(p1: *const PgpDigParams,
398 p2: *const PgpDigParams)
399 -> c_int[1]
400{
401 let p1 = check_ptr!(p1);
402 let p2 = check_ptr!(p2);
403
404 let r = match (&p1.obj, &p2.obj) {
405 (PgpDigParamsObj::Cert(c1), PgpDigParamsObj::Cert(c2)) => {
406 c1.fingerprint() == c2.fingerprint()
407 }
408 (PgpDigParamsObj::Subkey(_, f1), PgpDigParamsObj::Subkey(_, f2)) => {
409 f1 == f2
410 }
411 (PgpDigParamsObj::Signature(s1), PgpDigParamsObj::Signature(s2)) => {
412 t!("s1: {:?}", s1);
413 t!("s2: {:?}", s2);
414 s1.hash_algo() == s2.hash_algo()
415 && s1.pk_algo() == s2.pk_algo()
416 && s1.version() == s2.version()
417 && s1.typ() == s2.typ()
418 && p1.signid == p2.signid
419 }
420 _ => {
421 false
422 }
423 };
424
425 Ok(if r { 0 } else { 1 })
426});
427
428const PGPVAL_PUBKEYALGO: c_uint = 6;
429const PGPVAL_HASHALGO: c_uint = 9;
430
431ffi!(
432fn _pgpDigParamsAlgo(dig: *const PgpDigParams,
438 algotype: c_uint) -> c_uint[0]
439{
440 let dig = check_ptr!(dig);
441
442 match (algotype, &dig.obj) {
443 (PGPVAL_PUBKEYALGO, PgpDigParamsObj::Cert(cert)) => {
445 Ok(u8::from(cert.primary_key().key().pk_algo()).into())
446 }
447 (PGPVAL_PUBKEYALGO, PgpDigParamsObj::Subkey(_, _)) => {
448 Ok(u8::from(dig.key().expect("valid").key().pk_algo()).into())
449 }
450 (PGPVAL_PUBKEYALGO, PgpDigParamsObj::Signature(sig)) => {
451 Ok(u8::from(sig.pk_algo()).into())
452 }
453
454 (PGPVAL_HASHALGO, PgpDigParamsObj::Cert(cert)) => {
456 match cert.with_policy(&*P.read().unwrap(), None) {
457 Ok(vc) => {
458 let algo = vc.primary_key().binding_signature().hash_algo();
459 Ok(u8::from(algo).into())
460 }
461 Err(err) => {
462 Err(Error::Fail(
463 format!("Using {}: {}", cert.fingerprint(), err)))
464 }
465 }
466 }
467 (PGPVAL_HASHALGO, PgpDigParamsObj::Subkey(_, fpr)) => {
468 let ka = dig.key().expect("valid");
469 match ka.with_policy(&*P.read().unwrap(), None) {
470 Ok(ka) => {
471 let algo = ka.binding_signature().hash_algo();
472 Ok(u8::from(algo).into())
473 }
474 Err(err) => {
475 Err(Error::Fail(
476 format!("Using {}: {}", fpr, err)))
477 }
478 }
479 }
480 (PGPVAL_HASHALGO, PgpDigParamsObj::Signature(sig)) => {
481 Ok(u8::from(sig.hash_algo()).into())
482 }
483
484 (t, PgpDigParamsObj::Cert(_))
486 | (t, PgpDigParamsObj::Subkey(_, _))
487 | (t, PgpDigParamsObj::Signature(_)) => {
488 Err(Error::Fail(format!("Invalid algorithm type: {}", t)))
489 }
490 }
491});
492
493ffi!(
494fn _pgpDigParamsSignID(dig: *const PgpDigParams) -> *const u8 {
505 let dig = check_ptr!(dig);
506 t!("SignID: {}",
507 dig.signid.iter().map(|v| format!("{:02X}", v)).collect::<String>());
508 Ok(dig.signid.as_ptr())
509});
510
511ffi!(
512fn _pgpDigParamsUserID(dig: *const PgpDigParams) -> *const c_char {
524 let dig = check_ptr!(dig);
525 if let Some(ref userid) = dig.userid {
526 Ok(userid.as_ptr())
527 } else {
528 Ok(std::ptr::null())
529 }
530});
531
532ffi!(
533fn _pgpDigParamsVersion(dig: *const PgpDigParams) -> c_int[0] {
544 let dig = check_ptr!(dig);
545 let version = match &dig.obj {
546 PgpDigParamsObj::Cert(cert) => {
547 cert.primary_key().key().version()
548 }
549 PgpDigParamsObj::Subkey(_, _) => {
550 dig.key().unwrap().key().version()
551 }
552 PgpDigParamsObj::Signature(sig) => {
553 sig.version()
554 }
555 };
556 Ok(version as c_int)
557});
558
559ffi!(
560fn _pgpDigParamsCreationTime(dig: *const PgpDigParams) -> u32[0] {
571 let dig = check_ptr!(dig);
572 let t = match &dig.obj {
573 PgpDigParamsObj::Cert(cert) => {
574 cert.primary_key().key().creation_time()
575 }
576 PgpDigParamsObj::Subkey(cert, fpr) => {
577 cert.keys().subkeys()
578 .key_handle(fpr)
579 .next()
580 .expect("subkey missing")
581 .key()
582 .creation_time()
583 }
584 PgpDigParamsObj::Signature(sig) => {
585 sig.signature_creation_time().unwrap_or(UNIX_EPOCH)
586 }
587 };
588 Ok(t.duration_since(UNIX_EPOCH)
589 .map_err(|_| Error::Fail("time".into()))?
590 .as_secs() as u32)
591});
592
593ffi!(
594fn _pgpDigParamsSalt(dig: *const PgpDigParams,
606 datap: *mut *const u8,
607 lenp: *mut size_t)
608 -> ErrorCode
609{
610 let dig = check_ptr!(dig);
611 let datap = check_mut!(datap);
612 let lenp = check_mut!(lenp);
613
614 let sig = dig.signature().ok_or_else(|| {
615 Error::Fail("dig parameter does not designate a signature".into())
616 })?;
617
618 if let Some(salt) = sig.salt() {
619 t!("Salt: {}",
620 salt.iter().map(|v| format!("{:02X}", v)).collect::<String>());
621 *lenp = salt.len() as size_t;
622 *datap = salt.as_ptr();
623 Ok(())
624 } else {
625 Err(Error::Fail("The provided signature does not have any salt".into()))
626 }
627});
628
629
630ffi!(
631fn _pgpVerifySignature(key: *const PgpDigParams,
668 sig: *const PgpDigParams,
669 ctx: *const digest::DigestContext) -> ErrorCode {
670 match _pgpVerifySignature2(key, sig, ctx, std::ptr::null_mut()) {
671 0 => Ok(()),
672 ec => Err(Error::from(ec)),
673 }
674});
675
676ffi!(
677fn _pgpVerifySignature2(key: *const PgpDigParams,
680 sig: *const PgpDigParams,
681 ctx: *const digest::DigestContext,
682 lint_str: *mut *mut c_char) -> ErrorCode {
683 let key: Option<&PgpDigParams> = check_optional_ptr!(key);
684 let sig: &PgpDigParams = check_ptr!(sig);
685 let mut ctx = check_ptr!(ctx).clone();
687 let mut lint_str: Option<&mut _> = check_optional_mut!(lint_str);
688
689 if let Some(lint_str) = lint_str.as_mut() {
690 **lint_str = std::ptr::null_mut();
691 }
692
693 let mut lints = Vec::new();
694 let r = pgp_verify_signature(key, sig, ctx, &mut lints);
695
696 if lints.len() > 0 {
698 let mut s: String = if let Some(key) = key {
699 format!(
700 "Verifying a signature using certificate {} ({}):",
701 key.cert()
702 .map(|cert| cert.fingerprint().to_string())
703 .unwrap_or_else(|| "<invalid certificate>".to_string()),
704 key.cert()
705 .and_then(|cert| {
706 cert.userids().next()
707 .map(|userid| {
708 String::from_utf8_lossy(userid.userid().value()).into_owned()
709 })
710 })
711 .unwrap_or_else(|| {
712 "<unknown>".into()
713 }))
714 } else {
715 format!(
716 "Verifying a signature, but no certificate was \
717 provided:")
718 };
719
720 let sep = "\n ";
722
723 let lints_count = lints.len();
724 for (err_i, err) in lints.into_iter().enumerate() {
725 for (cause_i, cause) in error_chain(&err).into_iter().enumerate() {
726 if cause_i == 0 {
727 s.push_str(sep);
728 if lints_count > 1 {
729 s.push_str(&format!("{}. ", err_i + 1));
730 }
731 } else {
732 s.push_str(sep);
733 s.push_str(" because: ");
734 }
735 s.push_str(&cause);
736 }
737 }
738
739 t!("Lints: {}", s);
740
741 if let Some(lint_str) = lint_str.as_mut() {
742 s.push('\0');
744
745 **lint_str = s.as_mut_ptr() as *mut c_char;
746 std::mem::forget(s);
748 }
749 }
750
751 r
752});
753
754fn pgp_verify_signature(key: Option<&PgpDigParams>,
758 sig: &PgpDigParams,
759 mut ctx: digest::DigestContext,
760 lints: &mut Vec<anyhow::Error>)
761 -> Result<()>
762{
763 tracer!(*crate::TRACE, "pgp_verify_signature");
764
765 linter!($, lints);
766
767 let mut legacy = false;
769
770 let sig = sig.signature().ok_or_else(|| {
771 Error::Fail("sig parameter does not designate a signature".into())
772 })?;
773
774 let sig_id = || {
775 let digest_prefix = sig.digest_prefix();
776 format!("{:02x}{:02x} created at {}",
777 digest_prefix[0],
778 digest_prefix[1],
779 if let Some(t) = sig.signature_creation_time() {
780 DateTime::<Utc>::from(t)
781 .format("%c").to_string()
782 } else {
783 "<unknown>".to_string()
784 })
785 };
786
787 let sig_time = if let Some(t) = sig.signature_creation_time() {
788 t
789 } else {
790 return_err!(
791 None,
792 "Signature {} invalid: signature missing a creation time",
793 sig_id());
794 };
795
796 if let Err(err) = sig.signature_alive(None, Duration::new(5 * 60, 0)) {
798 return_err!(
799 Some(err),
800 "Signature {} invalid: signature is not alive",
801 sig_id());
802 }
803
804 {
805 let policy = P.read().unwrap();
806 if let Err(err) = policy.signature(sig, Default::default()) {
807 if NP.signature(sig, Default::default()).is_ok() {
808 legacy = true;
809 add_lint!(
810 Some(err),
811 "Signature {} invalid: signature relies on legacy cryptography",
812 sig_id());
813 } else {
814 return_err!(
815 Some(err),
816 "Signature {} invalid: policy violation", sig_id());
817 }
818 }
819 if let Err(err) = policy.packet(&Packet::from(sig.clone())) {
824 if NP.packet(&Packet::from(sig.clone())).is_ok() {
825 legacy = true;
826 add_lint!(
827 Some(err),
828 "Signature {} invalid: signature relies on legacy cryptography",
829 sig_id());
830 } else {
831 return_err!(
832 Some(err),
833 "Signature {} invalid: policy violation", sig_id());
834 }
835 }
836 }
837
838 let issuer = match sig.get_issuers().into_iter().next() {
841 Some(issuer) => issuer,
842 None => return_err!(
843 None,
844 "Signature {} invalid: signature has no issuer subpacket",
845 sig_id()),
846 };
847
848 if let Some(key) = key {
849 let cert = key.cert().ok_or_else(|| {
851 Error::Fail("key parameter is not a cert".into())
852 })?;
853 let subkey = key.key().expect("is a certificate").key().fingerprint();
854
855 t!("Checking signature {} using {} with {} / {}",
856 sig_id(), sig.hash_algo(),
857 cert.fingerprint(), subkey);
858
859 let p = &*P.read().unwrap();
862 let vc = cert.with_policy(p, sig_time)
863 .or_else(|err| {
864 match cert.with_policy(p, None) {
868 Ok(vc) => {
869 Ok(vc)
882 }
883 Err(err2) => {
884 add_lint!(
885 Some(err),
886 "Certificate {} invalid: policy violation",
887 cert.keyid());
888 Err(err2)
889 }
890 }
891 })
892 .or_else(|err| {
893 legacy = true;
894 add_lint!(
895 Some(err),
896 "Certificate {} invalid: policy violation",
897 cert.keyid());
898 cert.with_policy(NP, sig_time)
899 })?;
900
901 if let Err(err) = vc.alive() {
902 legacy = true;
903 add_lint!(
904 Some(err),
905 "Certificate {} invalid: certificate is not alive",
906 vc.keyid());
907 }
908 if let RevocationStatus::Revoked(_) = vc.revocation_status() {
909 legacy = true;
910 add_lint!(
911 None,
912 "Certificate {} invalid: certificate is revoked",
913 vc.keyid());
914 }
915
916 match vc.keys().key_handle(issuer.clone()).next() {
918 Some(ka) => {
919 if ka.key().fingerprint() != subkey {
920 return_err!(None,
921 "Key {} invalid: wrong subkey ({})",
922 ka.key().keyid(), subkey);
923 }
924 if ! ka.for_signing() {
925 return_err!(None,
926 "Key {} invalid: not signing capable",
927 ka.key().keyid());
928 }
929 if let Err(err) = ka.alive() {
930 legacy = true;
931 add_lint!(Some(err),
932 "Key {} invalid: key is not alive",
933 ka.key().keyid());
934 }
935 if let RevocationStatus::Revoked(_) = ka.revocation_status() {
936 legacy = true;
937 add_lint!(None,
938 "Key {} is invalid: key is revoked",
939 ka.key().keyid());
940 }
941
942 sig.clone().verify_hash(ka.key(), ctx.ctx.clone())?;
944 if legacy {
945 return Err(Error::NotTrusted(
946 "Verification relies on legacy crypto".into())
947 .into());
948 } else {
949 return Ok(());
950 }
951 }
952 None => {
953 return_err!(None,
954 "Certificate {} does not contain key {} \
955 or it is not valid",
956 vc.keyid(), issuer);
957 }
958 }
959 } else {
960 use openpgp::serialize::Marshal;
966 use openpgp::serialize::MarshalInto;
967
968 let mut sig_data = Vec::with_capacity(128);
970
971 match sig.version() {
973 4 | 6 => {
974 sig_data.push(sig.version());
975 sig_data.push(sig.typ().into());
976 sig_data.push(sig.pk_algo().into());
977 sig_data.push(sig.hash_algo().into());
978
979 let l = sig.hashed_area().serialized_len();
980 if sig.version() == 6 {
981 sig_data.push((l >> 24) as u8);
983 sig_data.push((l >> 16) as u8);
984 }
985 sig_data.push((l >> 8) as u8);
986 sig_data.push((l >> 0) as u8);
987
988 sig.hashed_area().serialize(&mut sig_data).expect("vec");
989
990 let sig_len = sig_data.len();
991
992 sig_data.push(sig.version());
994 sig_data.push(0xFF);
995 sig_data.push((sig_len >> 24) as u8);
996 sig_data.push((sig_len >> 16) as u8);
997 sig_data.push((sig_len >> 8) as u8);
998 sig_data.push((sig_len >> 0) as u8);
999 }
1000 3 => {
1001 sig_data.push(sig.typ().into());
1002 let ct = sig.signature_creation_time().unwrap_or(UNIX_EPOCH);
1003 let ct = ct.duration_since(UNIX_EPOCH)
1004 .map_err(|_| Error::Fail("time".into()))?
1005 .as_secs() as u32;
1006 sig_data.push((ct >> 24) as u8);
1007 sig_data.push((ct >> 16) as u8);
1008 sig_data.push((ct >> 8) as u8);
1009 sig_data.push((ct >> 0) as u8);
1010 }
1011 v => {
1012 return Err(Error::Fail(
1013 format!("Unsupported signature version: {}", v)));
1014 }
1015 }
1016
1017 ctx.update(&sig_data);
1018
1019 let digest_size = ctx.digest_size();
1020 let mut digest: Vec<u8> = Vec::with_capacity(digest_size);
1021 for _ in 0..digest_size {
1022 digest.push(0);
1023 }
1024 ctx.digest(&mut digest[..])?;
1025
1026 let p = sig.digest_prefix();
1027 if p[0] != digest[0] || p[1] != digest[1] {
1028 return Err(Error::Fail("digest prefix mismatch".into()));
1029 } else {
1030 t!("digest prefix matches");
1031 }
1032
1033 if ! sig.pk_algo().is_supported() {
1034 return Err(Error::NotTrusted(
1035 format!("Signature relies on unknown or unsupported \
1036 cryptographic algorithm {}",
1037 sig.pk_algo())));
1038 } else if legacy {
1039 return Err(Error::NotTrusted(
1040 "Signature relies on legacy crypto".into())
1041 .into());
1042 } else {
1043 return Err(Error::NoKey(
1044 format!("Not provided (issuer: {})", issuer).into()));
1045 }
1046 }
1047}
1048
1049ffi!(
1050fn _pgpPubkeyKeyID(pkt: *const u8, pktlen: size_t, keyid: *mut u8)
1063 -> Binary
1064{
1065 let pkt = check_slice!(pkt, pktlen);
1066
1067 let ppr = PacketParser::from_bytes(pkt)?;
1068 let k = if let PacketParserResult::Some(ref pp) = ppr {
1069 match &pp.packet {
1070 Packet::PublicKey(key) => Some(key.keyid()),
1071 Packet::SecretKey(key) => Some(key.keyid()),
1072 _ => None,
1073 }
1074 } else {
1075 None
1076 };
1077
1078 t!("Key ID: {}",
1079 k.as_ref()
1080 .map(|k| k.to_string())
1081 .unwrap_or_else(|| String::from("none")));
1082
1083 if let Some(k) = k {
1084 let buffer = check_mut_slice!(keyid, 8);
1085 buffer.copy_from_slice(k.as_bytes());
1086
1087 Ok(())
1088 } else {
1089 Err(Error::Fail("Not a key".into()))
1090 }
1091});
1092
1093ffi!(
1094fn _pgpPubkeyFingerprint(pkt: *const u8, pktlen: size_t,
1106 fprout: *mut *mut u8, fprlen: *mut size_t)
1107 -> Binary
1108{
1109 let pkt = check_slice!(pkt, pktlen);
1110
1111 let ppr = PacketParserBuilder::from_bytes(pkt)?
1112 .dearmor(Dearmor::Disabled) .build()?;
1114 let fpr = if let PacketParserResult::Some(ref pp) = ppr {
1115 match &pp.packet {
1116 Packet::PublicKey(key) => Some(key.fingerprint()),
1117 Packet::SecretKey(key) => Some(key.fingerprint()),
1118 _ => None,
1119 }
1120 } else {
1121 None
1122 };
1123
1124 t!("Fingerprint: {}",
1125 fpr.as_ref()
1126 .map(|fpr| fpr.to_string())
1127 .unwrap_or_else(|| String::from("none")));
1128
1129 if let Some(fpr) = fpr {
1130 let fpr = fpr.as_bytes();
1131 unsafe {
1132 let buffer = libc::malloc(fpr.len());
1133 if buffer.is_null() {
1134 return Err(Error::Fail("out of memory".into()));
1135 }
1136 libc::memcpy(buffer, fpr.as_ptr() as *const c_void, fpr.len());
1137 *fprout = buffer as *mut u8;
1138 *fprlen = fpr.len();
1139 }
1140
1141 Ok(())
1142 } else {
1143 Err(Error::Fail("Not a key".into()))
1144 }
1145});
1146
1147ffi!(
1148fn _pgpArmorWrap(atype: c_int, s: *const c_char, ns: size_t)
1156 -> *mut c_char
1157{
1158 let atype = armor::Kind::try_from(PgpArmor::from(atype))?;
1159 let s = check_slice!(s, ns);
1160
1161 let mut writer = armor::Writer::new(Vec::new(), atype)
1162 .map_err(|err| Error::Fail(format!("creating armor writer: {}", err)))?;
1163 writer.write(s)
1164 .map_err(|err| Error::Fail(format!("writing armor body: {}", err)))?;
1165
1166 let mut buffer = writer.finalize()
1167 .map_err(|err| Error::Fail(format!("finalizing armor: {}", err)))?;
1168 buffer.push(0);
1170
1171 let ptr = buffer.as_mut_ptr() as *mut c_char;
1172 std::mem::forget(buffer);
1173
1174 Ok(ptr)
1175});
1176
1177ffi!(
1178fn _pgpPubKeyCertLen(pkts: *const u8, pktslen: size_t,
1185 certlen: *mut size_t) -> Binary
1186{
1187 use openpgp::packet::Header;
1188 use openpgp::packet::header::PacketLengthType;
1189 use openpgp::packet::header::BodyLength;
1190 use openpgp::packet::header::CTB;
1191 use buffered_reader::BufferedReader;
1192
1193 let pkts = check_slice!(pkts, pktslen);
1194 let certlen = check_mut!(certlen);
1195
1196 fn body_length_parse_new_format<T, C>(bio: &mut T)
1200 -> openpgp::Result<BodyLength>
1201 where T: BufferedReader<C>, C: Debug + Send + Sync
1202 {
1203 let octet1 : u8 = bio.data_consume_hard(1)?[0];
1204 match octet1 {
1205 0..=191 => Ok(BodyLength::Full(octet1 as u32)),
1207 192..=223 => { let octet2 = bio.data_consume_hard(1)?[0];
1209 Ok(BodyLength::Full(((octet1 as u32 - 192) << 8)
1210 + octet2 as u32 + 192))
1211 },
1212 224..=254 => Ok(BodyLength::Partial(1 << (octet1 & 0x1F))),
1214 255 => Ok(BodyLength::Full(bio.read_be_u32()?)),
1216 }
1217 }
1218
1219 fn body_length_parse_old_format<T, C>(bio: &mut T,
1224 length_type: PacketLengthType)
1225 -> openpgp::Result<BodyLength>
1226 where T: BufferedReader<C>, C: Debug + Send + Sync
1227 {
1228 match length_type {
1229 PacketLengthType::OneOctet =>
1230 Ok(BodyLength::Full(bio.data_consume_hard(1)?[0] as u32)),
1231 PacketLengthType::TwoOctets =>
1232 Ok(BodyLength::Full(bio.read_be_u16()? as u32)),
1233 PacketLengthType::FourOctets =>
1234 Ok(BodyLength::Full(bio.read_be_u32()? as u32)),
1235 PacketLengthType::Indeterminate =>
1236 Ok(BodyLength::Indeterminate),
1237 }
1238 }
1239
1240 fn parse_header<T, C>(bio: &mut T)
1241 -> openpgp::Result<Header>
1242 where T: BufferedReader<C>, C: Debug + Send + Sync
1243 {
1244 let ctb = CTB::try_from(bio.data_consume_hard(1)?[0])?;
1245 let length = match ctb {
1246 CTB::New(_) => body_length_parse_new_format(bio)?,
1247 CTB::Old(ref ctb) =>
1248 body_length_parse_old_format(bio, ctb.length_type())?,
1249 };
1250 return Ok(Header::new(ctb, length));
1251 }
1252
1253 let mut br = buffered_reader::Memory::new(pkts);
1254
1255 let mut found_cert = false;
1256 let len: Option<usize> = loop {
1257 let start_of_packet = br.total_out();
1259
1260 if start_of_packet == pkts.len() {
1261 break Some(start_of_packet);
1263 }
1264
1265 let header = match parse_header(&mut br) {
1266 Ok(header) => header,
1267 Err(err) => {
1268 t!("Error reading certificate at offset {}: {}",
1269 start_of_packet, err);
1270 break None;
1271 }
1272 };
1273
1274 use Tag::*;
1275 let t = header.ctb().tag();
1276 t!("Found a {:?} at offset {}, length: {:?}",
1277 t, start_of_packet, header.length());
1278 match t {
1279 PublicKey | SecretKey => {
1281 if found_cert {
1282 break Some(start_of_packet);
1283 } else {
1284 found_cert = true;
1285 }
1286 }
1287
1288 PublicSubkey
1290 | SecretSubkey
1291 | UserID
1292 | UserAttribute
1293 | Signature
1294 | Marker
1295 | Trust
1296 | Unknown(_)
1297 | Private(_) => {
1298 if start_of_packet == 0 {
1299 t!("Encountered a ({:?}) at offset {}, \
1300 which is not a valid start of a certificate",
1301 t, start_of_packet);
1302 break None;
1303 }
1304 }
1305
1306 Reserved
1307 | PKESK
1308 | SKESK
1309 | OnePassSig
1310 | CompressedData
1311 | SED
1312 | Literal
1313 | SEIP
1314 | MDC
1315 | AED =>
1316 {
1317 t!("Encountered a ({:?}) at offset {}, \
1318 which does not belong in a certificate",
1319 t, start_of_packet);
1320 break None;
1321 }
1322
1323 t => if t.is_critical() {
1324 t!("Encountered a ({:?}) at offset {}, \
1325 which does not belong in a certificate",
1326 t, start_of_packet);
1327 break None;
1328 } else {
1329 },
1331 }
1332
1333 match header.length() {
1335 BodyLength::Full(l) => {
1336 let l = *l as usize;
1337 if let Err(err) = br.data_consume_hard(l) {
1338 t!("Error while reading packet: {}", err);
1339 break None;
1340 }
1341 }
1342 BodyLength::Partial(_) => {
1343 t!("Packet {} has partial body length, \
1344 which is unsupported by keyring splitter",
1345 t);
1346 break None;
1347 }
1348 BodyLength::Indeterminate => {
1349 t!("Packet {} has intedeterminite length, \
1350 which is unsupported by keyring splitter",
1351 t);
1352 break None;
1353 }
1354 }
1355 };
1356
1357 if let Some(len) = len {
1358 *certlen = len;
1359 Ok(())
1360 } else {
1361 Err(Error::Fail("No certificate found".into()))
1362 }
1363});
1364
1365ffi!(
1366fn _pgpPrtParams(pkts: *const u8, pktlen: size_t,
1382 pkttype: c_uint, paramsp: *mut *mut PgpDigParams)
1383 -> Binary
1384{
1385 match _pgpPrtParams2(pkts, pktlen, pkttype, paramsp, std::ptr::null_mut()) {
1386 0 => Ok(()),
1387 ec => Err(Error::from(ec)),
1388 }
1389});
1390
1391ffi!(
1392fn _pgpPrtParams2(pkts: *const u8, pktlen: size_t,
1395 pkttype: c_uint, paramsp: *mut *mut PgpDigParams,
1396 lint_str: *mut *mut c_char)
1397 -> Binary
1398{
1399 let mut lint_str: Option<&mut _> = check_optional_mut!(lint_str);
1400
1401 if let Some(lint_str) = lint_str.as_mut() {
1402 **lint_str = std::ptr::null_mut();
1403 }
1404
1405 let mut lints = Vec::new();
1406 let r = pgp_prt_params(pkts, pktlen, pkttype, paramsp, &mut lints);
1407
1408 if lints.len() > 0 {
1410 let mut s: String = format!("Parsing an OpenPGP packet:");
1411
1412 let sep = "\n ";
1414
1415 let lints_count = lints.len();
1416 for (err_i, err) in lints.into_iter().enumerate() {
1417 for (cause_i, cause) in error_chain(&err).into_iter().enumerate() {
1418 if cause_i == 0 {
1419 s.push_str(sep);
1420 if lints_count > 1 {
1421 s.push_str(&format!("{}. ", err_i + 1));
1422 }
1423 } else {
1424 s.push_str(sep);
1425 s.push_str(" because: ");
1426 }
1427 s.push_str(&cause);
1428 }
1429 }
1430
1431 t!("Lints: {}", s);
1432
1433 if let Some(lint_str) = lint_str.as_mut() {
1434 s.push('\0');
1436
1437 **lint_str = s.as_mut_ptr() as *mut c_char;
1438 std::mem::forget(s);
1440 }
1441 }
1442
1443 r
1444});
1445
1446fn pgp_prt_params(pkts: *const u8, pktlen: size_t,
1447 pkttype: c_uint, paramsp: *mut *mut PgpDigParams,
1448 lints: &mut Vec<anyhow::Error>)
1449 -> Result<()>
1450{
1451 tracer!(*crate::TRACE, "pgp_prt_params");
1452
1453 linter!($, lints);
1454
1455 let pkttype: Option<Tag> = if pkttype == 0 {
1456 None
1457 } else {
1458 Some(Tag::from(pkttype as u8))
1459 };
1460
1461 let pkts = check_slice!(pkts, pktlen);
1462 let paramsp = check_mut!(paramsp);
1463 *paramsp = std::ptr::null_mut();
1464
1465 let ppr = PacketParser::from_bytes(pkts)?;
1466
1467 let (obj, issuer, userid) = if let PacketParserResult::Some(pp) = ppr {
1468 match pp.packet {
1470 Packet::Signature(_)
1471 if pkttype.is_none() || pkttype == Some(Tag::Signature) =>
1472 {
1473 let (packet, next_ppr) = pp.next()?;
1474
1475 if let PacketParserResult::Some(p) = next_ppr {
1476 return_err!(None,
1477 "Expected a bare OpenPGP signature, \
1478 but it's followed by a {}",
1479 p.packet.tag());
1480 }
1481
1482 let sig = if let Packet::Signature(sig) = packet {
1483 sig
1484 } else {
1485 panic!("it's a sig");
1486 };
1487
1488 (PgpDigParamsObj::Signature(sig.clone()),
1489 sig.get_issuers().into_iter().next()
1494 .map(|i| KeyID::from(&i)),
1495 None)
1496 }
1497 Packet::PublicKey(_) | Packet::SecretKey(_)
1498 if pkttype.is_none()
1499 || pkttype == Some(Tag::PublicKey)
1500 || pkttype == Some(Tag::SecretKey) =>
1501 {
1502 let cert = match CertParser::from(PacketParserResult::Some(pp)).next()
1503 {
1504 Some(Ok(cert)) => cert,
1505 Some(Err(err)) => return_err!(
1506 Some(err),
1507 "Failed to read an OpenPGP certificate"),
1508 None => return_err!(
1509 None,
1510 "Failed to read an OpenPGP certificate"),
1511 };
1512
1513 let keyid = cert.keyid().clone();
1514
1515 let userid = if let Ok(vc)
1516 = cert.with_policy(&*P.read().unwrap(), None)
1517 {
1518 vc.primary_userid()
1519 .ok()
1520 .and_then(|u| {
1521 CString::new(u.userid().value()).ok()
1522 })
1523 } else {
1524 None
1525 };
1526
1527 (PgpDigParamsObj::Cert(cert),
1528 Some(keyid),
1529 userid)
1530 }
1531 Packet::Unknown(mut u) => {
1532 let mut err = u.set_error(anyhow::anyhow!("Error"));
1533 if let Some(openpgp::Error::MalformedMPI(_))
1534 = err.downcast_ref::<openpgp::Error>()
1535 {
1536 err = err.context("\
1537 Signature appears to be created by a \
1538 non-conformant OpenPGP implementation, see \
1539 <https://github.com/rpm-software-management/rpm/issues/2351>.");
1540 }
1541
1542 return_err!(Some(err), "Failed to parse {}", u.tag());
1543 }
1544 ref p => {
1545 return_err!(
1546 None,
1547 "Unexpected OpenPGP packet in this context {}",
1548 p.tag());
1549 }
1550 }
1551 } else {
1552 return_err!(
1553 None,
1554 "Expected an OpenPGP packet, encountered the end of the file");
1555 };
1556
1557 let mut buffer: [u8; 8] = [0; 8];
1558 if let Some(issuer) = issuer {
1559 for (i, c) in issuer.as_bytes().into_iter().enumerate() {
1560 buffer[i] = *c as u8;
1561 }
1562 }
1563
1564 *paramsp = move_to_c!(PgpDigParams {
1565 obj,
1566 signid: buffer,
1567 userid: userid,
1568 });
1569
1570 Ok(())
1571}
1572
1573ffi!(
1574fn _pgpPrtParamsSubkeys(pkts: *const u8, pktlen: size_t,
1580 _mainkey: *const PgpDigParams,
1581 subkeys: *mut *mut PgpDigParams,
1582 subkeys_count: *mut c_int) -> Binary {
1583 let pkts = check_slice!(pkts, pktlen);
1584 let subkeys = check_mut!(subkeys);
1585 *subkeys = std::ptr::null_mut();
1586 let subkeys_count = check_mut!(subkeys_count);
1587
1588 let ppr = PacketParser::from_bytes(pkts)?;
1589
1590 let cert = match ppr {
1591 PacketParserResult::Some(ref pp) => {
1592 match pp.packet {
1593 Packet::PublicKey(_) | Packet::SecretKey(_) => {
1594 let cert = CertParser::from(ppr)
1595 .next()
1596 .ok_or(Error::Fail("Not an OpenPGP certificate".into()))??;
1597 cert
1598 }
1599 ref p => {
1600 return Err(Error::Fail(format!("{}", p.tag())));
1601 }
1602 }
1603 }
1604 _ => return Err(Error::Fail("Not an OpenPGP message".into())),
1605 };
1606
1607 let userid = if let Ok(vc) = cert.with_policy(&*P.read().unwrap(), None) {
1608 vc.primary_userid()
1609 .ok()
1610 .and_then(|u| {
1611 CString::new(u.userid().value()).ok()
1612 })
1613 } else {
1614 None
1615 };
1616
1617 let mut keys: Vec<*mut PgpDigParams> = cert
1620 .keys().subkeys()
1621 .map(|ka| {
1622 t!("Subkey: {}", ka.key().keyid());
1623
1624 let zeros = [0; 8];
1625 let mut dig = PgpDigParams {
1626 obj: PgpDigParamsObj::Subkey(cert.clone(), ka.key().fingerprint()),
1627 signid: zeros,
1628 userid: userid.clone(),
1629 };
1630 dig.signid.copy_from_slice(ka.key().keyid().as_bytes());
1631 move_to_c!(dig)
1632 })
1633 .collect();
1634
1635 t!("Got {} subkeys", keys.len());
1636 *subkeys_count = keys.len() as c_int;
1637 if keys.len() == 0 {
1638 *subkeys = std::ptr::null_mut();
1639 } else {
1640 *subkeys = keys.as_mut_ptr() as *mut PgpDigParams;
1641 std::mem::forget(keys);
1643 }
1644
1645 Ok(())
1646});
1647
1648ffi!(
1649fn _pgpParsePkts(armor: *const c_char,
1657 pkt: *mut *mut c_char, pktlen: *mut size_t)
1658 -> PgpArmor
1659{
1660 let armor = check_cstr!(armor);
1661 let pkt = check_mut!(pkt);
1662 *pkt = std::ptr::null_mut();
1663 let pktlen = check_mut!(pktlen);
1664
1665 let mut reader = armor::Reader::from_reader(
1666 std::io::BufReader::new(
1667 armor.to_str().map_err(|_| PgpArmorError::BodyDecode)?.as_bytes()),
1668 armor::ReaderMode::Tolerant(None));
1669
1670 let mut buf = Vec::new();
1671 reader.read_to_end(&mut buf).map_err(|_| PgpArmorError::BodyDecode)?;
1672
1673 let kind = reader.kind();
1674
1675 *pktlen = buf.len() as size_t;
1676 *pkt = buf.as_mut_ptr() as *mut c_char;
1677 std::mem::forget(buf);
1679
1680 Ok(kind.into())
1681});
1682
1683ffi!(
1684fn _pgpPubKeyLint(pkts: *const c_char,
1709 pktslen: size_t,
1710 explanation: *mut *mut c_char) -> ErrorCode
1711{
1712 let pkts = check_slice!(pkts, pktslen);
1713 let explanation = check_mut!(explanation);
1714
1715 *explanation = std::ptr::null_mut();
1717
1718 let cert = CertParser::from_bytes(pkts)?.next()
1719 .ok_or(Error::Fail("Not an OpenPGP certificate".into()))??;
1720
1721 let mut lints: Vec<String> = Vec::new();
1722 let mut lint = |l: &str| {
1723 lints.push(l.into());
1724 };
1725
1726 #[allow(clippy::never_loop)]
1727 let usable = 'done : loop {
1728 match cert.with_policy(&*P.read().unwrap(), None) {
1729 Err(err) => {
1730 lint(&format!("Policy rejects {}: {}", cert.keyid(), err));
1731 break 'done false;
1732 }
1733 Ok(vc) => {
1734 if let RevocationStatus::Revoked(revs)
1735 = vc.revocation_status()
1736 {
1737 for rev in revs {
1738 if let Some((reason, msg))
1739 = rev.reason_for_revocation()
1740 {
1741 let mut l = format!(
1742 "The certificate was revoked: {}", reason);
1743 if ! msg.is_empty() {
1744 l.push_str(&format!(
1745 ", {}",
1746 String::from_utf8_lossy(msg)));
1747 }
1748 lint(&l);
1749 } else {
1750 lint("The certificate was revoked: \
1751 unspecified reason");
1752 }
1753 }
1754 }
1755
1756 if let Err(err) = vc.alive() {
1757 if let Some(e) = vc.primary_key().key_expiration_time() {
1758 if e <= SystemTime::now() {
1759 lint(&format!("The certificate is expired: {}",
1760 err));
1761 } else {
1762 lint(&format!("The certificate is not live: {}",
1763 err));
1764 }
1765 }
1766 }
1767 }
1768 };
1769
1770 let mut have_signing = false;
1771 for ka in cert.keys() {
1772 let keyid = ka.key().keyid();
1773
1774 match ka.with_policy(&*P.read().unwrap(), None) {
1775 Err(err) => {
1776 lint(&format!("Policy rejects subkey {}: {}",
1777 keyid, err));
1778 continue;
1779 }
1780 Ok(ka) => {
1781 if ! ka.for_signing() {
1782 continue;
1785 }
1786
1787 if let RevocationStatus::Revoked(revs)
1788 = ka.revocation_status()
1789 {
1790 for rev in revs {
1791 if let Some((reason, msg))
1792 = rev.reason_for_revocation()
1793 {
1794 let mut l = format!(
1795 "Subkey {} was revoked: {}",
1796 keyid, reason);
1797 if ! msg.is_empty() {
1798 l.push_str(&format!(
1799 ", {}",
1800 String::from_utf8_lossy(msg)));
1801 }
1802 lint(&l);
1803 } else {
1804 lint(&format!(
1805 "Subkey {} was revoked: \
1806 unspecified reason",
1807 keyid));
1808 }
1809 }
1810 continue;
1811 }
1812
1813 if let Err(err) = ka.alive() {
1814 if let Some(e) = ka.key_expiration_time() {
1815 if e <= SystemTime::now() {
1816 lint(&format!("Subkey {} is expired: {}",
1817 keyid, err));
1818 } else {
1819 lint(&format!("Subkey {} is not live: {}",
1820 keyid, err));
1821 }
1822 }
1823 continue;
1824 }
1825
1826 if ! ka.key().pk_algo().is_supported() {
1827 lint(&format!("Subkey {} is not supported \
1828 (no support for {})",
1829 keyid,
1830 ka.key().pk_algo()));
1831 continue;
1832 }
1833
1834 have_signing = true;
1835 }
1836 }
1837 }
1838
1839 if ! have_signing {
1840 lint("Certificate does not have any usable signing keys");
1841 }
1842
1843 break true;
1844 };
1845
1846 if ! lints.is_empty() {
1847 let sep = "\n ";
1849
1850 let mut s: String = format!("Certificate {}:{}", cert.keyid(), sep);
1851 s.push_str(&lints.join(sep));
1852 s.push('\0');
1853
1854 *explanation = s.as_mut_ptr() as *mut c_char;
1855 std::mem::forget(s);
1857 }
1858
1859 if usable {
1860 Ok(())
1861 } else {
1862 Err(Error::Fail(format!("Certificate {} is unusable", cert.keyid())))
1863 }
1864});
1865
1866pub struct PgpDig {
1871 cert: Option<Box<PgpDigParams>>,
1872 sig: Option<Box<PgpDigParams>>,
1873}
1874
1875fn dump_packets(pkts: &[u8]) -> Result<()> {
1881 use openpgp::types::CompressionAlgorithm;
1882 use openpgp::types::KeyServerPreferences;
1883 use openpgp::types::PublicKeyAlgorithm;
1884 use openpgp::types::SignatureType;
1885 use openpgp::types::SymmetricAlgorithm;
1886 use openpgp::packet::signature::subpacket::Subpacket;
1887 use openpgp::packet::signature::subpacket::SubpacketTag;
1888 use openpgp::packet::signature::subpacket::SubpacketValue;
1889
1890 let mut ppr = PacketParser::from_bytes(pkts)?;
1891
1892 fn pk_algo(a: PublicKeyAlgorithm) -> &'static str {
1893 use PublicKeyAlgorithm::*;
1894 #[allow(deprecated)]
1895 match a {
1896 RSAEncryptSign => "RSA",
1897 RSAEncrypt => "RSA(Encrypt-Only)",
1898 RSASign => "RSA(Sign-Only)",
1899 ElGamalEncrypt => "Elgamal(Encrypt-Only)",
1900 DSA => "DSA",
1901 ECDH => "Elliptic Curve",
1902 ECDSA => "ECDSA",
1903 ElGamalEncryptSign => "Elgamal",
1904 EdDSA => "EdDSA",
1905 _ => "Unknown public key algorithm",
1906 }
1907 }
1908
1909 fn sigtype(t: SignatureType) -> &'static str {
1910 use SignatureType::*;
1911 match t {
1912 Binary => "Binary document signature",
1913 Text => "Text document signature",
1914 Standalone => "Standalone signature",
1915 GenericCertification => "Generic certification of a User ID and Public Key",
1916 PersonaCertification => "Persona certification of a User ID and Public Key",
1917 CasualCertification => "Casual certification of a User ID and Public Key",
1918 PositiveCertification => "Positive certification of a User ID and Public Key",
1919 SubkeyBinding => "Subkey Binding Signature",
1920 PrimaryKeyBinding => "Primary Key Binding Signature",
1921 DirectKey => "Signature directly on a key",
1922 KeyRevocation => "Key revocation signature",
1923 SubkeyRevocation => "Subkey revocation signature",
1924 CertificationRevocation => "Certification revocation signature",
1925 Timestamp => "Timestamp signature",
1926 _ => "Unknown signature type",
1927 }
1928 }
1929
1930 fn symalgo(a: SymmetricAlgorithm) -> &'static str {
1931 use SymmetricAlgorithm::*;
1932 #[allow(deprecated)]
1933 match a {
1934 Unencrypted => "Plaintext",
1935 IDEA => "IDEA",
1936 TripleDES => "3DES",
1937 CAST5 => "CAST5",
1938 Blowfish => "BLOWFISH",
1939 AES128 => "AES(128-bit key)",
1940 AES192 => "AES(192-bit key)",
1941 AES256 => "AES(256-bit key)",
1942 Twofish => "TWOFISH(256-bit key)",
1943 _ => "Unknown symmetric key algorithm",
1944 }
1945 }
1946
1947 fn compalgo(a: CompressionAlgorithm) -> &'static str {
1948 use CompressionAlgorithm::*;
1949 match a {
1950 Uncompressed => "Uncompressed",
1951 Zip => "ZIP",
1952 Zlib => "ZLIB",
1953 BZip2 => "BZIP2",
1954 _ => "Unknown compression algorithm",
1955 }
1956 }
1957
1958 fn ksprefs(prefs: KeyServerPreferences) -> &'static str {
1959 if prefs.no_modify() {
1962 "No-modify(128)"
1963 } else if KeyServerPreferences::empty().normalized_eq(&prefs) {
1964 ""
1965 } else {
1966 "Unknown key server preference"
1967 }
1968 }
1969
1970 fn subpacket(sp: &Subpacket) -> String {
1971 let mut output: Vec<String> = Vec::new();
1972
1973 let tag = sp.tag();
1974 let s = {
1975 use SubpacketTag::*;
1976 match tag {
1977 SignatureCreationTime => "signature creation time",
1978 SignatureExpirationTime => "signature expiration time",
1979 ExportableCertification => "exportable certification",
1980 TrustSignature => "trust signature",
1981 RegularExpression => "regular expression",
1982 Revocable => "revocable",
1983 KeyExpirationTime => "key expiration time",
1984 PlaceholderForBackwardCompatibility => "additional recipient request",
1985 PreferredSymmetricAlgorithms => "preferred symmetric algorithms",
1986 RevocationKey => "revocation key",
1987 Issuer => "issuer key ID",
1988 NotationData => "notation data",
1989 PreferredHashAlgorithms => "preferred hash algorithms",
1990 PreferredCompressionAlgorithms => "preferred compression algorithms",
1991 KeyServerPreferences => "key server preferences",
1992 PreferredKeyServer => "preferred key server",
1993 PrimaryUserID => "primary user id",
1994 PolicyURI => "policy URL",
1995 KeyFlags => "key flags",
1996 SignersUserID => "signer's user id",
1997 ReasonForRevocation => "reason for revocation",
1998 Features => "features",
1999 EmbeddedSignature => "embedded signature",
2000 _ => "Unknown signature subkey type",
2001 }
2002 };
2003 output.push(s.into());
2004
2005 output.push(format!("({})", Into::<u8>::into(tag)));
2006
2007 if sp.critical() {
2008 output.push(" *CRITICAL*".into());
2009 }
2010
2011 {
2012 use SubpacketValue::*;
2013 match sp.value() {
2014 PreferredSymmetricAlgorithms(algos) => {
2015 output.push(" ".into());
2016 output.push(
2017 algos.iter()
2018 .map(|a| {
2019 format!("{}({})",
2020 symalgo(*a),
2021 Into::<u8>::into(*a))
2022 })
2023 .collect::<Vec<String>>()
2024 .join(" "))
2025 }
2026 PreferredHashAlgorithms(algos) => {
2027 output.push(" ".into());
2028 output.push(
2029 algos.iter()
2030 .map(|a| {
2031 format!("{}({})",
2032 a,
2033 Into::<u8>::into(*a))
2034 })
2035 .collect::<Vec<String>>()
2036 .join(" "))
2037 }
2038 PreferredCompressionAlgorithms(algos) => {
2039 output.push(" ".into());
2040 output.push(
2041 algos.iter()
2042 .map(|a| {
2043 format!("{}({})",
2044 compalgo(*a),
2045 Into::<u8>::into(*a))
2046 })
2047 .collect::<Vec<String>>()
2048 .join(" "))
2049 }
2050 KeyServerPreferences(prefs) => {
2051 output.push(format!(" {}", ksprefs(prefs.clone())))
2052 }
2053 SignatureExpirationTime(d)
2054 | KeyExpirationTime(d) =>
2055 {
2056 let t = DateTime::from_timestamp(
2062 d.as_secs() as i64, 0)
2063 .unwrap_or_default();
2066 output.push(format!(" {}(0x{:08x})",
2067 t.format("%c"),
2068 d.as_secs()));
2069 }
2070
2071 SignatureCreationTime(_)
2072 | Issuer(_)
2073 | KeyFlags(_) => (),
2074
2075 _ => {
2076 use sequoia_openpgp::serialize::MarshalInto;
2077
2078 output.push(" ".into());
2079 output.extend(
2080 sp.value()
2081 .to_vec()
2082 .unwrap_or(Vec::new())
2083 .into_iter()
2084 .map(|b| format!("{:02x}", b)))
2085 }
2086 }
2087 }
2088
2089 output.join("")
2090 }
2091
2092 while let PacketParserResult::Some(pp) = ppr {
2093 let (packet, next_ppr) = pp.recurse()?;
2094 ppr = next_ppr;
2095
2096 #[allow(deprecated)]
2099 match packet {
2100 Packet::Signature(sig) => {
2101 eprintln!("V{} Signature(2) {}({}) {}({}) {}({})",
2106 sig.version(),
2107 pk_algo(sig.pk_algo()),
2108 Into::<u8>::into(sig.pk_algo()),
2109 sig.hash_algo(),
2110 Into::<u8>::into(sig.hash_algo()),
2111 sigtype(sig.typ()),
2112 Into::<u8>::into(sig.typ()));
2113 sig.hashed_area().iter().for_each(|sb| {
2114 eprintln!(" {}", subpacket(sb));
2115 });
2116 sig.unhashed_area().iter().for_each(|sb| {
2117 eprintln!(" {}", subpacket(sb));
2118 });
2119
2120 eprintln!(" signhash16 {:02x}{:02x}",
2121 sig.digest_prefix()[0],
2122 sig.digest_prefix()[1]);
2123 },
2124 Packet::PublicKey(key) => {
2125 let secs = key.creation_time()
2128 .duration_since(SystemTime::UNIX_EPOCH)
2129 .map(|d| d.as_secs())
2130 .unwrap_or(0);
2131 let t: DateTime::<Utc> = key.creation_time().into();
2132
2133 eprintln!("V{} Public Key(6) {}({}) {}(0x{:08x})",
2134 key.version(),
2135 pk_algo(key.pk_algo()),
2136 Into::<u8>::into(key.pk_algo()),
2137 t.format("%c"), secs);
2138 }
2139 Packet::PublicSubkey(key) => {
2140 use sequoia_openpgp::serialize::MarshalInto;
2142
2143 let secs = key.creation_time()
2144 .duration_since(SystemTime::UNIX_EPOCH)
2145 .map(|d| d.as_secs())
2146 .unwrap_or(0);
2147
2148 eprintln!("Public Subkey(14) {:02}{:08x}{:02x}{}",
2149 key.version(), secs,
2150 Into::<u8>::into(key.pk_algo()),
2151 key.mpis().to_vec()
2152 .unwrap_or_else(|_| Vec::new())
2153 .into_iter()
2154 .map(|b| format!("{:02x}", b))
2155 .collect::<String>());
2156 }
2157 Packet::UserID(userid) => {
2158 eprintln!("User ID(13) {:?}",
2160 String::from_utf8_lossy(userid.value()));
2161 }
2162
2163 Packet::Unknown(_pkt) => (),
2164 Packet::OnePassSig(_ops) => (),
2165 Packet::SecretKey(_key) => (),
2166 Packet::SecretSubkey(_key) => (),
2167 Packet::Marker(_marker) => (),
2168 Packet::Trust(_trust) => (),
2169 Packet::UserAttribute(_ua) => (),
2170 Packet::Literal(_lit) => (),
2171 Packet::CompressedData(_cd) => (),
2172 Packet::PKESK(_pkesk) => (),
2173 Packet::SKESK(_skesk) => (),
2174 Packet::SEIP(_seip) => (),
2175 Packet::MDC(_mdc) => (),
2176 _ => (),
2177 }
2178 }
2179
2180 Ok(())
2181}
2182
2183ffi!(
2184fn _pgpPrtPkts(pkts: *const u8, pktslen: size_t,
2196 dig: *mut PgpDig, printing: c_int)
2197 -> Binary
2198{
2199 let dig = check_mut!(dig);
2200
2201 let mut params: *mut PgpDigParams = std::ptr::null_mut();
2202
2203 if printing != 0 {
2204 let _ = dump_packets(check_slice!(pkts, pktslen));
2207 }
2208
2209 let result = _pgpPrtParams(pkts, pktslen, 0, &mut params);
2210 if result == -1 {
2211 return Err(Error::Fail("Parse error".into()));
2212 }
2213
2214 let params = claim_from_c!(params);
2215 match params.obj {
2216 PgpDigParamsObj::Cert(_) => dig.cert = Some(params),
2217 PgpDigParamsObj::Subkey(_, _) => dig.cert = Some(params),
2218 PgpDigParamsObj::Signature(_) => dig.sig = Some(params),
2219 }
2220
2221 Ok(())
2222});
2223
2224ffi!(
2225fn _pgpNewDig() -> *mut PgpDig {
2232 Ok(move_to_c!(PgpDig {
2233 cert: None,
2234 sig: None,
2235 }))
2236});
2237
2238ffi!(
2239fn _pgpCleanDig(dig: *mut PgpDig) {
2246 let dig = check_mut!(dig);
2247 dig.cert = None;
2248 dig.sig = None;
2249});
2250
2251ffi!(
2252fn _pgpFreeDig(dig: Option<&mut PgpDig>) -> *mut PgpDig {
2260 free!(dig);
2261 Ok(std::ptr::null_mut())
2262});
2263
2264ffi!(
2265fn _pgpDigGetParams(dig: *const PgpDig, pkttype: c_uint)
2274 -> *const PgpDigParams
2275{
2276 let dig = check_ptr!(dig);
2277
2278 let ptr = match Tag::from(pkttype as u8) {
2279 Tag::PublicKey => {
2280 if let Some(ref cert) = dig.cert {
2281 cert.as_ref()
2282 } else {
2283 std::ptr::null()
2284 }
2285 }
2286 Tag::Signature => {
2287 if let Some(ref sig) = dig.sig {
2288 sig.as_ref()
2289 } else {
2290 std::ptr::null()
2291 }
2292 }
2293 _ => {
2294 std::ptr::null()
2295 }
2296 };
2297
2298 Ok(ptr)
2299});
2300
2301ffi!(
2302fn _pgpVerifySig(dig: *const PgpDig,
2311 ctx: *const digest::DigestContext) -> ErrorCode {
2312 Err(
2313 _pgpVerifySignature(
2314 _pgpDigGetParams(dig, u8::from(Tag::PublicKey) as u32),
2315 _pgpDigGetParams(dig, u8::from(Tag::Signature) as u32),
2316 ctx).into())
2317});
2318
2319ffi!(
2320fn _pgpPubkeyMerge(
2335 pkts1: *const u8, pkts1len: size_t,
2336 pkts2: *const u8, pkts2len: size_t,
2337 pktsm: *mut *mut u8, pktsmlen: *mut size_t,
2338 flags: c_int)
2339 -> ErrorCode
2340{
2341 let pkts1 = check_slice!(pkts1, pkts1len);
2342 let pkts2 = check_slice!(pkts2, pkts2len);
2343
2344 let cert1 = Cert::from_bytes(pkts1)?;
2345 let cert2 = Cert::from_bytes(pkts2)?;
2346
2347 if cert1.fingerprint() != cert2.fingerprint() {
2348 return Err(Error::Fail("Can't merge different certificates".into()));
2349 }
2350
2351 let (merged, updated)
2352 = cert1.clone().insert_packets(cert2.into_packets())?;
2353
2354 let merged_bytes_;
2355 let (result, result_len) = if ! updated {
2356 (pkts1.as_ptr(), pkts1len)
2362 } else {
2363 merged_bytes_ = merged.to_vec()?;
2364 (merged_bytes_.as_ptr(), merged_bytes_.len())
2365 };
2366
2367 unsafe {
2368 let buffer = libc::malloc(result_len);
2369 if buffer.is_null() {
2370 return Err(Error::Fail("out of memory".into()));
2371 }
2372 libc::memcpy(buffer, result as *const c_void, result_len);
2373
2374 *pktsmlen = result_len as size_t;
2375 *pktsm = buffer as *mut u8;
2376 }
2377
2378 Ok(())
2379});
2380
2381
2382#[cfg(test)]
2383mod tests {
2384 use super::*;
2385
2386 use openpgp::cert::CertBuilder;
2387 use openpgp::serialize::SerializeInto;
2388 use openpgp::types::KeyFlags;
2389
2390 #[test]
2392 fn merge_certs() {
2393 let p = openpgp::policy::StandardPolicy::new();
2394
2395 let (cert, _rev) = CertBuilder::new()
2396 .add_userid("Alice")
2397 .generate()
2398 .unwrap();
2399
2400 let vc = cert.with_policy(&p, None).unwrap();
2401
2402 assert_eq!(vc.keys().for_signing().count(), 0);
2404 assert_eq!(vc.keys().for_transport_encryption().count(), 0);
2405 assert_eq!(vc.keys().for_storage_encryption().count(), 0);
2406
2407 let cert2 = KeyBuilder::new(
2409 KeyFlags::empty().set_signing())
2410 .subkey(vc.clone()).unwrap()
2411 .attach_cert().unwrap();
2412
2413 let cert3 = KeyBuilder::new(
2415 KeyFlags::empty().set_transport_encryption())
2416 .subkey(vc.clone()).unwrap()
2417 .attach_cert().unwrap();
2418
2419 let cert2_bytes = cert2.to_vec().unwrap();
2420 let cert3_bytes = cert3.to_vec().unwrap();
2421
2422 let mut result: *mut u8 = std::ptr::null_mut();
2423 let mut result_len: size_t = 0;
2424
2425 eprintln!("About to run pgpPubkeyMerge");
2426 let ec = _pgpPubkeyMerge(
2427 cert2_bytes.as_ptr(), cert2_bytes.len(),
2428 cert3_bytes.as_ptr(), cert3_bytes.len(),
2429 &mut result, &mut result_len,
2430 0);
2431
2432 assert_eq!(ec, 0);
2433
2434 assert!(! result.is_null());
2435 let result = unsafe {
2436 std::slice::from_raw_parts(result as *const u8, result_len)
2437 };
2438
2439 let result = Cert::from_bytes(result).expect("valid cert");
2440
2441 assert_eq!(cert.fingerprint(), result.fingerprint());
2442 assert!(result != cert);
2443 assert!(result != cert2);
2444 assert!(result != cert3);
2445
2446 let expected = cert2.clone().merge_public(cert3.clone()).unwrap();
2447 assert_eq!(result, expected);
2448
2449 let result_vc = result.with_policy(&p, None).unwrap();
2450
2451 assert_eq!(result_vc.keys().for_signing().count(), 1);
2452 assert_eq!(result_vc.keys().for_transport_encryption().count(), 1);
2453 assert_eq!(result_vc.keys().for_storage_encryption().count(), 0);
2454 }
2455
2456 #[test]
2459 fn merge_certs_mismatch() {
2460 let (cert, _rev) = CertBuilder::new()
2461 .add_userid("Alice")
2462 .generate()
2463 .unwrap();
2464 let (cert2, _rev) = CertBuilder::new()
2465 .add_userid("Bob")
2466 .generate()
2467 .unwrap();
2468
2469 let cert_bytes = cert.to_vec().unwrap();
2470 let cert2_bytes = cert2.to_vec().unwrap();
2471
2472 let mut result: *mut u8 = std::ptr::null_mut();
2473 let mut result_len: size_t = 0;
2474
2475 eprintln!("About to run pgpPubkeyMerge");
2476 let ec = _pgpPubkeyMerge(
2477 cert_bytes.as_ptr(), cert_bytes.len(),
2478 cert2_bytes.as_ptr(), cert2_bytes.len(),
2479 &mut result, &mut result_len,
2480 0);
2481
2482 assert_ne!(ec, 0);
2483 }
2484}