xref: /aosp_15_r20/external/mbedtls/library/pkcs5.c (revision 62c56f9862f102b96d72393aff6076c951fb8148)
1*62c56f98SSadaf Ebrahimi /**
2*62c56f98SSadaf Ebrahimi  * \file pkcs5.c
3*62c56f98SSadaf Ebrahimi  *
4*62c56f98SSadaf Ebrahimi  * \brief PKCS#5 functions
5*62c56f98SSadaf Ebrahimi  *
6*62c56f98SSadaf Ebrahimi  * \author Mathias Olsson <[email protected]>
7*62c56f98SSadaf Ebrahimi  *
8*62c56f98SSadaf Ebrahimi  *  Copyright The Mbed TLS Contributors
9*62c56f98SSadaf Ebrahimi  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
10*62c56f98SSadaf Ebrahimi  */
11*62c56f98SSadaf Ebrahimi /*
12*62c56f98SSadaf Ebrahimi  * PKCS#5 includes PBKDF2 and more
13*62c56f98SSadaf Ebrahimi  *
14*62c56f98SSadaf Ebrahimi  * http://tools.ietf.org/html/rfc2898 (Specification)
15*62c56f98SSadaf Ebrahimi  * http://tools.ietf.org/html/rfc6070 (Test vectors)
16*62c56f98SSadaf Ebrahimi  */
17*62c56f98SSadaf Ebrahimi 
18*62c56f98SSadaf Ebrahimi #include "common.h"
19*62c56f98SSadaf Ebrahimi 
20*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_PKCS5_C)
21*62c56f98SSadaf Ebrahimi 
22*62c56f98SSadaf Ebrahimi #include "mbedtls/pkcs5.h"
23*62c56f98SSadaf Ebrahimi #include "mbedtls/error.h"
24*62c56f98SSadaf Ebrahimi 
25*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ASN1_PARSE_C)
26*62c56f98SSadaf Ebrahimi #include "mbedtls/asn1.h"
27*62c56f98SSadaf Ebrahimi #include "mbedtls/cipher.h"
28*62c56f98SSadaf Ebrahimi #include "mbedtls/oid.h"
29*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ASN1_PARSE_C */
30*62c56f98SSadaf Ebrahimi 
31*62c56f98SSadaf Ebrahimi #include <string.h>
32*62c56f98SSadaf Ebrahimi 
33*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
34*62c56f98SSadaf Ebrahimi 
35*62c56f98SSadaf Ebrahimi #include "psa_util_internal.h"
36*62c56f98SSadaf Ebrahimi 
37*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ASN1_PARSE_C)
pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf * params,mbedtls_asn1_buf * salt,int * iterations,int * keylen,mbedtls_md_type_t * md_type)38*62c56f98SSadaf Ebrahimi static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
39*62c56f98SSadaf Ebrahimi                                      mbedtls_asn1_buf *salt, int *iterations,
40*62c56f98SSadaf Ebrahimi                                      int *keylen, mbedtls_md_type_t *md_type)
41*62c56f98SSadaf Ebrahimi {
42*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
43*62c56f98SSadaf Ebrahimi     mbedtls_asn1_buf prf_alg_oid;
44*62c56f98SSadaf Ebrahimi     unsigned char *p = params->p;
45*62c56f98SSadaf Ebrahimi     const unsigned char *end = params->p + params->len;
46*62c56f98SSadaf Ebrahimi 
47*62c56f98SSadaf Ebrahimi     if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
48*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
49*62c56f98SSadaf Ebrahimi                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
50*62c56f98SSadaf Ebrahimi     }
51*62c56f98SSadaf Ebrahimi     /*
52*62c56f98SSadaf Ebrahimi      *  PBKDF2-params ::= SEQUENCE {
53*62c56f98SSadaf Ebrahimi      *    salt              OCTET STRING,
54*62c56f98SSadaf Ebrahimi      *    iterationCount    INTEGER,
55*62c56f98SSadaf Ebrahimi      *    keyLength         INTEGER OPTIONAL
56*62c56f98SSadaf Ebrahimi      *    prf               AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
57*62c56f98SSadaf Ebrahimi      *  }
58*62c56f98SSadaf Ebrahimi      *
59*62c56f98SSadaf Ebrahimi      */
60*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len,
61*62c56f98SSadaf Ebrahimi                                     MBEDTLS_ASN1_OCTET_STRING)) != 0) {
62*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
63*62c56f98SSadaf Ebrahimi     }
64*62c56f98SSadaf Ebrahimi 
65*62c56f98SSadaf Ebrahimi     salt->p = p;
66*62c56f98SSadaf Ebrahimi     p += salt->len;
67*62c56f98SSadaf Ebrahimi 
68*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0) {
69*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
70*62c56f98SSadaf Ebrahimi     }
71*62c56f98SSadaf Ebrahimi 
72*62c56f98SSadaf Ebrahimi     if (p == end) {
73*62c56f98SSadaf Ebrahimi         return 0;
74*62c56f98SSadaf Ebrahimi     }
75*62c56f98SSadaf Ebrahimi 
76*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_asn1_get_int(&p, end, keylen)) != 0) {
77*62c56f98SSadaf Ebrahimi         if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
78*62c56f98SSadaf Ebrahimi             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
79*62c56f98SSadaf Ebrahimi         }
80*62c56f98SSadaf Ebrahimi     }
81*62c56f98SSadaf Ebrahimi 
82*62c56f98SSadaf Ebrahimi     if (p == end) {
83*62c56f98SSadaf Ebrahimi         return 0;
84*62c56f98SSadaf Ebrahimi     }
85*62c56f98SSadaf Ebrahimi 
86*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0) {
87*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
88*62c56f98SSadaf Ebrahimi     }
89*62c56f98SSadaf Ebrahimi 
90*62c56f98SSadaf Ebrahimi     if (mbedtls_oid_get_md_hmac(&prf_alg_oid, md_type) != 0) {
91*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
92*62c56f98SSadaf Ebrahimi     }
93*62c56f98SSadaf Ebrahimi 
94*62c56f98SSadaf Ebrahimi     if (p != end) {
95*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
96*62c56f98SSadaf Ebrahimi                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
97*62c56f98SSadaf Ebrahimi     }
98*62c56f98SSadaf Ebrahimi 
99*62c56f98SSadaf Ebrahimi     return 0;
100*62c56f98SSadaf Ebrahimi }
101*62c56f98SSadaf Ebrahimi 
102*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
103*62c56f98SSadaf Ebrahimi int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode,
104*62c56f98SSadaf Ebrahimi                             const unsigned char *pwd,  size_t pwdlen,
105*62c56f98SSadaf Ebrahimi                             const unsigned char *data, size_t datalen,
106*62c56f98SSadaf Ebrahimi                             unsigned char *output, size_t output_size,
107*62c56f98SSadaf Ebrahimi                             size_t *output_len);
108*62c56f98SSadaf Ebrahimi #endif
109*62c56f98SSadaf Ebrahimi 
110*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf * pbe_params,int mode,const unsigned char * pwd,size_t pwdlen,const unsigned char * data,size_t datalen,unsigned char * output)111*62c56f98SSadaf Ebrahimi int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
112*62c56f98SSadaf Ebrahimi                         const unsigned char *pwd,  size_t pwdlen,
113*62c56f98SSadaf Ebrahimi                         const unsigned char *data, size_t datalen,
114*62c56f98SSadaf Ebrahimi                         unsigned char *output)
115*62c56f98SSadaf Ebrahimi {
116*62c56f98SSadaf Ebrahimi     size_t output_len = 0;
117*62c56f98SSadaf Ebrahimi 
118*62c56f98SSadaf Ebrahimi     /* We assume caller of the function is providing a big enough output buffer
119*62c56f98SSadaf Ebrahimi      * so we pass output_size as SIZE_MAX to pass checks, However, no guarantees
120*62c56f98SSadaf Ebrahimi      * for the output size actually being correct.
121*62c56f98SSadaf Ebrahimi      */
122*62c56f98SSadaf Ebrahimi     return mbedtls_pkcs5_pbes2_ext(pbe_params, mode, pwd, pwdlen, data,
123*62c56f98SSadaf Ebrahimi                                    datalen, output, SIZE_MAX, &output_len);
124*62c56f98SSadaf Ebrahimi }
125*62c56f98SSadaf Ebrahimi #endif
126*62c56f98SSadaf Ebrahimi 
mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf * pbe_params,int mode,const unsigned char * pwd,size_t pwdlen,const unsigned char * data,size_t datalen,unsigned char * output,size_t output_size,size_t * output_len)127*62c56f98SSadaf Ebrahimi int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode,
128*62c56f98SSadaf Ebrahimi                             const unsigned char *pwd,  size_t pwdlen,
129*62c56f98SSadaf Ebrahimi                             const unsigned char *data, size_t datalen,
130*62c56f98SSadaf Ebrahimi                             unsigned char *output, size_t output_size,
131*62c56f98SSadaf Ebrahimi                             size_t *output_len)
132*62c56f98SSadaf Ebrahimi {
133*62c56f98SSadaf Ebrahimi     int ret, iterations = 0, keylen = 0;
134*62c56f98SSadaf Ebrahimi     unsigned char *p, *end;
135*62c56f98SSadaf Ebrahimi     mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params;
136*62c56f98SSadaf Ebrahimi     mbedtls_asn1_buf salt;
137*62c56f98SSadaf Ebrahimi     mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
138*62c56f98SSadaf Ebrahimi     unsigned char key[32], iv[32];
139*62c56f98SSadaf Ebrahimi     const mbedtls_cipher_info_t *cipher_info;
140*62c56f98SSadaf Ebrahimi     mbedtls_cipher_type_t cipher_alg;
141*62c56f98SSadaf Ebrahimi     mbedtls_cipher_context_t cipher_ctx;
142*62c56f98SSadaf Ebrahimi     unsigned int padlen = 0;
143*62c56f98SSadaf Ebrahimi 
144*62c56f98SSadaf Ebrahimi     p = pbe_params->p;
145*62c56f98SSadaf Ebrahimi     end = p + pbe_params->len;
146*62c56f98SSadaf Ebrahimi 
147*62c56f98SSadaf Ebrahimi     /*
148*62c56f98SSadaf Ebrahimi      *  PBES2-params ::= SEQUENCE {
149*62c56f98SSadaf Ebrahimi      *    keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
150*62c56f98SSadaf Ebrahimi      *    encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
151*62c56f98SSadaf Ebrahimi      *  }
152*62c56f98SSadaf Ebrahimi      */
153*62c56f98SSadaf Ebrahimi     if (pbe_params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
154*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
155*62c56f98SSadaf Ebrahimi                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
156*62c56f98SSadaf Ebrahimi     }
157*62c56f98SSadaf Ebrahimi 
158*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_asn1_get_alg(&p, end, &kdf_alg_oid,
159*62c56f98SSadaf Ebrahimi                                     &kdf_alg_params)) != 0) {
160*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
161*62c56f98SSadaf Ebrahimi     }
162*62c56f98SSadaf Ebrahimi 
163*62c56f98SSadaf Ebrahimi     // Only PBKDF2 supported at the moment
164*62c56f98SSadaf Ebrahimi     //
165*62c56f98SSadaf Ebrahimi     if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid) != 0) {
166*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
167*62c56f98SSadaf Ebrahimi     }
168*62c56f98SSadaf Ebrahimi 
169*62c56f98SSadaf Ebrahimi     if ((ret = pkcs5_parse_pbkdf2_params(&kdf_alg_params,
170*62c56f98SSadaf Ebrahimi                                          &salt, &iterations, &keylen,
171*62c56f98SSadaf Ebrahimi                                          &md_type)) != 0) {
172*62c56f98SSadaf Ebrahimi         return ret;
173*62c56f98SSadaf Ebrahimi     }
174*62c56f98SSadaf Ebrahimi 
175*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_asn1_get_alg(&p, end, &enc_scheme_oid,
176*62c56f98SSadaf Ebrahimi                                     &enc_scheme_params)) != 0) {
177*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
178*62c56f98SSadaf Ebrahimi     }
179*62c56f98SSadaf Ebrahimi 
180*62c56f98SSadaf Ebrahimi     if (mbedtls_oid_get_cipher_alg(&enc_scheme_oid, &cipher_alg) != 0) {
181*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
182*62c56f98SSadaf Ebrahimi     }
183*62c56f98SSadaf Ebrahimi 
184*62c56f98SSadaf Ebrahimi     cipher_info = mbedtls_cipher_info_from_type(cipher_alg);
185*62c56f98SSadaf Ebrahimi     if (cipher_info == NULL) {
186*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
187*62c56f98SSadaf Ebrahimi     }
188*62c56f98SSadaf Ebrahimi 
189*62c56f98SSadaf Ebrahimi     /*
190*62c56f98SSadaf Ebrahimi      * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
191*62c56f98SSadaf Ebrahimi      * since it is optional and we don't know if it was set or not
192*62c56f98SSadaf Ebrahimi      */
193*62c56f98SSadaf Ebrahimi     keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
194*62c56f98SSadaf Ebrahimi 
195*62c56f98SSadaf Ebrahimi     if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING ||
196*62c56f98SSadaf Ebrahimi         enc_scheme_params.len != mbedtls_cipher_info_get_iv_size(cipher_info)) {
197*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_PKCS5_INVALID_FORMAT;
198*62c56f98SSadaf Ebrahimi     }
199*62c56f98SSadaf Ebrahimi 
200*62c56f98SSadaf Ebrahimi     if (mode == MBEDTLS_PKCS5_DECRYPT) {
201*62c56f98SSadaf Ebrahimi         if (output_size < datalen) {
202*62c56f98SSadaf Ebrahimi             return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
203*62c56f98SSadaf Ebrahimi         }
204*62c56f98SSadaf Ebrahimi     }
205*62c56f98SSadaf Ebrahimi 
206*62c56f98SSadaf Ebrahimi     if (mode == MBEDTLS_PKCS5_ENCRYPT) {
207*62c56f98SSadaf Ebrahimi         padlen = cipher_info->block_size - (datalen % cipher_info->block_size);
208*62c56f98SSadaf Ebrahimi         if (output_size < (datalen + padlen)) {
209*62c56f98SSadaf Ebrahimi             return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
210*62c56f98SSadaf Ebrahimi         }
211*62c56f98SSadaf Ebrahimi     }
212*62c56f98SSadaf Ebrahimi 
213*62c56f98SSadaf Ebrahimi     mbedtls_cipher_init(&cipher_ctx);
214*62c56f98SSadaf Ebrahimi 
215*62c56f98SSadaf Ebrahimi     memcpy(iv, enc_scheme_params.p, enc_scheme_params.len);
216*62c56f98SSadaf Ebrahimi 
217*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, pwd, pwdlen, salt.p,
218*62c56f98SSadaf Ebrahimi                                              salt.len, iterations, keylen,
219*62c56f98SSadaf Ebrahimi                                              key)) != 0) {
220*62c56f98SSadaf Ebrahimi         goto exit;
221*62c56f98SSadaf Ebrahimi     }
222*62c56f98SSadaf Ebrahimi 
223*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) {
224*62c56f98SSadaf Ebrahimi         goto exit;
225*62c56f98SSadaf Ebrahimi     }
226*62c56f98SSadaf Ebrahimi 
227*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen,
228*62c56f98SSadaf Ebrahimi                                      (mbedtls_operation_t) mode)) != 0) {
229*62c56f98SSadaf Ebrahimi         goto exit;
230*62c56f98SSadaf Ebrahimi     }
231*62c56f98SSadaf Ebrahimi 
232*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
233*62c56f98SSadaf Ebrahimi     /* PKCS5 uses CBC with PKCS7 padding (which is the same as
234*62c56f98SSadaf Ebrahimi      * "PKCS5 padding" except that it's typically only called PKCS5
235*62c56f98SSadaf Ebrahimi      * with 64-bit-block ciphers).
236*62c56f98SSadaf Ebrahimi      */
237*62c56f98SSadaf Ebrahimi     mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7;
238*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
239*62c56f98SSadaf Ebrahimi     /* For historical reasons, when decrypting, this function works when
240*62c56f98SSadaf Ebrahimi      * decrypting even when support for PKCS7 padding is disabled. In this
241*62c56f98SSadaf Ebrahimi      * case, it ignores the padding, and so will never report a
242*62c56f98SSadaf Ebrahimi      * password mismatch.
243*62c56f98SSadaf Ebrahimi      */
244*62c56f98SSadaf Ebrahimi     if (mode == MBEDTLS_DECRYPT) {
245*62c56f98SSadaf Ebrahimi         padding = MBEDTLS_PADDING_NONE;
246*62c56f98SSadaf Ebrahimi     }
247*62c56f98SSadaf Ebrahimi #endif
248*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) {
249*62c56f98SSadaf Ebrahimi         goto exit;
250*62c56f98SSadaf Ebrahimi     }
251*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
252*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len,
253*62c56f98SSadaf Ebrahimi                                     data, datalen, output, output_len)) != 0) {
254*62c56f98SSadaf Ebrahimi         ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH;
255*62c56f98SSadaf Ebrahimi     }
256*62c56f98SSadaf Ebrahimi 
257*62c56f98SSadaf Ebrahimi exit:
258*62c56f98SSadaf Ebrahimi     mbedtls_cipher_free(&cipher_ctx);
259*62c56f98SSadaf Ebrahimi 
260*62c56f98SSadaf Ebrahimi     return ret;
261*62c56f98SSadaf Ebrahimi }
262*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ASN1_PARSE_C */
263*62c56f98SSadaf Ebrahimi 
pkcs5_pbkdf2_hmac(mbedtls_md_context_t * ctx,const unsigned char * password,size_t plen,const unsigned char * salt,size_t slen,unsigned int iteration_count,uint32_t key_length,unsigned char * output)264*62c56f98SSadaf Ebrahimi static int pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,
265*62c56f98SSadaf Ebrahimi                              const unsigned char *password,
266*62c56f98SSadaf Ebrahimi                              size_t plen, const unsigned char *salt, size_t slen,
267*62c56f98SSadaf Ebrahimi                              unsigned int iteration_count,
268*62c56f98SSadaf Ebrahimi                              uint32_t key_length, unsigned char *output)
269*62c56f98SSadaf Ebrahimi {
270*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
271*62c56f98SSadaf Ebrahimi     unsigned int i;
272*62c56f98SSadaf Ebrahimi     unsigned char md1[MBEDTLS_MD_MAX_SIZE];
273*62c56f98SSadaf Ebrahimi     unsigned char work[MBEDTLS_MD_MAX_SIZE];
274*62c56f98SSadaf Ebrahimi     unsigned char md_size = mbedtls_md_get_size(ctx->md_info);
275*62c56f98SSadaf Ebrahimi     size_t use_len;
276*62c56f98SSadaf Ebrahimi     unsigned char *out_p = output;
277*62c56f98SSadaf Ebrahimi     unsigned char counter[4];
278*62c56f98SSadaf Ebrahimi 
279*62c56f98SSadaf Ebrahimi     memset(counter, 0, 4);
280*62c56f98SSadaf Ebrahimi     counter[3] = 1;
281*62c56f98SSadaf Ebrahimi 
282*62c56f98SSadaf Ebrahimi #if UINT_MAX > 0xFFFFFFFF
283*62c56f98SSadaf Ebrahimi     if (iteration_count > 0xFFFFFFFF) {
284*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA;
285*62c56f98SSadaf Ebrahimi     }
286*62c56f98SSadaf Ebrahimi #endif
287*62c56f98SSadaf Ebrahimi 
288*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_md_hmac_starts(ctx, password, plen)) != 0) {
289*62c56f98SSadaf Ebrahimi         return ret;
290*62c56f98SSadaf Ebrahimi     }
291*62c56f98SSadaf Ebrahimi     while (key_length) {
292*62c56f98SSadaf Ebrahimi         // U1 ends up in work
293*62c56f98SSadaf Ebrahimi         //
294*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_update(ctx, salt, slen)) != 0) {
295*62c56f98SSadaf Ebrahimi             goto cleanup;
296*62c56f98SSadaf Ebrahimi         }
297*62c56f98SSadaf Ebrahimi 
298*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_update(ctx, counter, 4)) != 0) {
299*62c56f98SSadaf Ebrahimi             goto cleanup;
300*62c56f98SSadaf Ebrahimi         }
301*62c56f98SSadaf Ebrahimi 
302*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_finish(ctx, work)) != 0) {
303*62c56f98SSadaf Ebrahimi             goto cleanup;
304*62c56f98SSadaf Ebrahimi         }
305*62c56f98SSadaf Ebrahimi 
306*62c56f98SSadaf Ebrahimi         if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) {
307*62c56f98SSadaf Ebrahimi             goto cleanup;
308*62c56f98SSadaf Ebrahimi         }
309*62c56f98SSadaf Ebrahimi 
310*62c56f98SSadaf Ebrahimi         memcpy(md1, work, md_size);
311*62c56f98SSadaf Ebrahimi 
312*62c56f98SSadaf Ebrahimi         for (i = 1; i < iteration_count; i++) {
313*62c56f98SSadaf Ebrahimi             // U2 ends up in md1
314*62c56f98SSadaf Ebrahimi             //
315*62c56f98SSadaf Ebrahimi             if ((ret = mbedtls_md_hmac_update(ctx, md1, md_size)) != 0) {
316*62c56f98SSadaf Ebrahimi                 goto cleanup;
317*62c56f98SSadaf Ebrahimi             }
318*62c56f98SSadaf Ebrahimi 
319*62c56f98SSadaf Ebrahimi             if ((ret = mbedtls_md_hmac_finish(ctx, md1)) != 0) {
320*62c56f98SSadaf Ebrahimi                 goto cleanup;
321*62c56f98SSadaf Ebrahimi             }
322*62c56f98SSadaf Ebrahimi 
323*62c56f98SSadaf Ebrahimi             if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) {
324*62c56f98SSadaf Ebrahimi                 goto cleanup;
325*62c56f98SSadaf Ebrahimi             }
326*62c56f98SSadaf Ebrahimi 
327*62c56f98SSadaf Ebrahimi             // U1 xor U2
328*62c56f98SSadaf Ebrahimi             //
329*62c56f98SSadaf Ebrahimi             mbedtls_xor(work, work, md1, md_size);
330*62c56f98SSadaf Ebrahimi         }
331*62c56f98SSadaf Ebrahimi 
332*62c56f98SSadaf Ebrahimi         use_len = (key_length < md_size) ? key_length : md_size;
333*62c56f98SSadaf Ebrahimi         memcpy(out_p, work, use_len);
334*62c56f98SSadaf Ebrahimi 
335*62c56f98SSadaf Ebrahimi         key_length -= (uint32_t) use_len;
336*62c56f98SSadaf Ebrahimi         out_p += use_len;
337*62c56f98SSadaf Ebrahimi 
338*62c56f98SSadaf Ebrahimi         for (i = 4; i > 0; i--) {
339*62c56f98SSadaf Ebrahimi             if (++counter[i - 1] != 0) {
340*62c56f98SSadaf Ebrahimi                 break;
341*62c56f98SSadaf Ebrahimi             }
342*62c56f98SSadaf Ebrahimi         }
343*62c56f98SSadaf Ebrahimi     }
344*62c56f98SSadaf Ebrahimi 
345*62c56f98SSadaf Ebrahimi cleanup:
346*62c56f98SSadaf Ebrahimi     /* Zeroise buffers to clear sensitive data from memory. */
347*62c56f98SSadaf Ebrahimi     mbedtls_platform_zeroize(work, MBEDTLS_MD_MAX_SIZE);
348*62c56f98SSadaf Ebrahimi     mbedtls_platform_zeroize(md1, MBEDTLS_MD_MAX_SIZE);
349*62c56f98SSadaf Ebrahimi 
350*62c56f98SSadaf Ebrahimi     return ret;
351*62c56f98SSadaf Ebrahimi }
352*62c56f98SSadaf Ebrahimi 
353*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t * ctx,const unsigned char * password,size_t plen,const unsigned char * salt,size_t slen,unsigned int iteration_count,uint32_t key_length,unsigned char * output)354*62c56f98SSadaf Ebrahimi int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,
355*62c56f98SSadaf Ebrahimi                               const unsigned char *password,
356*62c56f98SSadaf Ebrahimi                               size_t plen, const unsigned char *salt, size_t slen,
357*62c56f98SSadaf Ebrahimi                               unsigned int iteration_count,
358*62c56f98SSadaf Ebrahimi                               uint32_t key_length, unsigned char *output)
359*62c56f98SSadaf Ebrahimi {
360*62c56f98SSadaf Ebrahimi     return pkcs5_pbkdf2_hmac(ctx, password, plen, salt, slen, iteration_count,
361*62c56f98SSadaf Ebrahimi                              key_length, output);
362*62c56f98SSadaf Ebrahimi }
363*62c56f98SSadaf Ebrahimi #endif
364*62c56f98SSadaf Ebrahimi 
mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg,const unsigned char * password,size_t plen,const unsigned char * salt,size_t slen,unsigned int iteration_count,uint32_t key_length,unsigned char * output)365*62c56f98SSadaf Ebrahimi int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg,
366*62c56f98SSadaf Ebrahimi                                   const unsigned char *password,
367*62c56f98SSadaf Ebrahimi                                   size_t plen, const unsigned char *salt, size_t slen,
368*62c56f98SSadaf Ebrahimi                                   unsigned int iteration_count,
369*62c56f98SSadaf Ebrahimi                                   uint32_t key_length, unsigned char *output)
370*62c56f98SSadaf Ebrahimi {
371*62c56f98SSadaf Ebrahimi     mbedtls_md_context_t md_ctx;
372*62c56f98SSadaf Ebrahimi     const mbedtls_md_info_t *md_info = NULL;
373*62c56f98SSadaf Ebrahimi     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
374*62c56f98SSadaf Ebrahimi 
375*62c56f98SSadaf Ebrahimi     md_info = mbedtls_md_info_from_type(md_alg);
376*62c56f98SSadaf Ebrahimi     if (md_info == NULL) {
377*62c56f98SSadaf Ebrahimi         return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
378*62c56f98SSadaf Ebrahimi     }
379*62c56f98SSadaf Ebrahimi 
380*62c56f98SSadaf Ebrahimi     mbedtls_md_init(&md_ctx);
381*62c56f98SSadaf Ebrahimi 
382*62c56f98SSadaf Ebrahimi     if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) {
383*62c56f98SSadaf Ebrahimi         goto exit;
384*62c56f98SSadaf Ebrahimi     }
385*62c56f98SSadaf Ebrahimi     ret = pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen,
386*62c56f98SSadaf Ebrahimi                             iteration_count, key_length, output);
387*62c56f98SSadaf Ebrahimi exit:
388*62c56f98SSadaf Ebrahimi     mbedtls_md_free(&md_ctx);
389*62c56f98SSadaf Ebrahimi     return ret;
390*62c56f98SSadaf Ebrahimi }
391*62c56f98SSadaf Ebrahimi 
392*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_SELF_TEST)
393*62c56f98SSadaf Ebrahimi 
394*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_MD_CAN_SHA1)
mbedtls_pkcs5_self_test(int verbose)395*62c56f98SSadaf Ebrahimi int mbedtls_pkcs5_self_test(int verbose)
396*62c56f98SSadaf Ebrahimi {
397*62c56f98SSadaf Ebrahimi     if (verbose != 0) {
398*62c56f98SSadaf Ebrahimi         mbedtls_printf("  PBKDF2 (SHA1): skipped\n\n");
399*62c56f98SSadaf Ebrahimi     }
400*62c56f98SSadaf Ebrahimi 
401*62c56f98SSadaf Ebrahimi     return 0;
402*62c56f98SSadaf Ebrahimi }
403*62c56f98SSadaf Ebrahimi #else
404*62c56f98SSadaf Ebrahimi 
405*62c56f98SSadaf Ebrahimi #define MAX_TESTS   6
406*62c56f98SSadaf Ebrahimi 
407*62c56f98SSadaf Ebrahimi static const size_t plen_test_data[MAX_TESTS] =
408*62c56f98SSadaf Ebrahimi { 8, 8, 8, 24, 9 };
409*62c56f98SSadaf Ebrahimi 
410*62c56f98SSadaf Ebrahimi static const unsigned char password_test_data[MAX_TESTS][32] =
411*62c56f98SSadaf Ebrahimi {
412*62c56f98SSadaf Ebrahimi     "password",
413*62c56f98SSadaf Ebrahimi     "password",
414*62c56f98SSadaf Ebrahimi     "password",
415*62c56f98SSadaf Ebrahimi     "passwordPASSWORDpassword",
416*62c56f98SSadaf Ebrahimi     "pass\0word",
417*62c56f98SSadaf Ebrahimi };
418*62c56f98SSadaf Ebrahimi 
419*62c56f98SSadaf Ebrahimi static const size_t slen_test_data[MAX_TESTS] =
420*62c56f98SSadaf Ebrahimi { 4, 4, 4, 36, 5 };
421*62c56f98SSadaf Ebrahimi 
422*62c56f98SSadaf Ebrahimi static const unsigned char salt_test_data[MAX_TESTS][40] =
423*62c56f98SSadaf Ebrahimi {
424*62c56f98SSadaf Ebrahimi     "salt",
425*62c56f98SSadaf Ebrahimi     "salt",
426*62c56f98SSadaf Ebrahimi     "salt",
427*62c56f98SSadaf Ebrahimi     "saltSALTsaltSALTsaltSALTsaltSALTsalt",
428*62c56f98SSadaf Ebrahimi     "sa\0lt",
429*62c56f98SSadaf Ebrahimi };
430*62c56f98SSadaf Ebrahimi 
431*62c56f98SSadaf Ebrahimi static const uint32_t it_cnt_test_data[MAX_TESTS] =
432*62c56f98SSadaf Ebrahimi { 1, 2, 4096, 4096, 4096 };
433*62c56f98SSadaf Ebrahimi 
434*62c56f98SSadaf Ebrahimi static const uint32_t key_len_test_data[MAX_TESTS] =
435*62c56f98SSadaf Ebrahimi { 20, 20, 20, 25, 16 };
436*62c56f98SSadaf Ebrahimi 
437*62c56f98SSadaf Ebrahimi static const unsigned char result_key_test_data[MAX_TESTS][32] =
438*62c56f98SSadaf Ebrahimi {
439*62c56f98SSadaf Ebrahimi     { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
440*62c56f98SSadaf Ebrahimi       0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
441*62c56f98SSadaf Ebrahimi       0x2f, 0xe0, 0x37, 0xa6 },
442*62c56f98SSadaf Ebrahimi     { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
443*62c56f98SSadaf Ebrahimi       0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
444*62c56f98SSadaf Ebrahimi       0xd8, 0xde, 0x89, 0x57 },
445*62c56f98SSadaf Ebrahimi     { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
446*62c56f98SSadaf Ebrahimi       0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
447*62c56f98SSadaf Ebrahimi       0x65, 0xa4, 0x29, 0xc1 },
448*62c56f98SSadaf Ebrahimi     { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
449*62c56f98SSadaf Ebrahimi       0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
450*62c56f98SSadaf Ebrahimi       0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
451*62c56f98SSadaf Ebrahimi       0x38 },
452*62c56f98SSadaf Ebrahimi     { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
453*62c56f98SSadaf Ebrahimi       0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },
454*62c56f98SSadaf Ebrahimi };
455*62c56f98SSadaf Ebrahimi 
mbedtls_pkcs5_self_test(int verbose)456*62c56f98SSadaf Ebrahimi int mbedtls_pkcs5_self_test(int verbose)
457*62c56f98SSadaf Ebrahimi {
458*62c56f98SSadaf Ebrahimi     int ret, i;
459*62c56f98SSadaf Ebrahimi     unsigned char key[64];
460*62c56f98SSadaf Ebrahimi 
461*62c56f98SSadaf Ebrahimi     for (i = 0; i < MAX_TESTS; i++) {
462*62c56f98SSadaf Ebrahimi         if (verbose != 0) {
463*62c56f98SSadaf Ebrahimi             mbedtls_printf("  PBKDF2 (SHA1) #%d: ", i);
464*62c56f98SSadaf Ebrahimi         }
465*62c56f98SSadaf Ebrahimi 
466*62c56f98SSadaf Ebrahimi         ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, password_test_data[i],
467*62c56f98SSadaf Ebrahimi                                             plen_test_data[i], salt_test_data[i],
468*62c56f98SSadaf Ebrahimi                                             slen_test_data[i], it_cnt_test_data[i],
469*62c56f98SSadaf Ebrahimi                                             key_len_test_data[i], key);
470*62c56f98SSadaf Ebrahimi         if (ret != 0 ||
471*62c56f98SSadaf Ebrahimi             memcmp(result_key_test_data[i], key, key_len_test_data[i]) != 0) {
472*62c56f98SSadaf Ebrahimi             if (verbose != 0) {
473*62c56f98SSadaf Ebrahimi                 mbedtls_printf("failed\n");
474*62c56f98SSadaf Ebrahimi             }
475*62c56f98SSadaf Ebrahimi 
476*62c56f98SSadaf Ebrahimi             ret = 1;
477*62c56f98SSadaf Ebrahimi             goto exit;
478*62c56f98SSadaf Ebrahimi         }
479*62c56f98SSadaf Ebrahimi 
480*62c56f98SSadaf Ebrahimi         if (verbose != 0) {
481*62c56f98SSadaf Ebrahimi             mbedtls_printf("passed\n");
482*62c56f98SSadaf Ebrahimi         }
483*62c56f98SSadaf Ebrahimi     }
484*62c56f98SSadaf Ebrahimi 
485*62c56f98SSadaf Ebrahimi     if (verbose != 0) {
486*62c56f98SSadaf Ebrahimi         mbedtls_printf("\n");
487*62c56f98SSadaf Ebrahimi     }
488*62c56f98SSadaf Ebrahimi 
489*62c56f98SSadaf Ebrahimi exit:
490*62c56f98SSadaf Ebrahimi     return ret;
491*62c56f98SSadaf Ebrahimi }
492*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_MD_CAN_SHA1 */
493*62c56f98SSadaf Ebrahimi 
494*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_SELF_TEST */
495*62c56f98SSadaf Ebrahimi 
496*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_PKCS5_C */
497