22
33use crate :: authenticated_safe:: AuthenticatedSafe ;
44use crate :: cert_type:: CertBag ;
5+ use crate :: pbe_params:: EncryptedPrivateKeyInfo as OtherEncryptedPrivateKeyInfo ;
6+ use core:: str:: Utf8Error ;
7+
8+ #[ cfg( all( feature = "kdf" , feature = "insecure" ) ) ]
9+ use crate :: decrypt_kdf:: * ;
10+
511use crate :: pfx:: Pfx ;
612use crate :: safe_bag:: { PrivateKeyInfo , SafeContents } ;
713use cms:: encrypted_data:: EncryptedData ;
@@ -10,7 +16,7 @@ use const_oid::ObjectIdentifier;
1016use der:: asn1:: ContextSpecific ;
1117use der:: asn1:: OctetString ;
1218use der:: { Any , Decode , Encode } ;
13- use pkcs5:: pbes2;
19+ use pkcs5:: pbes2:: PBES2_OID ;
1420use pkcs8:: EncryptedPrivateKeyInfo ;
1521use x509_cert:: Certificate ;
1622
@@ -41,8 +47,12 @@ pub enum Error {
4147
4248 /// Missing expected content
4349 UnexpectedAlgorithm ( ObjectIdentifier ) ,
50+
51+ /// String conversion error
52+ Utf8Error ( Utf8Error ) ,
4453}
45- type Result < T > = core:: result:: Result < T , Error > ;
54+ /// Result type for PKCS #12 der
55+ pub type Result < T > = core:: result:: Result < T , Error > ;
4656
4757fn process_safe_contents (
4858 data : & [ u8 ] ,
@@ -67,19 +77,46 @@ fn process_safe_contents(
6777 }
6878 }
6979 crate :: PKCS_12_PKCS8_KEY_BAG_OID => {
70- let cs : ContextSpecific < EncryptedPrivateKeyInfo < ' _ > > =
80+ let cs_tmp : ContextSpecific < OtherEncryptedPrivateKeyInfo > =
7181 ContextSpecific :: from_der ( & safe_bag. bag_value ) . map_err ( |e| Error :: Asn1 ( e) ) ?;
72- let mut ciphertext = cs. value . encrypted_data . to_vec ( ) ;
73- let plaintext = cs
74- . value
75- . encryption_algorithm
76- . decrypt_in_place ( password, & mut ciphertext)
77- . map_err ( |e| Error :: Pkcs5 ( e) ) ?;
78- if key. is_none ( ) {
79- key = Some ( PrivateKeyInfo :: from_der ( plaintext) . map_err ( |e| Error :: Asn1 ( e) ) ?) ;
80- } else {
81- return Err ( Error :: UnexpectedSafeBag ) ;
82- }
82+ match cs_tmp. value . encryption_algorithm . oid {
83+ PBES2_OID => {
84+ let cs: ContextSpecific < EncryptedPrivateKeyInfo < ' _ > > =
85+ ContextSpecific :: from_der ( & safe_bag. bag_value )
86+ . map_err ( |e| Error :: Asn1 ( e) ) ?;
87+ let mut ciphertext = cs. value . encrypted_data . to_vec ( ) ;
88+ let plaintext = cs
89+ . value
90+ . encryption_algorithm
91+ . decrypt_in_place ( password, & mut ciphertext)
92+ . map_err ( |e| Error :: Pkcs5 ( e) ) ?;
93+ if key. is_none ( ) {
94+ key = Some (
95+ PrivateKeyInfo :: from_der ( plaintext) . map_err ( |e| Error :: Asn1 ( e) ) ?,
96+ ) ;
97+ } else {
98+ return Err ( Error :: UnexpectedSafeBag ) ;
99+ }
100+ }
101+ #[ cfg( all( feature = "kdf" , feature = "insecure" ) ) ]
102+ _ => {
103+ let cur_key = pkcs12_pbe_key (
104+ cs_tmp. value . encrypted_data ,
105+ password,
106+ & cs_tmp. value . encryption_algorithm ,
107+ ) ?;
108+ if key. is_some ( ) {
109+ return Err ( Error :: UnexpectedAuthSafe ) ;
110+ }
111+ key = Some ( cur_key) ;
112+ }
113+ #[ cfg( not( all( feature = "kdf" , feature = "insecure" ) ) ) ]
114+ _ => {
115+ return Err ( Error :: UnexpectedAlgorithm (
116+ cs_tmp. value . encryption_algorithm . oid ,
117+ ) )
118+ }
119+ } ;
83120 }
84121 crate :: PKCS_12_KEY_BAG_OID => {
85122 if key. is_none ( ) {
@@ -103,38 +140,50 @@ fn process_encrypted_data(
103140) -> Result < ( Option < PrivateKeyInfo > , Option < Certificate > ) > {
104141 let enc_data_os = & data. to_der ( ) . map_err ( |e| Error :: Asn1 ( e) ) ?;
105142 let enc_data = EncryptedData :: from_der ( enc_data_os. as_slice ( ) ) . map_err ( |e| Error :: Asn1 ( e) ) ?;
106- let enc_params = match enc_data
107- . enc_content_info
108- . content_enc_alg
109- . parameters
110- . as_ref ( )
111- {
112- Some ( params) => params. to_der ( ) . map_err ( |e| Error :: Asn1 ( e) ) ?,
113- None => return Err ( Error :: MissingParameters ) ,
114- } ;
115-
116- let params = match enc_data. enc_content_info . content_enc_alg . oid {
117- pbes2:: PBES2_OID => {
118- pkcs8:: pkcs5:: pbes2:: Parameters :: from_der ( & enc_params) . map_err ( |e| Error :: Asn1 ( e) ) ?
143+
144+ match enc_data. enc_content_info . content_enc_alg . oid {
145+ PBES2_OID => {
146+ let enc_params = match enc_data
147+ . enc_content_info
148+ . content_enc_alg
149+ . parameters
150+ . as_ref ( )
151+ {
152+ Some ( params) => params. to_der ( ) . map_err ( |e| Error :: Asn1 ( e) ) ?,
153+ None => return Err ( Error :: MissingParameters ) ,
154+ } ;
155+ let params = pkcs8:: pkcs5:: pbes2:: Parameters :: from_der ( & enc_params)
156+ . map_err ( |e| Error :: Asn1 ( e) ) ?;
157+ let scheme = pkcs5:: EncryptionScheme :: try_from ( params. clone ( ) )
158+ . map_err ( |_e| Error :: EncryptionScheme ) ?;
159+ match enc_data. enc_content_info . encrypted_content {
160+ Some ( content) => {
161+ let mut ciphertext = content. as_bytes ( ) . to_vec ( ) ;
162+ let plaintext = scheme
163+ . decrypt_in_place ( password, & mut ciphertext)
164+ . map_err ( |e| Error :: Pkcs5 ( e) ) ?;
165+ process_safe_contents ( plaintext, password)
166+ }
167+ None => return Err ( Error :: MissingContent ) ,
168+ }
169+ }
170+ #[ cfg( all( feature = "kdf" , feature = "insecure" ) ) ]
171+ crate :: PKCS_12_PBE_WITH_SHAAND3_KEY_TRIPLE_DES_CBC => {
172+ let plaintext = match enc_data. enc_content_info . encrypted_content {
173+ Some ( encrypted_content) => pkcs12_pbe (
174+ encrypted_content,
175+ password,
176+ & enc_data. enc_content_info . content_enc_alg ,
177+ ) ?,
178+ None => return Err ( Error :: MissingParameters ) ,
179+ } ;
180+ process_safe_contents ( & plaintext, password)
119181 }
120182 _ => {
121183 return Err ( Error :: UnexpectedAlgorithm (
122184 enc_data. enc_content_info . content_enc_alg . oid ,
123185 ) )
124186 }
125- } ;
126-
127- let scheme =
128- pkcs5:: EncryptionScheme :: try_from ( params. clone ( ) ) . map_err ( |_e| Error :: EncryptionScheme ) ?;
129- match enc_data. enc_content_info . encrypted_content {
130- Some ( content) => {
131- let mut ciphertext = content. as_bytes ( ) . to_vec ( ) ;
132- let plaintext = scheme
133- . decrypt_in_place ( password, & mut ciphertext)
134- . map_err ( |e| Error :: Pkcs5 ( e) ) ?;
135- process_safe_contents ( plaintext, password)
136- }
137- None => return Err ( Error :: MissingContent ) ,
138187 }
139188}
140189
0 commit comments