blob: bbbe82c70c1dcf72b8005b687a7b2c567fdef481 [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
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02009 * SPDX-License-Identifier: Apache-2.0
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License"); you may
12 * not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
19 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
Paul Bakkerb0c19a42013-06-24 19:26:38 +020022 */
23/*
24 * PKCS#5 includes PBKDF2 and more
25 *
26 * http://tools.ietf.org/html/rfc2898 (Specification)
27 * http://tools.ietf.org/html/rfc6070 (Test vectors)
28 */
29
Gilles Peskinedb09ef62020-06-03 01:43:33 +020030#include "common.h"
Paul Bakkerb0c19a42013-06-24 19:26:38 +020031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if defined(MBEDTLS_PKCS5_C)
Paul Bakkerb0c19a42013-06-24 19:26:38 +020033
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000034#include "mbedtls/pkcs5.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000035#include "mbedtls/error.h"
Marcos Del Sol Vives8a0dfac2016-11-06 12:22:25 +010036
37#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000038#include "mbedtls/asn1.h"
39#include "mbedtls/cipher.h"
40#include "mbedtls/oid.h"
Andres Amaya Garciaaf9a4862018-03-27 20:53:07 +010041#endif /* MBEDTLS_ASN1_PARSE_C */
42
43#include <string.h>
Rich Evans00ab4702015-02-06 13:43:58 +000044
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000045#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010046
Hanno Becker1ea604d2018-10-12 10:57:33 +010047#if defined(MBEDTLS_ASN1_PARSE_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010048static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
49 mbedtls_asn1_buf *salt, int *iterations,
50 int *keylen, mbedtls_md_type_t *md_type)
Paul Bakker28144de2013-06-24 19:28:55 +020051{
Janos Follath24eed8d2019-11-22 13:21:35 +000052 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053 mbedtls_asn1_buf prf_alg_oid;
Manuel Pégourié-Gonnardedc3ab22014-06-12 17:08:27 +020054 unsigned char *p = params->p;
Paul Bakkerf8d018a2013-06-29 12:16:17 +020055 const unsigned char *end = params->p + params->len;
Paul Bakker28144de2013-06-24 19:28:55 +020056
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010057 if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
58 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
59 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
60 }
Paul Bakker28144de2013-06-24 19:28:55 +020061 /*
62 * PBKDF2-params ::= SEQUENCE {
63 * salt OCTET STRING,
64 * iterationCount INTEGER,
65 * keyLength INTEGER OPTIONAL
66 * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
67 * }
68 *
69 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010070 if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len,
71 MBEDTLS_ASN1_OCTET_STRING)) != 0) {
72 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
73 }
Paul Bakker28144de2013-06-24 19:28:55 +020074
Manuel Pégourié-Gonnardedc3ab22014-06-12 17:08:27 +020075 salt->p = p;
76 p += salt->len;
Paul Bakker28144de2013-06-24 19:28:55 +020077
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010078 if ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0) {
79 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
Paul Bakker28144de2013-06-24 19:28:55 +020080 }
81
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010082 if (p == end) {
83 return 0;
84 }
Paul Bakker28144de2013-06-24 19:28:55 +020085
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010086 if ((ret = mbedtls_asn1_get_int(&p, end, keylen)) != 0) {
87 if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
88 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
89 }
90 }
Paul Bakker28144de2013-06-24 19:28:55 +020091
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010092 if (p == end) {
93 return 0;
94 }
Paul Bakker28144de2013-06-24 19:28:55 +020095
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010096 if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0) {
97 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
98 }
Paul Bakker28144de2013-06-24 19:28:55 +020099
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100100 if (mbedtls_oid_get_md_hmac(&prf_alg_oid, md_type) != 0) {
101 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
102 }
103
104 if (p != end) {
105 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
106 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
107 }
108
109 return 0;
Paul Bakker28144de2013-06-24 19:28:55 +0200110}
111
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100112int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
113 const unsigned char *pwd, size_t pwdlen,
114 const unsigned char *data, size_t datalen,
115 unsigned char *output)
Paul Bakker28144de2013-06-24 19:28:55 +0200116{
117 int ret, iterations = 0, keylen = 0;
Paul Bakkerf8d018a2013-06-29 12:16:17 +0200118 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119 mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params;
120 mbedtls_asn1_buf salt;
121 mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
Paul Bakker28144de2013-06-24 19:28:55 +0200122 unsigned char key[32], iv[32];
Paul Bakkerf8d018a2013-06-29 12:16:17 +0200123 size_t olen = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 const mbedtls_md_info_t *md_info;
125 const mbedtls_cipher_info_t *cipher_info;
126 mbedtls_md_context_t md_ctx;
127 mbedtls_cipher_type_t cipher_alg;
128 mbedtls_cipher_context_t cipher_ctx;
Paul Bakker28144de2013-06-24 19:28:55 +0200129
130 p = pbe_params->p;
131 end = p + pbe_params->len;
132
133 /*
134 * PBES2-params ::= SEQUENCE {
135 * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
136 * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
137 * }
138 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100139 if (pbe_params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
140 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
141 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
142 }
Paul Bakkerf8d018a2013-06-29 12:16:17 +0200143
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100144 if ((ret = mbedtls_asn1_get_alg(&p, end, &kdf_alg_oid,
145 &kdf_alg_params)) != 0) {
146 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
147 }
Paul Bakker28144de2013-06-24 19:28:55 +0200148
149 // Only PBKDF2 supported at the moment
150 //
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100151 if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid) != 0) {
152 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
Paul Bakker28144de2013-06-24 19:28:55 +0200153 }
154
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100155 if ((ret = pkcs5_parse_pbkdf2_params(&kdf_alg_params,
156 &salt, &iterations, &keylen,
157 &md_type)) != 0) {
158 return ret;
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200159 }
Paul Bakker28144de2013-06-24 19:28:55 +0200160
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100161 md_info = mbedtls_md_info_from_type(md_type);
162 if (md_info == NULL) {
163 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
164 }
Paul Bakker28144de2013-06-24 19:28:55 +0200165
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100166 if ((ret = mbedtls_asn1_get_alg(&p, end, &enc_scheme_oid,
167 &enc_scheme_params)) != 0) {
168 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
169 }
170
171 if (mbedtls_oid_get_cipher_alg(&enc_scheme_oid, &cipher_alg) != 0) {
172 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
173 }
174
175 cipher_info = mbedtls_cipher_info_from_type(cipher_alg);
176 if (cipher_info == NULL) {
177 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
178 }
Paul Bakker28144de2013-06-24 19:28:55 +0200179
Manuel Pégourié-Gonnard66aca932014-06-12 13:14:55 +0200180 /*
181 * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
182 * since it is optional and we don't know if it was set or not
183 */
Manuel Pégourié-Gonnard898e0aa2015-06-18 15:28:12 +0200184 keylen = cipher_info->key_bitlen / 8;
Paul Bakker28144de2013-06-24 19:28:55 +0200185
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100186 if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING ||
187 enc_scheme_params.len != cipher_info->iv_size) {
188 return MBEDTLS_ERR_PKCS5_INVALID_FORMAT;
Paul Bakkerf8d018a2013-06-29 12:16:17 +0200189 }
Paul Bakker28144de2013-06-24 19:28:55 +0200190
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100191 mbedtls_md_init(&md_ctx);
192 mbedtls_cipher_init(&cipher_ctx);
Paul Bakker84bbeb52014-07-01 14:53:22 +0200193
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100194 memcpy(iv, enc_scheme_params.p, enc_scheme_params.len);
Paul Bakker28144de2013-06-24 19:28:55 +0200195
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100196 if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) {
Paul Bakker46320832013-07-03 14:01:52 +0200197 goto exit;
Paul Bakker28144de2013-06-24 19:28:55 +0200198 }
199
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100200 if ((ret = mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, pwd, pwdlen, salt.p, salt.len,
201 iterations, keylen, key)) != 0) {
Paul Bakker46320832013-07-03 14:01:52 +0200202 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100203 }
Paul Bakker46320832013-07-03 14:01:52 +0200204
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100205 if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) {
Paul Bakker46320832013-07-03 14:01:52 +0200206 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100207 }
Paul Bakker28144de2013-06-24 19:28:55 +0200208
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100209 if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen,
210 (mbedtls_operation_t) mode)) != 0) {
211 goto exit;
212 }
213
Waleed Elmelegya2307352023-07-21 16:20:17 +0100214#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
Waleed Elmelegy412629c2023-07-19 14:01:35 +0100215 /* PKCS5 uses CBC with PKCS7 padding (which is the same as
216 * "PKCS5 padding" except that it's typically only called PKCS5
217 * with 64-bit-block ciphers).
218 */
219 mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7;
220#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
221 /* For historical reasons, when decrypting, this function works when
222 * decrypting even when support for PKCS7 padding is disabled. In this
223 * case, it ignores the padding, and so will never report a
224 * password mismatch.
225 */
Waleed Elmelegya2307352023-07-21 16:20:17 +0100226 if (mode == MBEDTLS_DECRYPT) {
Waleed Elmelegy412629c2023-07-19 14:01:35 +0100227 padding = MBEDTLS_PADDING_NONE;
Waleed Elmelegya2307352023-07-21 16:20:17 +0100228 }
Waleed Elmelegy412629c2023-07-19 14:01:35 +0100229#endif
230 if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) {
231 goto exit;
232 }
Waleed Elmelegya2307352023-07-21 16:20:17 +0100233#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100234 if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len,
235 data, datalen, output, &olen)) != 0) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100237 }
Paul Bakker28144de2013-06-24 19:28:55 +0200238
Paul Bakker46320832013-07-03 14:01:52 +0200239exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100240 mbedtls_md_free(&md_ctx);
241 mbedtls_cipher_free(&cipher_ctx);
Paul Bakker46320832013-07-03 14:01:52 +0200242
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100243 return ret;
Paul Bakker28144de2013-06-24 19:28:55 +0200244}
Marcos Del Sol Vives8a0dfac2016-11-06 12:22:25 +0100245#endif /* MBEDTLS_ASN1_PARSE_C */
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200246
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100247int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,
248 const unsigned char *password,
249 size_t plen, const unsigned char *salt, size_t slen,
250 unsigned int iteration_count,
251 uint32_t key_length, unsigned char *output)
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200252{
gabor-mezei-armb8513fa2020-08-24 09:53:04 +0200253 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
254 int j;
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200255 unsigned int i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 unsigned char md1[MBEDTLS_MD_MAX_SIZE];
257 unsigned char work[MBEDTLS_MD_MAX_SIZE];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100258 unsigned char md_size = mbedtls_md_get_size(ctx->md_info);
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200259 size_t use_len;
260 unsigned char *out_p = output;
261 unsigned char counter[4];
262
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100263 memset(counter, 0, 4);
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200264 counter[3] = 1;
265
Azim Khan45b79cf2018-05-23 16:55:16 +0100266#if UINT_MAX > 0xFFFFFFFF
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100267 if (iteration_count > 0xFFFFFFFF) {
268 return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA;
269 }
Azim Khan45b79cf2018-05-23 16:55:16 +0100270#endif
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200271
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100272 if ((ret = mbedtls_md_hmac_starts(ctx, password, plen)) != 0) {
273 return ret;
274 }
275 while (key_length) {
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200276 // U1 ends up in work
277 //
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100278 if ((ret = mbedtls_md_hmac_update(ctx, salt, slen)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200279 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100280 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200281
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100282 if ((ret = mbedtls_md_hmac_update(ctx, counter, 4)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200283 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100284 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200285
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100286 if ((ret = mbedtls_md_hmac_finish(ctx, work)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200287 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100288 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200289
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100290 if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200291 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100292 }
Jack Lloyd71657492019-09-23 19:15:54 -0400293
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100294 memcpy(md1, work, md_size);
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200295
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100296 for (i = 1; i < iteration_count; i++) {
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200297 // U2 ends up in md1
298 //
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100299 if ((ret = mbedtls_md_hmac_update(ctx, md1, md_size)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200300 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100301 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200302
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100303 if ((ret = mbedtls_md_hmac_finish(ctx, md1)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200304 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100305 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200306
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100307 if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) {
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200308 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100309 }
Jack Lloyd71657492019-09-23 19:15:54 -0400310
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200311 // U1 xor U2
312 //
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100313 for (j = 0; j < md_size; j++) {
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200314 work[j] ^= md1[j];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100315 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200316 }
317
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100318 use_len = (key_length < md_size) ? key_length : md_size;
319 memcpy(out_p, work, use_len);
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200320
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200321 key_length -= (uint32_t) use_len;
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200322 out_p += use_len;
323
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100324 for (i = 4; i > 0; i--) {
325 if (++counter[i - 1] != 0) {
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200326 break;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100327 }
328 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200329 }
330
gabor-mezei-arm4553dd42020-08-19 14:01:03 +0200331cleanup:
gabor-mezei-arm76749ae2020-07-30 16:41:25 +0200332 /* Zeroise buffers to clear sensitive data from memory. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100333 mbedtls_platform_zeroize(work, MBEDTLS_MD_MAX_SIZE);
334 mbedtls_platform_zeroize(md1, MBEDTLS_MD_MAX_SIZE);
gabor-mezei-arm76749ae2020-07-30 16:41:25 +0200335
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100336 return ret;
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200337}
338
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200339#if defined(MBEDTLS_SELF_TEST)
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341#if !defined(MBEDTLS_SHA1_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100342int mbedtls_pkcs5_self_test(int verbose)
Manuel Pégourié-Gonnard2a8afa92014-06-12 12:00:44 +0200343{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100344 if (verbose != 0) {
345 mbedtls_printf(" PBKDF2 (SHA1): skipped\n\n");
346 }
Manuel Pégourié-Gonnard2a8afa92014-06-12 12:00:44 +0200347
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100348 return 0;
Manuel Pégourié-Gonnard2a8afa92014-06-12 12:00:44 +0200349}
350#else
351
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200352#define MAX_TESTS 6
353
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100354static const size_t plen_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100355{ 8, 8, 8, 24, 9 };
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200356
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100357static const unsigned char password_test_data[MAX_TESTS][32] =
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200358{
359 "password",
360 "password",
361 "password",
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200362 "passwordPASSWORDpassword",
363 "pass\0word",
364};
365
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100366static const size_t slen_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100367{ 4, 4, 4, 36, 5 };
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200368
Michał Janiszewski9aeea932018-10-30 23:00:15 +0100369static const unsigned char salt_test_data[MAX_TESTS][40] =
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200370{
371 "salt",
372 "salt",
373 "salt",
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200374 "saltSALTsaltSALTsaltSALTsaltSALTsalt",
375 "sa\0lt",
376};
377
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100378static const uint32_t it_cnt_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100379{ 1, 2, 4096, 4096, 4096 };
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200380
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100381static const uint32_t key_len_test_data[MAX_TESTS] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100382{ 20, 20, 20, 25, 16 };
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200383
Michał Janiszewskic79e92b2018-10-31 20:43:05 +0100384static const unsigned char result_key_test_data[MAX_TESTS][32] =
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200385{
386 { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
387 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
388 0x2f, 0xe0, 0x37, 0xa6 },
389 { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
390 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
391 0xd8, 0xde, 0x89, 0x57 },
392 { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
393 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
394 0x65, 0xa4, 0x29, 0xc1 },
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200395 { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
396 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
397 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
398 0x38 },
399 { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
400 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },
401};
402
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100403int mbedtls_pkcs5_self_test(int verbose)
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200404{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200405 mbedtls_md_context_t sha1_ctx;
406 const mbedtls_md_info_t *info_sha1;
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200407 int ret, i;
408 unsigned char key[64];
409
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100410 mbedtls_md_init(&sha1_ctx);
Paul Bakker84bbeb52014-07-01 14:53:22 +0200411
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100412 info_sha1 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
413 if (info_sha1 == NULL) {
Paul Bakker84bbeb52014-07-01 14:53:22 +0200414 ret = 1;
415 goto exit;
416 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200417
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100418 if ((ret = mbedtls_md_setup(&sha1_ctx, info_sha1, 1)) != 0) {
Paul Bakker84bbeb52014-07-01 14:53:22 +0200419 ret = 1;
420 goto exit;
421 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200422
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100423 for (i = 0; i < MAX_TESTS; i++) {
424 if (verbose != 0) {
425 mbedtls_printf(" PBKDF2 (SHA1) #%d: ", i);
426 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200427
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100428 ret = mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, password_test_data[i],
429 plen_test_data[i], salt_test_data[i],
430 slen_test_data[i], it_cnt_test_data[i],
431 key_len_test_data[i], key);
432 if (ret != 0 ||
433 memcmp(result_key_test_data[i], key, key_len_test_data[i]) != 0) {
434 if (verbose != 0) {
435 mbedtls_printf("failed\n");
436 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200437
Paul Bakker84bbeb52014-07-01 14:53:22 +0200438 ret = 1;
439 goto exit;
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200440 }
441
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100442 if (verbose != 0) {
443 mbedtls_printf("passed\n");
444 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200445 }
446
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100447 if (verbose != 0) {
448 mbedtls_printf("\n");
449 }
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200450
Paul Bakker84bbeb52014-07-01 14:53:22 +0200451exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100452 mbedtls_md_free(&sha1_ctx);
Paul Bakkerf8634852013-07-03 13:31:52 +0200453
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100454 return ret;
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200455}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456#endif /* MBEDTLS_SHA1_C */
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458#endif /* MBEDTLS_SELF_TEST */
Paul Bakkerb0c19a42013-06-24 19:26:38 +0200459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460#endif /* MBEDTLS_PKCS5_C */