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-2014, Brainspark B.V. 00009 * 00010 * This file is part of PolarSSL (http://www.polarssl.org) 00011 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> 00012 * 00013 * All rights reserved. 00014 * 00015 * This program is free software; you can redistribute it and/or modify 00016 * it under the terms of the GNU General Public License as published by 00017 * the Free Software Foundation; either version 2 of the License, or 00018 * (at your option) any later version. 00019 * 00020 * This program is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * You should have received a copy of the GNU General Public License along 00026 * with this program; if not, write to the Free Software Foundation, Inc., 00027 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00028 */ 00029 /* 00030 * PKCS#5 includes PBKDF2 and more 00031 * 00032 * http://tools.ietf.org/html/rfc2898 (Specification) 00033 * http://tools.ietf.org/html/rfc6070 (Test vectors) 00034 */ 00035 00036 #if !defined(POLARSSL_CONFIG_FILE) 00037 #include "polarssl/config.h" 00038 #else 00039 #include POLARSSL_CONFIG_FILE 00040 #endif 00041 00042 #if defined(POLARSSL_PKCS5_C) 00043 00044 #include "polarssl/pkcs5.h" 00045 #include "polarssl/asn1.h" 00046 #include "polarssl/cipher.h" 00047 #include "polarssl/oid.h" 00048 00049 #if defined(POLARSSL_PLATFORM_C) 00050 #include "polarssl/platform.h" 00051 #else 00052 #define polarssl_printf printf 00053 #endif 00054 00055 static int pkcs5_parse_pbkdf2_params( asn1_buf *params, 00056 asn1_buf *salt, int *iterations, 00057 int *keylen, md_type_t *md_type ) 00058 { 00059 int ret; 00060 asn1_buf prf_alg_oid; 00061 unsigned char **p = ¶ms->p; 00062 const unsigned char *end = params->p + params->len; 00063 00064 if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) 00065 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + 00066 POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); 00067 /* 00068 * PBKDF2-params ::= SEQUENCE { 00069 * salt OCTET STRING, 00070 * iterationCount INTEGER, 00071 * keyLength INTEGER OPTIONAL 00072 * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 00073 * } 00074 * 00075 */ 00076 if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 ) 00077 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); 00078 00079 salt->p = *p; 00080 *p += salt->len; 00081 00082 if( ( ret = asn1_get_int( p, end, iterations ) ) != 0 ) 00083 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); 00084 00085 if( *p == end ) 00086 return( 0 ); 00087 00088 if( ( ret = asn1_get_int( p, end, keylen ) ) != 0 ) 00089 { 00090 if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) 00091 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); 00092 } 00093 00094 if( *p == end ) 00095 return( 0 ); 00096 00097 if( ( ret = asn1_get_alg_null( p, end, &prf_alg_oid ) ) != 0 ) 00098 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); 00099 00100 if( !OID_CMP( OID_HMAC_SHA1, &prf_alg_oid ) ) 00101 return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00102 00103 *md_type = POLARSSL_MD_SHA1; 00104 00105 if( *p != end ) 00106 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + 00107 POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); 00108 00109 return( 0 ); 00110 } 00111 00112 int pkcs5_pbes2( asn1_buf *pbe_params, int mode, 00113 const unsigned char *pwd, size_t pwdlen, 00114 const unsigned char *data, size_t datalen, 00115 unsigned char *output ) 00116 { 00117 int ret, iterations = 0, keylen = 0; 00118 unsigned char *p, *end; 00119 asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; 00120 asn1_buf salt; 00121 md_type_t md_type = POLARSSL_MD_SHA1; 00122 unsigned char key[32], iv[32]; 00123 size_t olen = 0; 00124 const md_info_t *md_info; 00125 const cipher_info_t *cipher_info; 00126 md_context_t md_ctx; 00127 cipher_type_t cipher_alg; 00128 cipher_context_t cipher_ctx; 00129 00130 p = pbe_params->p; 00131 end = p + pbe_params->len; 00132 00133 memset( &md_ctx, 0, sizeof(md_context_t) ); 00134 memset( &cipher_ctx, 0, sizeof(cipher_context_t) ); 00135 00136 /* 00137 * PBES2-params ::= SEQUENCE { 00138 * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, 00139 * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} 00140 * } 00141 */ 00142 if( pbe_params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) 00143 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + 00144 POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); 00145 00146 if( ( ret = asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) 00147 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); 00148 00149 // Only PBKDF2 supported at the moment 00150 // 00151 if( !OID_CMP( OID_PKCS5_PBKDF2, &kdf_alg_oid ) ) 00152 return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00153 00154 if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, 00155 &salt, &iterations, &keylen, 00156 &md_type ) ) != 0 ) 00157 { 00158 return( ret ); 00159 } 00160 00161 md_info = md_info_from_type( md_type ); 00162 if( md_info == NULL ) 00163 return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00164 00165 if( ( ret = asn1_get_alg( &p, end, &enc_scheme_oid, 00166 &enc_scheme_params ) ) != 0 ) 00167 { 00168 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); 00169 } 00170 00171 if ( oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) 00172 return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00173 00174 cipher_info = cipher_info_from_type( cipher_alg ); 00175 if( cipher_info == NULL ) 00176 return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00177 00178 keylen = cipher_info->key_length / 8; 00179 00180 if( enc_scheme_params.tag != ASN1_OCTET_STRING || 00181 enc_scheme_params.len != cipher_info->iv_size ) 00182 { 00183 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT ); 00184 } 00185 00186 memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); 00187 00188 if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 ) 00189 goto exit; 00190 00191 if ( ( ret = pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, 00192 iterations, keylen, key ) ) != 0 ) 00193 { 00194 goto exit; 00195 } 00196 00197 if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 ) 00198 goto exit; 00199 00200 if( ( ret = cipher_setkey( &cipher_ctx, key, 8 * keylen, mode ) ) != 0 ) 00201 goto exit; 00202 00203 if( ( ret = cipher_set_iv( &cipher_ctx, iv, enc_scheme_params.len ) ) != 0 ) 00204 goto exit; 00205 00206 if( ( ret = cipher_reset( &cipher_ctx ) ) != 0 ) 00207 goto exit; 00208 00209 if( ( ret = cipher_update( &cipher_ctx, data, datalen, 00210 output, &olen ) ) != 0 ) 00211 { 00212 goto exit; 00213 } 00214 00215 if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) 00216 ret = POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH; 00217 00218 exit: 00219 md_free_ctx( &md_ctx ); 00220 cipher_free_ctx( &cipher_ctx ); 00221 00222 return( ret ); 00223 } 00224 00225 int pkcs5_pbkdf2_hmac( md_context_t *ctx, const unsigned char *password, 00226 size_t plen, const unsigned char *salt, size_t slen, 00227 unsigned int iteration_count, 00228 uint32_t key_length, unsigned char *output ) 00229 { 00230 int ret, j; 00231 unsigned int i; 00232 unsigned char md1[POLARSSL_MD_MAX_SIZE]; 00233 unsigned char work[POLARSSL_MD_MAX_SIZE]; 00234 unsigned char md_size = md_get_size( ctx->md_info ); 00235 size_t use_len; 00236 unsigned char *out_p = output; 00237 unsigned char counter[4]; 00238 00239 memset( counter, 0, 4 ); 00240 counter[3] = 1; 00241 00242 if( iteration_count > 0xFFFFFFFF ) 00243 return( POLARSSL_ERR_PKCS5_BAD_INPUT_DATA ); 00244 00245 while( key_length ) 00246 { 00247 // U1 ends up in work 00248 // 00249 if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 ) 00250 return( ret ); 00251 00252 if( ( ret = md_hmac_update( ctx, salt, slen ) ) != 0 ) 00253 return( ret ); 00254 00255 if( ( ret = md_hmac_update( ctx, counter, 4 ) ) != 0 ) 00256 return( ret ); 00257 00258 if( ( ret = md_hmac_finish( ctx, work ) ) != 0 ) 00259 return( ret ); 00260 00261 memcpy( md1, work, md_size ); 00262 00263 for ( i = 1; i < iteration_count; i++ ) 00264 { 00265 // U2 ends up in md1 00266 // 00267 if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 ) 00268 return( ret ); 00269 00270 if( ( ret = md_hmac_update( ctx, md1, md_size ) ) != 0 ) 00271 return( ret ); 00272 00273 if( ( ret = md_hmac_finish( ctx, md1 ) ) != 0 ) 00274 return( ret ); 00275 00276 // U1 xor U2 00277 // 00278 for( j = 0; j < md_size; j++ ) 00279 work[j] ^= md1[j]; 00280 } 00281 00282 use_len = ( key_length < md_size ) ? key_length : md_size; 00283 memcpy( out_p, work, use_len ); 00284 00285 key_length -= (uint32_t) use_len; 00286 out_p += use_len; 00287 00288 for( i = 4; i > 0; i-- ) 00289 if( ++counter[i - 1] != 0 ) 00290 break; 00291 } 00292 00293 return( 0 ); 00294 } 00295 00296 #if defined(POLARSSL_SELF_TEST) 00297 00298 #include <stdio.h> 00299 00300 #define MAX_TESTS 6 00301 00302 size_t plen[MAX_TESTS] = 00303 { 8, 8, 8, 8, 24, 9 }; 00304 00305 unsigned char password[MAX_TESTS][32] = 00306 { 00307 "password", 00308 "password", 00309 "password", 00310 "password", 00311 "passwordPASSWORDpassword", 00312 "pass\0word", 00313 }; 00314 00315 size_t slen[MAX_TESTS] = 00316 { 4, 4, 4, 4, 36, 5 }; 00317 00318 unsigned char salt[MAX_TESTS][40] = 00319 { 00320 "salt", 00321 "salt", 00322 "salt", 00323 "salt", 00324 "saltSALTsaltSALTsaltSALTsaltSALTsalt", 00325 "sa\0lt", 00326 }; 00327 00328 uint32_t it_cnt[MAX_TESTS] = 00329 { 1, 2, 4096, 16777216, 4096, 4096 }; 00330 00331 uint32_t key_len[MAX_TESTS] = 00332 { 20, 20, 20, 20, 25, 16 }; 00333 00334 00335 unsigned char result_key[MAX_TESTS][32] = 00336 { 00337 { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 00338 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, 00339 0x2f, 0xe0, 0x37, 0xa6 }, 00340 { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 00341 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, 00342 0xd8, 0xde, 0x89, 0x57 }, 00343 { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 00344 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, 00345 0x65, 0xa4, 0x29, 0xc1 }, 00346 { 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, 00347 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, 00348 0x26, 0x34, 0xe9, 0x84 }, 00349 { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 00350 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, 00351 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, 00352 0x38 }, 00353 { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 00354 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, 00355 }; 00356 00357 int pkcs5_self_test( int verbose ) 00358 { 00359 md_context_t sha1_ctx; 00360 const md_info_t *info_sha1; 00361 int ret, i; 00362 unsigned char key[64]; 00363 00364 info_sha1 = md_info_from_type( POLARSSL_MD_SHA1 ); 00365 if( info_sha1 == NULL ) 00366 return( 1 ); 00367 00368 if( ( ret = md_init_ctx( &sha1_ctx, info_sha1 ) ) != 0 ) 00369 return( 1 ); 00370 00371 if( verbose != 0 ) 00372 polarssl_printf( " PBKDF2 note: test #3 may be slow!\n" ); 00373 00374 for( i = 0; i < MAX_TESTS; i++ ) 00375 { 00376 if( verbose != 0 ) 00377 polarssl_printf( " PBKDF2 (SHA1) #%d: ", i ); 00378 00379 ret = pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], 00380 slen[i], it_cnt[i], key_len[i], key ); 00381 if( ret != 0 || 00382 memcmp( result_key[i], key, key_len[i] ) != 0 ) 00383 { 00384 if( verbose != 0 ) 00385 polarssl_printf( "failed\n" ); 00386 00387 return( 1 ); 00388 } 00389 00390 if( verbose != 0 ) 00391 polarssl_printf( "passed\n" ); 00392 } 00393 00394 polarssl_printf( "\n" ); 00395 00396 if( ( ret = md_free_ctx( &sha1_ctx ) ) != 0 ) 00397 return( 1 ); 00398 00399 return( 0 ); 00400 } 00401 00402 #endif /* POLARSSL_SELF_TEST */ 00403 00404 #endif /* POLARSSL_PKCS5_C */ 00405 00406
Generated on Tue Jul 12 2022 19:40:20 by
1.7.2