Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
pkcs5.c
00001 /** 00002 * \file pkcs5.c 00003 * 00004 * \brief PKCS#5 functions 00005 * 00006 * \author Mathias Olsson <mathias@kompetensum.com> 00007 * 00008 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00009 * SPDX-License-Identifier: Apache-2.0 00010 * 00011 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00012 * not use this file except in compliance with the License. 00013 * You may obtain a copy of the License at 00014 * 00015 * http://www.apache.org/licenses/LICENSE-2.0 00016 * 00017 * Unless required by applicable law or agreed to in writing, software 00018 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00019 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00020 * See the License for the specific language governing permissions and 00021 * limitations under the License. 00022 * 00023 * This file is part of mbed TLS (https://tls.mbed.org) 00024 */ 00025 /* 00026 * PKCS#5 includes PBKDF2 and more 00027 * 00028 * http://tools.ietf.org/html/rfc2898 (Specification) 00029 * http://tools.ietf.org/html/rfc6070 (Test vectors) 00030 */ 00031 00032 #if !defined(MBEDTLS_CONFIG_FILE) 00033 #include "mbedtls/config.h" 00034 #else 00035 #include MBEDTLS_CONFIG_FILE 00036 #endif 00037 00038 #if defined(MBEDTLS_PKCS5_C) 00039 00040 #include "mbedtls/pkcs5.h" 00041 00042 #if defined(MBEDTLS_ASN1_PARSE_C) 00043 #include "mbedtls/asn1.h" 00044 #include "mbedtls/cipher.h" 00045 #include "mbedtls/oid.h" 00046 #endif /* MBEDTLS_ASN1_PARSE_C */ 00047 00048 #include <string.h> 00049 00050 #if defined(MBEDTLS_PLATFORM_C) 00051 #include "mbedtls/platform.h" 00052 #else 00053 #include <stdio.h> 00054 #define mbedtls_printf printf 00055 #endif 00056 00057 #if !defined(MBEDTLS_ASN1_PARSE_C) 00058 int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, 00059 const unsigned char *pwd, size_t pwdlen, 00060 const unsigned char *data, size_t datalen, 00061 unsigned char *output ) 00062 { 00063 ((void) pbe_params); 00064 ((void) mode); 00065 ((void) pwd); 00066 ((void) pwdlen); 00067 ((void) data); 00068 ((void) datalen); 00069 ((void) output); 00070 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00071 } 00072 #else 00073 static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, 00074 mbedtls_asn1_buf *salt, int *iterations, 00075 int *keylen, mbedtls_md_type_t *md_type ) 00076 { 00077 int ret; 00078 mbedtls_asn1_buf prf_alg_oid; 00079 unsigned char *p = params->p; 00080 const unsigned char *end = params->p + params->len; 00081 00082 if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) 00083 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + 00084 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 00085 /* 00086 * PBKDF2-params ::= SEQUENCE { 00087 * salt OCTET STRING, 00088 * iterationCount INTEGER, 00089 * keyLength INTEGER OPTIONAL 00090 * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 00091 * } 00092 * 00093 */ 00094 if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) 00095 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); 00096 00097 salt->p = p; 00098 p += salt->len; 00099 00100 if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) 00101 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); 00102 00103 if( p == end ) 00104 return( 0 ); 00105 00106 if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) 00107 { 00108 if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 00109 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); 00110 } 00111 00112 if( p == end ) 00113 return( 0 ); 00114 00115 if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) 00116 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); 00117 00118 if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 ) 00119 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00120 00121 if( p != end ) 00122 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + 00123 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 00124 00125 return( 0 ); 00126 } 00127 00128 int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, 00129 const unsigned char *pwd, size_t pwdlen, 00130 const unsigned char *data, size_t datalen, 00131 unsigned char *output ) 00132 { 00133 int ret, iterations = 0, keylen = 0; 00134 unsigned char *p, *end; 00135 mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; 00136 mbedtls_asn1_buf salt; 00137 mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; 00138 unsigned char key[32], iv[32]; 00139 size_t olen = 0; 00140 const mbedtls_md_info_t *md_info; 00141 const mbedtls_cipher_info_t *cipher_info; 00142 mbedtls_md_context_t md_ctx; 00143 mbedtls_cipher_type_t cipher_alg; 00144 mbedtls_cipher_context_t cipher_ctx; 00145 00146 p = pbe_params->p; 00147 end = p + pbe_params->len; 00148 00149 /* 00150 * PBES2-params ::= SEQUENCE { 00151 * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, 00152 * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} 00153 * } 00154 */ 00155 if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) 00156 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + 00157 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 00158 00159 if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) 00160 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); 00161 00162 // Only PBKDF2 supported at the moment 00163 // 00164 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) 00165 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00166 00167 if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, 00168 &salt, &iterations, &keylen, 00169 &md_type ) ) != 0 ) 00170 { 00171 return( ret ); 00172 } 00173 00174 md_info = mbedtls_md_info_from_type( md_type ); 00175 if( md_info == NULL ) 00176 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00177 00178 if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, 00179 &enc_scheme_params ) ) != 0 ) 00180 { 00181 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); 00182 } 00183 00184 if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) 00185 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00186 00187 cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); 00188 if( cipher_info == NULL ) 00189 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00190 00191 /* 00192 * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored 00193 * since it is optional and we don't know if it was set or not 00194 */ 00195 keylen = cipher_info->key_bitlen / 8; 00196 00197 if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || 00198 enc_scheme_params.len != cipher_info->iv_size ) 00199 { 00200 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); 00201 } 00202 00203 mbedtls_md_init( &md_ctx ); 00204 mbedtls_cipher_init( &cipher_ctx ); 00205 00206 memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); 00207 00208 if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) 00209 goto exit; 00210 00211 if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, 00212 iterations, keylen, key ) ) != 0 ) 00213 { 00214 goto exit; 00215 } 00216 00217 if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) 00218 goto exit; 00219 00220 if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) 00221 goto exit; 00222 00223 if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, 00224 data, datalen, output, &olen ) ) != 0 ) 00225 ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; 00226 00227 exit: 00228 mbedtls_md_free( &md_ctx ); 00229 mbedtls_cipher_free( &cipher_ctx ); 00230 00231 return( ret ); 00232 } 00233 #endif /* MBEDTLS_ASN1_PARSE_C */ 00234 00235 int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, 00236 size_t plen, const unsigned char *salt, size_t slen, 00237 unsigned int iteration_count, 00238 uint32_t key_length, unsigned char *output ) 00239 { 00240 int ret, j; 00241 unsigned int i; 00242 unsigned char md1[MBEDTLS_MD_MAX_SIZE]; 00243 unsigned char work[MBEDTLS_MD_MAX_SIZE]; 00244 unsigned char md_size = mbedtls_md_get_size( ctx->md_info ); 00245 size_t use_len; 00246 unsigned char *out_p = output; 00247 unsigned char counter[4]; 00248 00249 memset( counter, 0, 4 ); 00250 counter[3] = 1; 00251 00252 if( iteration_count > 0xFFFFFFFF ) 00253 return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); 00254 00255 while( key_length ) 00256 { 00257 // U1 ends up in work 00258 // 00259 if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) 00260 return( ret ); 00261 00262 if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) 00263 return( ret ); 00264 00265 if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) 00266 return( ret ); 00267 00268 if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) 00269 return( ret ); 00270 00271 memcpy( md1, work, md_size ); 00272 00273 for( i = 1; i < iteration_count; i++ ) 00274 { 00275 // U2 ends up in md1 00276 // 00277 if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) 00278 return( ret ); 00279 00280 if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) 00281 return( ret ); 00282 00283 if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) 00284 return( ret ); 00285 00286 // U1 xor U2 00287 // 00288 for( j = 0; j < md_size; j++ ) 00289 work[j] ^= md1[j]; 00290 } 00291 00292 use_len = ( key_length < md_size ) ? key_length : md_size; 00293 memcpy( out_p, work, use_len ); 00294 00295 key_length -= (uint32_t) use_len; 00296 out_p += use_len; 00297 00298 for( i = 4; i > 0; i-- ) 00299 if( ++counter[i - 1] != 0 ) 00300 break; 00301 } 00302 00303 return( 0 ); 00304 } 00305 00306 #if defined(MBEDTLS_SELF_TEST) 00307 00308 #if !defined(MBEDTLS_SHA1_C) 00309 int mbedtls_pkcs5_self_test( int verbose ) 00310 { 00311 if( verbose != 0 ) 00312 mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); 00313 00314 return( 0 ); 00315 } 00316 #else 00317 00318 #define MAX_TESTS 6 00319 00320 static const size_t plen[MAX_TESTS] = 00321 { 8, 8, 8, 24, 9 }; 00322 00323 static const unsigned char password[MAX_TESTS][32] = 00324 { 00325 "password", 00326 "password", 00327 "password", 00328 "passwordPASSWORDpassword", 00329 "pass\0word", 00330 }; 00331 00332 static const size_t slen[MAX_TESTS] = 00333 { 4, 4, 4, 36, 5 }; 00334 00335 static const unsigned char salt[MAX_TESTS][40] = 00336 { 00337 "salt", 00338 "salt", 00339 "salt", 00340 "saltSALTsaltSALTsaltSALTsaltSALTsalt", 00341 "sa\0lt", 00342 }; 00343 00344 static const uint32_t it_cnt[MAX_TESTS] = 00345 { 1, 2, 4096, 4096, 4096 }; 00346 00347 static const uint32_t key_len[MAX_TESTS] = 00348 { 20, 20, 20, 25, 16 }; 00349 00350 static const unsigned char result_key[MAX_TESTS][32] = 00351 { 00352 { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 00353 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, 00354 0x2f, 0xe0, 0x37, 0xa6 }, 00355 { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 00356 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, 00357 0xd8, 0xde, 0x89, 0x57 }, 00358 { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 00359 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, 00360 0x65, 0xa4, 0x29, 0xc1 }, 00361 { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 00362 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, 00363 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, 00364 0x38 }, 00365 { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 00366 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, 00367 }; 00368 00369 int mbedtls_pkcs5_self_test( int verbose ) 00370 { 00371 mbedtls_md_context_t sha1_ctx; 00372 const mbedtls_md_info_t *info_sha1; 00373 int ret, i; 00374 unsigned char key[64]; 00375 00376 mbedtls_md_init( &sha1_ctx ); 00377 00378 info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); 00379 if( info_sha1 == NULL ) 00380 { 00381 ret = 1; 00382 goto exit; 00383 } 00384 00385 if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) 00386 { 00387 ret = 1; 00388 goto exit; 00389 } 00390 00391 for( i = 0; i < MAX_TESTS; i++ ) 00392 { 00393 if( verbose != 0 ) 00394 mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); 00395 00396 ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], 00397 slen[i], it_cnt[i], key_len[i], key ); 00398 if( ret != 0 || 00399 memcmp( result_key[i], key, key_len[i] ) != 0 ) 00400 { 00401 if( verbose != 0 ) 00402 mbedtls_printf( "failed\n" ); 00403 00404 ret = 1; 00405 goto exit; 00406 } 00407 00408 if( verbose != 0 ) 00409 mbedtls_printf( "passed\n" ); 00410 } 00411 00412 if( verbose != 0 ) 00413 mbedtls_printf( "\n" ); 00414 00415 exit: 00416 mbedtls_md_free( &sha1_ctx ); 00417 00418 return( ret ); 00419 } 00420 #endif /* MBEDTLS_SHA1_C */ 00421 00422 #endif /* MBEDTLS_SELF_TEST */ 00423 00424 #endif /* MBEDTLS_PKCS5_C */
Generated on Tue Jul 12 2022 12:45:41 by
