pkcs_12/
lib.rs

1//!
2//! pure rust pkcs12 tool
3//!
4//!
5
6use getrandom::getrandom;
7use lazy_static::lazy_static;
8use yasna::{models::ObjectIdentifier, ASN1Error, ASN1ErrorKind, BERReader, DERWriter, Tag};
9
10use hmac::{Hmac, Mac, NewMac};
11use sha1::{Digest, Sha1};
12
13type HmacSha1 = Hmac<Sha1>;
14
15fn as_oid(s: &'static [u64]) -> ObjectIdentifier {
16    ObjectIdentifier::from_slice(s)
17}
18
19lazy_static! {
20    static ref OID_DATA_CONTENT_TYPE: ObjectIdentifier = as_oid(&[1, 2, 840, 113_549, 1, 7, 1]);
21    static ref OID_ENCRYPTED_DATA_CONTENT_TYPE: ObjectIdentifier =
22        as_oid(&[1, 2, 840, 113_549, 1, 7, 6]);
23    static ref OID_FRIENDLY_NAME: ObjectIdentifier = as_oid(&[1, 2, 840, 113_549, 1, 9, 20]);
24    static ref OID_LOCAL_KEY_ID: ObjectIdentifier = as_oid(&[1, 2, 840, 113_549, 1, 9, 21]);
25    static ref OID_CERT_TYPE_X509_CERTIFICATE: ObjectIdentifier =
26        as_oid(&[1, 2, 840, 113_549, 1, 9, 22, 1]);
27    static ref OID_CERT_TYPE_SDSI_CERTIFICATE: ObjectIdentifier =
28        as_oid(&[1, 2, 840, 113_549, 1, 9, 22, 2]);
29    static ref OID_PBE_WITH_SHA_AND3_KEY_TRIPLE_DESCBC: ObjectIdentifier =
30        as_oid(&[1, 2, 840, 113_549, 1, 12, 1, 3]);
31    static ref OID_SHA1: ObjectIdentifier = as_oid(&[1, 3, 14, 3, 2, 26]);
32    static ref OID_PBE_WITH_SHA1_AND40_BIT_RC2_CBC: ObjectIdentifier =
33        as_oid(&[1, 2, 840, 113_549, 1, 12, 1, 6]);
34    static ref OID_KEY_BAG: ObjectIdentifier = as_oid(&[1, 2, 840, 113_549, 1, 12, 10, 1, 1]);
35    static ref OID_PKCS8_SHROUDED_KEY_BAG: ObjectIdentifier =
36        as_oid(&[1, 2, 840, 113_549, 1, 12, 10, 1, 2]);
37    static ref OID_CERT_BAG: ObjectIdentifier = as_oid(&[1, 2, 840, 113_549, 1, 12, 10, 1, 3]);
38    static ref OID_CRL_BAG: ObjectIdentifier = as_oid(&[1, 2, 840, 113_549, 1, 12, 10, 1, 4]);
39    static ref OID_SECRET_BAG: ObjectIdentifier = as_oid(&[1, 2, 840, 113_549, 1, 12, 10, 1, 5]);
40    static ref OID_SAFE_CONTENTS_BAG: ObjectIdentifier =
41        as_oid(&[1, 2, 840, 113_549, 1, 12, 10, 1, 6]);
42}
43
44const ITERATIONS: u64 = 2048;
45
46fn sha1(bytes: &[u8]) -> Vec<u8> {
47    let mut hasher = Sha1::new();
48    hasher.update(bytes);
49    hasher.finalize().to_vec()
50}
51
52#[derive(Debug, Clone)]
53pub struct EncryptedContentInfo {
54    pub content_encryption_algorithm: AlgorithmIdentifier,
55    pub encrypted_content: Vec<u8>,
56}
57
58impl EncryptedContentInfo {
59    pub fn parse(r: BERReader) -> Result<Self, ASN1Error> {
60        r.read_sequence(|r| {
61            let content_type = r.next().read_oid()?;
62            debug_assert_eq!(content_type, *OID_DATA_CONTENT_TYPE);
63            let content_encryption_algorithm = AlgorithmIdentifier::parse(r.next())?;
64            let encrypted_content = r
65                .next()
66                .read_tagged_implicit(Tag::context(0), |r| r.read_bytes())?;
67            Ok(EncryptedContentInfo {
68                content_encryption_algorithm,
69                encrypted_content,
70            })
71        })
72    }
73
74    pub fn data(&self, password: &[u8]) -> Option<Vec<u8>> {
75        self.content_encryption_algorithm
76            .decrypt_pbe(&self.encrypted_content, password)
77    }
78
79    pub fn write(&self, w: DERWriter) {
80        w.write_sequence(|w| {
81            w.next().write_oid(&OID_DATA_CONTENT_TYPE);
82            self.content_encryption_algorithm.write(w.next());
83            w.next()
84                .write_tagged_implicit(Tag::context(0), |w| w.write_bytes(&self.encrypted_content));
85        })
86    }
87
88    pub fn to_der(&self) -> Vec<u8> {
89        yasna::construct_der(|w| self.write(w))
90    }
91
92    pub fn from_safe_bags(safe_bags: &[SafeBag], password: &[u8]) -> Option<EncryptedContentInfo> {
93        let data = yasna::construct_der(|w| {
94            w.write_sequence_of(|w| {
95                for sb in safe_bags {
96                    sb.write(w.next());
97                }
98            })
99        });
100        let salt = rand()?.to_vec();
101        let encrypted_content =
102            pbe_with_sha1_and40_bit_rc2_cbc_encrypt(&data, password, &salt, ITERATIONS)?;
103        let content_encryption_algorithm =
104            AlgorithmIdentifier::PbewithSHAAnd40BitRC2CBC(Pkcs12PbeParams {
105                salt,
106                iterations: ITERATIONS,
107            });
108        Some(EncryptedContentInfo {
109            content_encryption_algorithm,
110            encrypted_content,
111        })
112    }
113}
114
115#[derive(Debug, Clone)]
116pub struct EncryptedData {
117    pub encrypted_content_info: EncryptedContentInfo,
118}
119
120impl EncryptedData {
121    pub fn parse(r: BERReader) -> Result<Self, ASN1Error> {
122        r.read_sequence(|r| {
123            let version = r.next().read_u8()?;
124            debug_assert_eq!(version, 0);
125
126            let encrypted_content_info = EncryptedContentInfo::parse(r.next())?;
127            Ok(EncryptedData {
128                encrypted_content_info,
129            })
130        })
131    }
132    pub fn data(&self, password: &[u8]) -> Option<Vec<u8>> {
133        self.encrypted_content_info.data(password)
134    }
135    pub fn write(&self, w: DERWriter) {
136        w.write_sequence(|w| {
137            w.next().write_u8(0);
138            self.encrypted_content_info.write(w.next());
139        })
140    }
141    pub fn from_safe_bags(safe_bags: &[SafeBag], password: &[u8]) -> Option<Self> {
142        let encrypted_content_info = EncryptedContentInfo::from_safe_bags(safe_bags, password)?;
143        Some(EncryptedData {
144            encrypted_content_info,
145        })
146    }
147}
148
149#[derive(Debug, Clone)]
150pub struct OtherContext {
151    pub content_type: ObjectIdentifier,
152    pub content: Vec<u8>,
153}
154
155#[derive(Debug, Clone)]
156pub enum ContentInfo {
157    Data(Vec<u8>),
158    EncryptedData(EncryptedData),
159    OtherContext(OtherContext),
160}
161
162impl ContentInfo {
163    pub fn parse(r: BERReader) -> Result<Self, ASN1Error> {
164        Ok(r.read_sequence(|r| {
165            let content_type = r.next().read_oid()?;
166            if content_type == *OID_DATA_CONTENT_TYPE {
167                let data = r.next().read_tagged(Tag::context(0), |r| r.read_bytes())?;
168                return Ok(ContentInfo::Data(data));
169            }
170            if content_type == *OID_ENCRYPTED_DATA_CONTENT_TYPE {
171                let result = r.next().read_tagged(Tag::context(0), |r| {
172                    Ok(ContentInfo::EncryptedData(EncryptedData::parse(r)?))
173                });
174                return result;
175            }
176
177            let content = r.next().read_tagged(Tag::context(0), |r| r.read_der())?;
178            Ok(ContentInfo::OtherContext(OtherContext {
179                content_type,
180                content,
181            }))
182        })?)
183    }
184    pub fn data(&self, password: &[u8]) -> Option<Vec<u8>> {
185        match self {
186            ContentInfo::Data(data) => Some(data.to_owned()),
187            ContentInfo::EncryptedData(encrypted) => encrypted.data(password),
188            ContentInfo::OtherContext(_) => None,
189        }
190    }
191    pub fn oid(&self) -> ObjectIdentifier {
192        match self {
193            ContentInfo::Data(_) => OID_DATA_CONTENT_TYPE.clone(),
194            ContentInfo::EncryptedData(_) => OID_ENCRYPTED_DATA_CONTENT_TYPE.clone(),
195            ContentInfo::OtherContext(other) => other.content_type.clone(),
196        }
197    }
198    pub fn write(&self, w: DERWriter) {
199        match self {
200            ContentInfo::Data(data) => w.write_sequence(|w| {
201                w.next().write_oid(&OID_DATA_CONTENT_TYPE);
202                w.next()
203                    .write_tagged(Tag::context(0), |w| w.write_bytes(data))
204            }),
205            ContentInfo::EncryptedData(encrypted_data) => w.write_sequence(|w| {
206                w.next().write_oid(&OID_ENCRYPTED_DATA_CONTENT_TYPE);
207                w.next()
208                    .write_tagged(Tag::context(0), |w| encrypted_data.write(w))
209            }),
210            ContentInfo::OtherContext(other) => w.write_sequence(|w| {
211                w.next().write_oid(&other.content_type);
212                w.next()
213                    .write_tagged(Tag::context(0), |w| w.write_der(&other.content))
214            }),
215        }
216    }
217    pub fn to_der(&self) -> Vec<u8> {
218        yasna::construct_der(|w| self.write(w))
219    }
220
221    pub fn from_der(der: &[u8]) -> Result<Self, ASN1Error> {
222        yasna::parse_der(der, Self::parse)
223    }
224}
225
226#[derive(Debug, Clone, PartialEq)]
227pub struct Pkcs12PbeParams {
228    pub salt: Vec<u8>,
229    pub iterations: u64,
230}
231
232impl Pkcs12PbeParams {
233    pub fn parse(r: BERReader) -> Result<Self, ASN1Error> {
234        r.read_sequence(|r| {
235            let salt = r.next().read_bytes()?;
236            let iterations = r.next().read_u64()?;
237            Ok(Pkcs12PbeParams { salt, iterations })
238        })
239    }
240    pub fn write(&self, w: DERWriter) {
241        w.write_sequence(|w| {
242            w.next().write_bytes(&self.salt);
243            w.next().write_u64(self.iterations);
244        })
245    }
246}
247
248#[derive(Debug, Clone, PartialEq)]
249pub struct OtherAlgorithmIdentifier {
250    pub algorithm_type: ObjectIdentifier,
251    pub params: Option<Vec<u8>>,
252}
253
254#[derive(Debug, Clone, PartialEq)]
255pub enum AlgorithmIdentifier {
256    Sha1,
257    PbewithSHAAnd40BitRC2CBC(Pkcs12PbeParams),
258    PbeWithSHAAnd3KeyTripleDESCBC(Pkcs12PbeParams),
259    OtherAlg(OtherAlgorithmIdentifier),
260}
261
262impl AlgorithmIdentifier {
263    pub fn parse(r: BERReader) -> Result<Self, ASN1Error> {
264        r.read_sequence(|r| {
265            let algorithm_type = r.next().read_oid()?;
266            if algorithm_type == *OID_SHA1 {
267                r.read_optional(|r| r.read_null())?;
268                return Ok(AlgorithmIdentifier::Sha1);
269            }
270            if algorithm_type == *OID_PBE_WITH_SHA1_AND40_BIT_RC2_CBC {
271                let params = Pkcs12PbeParams::parse(r.next())?;
272                return Ok(AlgorithmIdentifier::PbewithSHAAnd40BitRC2CBC(params));
273            }
274            if algorithm_type == *OID_PBE_WITH_SHA_AND3_KEY_TRIPLE_DESCBC {
275                let params = Pkcs12PbeParams::parse(r.next())?;
276                return Ok(AlgorithmIdentifier::PbeWithSHAAnd3KeyTripleDESCBC(params));
277            }
278            let params = r.read_optional(|r| r.read_der())?;
279            Ok(AlgorithmIdentifier::OtherAlg(OtherAlgorithmIdentifier {
280                algorithm_type,
281                params,
282            }))
283        })
284    }
285    pub fn decrypt_pbe(&self, ciphertext: &[u8], password: &[u8]) -> Option<Vec<u8>> {
286        match self {
287            AlgorithmIdentifier::Sha1 => None,
288            AlgorithmIdentifier::PbewithSHAAnd40BitRC2CBC(param) => {
289                pbe_with_sha1_and40_bit_rc2_cbc(ciphertext, password, &param.salt, param.iterations)
290            }
291            AlgorithmIdentifier::PbeWithSHAAnd3KeyTripleDESCBC(param) => {
292                pbe_with_sha_and3_key_triple_des_cbc(
293                    ciphertext,
294                    password,
295                    &param.salt,
296                    param.iterations,
297                )
298            }
299            AlgorithmIdentifier::OtherAlg(_) => None,
300        }
301    }
302    pub fn write(&self, w: DERWriter) {
303        w.write_sequence(|w| match self {
304            AlgorithmIdentifier::Sha1 => {
305                w.next().write_oid(&OID_SHA1);
306                w.next().write_null();
307            }
308            AlgorithmIdentifier::PbewithSHAAnd40BitRC2CBC(p) => {
309                w.next().write_oid(&OID_PBE_WITH_SHA1_AND40_BIT_RC2_CBC);
310                p.write(w.next());
311            }
312            AlgorithmIdentifier::PbeWithSHAAnd3KeyTripleDESCBC(p) => {
313                w.next().write_oid(&OID_PBE_WITH_SHA_AND3_KEY_TRIPLE_DESCBC);
314                p.write(w.next());
315            }
316            AlgorithmIdentifier::OtherAlg(other) => {
317                w.next().write_oid(&other.algorithm_type);
318                if let Some(der) = &other.params {
319                    w.next().write_der(der);
320                }
321            }
322        })
323    }
324}
325
326#[derive(Debug)]
327pub struct DigestInfo {
328    pub digest_algorithm: AlgorithmIdentifier,
329    pub digest: Vec<u8>,
330}
331
332impl DigestInfo {
333    pub fn parse(r: BERReader) -> Result<Self, ASN1Error> {
334        r.read_sequence(|r| {
335            let digest_algorithm = AlgorithmIdentifier::parse(r.next())?;
336            let digest = r.next().read_bytes()?;
337            Ok(DigestInfo {
338                digest_algorithm,
339                digest,
340            })
341        })
342    }
343    pub fn write(&self, w: DERWriter) {
344        w.write_sequence(|w| {
345            self.digest_algorithm.write(w.next());
346            w.next().write_bytes(&self.digest);
347        })
348    }
349}
350
351#[derive(Debug)]
352pub struct MacData {
353    pub mac: DigestInfo,
354    pub salt: Vec<u8>,
355    pub iterations: u32,
356}
357
358impl MacData {
359    pub fn parse(r: BERReader) -> Result<MacData, ASN1Error> {
360        Ok(r.read_sequence(|r| {
361            let mac = DigestInfo::parse(r.next())?;
362            let salt = r.next().read_bytes()?;
363            let iterations = r.next().read_u32()?;
364            Ok(MacData {
365                mac,
366                salt,
367                iterations,
368            })
369        })?)
370    }
371
372    pub fn write(&self, w: DERWriter) {
373        w.write_sequence(|w| {
374            self.mac.write(w.next());
375            w.next().write_bytes(&self.salt);
376            w.next().write_u32(self.iterations);
377        })
378    }
379
380    pub fn verify_mac(&self, data: &[u8], password: &[u8]) -> bool {
381        debug_assert_eq!(self.mac.digest_algorithm, AlgorithmIdentifier::Sha1);
382        let key = pbepkcs12sha1(password, &self.salt, self.iterations as u64, 3, 20);
383        let mut mac = HmacSha1::new_from_slice(&key).unwrap();
384        mac.update(data);
385        mac.verify(&self.mac.digest).is_ok()
386    }
387
388    pub fn new(data: &[u8], password: &[u8]) -> MacData {
389        let salt = rand().unwrap();
390        let key = pbepkcs12sha1(password, &salt, ITERATIONS, 3, 20);
391        let mut mac = HmacSha1::new_from_slice(&key).unwrap();
392        mac.update(data);
393        let digest = mac.finalize().into_bytes().to_vec();
394        MacData {
395            mac: DigestInfo {
396                digest_algorithm: AlgorithmIdentifier::Sha1,
397                digest,
398            },
399            salt: salt.to_vec(),
400            iterations: ITERATIONS as u32,
401        }
402    }
403}
404
405fn rand() -> Option<[u8; 8]> {
406    let mut buf = [0u8; 8];
407    if getrandom(&mut buf).is_ok() {
408        Some(buf)
409    } else {
410        None
411    }
412}
413
414#[derive(Debug)]
415pub struct PFX {
416    pub version: u8,
417    pub auth_safe: ContentInfo,
418    pub mac_data: Option<MacData>,
419}
420
421impl PFX {
422    pub fn new(
423        cert_der: &[u8],
424        key_der: &[u8],
425        ca_der: Option<&[u8]>,
426        password: &str,
427        name: &str,
428    ) -> Option<PFX> {
429        let mut cas = vec![];
430        if let Some(ca) = ca_der {
431            cas.push(ca);
432        }
433        Self::new_with_cas(cert_der, key_der, &cas, password, name)
434    }
435    pub fn new_with_cas(
436        cert_der: &[u8],
437        key_der: &[u8],
438        ca_der_list: &[&[u8]],
439        password: &str,
440        name: &str,
441    ) -> Option<PFX> {
442        let password = bmp_string(password);
443        let salt = rand()?.to_vec();
444        let encrypted_data =
445            pbe_with_sha_and3_key_triple_des_cbc_encrypt(key_der, &password, &salt, ITERATIONS)?;
446        let param = Pkcs12PbeParams {
447            salt: salt,
448            iterations: ITERATIONS,
449        };
450        let key_bag_inner = SafeBagKind::Pkcs8ShroudedKeyBag(EncryptedPrivateKeyInfo {
451            encryption_algorithm: AlgorithmIdentifier::PbeWithSHAAnd3KeyTripleDESCBC(param),
452            encrypted_data,
453        });
454        let friendly_name = PKCS12Attribute::FriendlyName(name.to_owned());
455        let local_key_id = PKCS12Attribute::LocalKeyId(sha1(cert_der));
456        let key_bag = SafeBag {
457            bag: key_bag_inner,
458            attributes: vec![friendly_name.clone(), local_key_id.clone()],
459        };
460        let cert_bag_inner = SafeBagKind::CertBag(CertBag::X509(cert_der.to_owned()));
461        let cert_bag = SafeBag {
462            bag: cert_bag_inner,
463            attributes: vec![friendly_name, local_key_id],
464        };
465        let mut cert_bags = vec![cert_bag];
466        for ca in ca_der_list {
467            cert_bags.push(SafeBag {
468                bag: SafeBagKind::CertBag(CertBag::X509((*ca).to_owned())),
469                attributes: vec![],
470            });
471        }
472        let contents = yasna::construct_der(|w| {
473            w.write_sequence_of(|w| {
474                ContentInfo::EncryptedData(
475                    EncryptedData::from_safe_bags(&cert_bags, &password)
476                        .ok_or_else(|| ASN1Error::new(ASN1ErrorKind::Invalid))
477                        .unwrap(),
478                )
479                .write(w.next());
480                ContentInfo::Data(yasna::construct_der(|w| {
481                    w.write_sequence_of(|w| {
482                        key_bag.write(w.next());
483                    })
484                }))
485                .write(w.next());
486            });
487        });
488        let mac_data = MacData::new(&contents, &password);
489        Some(PFX {
490            version: 3,
491            auth_safe: ContentInfo::Data(contents),
492            mac_data: Some(mac_data),
493        })
494    }
495
496    pub fn parse(bytes: &[u8]) -> Result<PFX, ASN1Error> {
497        yasna::parse_der(bytes, |r| {
498            r.read_sequence(|r| {
499                let version = r.next().read_u8()?;
500                let auth_safe = ContentInfo::parse(r.next())?;
501                let mac_data = r.read_optional(MacData::parse)?;
502                Ok(PFX {
503                    version,
504                    auth_safe,
505                    mac_data,
506                })
507            })
508        })
509    }
510
511    pub fn write(&self, w: DERWriter) {
512        w.write_sequence(|w| {
513            w.next().write_u8(self.version);
514            self.auth_safe.write(w.next());
515            if let Some(mac_data) = &self.mac_data {
516                mac_data.write(w.next())
517            }
518        })
519    }
520
521    pub fn to_der(&self) -> Vec<u8> {
522        yasna::construct_der(|w| self.write(w))
523    }
524    pub fn bags(&self, password: &str) -> Result<Vec<SafeBag>, ASN1Error> {
525        let password = bmp_string(password);
526
527        let data = self
528            .auth_safe
529            .data(&password)
530            .ok_or_else(|| ASN1Error::new(ASN1ErrorKind::Invalid))?;
531
532        let contents = yasna::parse_der(&data, |r| r.collect_sequence_of(ContentInfo::parse))?;
533
534        let mut result = vec![];
535        for content in contents.iter() {
536            let data = content
537                .data(&password)
538                .ok_or_else(|| ASN1Error::new(ASN1ErrorKind::Invalid))?;
539
540            let safe_bags = yasna::parse_der(&data, |r| r.collect_sequence_of(SafeBag::parse))?;
541
542            for safe_bag in safe_bags.iter() {
543                result.push(safe_bag.to_owned())
544            }
545        }
546        Ok(result)
547    }
548    //DER-encoded X.509 certificate
549    pub fn cert_bags(&self, password: &str) -> Result<Vec<Vec<u8>>, ASN1Error> {
550        self.cert_x509_bags(password)
551    }
552    //DER-encoded X.509 certificate
553    pub fn cert_x509_bags(&self, password: &str) -> Result<Vec<Vec<u8>>, ASN1Error> {
554        let mut result = vec![];
555        for safe_bag in self.bags(password)? {
556            if let Some(cert) = safe_bag.bag.get_x509_cert() {
557                result.push(cert);
558            }
559        }
560        Ok(result)
561    }
562    pub fn cert_sdsi_bags(&self, password: &str) -> Result<Vec<String>, ASN1Error> {
563        let mut result = vec![];
564        for safe_bag in self.bags(password)? {
565            if let Some(cert) = safe_bag.bag.get_sdsi_cert() {
566                result.push(cert);
567            }
568        }
569        Ok(result)
570    }
571    pub fn key_bags(&self, password: &str) -> Result<Vec<Vec<u8>>, ASN1Error> {
572        let bmp_password = bmp_string(password);
573        let mut result = vec![];
574        for safe_bag in self.bags(password)? {
575            if let Some(key) = safe_bag.bag.get_key(&bmp_password) {
576                result.push(key);
577            }
578        }
579        Ok(result)
580    }
581
582    pub fn verify_mac(&self, password: &str) -> bool {
583        let bmp_password = bmp_string(password);
584        if let Some(mac_data) = &self.mac_data {
585            return match self.auth_safe.data(&bmp_password) {
586                Some(data) => mac_data.verify_mac(&data, &bmp_password),
587                None => false,
588            };
589        }
590        true
591    }
592}
593
594#[inline(always)]
595fn pbepkcs12sha1core(d: &[u8], i: &[u8], a: &mut Vec<u8>, iterations: u64) -> Vec<u8> {
596    let mut ai: Vec<u8> = d.iter().chain(i.iter()).cloned().collect();
597    for _ in 0..iterations {
598        ai = sha1(&ai);
599    }
600    a.append(&mut ai.clone());
601    ai
602}
603
604#[allow(clippy::many_single_char_names)]
605fn pbepkcs12sha1(pass: &[u8], salt: &[u8], iterations: u64, id: u8, size: u64) -> Vec<u8> {
606    const U: u64 = 160 / 8;
607    const V: u64 = 512 / 8;
608    let r: u64 = iterations;
609    let d = [id; V as usize];
610    fn get_len(s: usize) -> usize {
611        let s = s as u64;
612        (V * ((s + V - 1) / V)) as usize
613    }
614    let s = salt.iter().cycle().take(get_len(salt.len()));
615    let p = pass.iter().cycle().take(get_len(pass.len()));
616    let mut i: Vec<u8> = s.chain(p).cloned().collect();
617    let c = (size + U - 1) / U;
618    let mut a: Vec<u8> = vec![];
619    for _ in 1..c {
620        let ai = pbepkcs12sha1core(&d, &i, &mut a, r);
621
622        let b: Vec<u8> = ai.iter().cycle().take(V as usize).cloned().collect();
623
624        let b_iter = b.iter().rev().cycle().take(i.len());
625        let i_b_iter = i.iter_mut().rev().zip(b_iter);
626        let mut inc = 1u8;
627        for (i3, (ii, bi)) in i_b_iter.enumerate() {
628            if ((i3 as u64) % V) == 0 {
629                inc = 1;
630            }
631            let (ii2, inc2) = ii.overflowing_add(*bi);
632            let (ii3, inc3) = ii2.overflowing_add(inc);
633            inc = (inc2 || inc3) as u8;
634            *ii = ii3;
635        }
636    }
637
638    pbepkcs12sha1core(&d, &i, &mut a, r);
639
640    a.iter().take(size as usize).cloned().collect()
641}
642
643fn pbe_with_sha1_and40_bit_rc2_cbc(
644    data: &[u8],
645    password: &[u8],
646    salt: &[u8],
647    iterations: u64,
648) -> Option<Vec<u8>> {
649    use block_modes::{block_padding::Pkcs7, BlockMode, Cbc};
650    use rc2::Rc2;
651    type Rc2Cbc = Cbc<Rc2, Pkcs7>;
652
653    let dk = pbepkcs12sha1(password, salt, iterations, 1, 5);
654    let iv = pbepkcs12sha1(password, salt, iterations, 2, 8);
655
656    let rc2 = Rc2Cbc::new_from_slices(&dk, &iv).ok()?;
657    rc2.decrypt_vec(data).ok()
658}
659
660fn pbe_with_sha1_and40_bit_rc2_cbc_encrypt(
661    data: &[u8],
662    password: &[u8],
663    salt: &[u8],
664    iterations: u64,
665) -> Option<Vec<u8>> {
666    use block_modes::{block_padding::Pkcs7, BlockMode, Cbc};
667    use rc2::Rc2;
668    type Rc2Cbc = Cbc<Rc2, Pkcs7>;
669
670    let dk = pbepkcs12sha1(password, salt, iterations, 1, 5);
671    let iv = pbepkcs12sha1(password, salt, iterations, 2, 8);
672
673    let rc2 = Rc2Cbc::new_from_slices(&dk, &iv).ok()?;
674    Some(rc2.encrypt_vec(data))
675}
676
677fn pbe_with_sha_and3_key_triple_des_cbc(
678    data: &[u8],
679    password: &[u8],
680    salt: &[u8],
681    iterations: u64,
682) -> Option<Vec<u8>> {
683    use block_modes::{block_padding::Pkcs7, BlockMode, Cbc};
684    use des::TdesEde3;
685    type TDesCbc = Cbc<TdesEde3, Pkcs7>;
686
687    let dk = pbepkcs12sha1(password, salt, iterations, 1, 24);
688    let iv = pbepkcs12sha1(password, salt, iterations, 2, 8);
689
690    let tdes = TDesCbc::new_from_slices(&dk, &iv).ok()?;
691    tdes.decrypt_vec(data).ok()
692}
693
694fn pbe_with_sha_and3_key_triple_des_cbc_encrypt(
695    data: &[u8],
696    password: &[u8],
697    salt: &[u8],
698    iterations: u64,
699) -> Option<Vec<u8>> {
700    use block_modes::{block_padding::Pkcs7, BlockMode, Cbc};
701    use des::TdesEde3;
702    type TDesCbc = Cbc<TdesEde3, Pkcs7>;
703
704    let dk = pbepkcs12sha1(password, salt, iterations, 1, 24);
705    let iv = pbepkcs12sha1(password, salt, iterations, 2, 8);
706
707    let tdes = TDesCbc::new_from_slices(&dk, &iv).ok()?;
708    Some(tdes.encrypt_vec(data))
709}
710
711fn bmp_string(s: &str) -> Vec<u8> {
712    let utf16: Vec<u16> = s.encode_utf16().collect();
713
714    let mut bytes = Vec::with_capacity(utf16.len() * 2 + 2);
715    for c in utf16 {
716        bytes.push((c / 256) as u8);
717        bytes.push((c % 256) as u8);
718    }
719    bytes.push(0x00);
720    bytes.push(0x00);
721    bytes
722}
723
724#[derive(Debug, Clone)]
725pub enum CertBag {
726    X509(Vec<u8>),
727    SDSI(String),
728}
729
730impl CertBag {
731    pub fn parse(r: BERReader) -> Result<Self, ASN1Error> {
732        r.read_sequence(|r| {
733            let oid = r.next().read_oid()?;
734            if oid == *OID_CERT_TYPE_X509_CERTIFICATE {
735                let x509 = r.next().read_tagged(Tag::context(0), |r| r.read_bytes())?;
736                return Ok(CertBag::X509(x509));
737            };
738            if oid == *OID_CERT_TYPE_SDSI_CERTIFICATE {
739                let sdsi = r
740                    .next()
741                    .read_tagged(Tag::context(0), |r| r.read_ia5_string())?;
742                return Ok(CertBag::SDSI(sdsi));
743            }
744            Err(ASN1Error::new(ASN1ErrorKind::Invalid))
745        })
746    }
747    pub fn write(&self, w: DERWriter) {
748        w.write_sequence(|w| match self {
749            CertBag::X509(x509) => {
750                w.next().write_oid(&OID_CERT_TYPE_X509_CERTIFICATE);
751                w.next()
752                    .write_tagged(Tag::context(0), |w| w.write_bytes(x509));
753            }
754            CertBag::SDSI(sdsi) => {
755                w.next().write_oid(&OID_CERT_TYPE_SDSI_CERTIFICATE);
756                w.next()
757                    .write_tagged(Tag::context(0), |w| w.write_ia5_string(sdsi));
758            }
759        })
760    }
761}
762
763#[derive(Debug, Clone, PartialEq)]
764pub struct EncryptedPrivateKeyInfo {
765    pub encryption_algorithm: AlgorithmIdentifier,
766    pub encrypted_data: Vec<u8>,
767}
768
769impl EncryptedPrivateKeyInfo {
770    pub fn parse(r: BERReader) -> Result<Self, ASN1Error> {
771        r.read_sequence(|r| {
772            let encryption_algorithm = AlgorithmIdentifier::parse(r.next())?;
773
774            let encrypted_data = r.next().read_bytes()?;
775
776            Ok(EncryptedPrivateKeyInfo {
777                encryption_algorithm,
778                encrypted_data,
779            })
780        })
781    }
782    pub fn write(&self, w: DERWriter) {
783        w.write_sequence(|w| {
784            self.encryption_algorithm.write(w.next());
785            w.next().write_bytes(&self.encrypted_data);
786        })
787    }
788    pub fn decrypt(&self, password: &[u8]) -> Option<Vec<u8>> {
789        self.encryption_algorithm
790            .decrypt_pbe(&self.encrypted_data, password)
791    }
792}
793
794#[test]
795fn test_encrypted_private_key_info() {
796    let epki = EncryptedPrivateKeyInfo {
797        encryption_algorithm: AlgorithmIdentifier::Sha1,
798        encrypted_data: b"foo".to_vec(),
799    };
800    let der = yasna::construct_der(|w| {
801        epki.write(w);
802    });
803    let epki2 = yasna::parse_ber(&der, |r| EncryptedPrivateKeyInfo::parse(r)).unwrap();
804    assert_eq!(epki2, epki);
805}
806
807#[derive(Debug, Clone)]
808pub struct OtherBag {
809    pub bag_id: ObjectIdentifier,
810    pub bag_value: Vec<u8>,
811}
812
813#[derive(Debug, Clone)]
814pub enum SafeBagKind {
815    //KeyBag(),
816    Pkcs8ShroudedKeyBag(EncryptedPrivateKeyInfo),
817    CertBag(CertBag),
818    //CRLBag(),
819    //SecretBag(),
820    //SafeContents(Vec<SafeBag>),
821    OtherBagKind(OtherBag),
822}
823
824impl SafeBagKind {
825    pub fn parse(r: BERReader, bag_id: ObjectIdentifier) -> Result<Self, ASN1Error> {
826        if bag_id == *OID_CERT_BAG {
827            return Ok(SafeBagKind::CertBag(CertBag::parse(r)?));
828        }
829        if bag_id == *OID_PKCS8_SHROUDED_KEY_BAG {
830            return Ok(SafeBagKind::Pkcs8ShroudedKeyBag(
831                EncryptedPrivateKeyInfo::parse(r)?,
832            ));
833        }
834        let bag_value = r.read_der()?;
835        Ok(SafeBagKind::OtherBagKind(OtherBag { bag_id, bag_value }))
836    }
837    pub fn write(&self, w: DERWriter) {
838        match self {
839            SafeBagKind::Pkcs8ShroudedKeyBag(epk) => epk.write(w),
840            SafeBagKind::CertBag(cb) => cb.write(w),
841            SafeBagKind::OtherBagKind(other) => w.write_der(&other.bag_value),
842        }
843    }
844    pub fn oid(&self) -> ObjectIdentifier {
845        match self {
846            SafeBagKind::Pkcs8ShroudedKeyBag(_) => OID_PKCS8_SHROUDED_KEY_BAG.clone(),
847            SafeBagKind::CertBag(_) => OID_CERT_BAG.clone(),
848            SafeBagKind::OtherBagKind(other) => other.bag_id.clone(),
849        }
850    }
851    pub fn get_x509_cert(&self) -> Option<Vec<u8>> {
852        if let SafeBagKind::CertBag(CertBag::X509(x509)) = self {
853            return Some(x509.to_owned());
854        }
855        None
856    }
857
858    pub fn get_sdsi_cert(&self) -> Option<String> {
859        if let SafeBagKind::CertBag(CertBag::SDSI(sdsi)) = self {
860            return Some(sdsi.to_owned());
861        }
862        None
863    }
864
865    pub fn get_key(&self, password: &[u8]) -> Option<Vec<u8>> {
866        if let SafeBagKind::Pkcs8ShroudedKeyBag(kb) = self {
867            return kb.decrypt(password);
868        }
869        None
870    }
871}
872
873#[derive(Debug, Clone)]
874pub struct OtherAttribute {
875    pub oid: ObjectIdentifier,
876    pub data: Vec<Vec<u8>>,
877}
878
879#[derive(Debug, Clone)]
880pub enum PKCS12Attribute {
881    FriendlyName(String),
882    LocalKeyId(Vec<u8>),
883    Other(OtherAttribute),
884}
885
886impl PKCS12Attribute {
887    pub fn parse(r: BERReader) -> Result<Self, ASN1Error> {
888        r.read_sequence(|r| {
889            let oid = r.next().read_oid()?;
890            if oid == *OID_FRIENDLY_NAME {
891                let name = r
892                    .next()
893                    .collect_set_of(|s| s.read_bmp_string())?
894                    .pop()
895                    .ok_or_else(|| ASN1Error::new(ASN1ErrorKind::Invalid))?;
896                return Ok(PKCS12Attribute::FriendlyName(name));
897            }
898            if oid == *OID_LOCAL_KEY_ID {
899                let local_key_id = r
900                    .next()
901                    .collect_set_of(|s| s.read_bytes())?
902                    .pop()
903                    .ok_or_else(|| ASN1Error::new(ASN1ErrorKind::Invalid))?;
904                return Ok(PKCS12Attribute::LocalKeyId(local_key_id));
905            }
906
907            let data = r.next().collect_set_of(|s| s.read_der())?;
908            let other = OtherAttribute { oid, data };
909            Ok(PKCS12Attribute::Other(other))
910        })
911    }
912    pub fn write(&self, w: DERWriter) {
913        w.write_sequence(|w| match self {
914            PKCS12Attribute::FriendlyName(name) => {
915                w.next().write_oid(&OID_FRIENDLY_NAME);
916                w.next().write_set_of(|w| {
917                    w.next().write_bmp_string(name);
918                })
919            }
920            PKCS12Attribute::LocalKeyId(id) => {
921                w.next().write_oid(&OID_LOCAL_KEY_ID);
922                w.next().write_set_of(|w| w.next().write_bytes(&id))
923            }
924            PKCS12Attribute::Other(other) => {
925                w.next().write_oid(&other.oid);
926                w.next().write_set_of(|w| {
927                    for bytes in other.data.iter() {
928                        w.next().write_der(&bytes);
929                    }
930                })
931            }
932        })
933    }
934}
935#[derive(Debug, Clone)]
936pub struct SafeBag {
937    pub bag: SafeBagKind,
938    pub attributes: Vec<PKCS12Attribute>,
939}
940
941impl SafeBag {
942    pub fn parse(r: BERReader) -> Result<Self, ASN1Error> {
943        r.read_sequence(|r| {
944            let oid = r.next().read_oid()?;
945
946            let bag = r
947                .next()
948                .read_tagged(Tag::context(0), |r| SafeBagKind::parse(r, oid))?;
949
950            let attributes = r
951                .read_optional(|r| r.collect_set_of(PKCS12Attribute::parse))?
952                .unwrap_or_else(|| vec![]);
953
954            Ok(SafeBag { bag, attributes })
955        })
956    }
957    pub fn write(&self, w: DERWriter) {
958        w.write_sequence(|w| {
959            w.next().write_oid(&self.bag.oid());
960            w.next()
961                .write_tagged(Tag::context(0), |w| self.bag.write(w));
962            if !self.attributes.is_empty() {
963                w.next().write_set_of(|w| {
964                    for attr in &self.attributes {
965                        attr.write(w.next());
966                    }
967                })
968            }
969        })
970    }
971    pub fn friendly_name(&self) -> Option<String> {
972        for attr in self.attributes.iter() {
973            if let PKCS12Attribute::FriendlyName(name) = attr {
974                return Some(name.to_owned());
975            }
976        }
977        None
978    }
979    pub fn local_key_id(&self) -> Option<Vec<u8>> {
980        for attr in self.attributes.iter() {
981            if let PKCS12Attribute::LocalKeyId(id) = attr {
982                return Some(id.to_owned());
983            }
984        }
985        None
986    }
987}
988
989#[test]
990fn test_create_p12() {
991    use std::fs::File;
992    use std::io::{Read, Write};
993    let mut cafile = File::open("ca.der").unwrap();
994    let mut ca = vec![];
995    cafile.read_to_end(&mut ca).unwrap();
996    let mut fcert = File::open("clientcert.der").unwrap();
997    let mut fkey = File::open("clientkey.der").unwrap();
998    let mut cert = vec![];
999    fcert.read_to_end(&mut cert).unwrap();
1000    let mut key = vec![];
1001    fkey.read_to_end(&mut key).unwrap();
1002    let p12 = PFX::new(&cert, &key, Some(&ca), "changeit", "look")
1003        .unwrap()
1004        .to_der();
1005
1006    let pfx = PFX::parse(&p12).unwrap();
1007
1008    let keys = pfx.key_bags("changeit").unwrap();
1009    assert_eq!(keys[0], key);
1010
1011    let certs = pfx.cert_x509_bags("changeit").unwrap();
1012    assert_eq!(certs[0], cert);
1013    assert_eq!(certs[1], ca);
1014    assert!(pfx.verify_mac("changeit"));
1015
1016    let mut fp12 = File::create("test.p12").unwrap();
1017    fp12.write_all(&p12).unwrap();
1018}
1019
1020#[test]
1021fn test_bmp_string() {
1022    let value = bmp_string("Beavis");
1023    assert!(
1024        value
1025            == [0x00, 0x42, 0x00, 0x65, 0x00, 0x61, 0x00, 0x76, 0x00, 0x69, 0x00, 0x73, 0x00, 0x00]
1026    )
1027}
1028
1029#[test]
1030fn test_pbepkcs12sha1() {
1031    use hex_literal::hex;
1032    let pass = bmp_string("");
1033    assert_eq!(pass, vec![0, 0]);
1034    let salt = hex!("9af4702958a8e95c");
1035    let iterations = 2048;
1036    let id = 1;
1037    let size = 24;
1038    let result = pbepkcs12sha1(&pass, &salt, iterations, id, size);
1039    let res = hex!("c2294aa6d02930eb5ce9c329eccb9aee1cb136baea746557");
1040    assert_eq!(result, res);
1041}
1042
1043#[test]
1044fn test_pbepkcs12sha1_2() {
1045    use hex_literal::hex;
1046    let pass = bmp_string("");
1047    assert_eq!(pass, vec![0, 0]);
1048    let salt = hex!("9af4702958a8e95c");
1049    let iterations = 2048;
1050    let id = 2;
1051    let size = 8;
1052    let result = pbepkcs12sha1(&pass, &salt, iterations, id, size);
1053    let res = hex!("8e9f8fc7664378bc");
1054    assert_eq!(result, res);
1055}