2 * PKCS#12 Personal Information Exchange Syntax
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 * The PKCS #12 Personal Information Exchange Syntax Standard v1.1
22 * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf
23 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn
28 #if defined(MBEDTLS_PKCS12_C)
30 #include "mbedtls/pkcs12.h"
31 #include "mbedtls/asn1.h"
32 #include "mbedtls/cipher.h"
33 #include "mbedtls/platform_util.h"
34 #include "mbedtls/error.h"
38 #if defined(MBEDTLS_ARC4_C)
39 #include "mbedtls/arc4.h"
42 #if defined(MBEDTLS_DES_C)
43 #include "mbedtls/des.h"
46 #if defined(MBEDTLS_ASN1_PARSE_C)
48 static int pkcs12_parse_pbe_params(mbedtls_asn1_buf
*params
,
49 mbedtls_asn1_buf
*salt
, int *iterations
) {
50 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
51 unsigned char **p
= ¶ms
->p
;
52 const unsigned char *end
= params
->p
+ params
->len
;
55 * pkcs-12PbeParams ::= SEQUENCE {
61 if (params
->tag
!= (MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
))
62 return (MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT
+
63 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
);
65 if ((ret
= mbedtls_asn1_get_tag(p
, end
, &salt
->len
, MBEDTLS_ASN1_OCTET_STRING
)) != 0)
66 return (MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT
+ ret
);
71 if ((ret
= mbedtls_asn1_get_int(p
, end
, iterations
)) != 0)
72 return (MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT
+ ret
);
75 return (MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT
+
76 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
81 #define PKCS12_MAX_PWDLEN 128
83 static int pkcs12_pbe_derive_key_iv(mbedtls_asn1_buf
*pbe_params
, mbedtls_md_type_t md_type
,
84 const unsigned char *pwd
, size_t pwdlen
,
85 unsigned char *key
, size_t keylen
,
86 unsigned char *iv
, size_t ivlen
) {
87 int ret
, iterations
= 0;
88 mbedtls_asn1_buf salt
;
90 unsigned char unipwd
[PKCS12_MAX_PWDLEN
* 2 + 2];
92 if (pwdlen
> PKCS12_MAX_PWDLEN
)
93 return (MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA
);
95 memset(&salt
, 0, sizeof(mbedtls_asn1_buf
));
96 memset(&unipwd
, 0, sizeof(unipwd
));
98 if ((ret
= pkcs12_parse_pbe_params(pbe_params
, &salt
,
102 for (i
= 0; i
< pwdlen
; i
++)
103 unipwd
[i
* 2 + 1] = pwd
[i
];
105 if ((ret
= mbedtls_pkcs12_derivation(key
, keylen
, unipwd
, pwdlen
* 2 + 2,
106 salt
.p
, salt
.len
, md_type
,
107 MBEDTLS_PKCS12_DERIVE_KEY
, iterations
)) != 0) {
111 if (iv
== NULL
|| ivlen
== 0)
114 if ((ret
= mbedtls_pkcs12_derivation(iv
, ivlen
, unipwd
, pwdlen
* 2 + 2,
115 salt
.p
, salt
.len
, md_type
,
116 MBEDTLS_PKCS12_DERIVE_IV
, iterations
)) != 0) {
122 #undef PKCS12_MAX_PWDLEN
124 int mbedtls_pkcs12_pbe_sha1_rc4_128(mbedtls_asn1_buf
*pbe_params
, int mode
,
125 const unsigned char *pwd
, size_t pwdlen
,
126 const unsigned char *data
, size_t len
,
127 unsigned char *output
) {
128 #if !defined(MBEDTLS_ARC4_C)
136 return (MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE
);
138 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
139 unsigned char key
[16];
140 mbedtls_arc4_context ctx
;
143 mbedtls_arc4_init(&ctx
);
145 if ((ret
= pkcs12_pbe_derive_key_iv(pbe_params
, MBEDTLS_MD_SHA1
,
147 key
, 16, NULL
, 0)) != 0) {
151 mbedtls_arc4_setup(&ctx
, key
, 16);
152 if ((ret
= mbedtls_arc4_crypt(&ctx
, len
, data
, output
)) != 0)
156 mbedtls_platform_zeroize(key
, sizeof(key
));
157 mbedtls_arc4_free(&ctx
);
160 #endif /* MBEDTLS_ARC4_C */
163 int mbedtls_pkcs12_pbe(mbedtls_asn1_buf
*pbe_params
, int mode
,
164 mbedtls_cipher_type_t cipher_type
, mbedtls_md_type_t md_type
,
165 const unsigned char *pwd
, size_t pwdlen
,
166 const unsigned char *data
, size_t len
,
167 unsigned char *output
) {
169 unsigned char key
[32];
170 unsigned char iv
[16];
171 const mbedtls_cipher_info_t
*cipher_info
;
172 mbedtls_cipher_context_t cipher_ctx
;
175 cipher_info
= mbedtls_cipher_info_from_type(cipher_type
);
176 if (cipher_info
== NULL
)
177 return (MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE
);
179 keylen
= cipher_info
->key_bitlen
/ 8;
181 if ((ret
= pkcs12_pbe_derive_key_iv(pbe_params
, md_type
, pwd
, pwdlen
,
183 iv
, cipher_info
->iv_size
)) != 0) {
187 mbedtls_cipher_init(&cipher_ctx
);
189 if ((ret
= mbedtls_cipher_setup(&cipher_ctx
, cipher_info
)) != 0)
192 if ((ret
= mbedtls_cipher_setkey(&cipher_ctx
, key
, 8 * keylen
, (mbedtls_operation_t
) mode
)) != 0)
195 if ((ret
= mbedtls_cipher_set_iv(&cipher_ctx
, iv
, cipher_info
->iv_size
)) != 0)
198 if ((ret
= mbedtls_cipher_reset(&cipher_ctx
)) != 0)
201 if ((ret
= mbedtls_cipher_update(&cipher_ctx
, data
, len
,
202 output
, &olen
)) != 0) {
206 if ((ret
= mbedtls_cipher_finish(&cipher_ctx
, output
+ olen
, &olen
)) != 0)
207 ret
= MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH
;
210 mbedtls_platform_zeroize(key
, sizeof(key
));
211 mbedtls_platform_zeroize(iv
, sizeof(iv
));
212 mbedtls_cipher_free(&cipher_ctx
);
217 #endif /* MBEDTLS_ASN1_PARSE_C */
219 static void pkcs12_fill_buffer(unsigned char *data
, size_t data_len
,
220 const unsigned char *filler
, size_t fill_len
) {
221 unsigned char *p
= data
;
224 while (data_len
> 0) {
225 use_len
= (data_len
> fill_len
) ? fill_len
: data_len
;
226 memcpy(p
, filler
, use_len
);
232 int mbedtls_pkcs12_derivation(unsigned char *data
, size_t datalen
,
233 const unsigned char *pwd
, size_t pwdlen
,
234 const unsigned char *salt
, size_t saltlen
,
235 mbedtls_md_type_t md_type
, int id
, int iterations
) {
236 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
239 unsigned char diversifier
[128];
240 unsigned char salt_block
[128], pwd_block
[128], hash_block
[128];
241 unsigned char hash_output
[MBEDTLS_MD_MAX_SIZE
];
245 size_t hlen
, use_len
, v
, i
;
247 const mbedtls_md_info_t
*md_info
;
248 mbedtls_md_context_t md_ctx
;
250 // This version only allows max of 64 bytes of password or salt
251 if (datalen
> 128 || pwdlen
> 64 || saltlen
> 64)
252 return (MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA
);
254 md_info
= mbedtls_md_info_from_type(md_type
);
256 return (MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE
);
258 mbedtls_md_init(&md_ctx
);
260 if ((ret
= mbedtls_md_setup(&md_ctx
, md_info
, 0)) != 0)
262 hlen
= mbedtls_md_get_size(md_info
);
269 memset(diversifier
, (unsigned char) id
, v
);
271 pkcs12_fill_buffer(salt_block
, v
, salt
, saltlen
);
272 pkcs12_fill_buffer(pwd_block
, v
, pwd
, pwdlen
);
275 while (datalen
> 0) {
276 // Calculate hash( diversifier || salt_block || pwd_block )
277 if ((ret
= mbedtls_md_starts(&md_ctx
)) != 0)
280 if ((ret
= mbedtls_md_update(&md_ctx
, diversifier
, v
)) != 0)
283 if ((ret
= mbedtls_md_update(&md_ctx
, salt_block
, v
)) != 0)
286 if ((ret
= mbedtls_md_update(&md_ctx
, pwd_block
, v
)) != 0)
289 if ((ret
= mbedtls_md_finish(&md_ctx
, hash_output
)) != 0)
292 // Perform remaining ( iterations - 1 ) recursive hash calculations
293 for (i
= 1; i
< (size_t) iterations
; i
++) {
294 if ((ret
= mbedtls_md(md_info
, hash_output
, hlen
, hash_output
)) != 0)
298 use_len
= (datalen
> hlen
) ? hlen
: datalen
;
299 memcpy(p
, hash_output
, use_len
);
306 // Concatenating copies of hash_output into hash_block (B)
307 pkcs12_fill_buffer(hash_block
, v
, hash_output
, hlen
);
310 for (i
= v
; i
> 0; i
--)
311 if (++hash_block
[i
- 1] != 0)
316 for (i
= v
; i
> 0; i
--) {
317 j
= salt_block
[i
- 1] + hash_block
[i
- 1] + c
;
318 c
= (unsigned char)(j
>> 8);
319 salt_block
[i
- 1] = j
& 0xFF;
324 for (i
= v
; i
> 0; i
--) {
325 j
= pwd_block
[i
- 1] + hash_block
[i
- 1] + c
;
326 c
= (unsigned char)(j
>> 8);
327 pwd_block
[i
- 1] = j
& 0xFF;
334 mbedtls_platform_zeroize(salt_block
, sizeof(salt_block
));
335 mbedtls_platform_zeroize(pwd_block
, sizeof(pwd_block
));
336 mbedtls_platform_zeroize(hash_block
, sizeof(hash_block
));
337 mbedtls_platform_zeroize(hash_output
, sizeof(hash_output
));
339 mbedtls_md_free(&md_ctx
);
344 #endif /* MBEDTLS_PKCS12_C */