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 UINT_MAX > 0xFFFFFFFF 00253 if( iteration_count > 0xFFFFFFFF ) 00254 return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); 00255 #endif 00256 00257 while( key_length ) 00258 { 00259 // U1 ends up in work 00260 // 00261 if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) 00262 return( ret ); 00263 00264 if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) 00265 return( ret ); 00266 00267 if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) 00268 return( ret ); 00269 00270 if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) 00271 return( ret ); 00272 00273 memcpy( md1, work, md_size ); 00274 00275 for( i = 1; i < iteration_count; i++ ) 00276 { 00277 // U2 ends up in md1 00278 // 00279 if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) 00280 return( ret ); 00281 00282 if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) 00283 return( ret ); 00284 00285 if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) 00286 return( ret ); 00287 00288 // U1 xor U2 00289 // 00290 for( j = 0; j < md_size; j++ ) 00291 work[j] ^= md1[j]; 00292 } 00293 00294 use_len = ( key_length < md_size ) ? key_length : md_size; 00295 memcpy( out_p, work, use_len ); 00296 00297 key_length -= (uint32_t) use_len; 00298 out_p += use_len; 00299 00300 for( i = 4; i > 0; i-- ) 00301 if( ++counter[i - 1] != 0 ) 00302 break; 00303 } 00304 00305 return( 0 ); 00306 } 00307 00308 #if defined(MBEDTLS_SELF_TEST) 00309 00310 #if !defined(MBEDTLS_SHA1_C) 00311 int mbedtls_pkcs5_self_test( int verbose ) 00312 { 00313 if( verbose != 0 ) 00314 mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); 00315 00316 return( 0 ); 00317 } 00318 #else 00319 00320 #define MAX_TESTS 6 00321 00322 static const size_t plen[MAX_TESTS] = 00323 { 8, 8, 8, 24, 9 }; 00324 00325 static const unsigned char password[MAX_TESTS][32] = 00326 { 00327 "password", 00328 "password", 00329 "password", 00330 "passwordPASSWORDpassword", 00331 "pass\0word", 00332 }; 00333 00334 static const size_t slen[MAX_TESTS] = 00335 { 4, 4, 4, 36, 5 }; 00336 00337 static const unsigned char salt[MAX_TESTS][40] = 00338 { 00339 "salt", 00340 "salt", 00341 "salt", 00342 "saltSALTsaltSALTsaltSALTsaltSALTsalt", 00343 "sa\0lt", 00344 }; 00345 00346 static const uint32_t it_cnt[MAX_TESTS] = 00347 { 1, 2, 4096, 4096, 4096 }; 00348 00349 static const uint32_t key_len[MAX_TESTS] = 00350 { 20, 20, 20, 25, 16 }; 00351 00352 static const unsigned char result_key[MAX_TESTS][32] = 00353 { 00354 { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 00355 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, 00356 0x2f, 0xe0, 0x37, 0xa6 }, 00357 { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 00358 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, 00359 0xd8, 0xde, 0x89, 0x57 }, 00360 { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 00361 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, 00362 0x65, 0xa4, 0x29, 0xc1 }, 00363 { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 00364 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, 00365 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, 00366 0x38 }, 00367 { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 00368 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, 00369 }; 00370 00371 int mbedtls_pkcs5_self_test( int verbose ) 00372 { 00373 mbedtls_md_context_t sha1_ctx; 00374 const mbedtls_md_info_t *info_sha1; 00375 int ret, i; 00376 unsigned char key[64]; 00377 00378 mbedtls_md_init( &sha1_ctx ); 00379 00380 info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); 00381 if( info_sha1 == NULL ) 00382 { 00383 ret = 1; 00384 goto exit; 00385 } 00386 00387 if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) 00388 { 00389 ret = 1; 00390 goto exit; 00391 } 00392 00393 for( i = 0; i < MAX_TESTS; i++ ) 00394 { 00395 if( verbose != 0 ) 00396 mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); 00397 00398 ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], 00399 slen[i], it_cnt[i], key_len[i], key ); 00400 if( ret != 0 || 00401 memcmp( result_key[i], key, key_len[i] ) != 0 ) 00402 { 00403 if( verbose != 0 ) 00404 mbedtls_printf( "failed\n" ); 00405 00406 ret = 1; 00407 goto exit; 00408 } 00409 00410 if( verbose != 0 ) 00411 mbedtls_printf( "passed\n" ); 00412 } 00413 00414 if( verbose != 0 ) 00415 mbedtls_printf( "\n" ); 00416 00417 exit: 00418 mbedtls_md_free( &sha1_ctx ); 00419 00420 return( ret ); 00421 } 00422 #endif /* MBEDTLS_SHA1_C */ 00423 00424 #endif /* MBEDTLS_SELF_TEST */ 00425 00426 #endif /* MBEDTLS_PKCS5_C */
Generated on Tue Jul 12 2022 13:53:31 by
