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.
Fork of mbedtls by
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 #include "mbedtls/asn1.h" 00042 #include "mbedtls/cipher.h" 00043 #include "mbedtls/oid.h" 00044 00045 #include <string.h> 00046 00047 #if defined(MBEDTLS_PLATFORM_C) 00048 #include "mbedtls/platform.h" 00049 #else 00050 #include <stdio.h> 00051 #define mbedtls_printf printf 00052 #endif 00053 00054 static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, 00055 mbedtls_asn1_buf *salt, int *iterations, 00056 int *keylen, mbedtls_md_type_t *md_type ) 00057 { 00058 int ret; 00059 mbedtls_asn1_buf prf_alg_oid; 00060 unsigned char *p = params->p; 00061 const unsigned char *end = params->p + params->len; 00062 00063 if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) 00064 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + 00065 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 00066 /* 00067 * PBKDF2-params ::= SEQUENCE { 00068 * salt OCTET STRING, 00069 * iterationCount INTEGER, 00070 * keyLength INTEGER OPTIONAL 00071 * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 00072 * } 00073 * 00074 */ 00075 if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) 00076 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); 00077 00078 salt->p = p; 00079 p += salt->len; 00080 00081 if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) 00082 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); 00083 00084 if( p == end ) 00085 return( 0 ); 00086 00087 if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) 00088 { 00089 if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 00090 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); 00091 } 00092 00093 if( p == end ) 00094 return( 0 ); 00095 00096 if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) 00097 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); 00098 00099 if( MBEDTLS_OID_CMP( MBEDTLS_OID_HMAC_SHA1, &prf_alg_oid ) != 0 ) 00100 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00101 00102 *md_type = MBEDTLS_MD_SHA1; 00103 00104 if( p != end ) 00105 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + 00106 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 00107 00108 return( 0 ); 00109 } 00110 00111 int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, 00112 const unsigned char *pwd, size_t pwdlen, 00113 const unsigned char *data, size_t datalen, 00114 unsigned char *output ) 00115 { 00116 int ret, iterations = 0, keylen = 0; 00117 unsigned char *p, *end; 00118 mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; 00119 mbedtls_asn1_buf salt; 00120 mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; 00121 unsigned char key[32], iv[32]; 00122 size_t olen = 0; 00123 const mbedtls_md_info_t *md_info; 00124 const mbedtls_cipher_info_t *cipher_info; 00125 mbedtls_md_context_t md_ctx; 00126 mbedtls_cipher_type_t cipher_alg; 00127 mbedtls_cipher_context_t cipher_ctx; 00128 00129 p = pbe_params->p; 00130 end = p + pbe_params->len; 00131 00132 /* 00133 * PBES2-params ::= SEQUENCE { 00134 * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, 00135 * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} 00136 * } 00137 */ 00138 if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) 00139 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + 00140 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 00141 00142 if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) 00143 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); 00144 00145 // Only PBKDF2 supported at the moment 00146 // 00147 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) 00148 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00149 00150 if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, 00151 &salt, &iterations, &keylen, 00152 &md_type ) ) != 0 ) 00153 { 00154 return( ret ); 00155 } 00156 00157 md_info = mbedtls_md_info_from_type( md_type ); 00158 if( md_info == NULL ) 00159 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00160 00161 if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, 00162 &enc_scheme_params ) ) != 0 ) 00163 { 00164 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); 00165 } 00166 00167 if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) 00168 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00169 00170 cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); 00171 if( cipher_info == NULL ) 00172 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00173 00174 /* 00175 * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored 00176 * since it is optional and we don't know if it was set or not 00177 */ 00178 keylen = cipher_info->key_bitlen / 8; 00179 00180 if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || 00181 enc_scheme_params.len != cipher_info->iv_size ) 00182 { 00183 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); 00184 } 00185 00186 mbedtls_md_init( &md_ctx ); 00187 mbedtls_cipher_init( &cipher_ctx ); 00188 00189 memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); 00190 00191 if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) 00192 goto exit; 00193 00194 if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, 00195 iterations, keylen, key ) ) != 0 ) 00196 { 00197 goto exit; 00198 } 00199 00200 if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) 00201 goto exit; 00202 00203 if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) 00204 goto exit; 00205 00206 if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, 00207 data, datalen, output, &olen ) ) != 0 ) 00208 ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; 00209 00210 exit: 00211 mbedtls_md_free( &md_ctx ); 00212 mbedtls_cipher_free( &cipher_ctx ); 00213 00214 return( ret ); 00215 } 00216 00217 int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, 00218 size_t plen, const unsigned char *salt, size_t slen, 00219 unsigned int iteration_count, 00220 uint32_t key_length, unsigned char *output ) 00221 { 00222 int ret, j; 00223 unsigned int i; 00224 unsigned char md1[MBEDTLS_MD_MAX_SIZE]; 00225 unsigned char work[MBEDTLS_MD_MAX_SIZE]; 00226 unsigned char md_size = mbedtls_md_get_size( ctx->md_info ); 00227 size_t use_len; 00228 unsigned char *out_p = output; 00229 unsigned char counter[4]; 00230 00231 memset( counter, 0, 4 ); 00232 counter[3] = 1; 00233 00234 if( iteration_count > 0xFFFFFFFF ) 00235 return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); 00236 00237 while( key_length ) 00238 { 00239 // U1 ends up in work 00240 // 00241 if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) 00242 return( ret ); 00243 00244 if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) 00245 return( ret ); 00246 00247 if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) 00248 return( ret ); 00249 00250 if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) 00251 return( ret ); 00252 00253 memcpy( md1, work, md_size ); 00254 00255 for( i = 1; i < iteration_count; i++ ) 00256 { 00257 // U2 ends up in md1 00258 // 00259 if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) 00260 return( ret ); 00261 00262 if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) 00263 return( ret ); 00264 00265 if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) 00266 return( ret ); 00267 00268 // U1 xor U2 00269 // 00270 for( j = 0; j < md_size; j++ ) 00271 work[j] ^= md1[j]; 00272 } 00273 00274 use_len = ( key_length < md_size ) ? key_length : md_size; 00275 memcpy( out_p, work, use_len ); 00276 00277 key_length -= (uint32_t) use_len; 00278 out_p += use_len; 00279 00280 for( i = 4; i > 0; i-- ) 00281 if( ++counter[i - 1] != 0 ) 00282 break; 00283 } 00284 00285 return( 0 ); 00286 } 00287 00288 #if defined(MBEDTLS_SELF_TEST) 00289 00290 #if !defined(MBEDTLS_SHA1_C) 00291 int mbedtls_pkcs5_self_test( int verbose ) 00292 { 00293 if( verbose != 0 ) 00294 mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); 00295 00296 return( 0 ); 00297 } 00298 #else 00299 00300 #define MAX_TESTS 6 00301 00302 static const size_t plen[MAX_TESTS] = 00303 { 8, 8, 8, 24, 9 }; 00304 00305 static const unsigned char password[MAX_TESTS][32] = 00306 { 00307 "password", 00308 "password", 00309 "password", 00310 "passwordPASSWORDpassword", 00311 "pass\0word", 00312 }; 00313 00314 static const size_t slen[MAX_TESTS] = 00315 { 4, 4, 4, 36, 5 }; 00316 00317 static const unsigned char salt[MAX_TESTS][40] = 00318 { 00319 "salt", 00320 "salt", 00321 "salt", 00322 "saltSALTsaltSALTsaltSALTsaltSALTsalt", 00323 "sa\0lt", 00324 }; 00325 00326 static const uint32_t it_cnt[MAX_TESTS] = 00327 { 1, 2, 4096, 4096, 4096 }; 00328 00329 static const uint32_t key_len[MAX_TESTS] = 00330 { 20, 20, 20, 25, 16 }; 00331 00332 static const unsigned char result_key[MAX_TESTS][32] = 00333 { 00334 { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 00335 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, 00336 0x2f, 0xe0, 0x37, 0xa6 }, 00337 { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 00338 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, 00339 0xd8, 0xde, 0x89, 0x57 }, 00340 { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 00341 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, 00342 0x65, 0xa4, 0x29, 0xc1 }, 00343 { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 00344 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, 00345 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, 00346 0x38 }, 00347 { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 00348 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, 00349 }; 00350 00351 int mbedtls_pkcs5_self_test( int verbose ) 00352 { 00353 mbedtls_md_context_t sha1_ctx; 00354 const mbedtls_md_info_t *info_sha1; 00355 int ret, i; 00356 unsigned char key[64]; 00357 00358 mbedtls_md_init( &sha1_ctx ); 00359 00360 info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); 00361 if( info_sha1 == NULL ) 00362 { 00363 ret = 1; 00364 goto exit; 00365 } 00366 00367 if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) 00368 { 00369 ret = 1; 00370 goto exit; 00371 } 00372 00373 for( i = 0; i < MAX_TESTS; i++ ) 00374 { 00375 if( verbose != 0 ) 00376 mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); 00377 00378 ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], 00379 slen[i], it_cnt[i], key_len[i], key ); 00380 if( ret != 0 || 00381 memcmp( result_key[i], key, key_len[i] ) != 0 ) 00382 { 00383 if( verbose != 0 ) 00384 mbedtls_printf( "failed\n" ); 00385 00386 ret = 1; 00387 goto exit; 00388 } 00389 00390 if( verbose != 0 ) 00391 mbedtls_printf( "passed\n" ); 00392 } 00393 00394 mbedtls_printf( "\n" ); 00395 00396 exit: 00397 mbedtls_md_free( &sha1_ctx ); 00398 00399 return( ret ); 00400 } 00401 #endif /* MBEDTLS_SHA1_C */ 00402 00403 #endif /* MBEDTLS_SELF_TEST */ 00404 00405 #endif /* MBEDTLS_PKCS5_C */
Generated on Tue Jul 12 2022 12:52:45 by
