1use 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, ¶m.salt, param.iterations)
290 }
291 AlgorithmIdentifier::PbeWithSHAAnd3KeyTripleDESCBC(param) => {
292 pbe_with_sha_and3_key_triple_des_cbc(
293 ciphertext,
294 password,
295 ¶m.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 pub fn cert_bags(&self, password: &str) -> Result<Vec<Vec<u8>>, ASN1Error> {
550 self.cert_x509_bags(password)
551 }
552 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 Pkcs8ShroudedKeyBag(EncryptedPrivateKeyInfo),
817 CertBag(CertBag),
818 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}