blob: 90703c45f9d38a687d394889648a77352aebf2bc [file] [log] [blame]
Paul Bakkerb0c19a42013-06-24 19:26:38 +02001/**
2 * \file pkcs5.c
3 *
4 * \brief PKCS#5 functions
5 *
6 * \author Mathias Olsson <mathias@kompetensum.com>
7 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02008 * Copyright The Mbed TLS Contributors
Dave Rodgman7ff79652023-11-03 12:04:52 +00009 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakkerb0c19a42013-06-24 19:26:38 +020010 */
11/*
12 * PKCS#5 includes PBKDF2 and more
13 *
14 * http://tools.ietf.org/html/rfc2898 (Specification)
15 * http://tools.ietf.org/html/rfc6070 (Test vectors)
16 */
17
Gilles Peskinedb09ef62020-06-03 01:43:33 +020018#include "common.h"
Paul Bakkerb0c19a42013-06-24 19:26:38 +020019
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020020#if defined(MBEDTLS_PKCS5_C)
Paul Bakkerb0c19a42013-06-24 19:26:38 +020021
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000022#include "mbedtls/pkcs5.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000023#include "mbedtls/error.h"
Marcos Del Sol Vives8a0dfac2016-11-06 12:22:25 +010024
25#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000026#include "mbedtls/asn1.h"
27#include "mbedtls/cipher.h"
28#include "mbedtls/oid.h"
Andres Amaya Garciaaf9a4862018-03-27 20:53:07 +010029#endif /* MBEDTLS_ASN1_PARSE_C */
30
31#include <string.h>
Rich Evans00ab4702015-02-06 13:43:58 +000032
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000033#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010034
Waleed Elmelegyb66cb652023-08-01 14:56:30 +010035
Hanno Becker1ea604d2018-10-12 10:57:33 +010036#if defined(MBEDTLS_ASN1_PARSE_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010037static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
38 mbedtls_asn1_buf *salt, int *iterations,
39 int *keylen, mbedtls_md_type_t *md_type)
Paul Bakker28144de2013-06-24 19:28:55 +020040{
Janos Follath24eed8d2019-11-22 13:21:35 +000041 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020042 mbedtls_asn1_buf prf_alg_oid;
Manuel Pégourié-Gonnardedc3ab22014-06-12 17:08:27 +020043 unsigned char *p = params->p;
Paul Bakkerf8d018a2013-06-29 12:16:17 +020044 const unsigned char *end = params->p + params->len;
Paul Bakker28144de2013-06-24 19:28:55 +020045
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010046 if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
47 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
48 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
49 }
Paul Bakker28144de2013-06-24 19:28:55 +020050 /*
51 * PBKDF2-params ::= SEQUENCE {
52 * salt OCTET STRING,
53 * iterationCount INTEGER,
54 * keyLength INTEGER OPTIONAL
55 * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
56 * }
57 *
58 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010059 if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len,
60 MBEDTLS_ASN1_OCTET_STRING)) != 0) {
61 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
62 }
Paul Bakker28144de2013-06-24 19:28:55 +020063
Manuel Pégourié-Gonnardedc3ab22014-06-12 17:08:27 +020064 salt->p = p;
65 p += salt->len;
Paul Bakker28144de2013-06-24 19:28:55 +020066
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010067 if ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0) {
68 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
Paul Bakker28144de2013-06-24 19:28:55 +020069 }
70
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010071 if (p == end) {
72 return 0;
73 }
Paul Bakker28144de2013-06-24 19:28:55 +020074
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010075 if ((ret = mbedtls_asn1_get_int(&p, end, keylen)) != 0) {
76 if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
77 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
78 }
79 }
Paul Bakker28144de2013-06-24 19:28:55 +020080
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010081 if (p == end) {
82 return 0;
83 }
Paul Bakker28144de2013-06-24 19:28:55 +020084
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010085 if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0) {
86 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
87 }
Paul Bakker28144de2013-06-24 19:28:55 +020088
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010089 if (mbedtls_oid_get_md_hmac(&prf_alg_oid, md_type) != 0) {
90 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
91 }
92
93 if (p != end) {
94 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
95 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
96 }
97
98 return 0;
Paul Bakker28144de2013-06-24 19:28:55 +020099}
100
Waleed Elmelegydcad1682023-08-29 14:55:03 +0100101#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
102int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode,
103 const unsigned char *pwd, size_t pwdlen,
104 const unsigned char *data, size_t datalen,
105 unsigned char *output, size_t output_size,
106 size_t *output_len);
107#endif
108
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100109int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
110 const unsigned char *pwd, size_t pwdlen,
111 const unsigned char *data, size_t datalen,
112 unsigned char *output)
Paul Bakker28144de2013-06-24 19:28:55 +0200113{
Waleed Elmelegyb66cb652023-08-01 14:56:30 +0100114 size_t output_len = 0;
115
116 /* We assume caller of the function is providing a big enough output buffer
Waleed-Ziad Maamoun-Elmelegy09f0a972023-08-31 20:47:15 +0100117 * so we pass output_size as SIZE_MAX to pass checks, However, no guarantees
Waleed Elmelegyb66cb652023-08-01 14:56:30 +0100118 * for the output size actually being correct.
119 */
120 return mbedtls_pkcs5_pbes2_ext(pbe_params, mode, pwd, pwdlen, data,
121 datalen, output, SIZE_MAX, &output_len);
122}
123
124int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode,
125 const unsigned char *pwd, size_t pwdlen,
126 const unsigned char *data, size_t datalen,
127 unsigned char *output, size_t output_size,
128 size_t *output_len)
129{
Paul Bakker28144de2013-06-24 19:28:55 +0200130 int ret, iterations = 0, keylen = 0;
Paul Bakkerf8d018a2013-06-29 12:16:17 +0200131 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params;
133 mbedtls_asn1_buf salt;
134 mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
Paul Bakker28144de2013-06-24 19:28:55 +0200135 unsigned char key[32], iv[32];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 const mbedtls_md_info_t *md_info;
137 const mbedtls_cipher_info_t *cipher_info;
138 mbedtls_md_context_t md_ctx;
139 mbedtls_cipher_type_t cipher_alg;
140 mbedtls_cipher_context_t cipher_ctx;
Waleed Elmelegyb66cb652023-08-01 14:56:30 +0100141 unsigned int padlen = 0;
Paul Bakker28144de2013-06-24 19:28:55 +0200142
143 p = pbe_params->p;
144 end = p + pbe_params->len;
145
146 /*
147 * PBES2-params ::= SEQUENCE {
148 * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
149 * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
150 * }
151 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100152 if (pbe_params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
153 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
154 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
155 }
Paul Bakkerf8d018a2013-06-29 12:16:17 +0200156
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100157 if ((ret = mbedtls_asn1_get_alg(&p, end, &kdf_alg_oid,
158 &kdf_alg_params)) != 0) {
159 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
160 }
Paul Bakker28144de2013-06-24 19:28:55 +0200161
162 // Only PBKDF2 supported at the moment
163 //
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100164 if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid) != 0) {
165 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
Paul Bakker28144de2013-06-24 19:28:55 +0200166 }
167
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100168 if ((ret = pkcs5_parse_pbkdf2_params(&kdf_alg_params,
169 &salt, &iterations, &keylen,
170 &md_type)) != 0) {
171 return ret;
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200172 }
Paul Bakker28144de2013-06-24 19:28:55 +0200173
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100174 md_info = mbedtls_md_info_from_type(md_type);
175 if (md_info == NULL) {
176 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
177 }
Paul Bakker28144de2013-06-24 19:28:55 +0200178
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100179 if ((ret = mbedtls_asn1_get_alg(&p, end, &enc_scheme_oid,
180 &enc_scheme_params)) != 0) {
181 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
182 }
183
184 if (mbedtls_oid_get_cipher_alg(&enc_scheme_oid, &cipher_alg) != 0) {
185 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
186 }
187
188 cipher_info = mbedtls_cipher_info_from_type(cipher_alg);
189 if (cipher_info == NULL) {
190 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
191 }
Paul Bakker28144de2013-06-24 19:28:55 +0200192
Manuel Pégourié-Gonnard66aca932014-06-12 13:14:55 +0200193 /*
194 * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
195 * since it is optional and we don't know if it was set or not
196 */
Manuel Pégourié-Gonnard898e0aa2015-06-18 15:28:12 +0200197 keylen = cipher_info->key_bitlen / 8;
Paul Bakker28144de2013-06-24 19:28:55 +0200198
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100199 if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING ||
200 enc_scheme_params.len != cipher_info->iv_size) {
201 return MBEDTLS_ERR_PKCS5_INVALID_FORMAT;
Paul Bakkerf8d018a2013-06-29 12:16:17 +0200202 }
Paul Bakker28144de2013-06-24 19:28:55 +0200203
Waleed Elmelegyb66cb652023-08-01 14:56:30 +0100204 if (mode == MBEDTLS_PKCS5_DECRYPT) {
205 if (output_size < datalen) {
206 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
207 }
208 }
209
210 if (mode == MBEDTLS_PKCS5_ENCRYPT) {
211 padlen = cipher_info->block_size - (datalen % cipher_info->block_size);
212 if (output_size < (datalen + padlen)) {
213 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
214 }
215 }
216
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100217 mbedtls_md_init(&md_ctx);
Waleed Elmelegyb66cb652023-08-01 14:56:30 +0100218
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 mbedtls_cipher_init(&cipher_ctx);
Paul Bakker84bbeb52014-07-01 14:53:22 +0200220
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100221 memcpy(iv, enc_scheme_params.p, enc_scheme_params.len);
Paul Bakker28144de2013-06-24 19:28:55 +0200222
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100223 if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) {
Paul Bakker46320832013-07-03 14:01:52 +0200224 goto exit;
Paul Bakker28144de2013-06-24 19:28:55 +0200225 }
226
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100227 if ((ret = mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, pwd, pwdlen, salt.p, salt.len,
228 iterations, keylen, key)) != 0) {
Paul Bakker46320832013-07-03 14:01:52 +0200229 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100230 }
Paul Bakker46320832013-07-03 14:01:52 +0200231
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100232 if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) {
Paul Bakker46320832013-07-03 14:01:52 +0200233 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100234 }
Paul Bakker28144de2013-06-24 19:28:55 +0200235
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100236 if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen,
237 (mbedtls_operation_t) mode)) != 0) {
238 goto exit;
239 }
240
Waleed Elmelegya2307352023-07-21 16:20:17 +0100241#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
Dave Rodgman2af05c82023-10-13 14:40:14 +0100242 {
243 /* PKCS5 uses CBC with PKCS7 padding (which is the same as
244 * "PKCS5 padding" except that it's typically only called PKCS5
245 * with 64-bit-block ciphers).
246 */
247 mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7;
Waleed Elmelegy412629c2023-07-19 14:01:35 +0100248#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
Dave Rodgman2af05c82023-10-13 14:40:14 +0100249 /* For historical reasons, when decrypting, this function works when
250 * decrypting even when support for PKCS7 padding is disabled. In this
251 * case, it ignores the padding, and so will never report a
252 * password mismatch.
253 */
254 if (mode == MBEDTLS_DECRYPT) {
255 padding = MBEDTLS_PADDING_NONE;
256 }
Waleed Elmelegy412629c2023-07-19 14:01:35 +0100257#endif
Dave Rodgman2af05c82023-10-13 14:40:14 +0100258 if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) {
259 goto exit;
260 }
Waleed Elmelegy412629c2023-07-19 14:01:35 +0100261 }
Waleed Elmelegya2307352023-07-21 16:20:17 +0100262#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100263 if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len,
Waleed Elmelegyb66cb652023-08-01 14:56:30 +0100264 data, datalen, output, output_len)) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100266 }
Paul Bakker28144de2013-06-24 19:28:55 +0200267
Paul Bakker46320832013-07-03 14:01:52 +0200268exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100269 mbedtls_md_free(&md_ctx);
270 mbedtls_cipher_free(&cipher_ctx);
Paul Bakker46320832013-07-03 14:01:52 +0200271
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100272 return ret;
Paul Bakker28144de2013-06-24 19:28:55 +0200273}
Marcos Del Sol Vives8a0dfac2016-11-06 12:22:25 +0100274#endif /* MBEDTLS_ASN1_PARSE_C */
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200275
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100276int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,
277 const unsigned char *password,
278 size_t plen, const unsigned char *salt, size_t slen,
279 unsigned int iteration_count,
280 uint32_t key_length, unsigned char *output)
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200281{
gabor-mezei-armb8513fa2020-08-24 09:53:04 +0200282 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
283 int j;
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200284 unsigned int i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 unsigned char md1[MBEDTLS_MD_MAX_SIZE];
286 unsigned char work[MBEDTLS_MD_MAX_SIZE];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100287 unsigned char md_size = mbedtls_md_get_size(ctx->md_info);
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200288 size_t use_len;
289 unsigned char *out_p = output;
290 unsigned char counter[4];
291
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100292 memset(counter, 0, 4);
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200293 counter[3] = 1;
294
Azim Khan45b79cf2018-05-23 16:55:16 +0100295#if UINT_MAX > 0xFFFFFFFF
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100296 if (iteration_count > 0xFFFFFFFF) {
297 return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA;
298 }
Azim Khan45b79cf2018-05-23 16:55:16 +0100299#endif
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200300
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100301 if ((ret = mbedtls_md_hmac_starts(ctx, password, plen)) != 0) {
302 return ret;
303 }
304 while (key_length) {
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200305 // U1 ends up in work
306 //
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100307 if ((ret = mbedtls_md_hmac_update(ctx, salt, slen)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200308 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100309 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200310
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100311 if ((ret = mbedtls_md_hmac_update(ctx, counter, 4)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200312 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100313 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200314
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100315 if ((ret = mbedtls_md_hmac_finish(ctx, work)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200316 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100317 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200318
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100319 if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200320 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100321 }
Jack Lloyd71657492019-09-23 19:15:54 -0400322
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100323 memcpy(md1, work, md_size);
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200324
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100325 for (i = 1; i < iteration_count; i++) {
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200326 // U2 ends up in md1
327 //
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100328 if ((ret = mbedtls_md_hmac_update(ctx, md1, md_size)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200329 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100330 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200331
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100332 if ((ret = mbedtls_md_hmac_finish(ctx, md1)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200333 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100334 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200335
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100336 if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200337 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100338 }
Jack Lloyd71657492019-09-23 19:15:54 -0400339
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200340 // U1 xor U2
341 //
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100342 for (j = 0; j < md_size; j++) {
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200343 work[j] ^= md1[j];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100344 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200345 }
346
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100347 use_len = (key_length < md_size) ? key_length : md_size;
348 memcpy(out_p, work, use_len);
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200349
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200350 key_length -= (uint32_t) use_len;
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200351 out_p += use_len;
352
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100353 for (i = 4; i > 0; i--) {
354 if (++counter[i - 1] != 0) {
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200355 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100356 }
357 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200358 }
359
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200360cleanup:
gabor-mezei-arm76749ae2020-07-30 16:41:25 +0200361 /* Zeroise buffers to clear sensitive data from memory. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100362 mbedtls_platform_zeroize(work, MBEDTLS_MD_MAX_SIZE);
363 mbedtls_platform_zeroize(md1, MBEDTLS_MD_MAX_SIZE);
gabor-mezei-arm76749ae2020-07-30 16:41:25 +0200364
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100365 return ret;
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200366}
367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368#if defined(MBEDTLS_SELF_TEST)
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370#if !defined(MBEDTLS_SHA1_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100371int mbedtls_pkcs5_self_test(int verbose)
Manuel Pégourié-Gonnard2a8afa92014-06-12 12:00:44 +0200372{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100373 if (verbose != 0) {
374 mbedtls_printf(" PBKDF2 (SHA1): skipped\n\n");
375 }
Manuel Pégourié-Gonnard2a8afa92014-06-12 12:00:44 +0200376
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100377 return 0;
Manuel Pégourié-Gonnard2a8afa92014-06-12 12:00:44 +0200378}
379#else
380
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200381#define MAX_TESTS 6
382
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100383static const size_t plen_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100384{ 8, 8, 8, 24, 9 };
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200385
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100386static const unsigned char password_test_data[MAX_TESTS][32] =
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200387{
388 "password",
389 "password",
390 "password",
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200391 "passwordPASSWORDpassword",
392 "pass\0word",
393};
394
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100395static const size_t slen_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100396{ 4, 4, 4, 36, 5 };
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200397
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100398static const unsigned char salt_test_data[MAX_TESTS][40] =
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200399{
400 "salt",
401 "salt",
402 "salt",
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200403 "saltSALTsaltSALTsaltSALTsaltSALTsalt",
404 "sa\0lt",
405};
406
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100407static const uint32_t it_cnt_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100408{ 1, 2, 4096, 4096, 4096 };
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200409
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100410static const uint32_t key_len_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100411{ 20, 20, 20, 25, 16 };
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200412
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100413static const unsigned char result_key_test_data[MAX_TESTS][32] =
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200414{
415 { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
416 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
417 0x2f, 0xe0, 0x37, 0xa6 },
418 { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
419 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
420 0xd8, 0xde, 0x89, 0x57 },
421 { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
422 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
423 0x65, 0xa4, 0x29, 0xc1 },
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200424 { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
425 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
426 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
427 0x38 },
428 { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
429 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },
430};
431
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100432int mbedtls_pkcs5_self_test(int verbose)
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200433{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 mbedtls_md_context_t sha1_ctx;
435 const mbedtls_md_info_t *info_sha1;
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200436 int ret, i;
437 unsigned char key[64];
438
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100439 mbedtls_md_init(&sha1_ctx);
Paul Bakker84bbeb52014-07-01 14:53:22 +0200440
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100441 info_sha1 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
442 if (info_sha1 == NULL) {
Paul Bakker84bbeb52014-07-01 14:53:22 +0200443 ret = 1;
444 goto exit;
445 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200446
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100447 if ((ret = mbedtls_md_setup(&sha1_ctx, info_sha1, 1)) != 0) {
Paul Bakker84bbeb52014-07-01 14:53:22 +0200448 ret = 1;
449 goto exit;
450 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200451
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100452 for (i = 0; i < MAX_TESTS; i++) {
453 if (verbose != 0) {
454 mbedtls_printf(" PBKDF2 (SHA1) #%d: ", i);
455 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200456
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100457 ret = mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, password_test_data[i],
458 plen_test_data[i], salt_test_data[i],
459 slen_test_data[i], it_cnt_test_data[i],
460 key_len_test_data[i], key);
461 if (ret != 0 ||
462 memcmp(result_key_test_data[i], key, key_len_test_data[i]) != 0) {
463 if (verbose != 0) {
464 mbedtls_printf("failed\n");
465 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200466
Paul Bakker84bbeb52014-07-01 14:53:22 +0200467 ret = 1;
468 goto exit;
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200469 }
470
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100471 if (verbose != 0) {
472 mbedtls_printf("passed\n");
473 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200474 }
475
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100476 if (verbose != 0) {
477 mbedtls_printf("\n");
478 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200479
Paul Bakker84bbeb52014-07-01 14:53:22 +0200480exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100481 mbedtls_md_free(&sha1_ctx);
Paul Bakkerf8634852013-07-03 13:31:52 +0200482
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100483 return ret;
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200484}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485#endif /* MBEDTLS_SHA1_C */
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487#endif /* MBEDTLS_SELF_TEST */
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489#endif /* MBEDTLS_PKCS5_C */