mbed TLS library
Dependents: HTTPClient-SSL WS_SERVER
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, ARM Limited, All Rights Reserved 00009 * 00010 * This file is part of mbed TLS (https://tls.mbed.org) 00011 * 00012 * This program is free software; you can redistribute it and/or modify 00013 * it under the terms of the GNU General Public License as published by 00014 * the Free Software Foundation; either version 2 of the License, or 00015 * (at your option) any later version. 00016 * 00017 * This program is distributed in the hope that it will be useful, 00018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 * GNU General Public License for more details. 00021 * 00022 * You should have received a copy of the GNU General Public License along 00023 * with this program; if not, write to the Free Software Foundation, Inc., 00024 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00025 */ 00026 /* 00027 * PKCS#5 includes PBKDF2 and more 00028 * 00029 * http://tools.ietf.org/html/rfc2898 (Specification) 00030 * http://tools.ietf.org/html/rfc6070 (Test vectors) 00031 */ 00032 00033 #if !defined(POLARSSL_CONFIG_FILE) 00034 #include "polarssl/config.h" 00035 #else 00036 #include POLARSSL_CONFIG_FILE 00037 #endif 00038 00039 #if defined(POLARSSL_PKCS5_C) 00040 00041 #include "polarssl/pkcs5.h" 00042 #include "polarssl/asn1.h" 00043 #include "polarssl/cipher.h" 00044 #include "polarssl/oid.h" 00045 00046 #include <string.h> 00047 00048 #if defined(POLARSSL_PLATFORM_C) 00049 #include "polarssl/platform.h" 00050 #else 00051 #include <stdio.h> 00052 #define polarssl_printf printf 00053 #endif 00054 00055 static int pkcs5_parse_pbkdf2_params( const 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 = params->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 /* 00134 * PBES2-params ::= SEQUENCE { 00135 * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, 00136 * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} 00137 * } 00138 */ 00139 if( pbe_params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) 00140 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + 00141 POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); 00142 00143 if( ( ret = asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) 00144 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); 00145 00146 // Only PBKDF2 supported at the moment 00147 // 00148 if( !OID_CMP( OID_PKCS5_PBKDF2, &kdf_alg_oid ) ) 00149 return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00150 00151 if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, 00152 &salt, &iterations, &keylen, 00153 &md_type ) ) != 0 ) 00154 { 00155 return( ret ); 00156 } 00157 00158 md_info = md_info_from_type( md_type ); 00159 if( md_info == NULL ) 00160 return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00161 00162 if( ( ret = asn1_get_alg( &p, end, &enc_scheme_oid, 00163 &enc_scheme_params ) ) != 0 ) 00164 { 00165 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT + ret ); 00166 } 00167 00168 if( oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) 00169 return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00170 00171 cipher_info = cipher_info_from_type( cipher_alg ); 00172 if( cipher_info == NULL ) 00173 return( POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE ); 00174 00175 /* 00176 * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored 00177 * since it is optional and we don't know if it was set or not 00178 */ 00179 keylen = cipher_info->key_length / 8; 00180 00181 if( enc_scheme_params.tag != ASN1_OCTET_STRING || 00182 enc_scheme_params.len != cipher_info->iv_size ) 00183 { 00184 return( POLARSSL_ERR_PKCS5_INVALID_FORMAT ); 00185 } 00186 00187 md_init( &md_ctx ); 00188 cipher_init( &cipher_ctx ); 00189 00190 memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); 00191 00192 if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 ) 00193 goto exit; 00194 00195 if( ( ret = pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, 00196 iterations, keylen, key ) ) != 0 ) 00197 { 00198 goto exit; 00199 } 00200 00201 if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 ) 00202 goto exit; 00203 00204 if( ( ret = cipher_setkey( &cipher_ctx, key, 8 * keylen, (operation_t) mode ) ) != 0 ) 00205 goto exit; 00206 00207 if( ( ret = cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, 00208 data, datalen, output, &olen ) ) != 0 ) 00209 ret = POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH; 00210 00211 exit: 00212 md_free( &md_ctx ); 00213 cipher_free( &cipher_ctx ); 00214 00215 return( ret ); 00216 } 00217 00218 int pkcs5_pbkdf2_hmac( md_context_t *ctx, const unsigned char *password, 00219 size_t plen, const unsigned char *salt, size_t slen, 00220 unsigned int iteration_count, 00221 uint32_t key_length, unsigned char *output ) 00222 { 00223 int ret, j; 00224 unsigned int i; 00225 unsigned char md1[POLARSSL_MD_MAX_SIZE]; 00226 unsigned char work[POLARSSL_MD_MAX_SIZE]; 00227 unsigned char md_size = md_get_size( ctx->md_info ); 00228 size_t use_len; 00229 unsigned char *out_p = output; 00230 unsigned char counter[4]; 00231 00232 memset( counter, 0, 4 ); 00233 counter[3] = 1; 00234 00235 if( iteration_count > 0xFFFFFFFF ) 00236 return( POLARSSL_ERR_PKCS5_BAD_INPUT_DATA ); 00237 00238 while( key_length ) 00239 { 00240 // U1 ends up in work 00241 // 00242 if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 ) 00243 return( ret ); 00244 00245 if( ( ret = md_hmac_update( ctx, salt, slen ) ) != 0 ) 00246 return( ret ); 00247 00248 if( ( ret = md_hmac_update( ctx, counter, 4 ) ) != 0 ) 00249 return( ret ); 00250 00251 if( ( ret = md_hmac_finish( ctx, work ) ) != 0 ) 00252 return( ret ); 00253 00254 memcpy( md1, work, md_size ); 00255 00256 for( i = 1; i < iteration_count; i++ ) 00257 { 00258 // U2 ends up in md1 00259 // 00260 if( ( ret = md_hmac_starts( ctx, password, plen ) ) != 0 ) 00261 return( ret ); 00262 00263 if( ( ret = md_hmac_update( ctx, md1, md_size ) ) != 0 ) 00264 return( ret ); 00265 00266 if( ( ret = md_hmac_finish( ctx, md1 ) ) != 0 ) 00267 return( ret ); 00268 00269 // U1 xor U2 00270 // 00271 for( j = 0; j < md_size; j++ ) 00272 work[j] ^= md1[j]; 00273 } 00274 00275 use_len = ( key_length < md_size ) ? key_length : md_size; 00276 memcpy( out_p, work, use_len ); 00277 00278 key_length -= (uint32_t) use_len; 00279 out_p += use_len; 00280 00281 for( i = 4; i > 0; i-- ) 00282 if( ++counter[i - 1] != 0 ) 00283 break; 00284 } 00285 00286 return( 0 ); 00287 } 00288 00289 #if defined(POLARSSL_SELF_TEST) 00290 00291 #if !defined(POLARSSL_SHA1_C) 00292 int pkcs5_self_test( int verbose ) 00293 { 00294 if( verbose != 0 ) 00295 polarssl_printf( " PBKDF2 (SHA1): skipped\n\n" ); 00296 00297 return( 0 ); 00298 } 00299 #else 00300 00301 #define MAX_TESTS 6 00302 00303 static const size_t plen[MAX_TESTS] = 00304 { 8, 8, 8, 24, 9 }; 00305 00306 static const unsigned char password[MAX_TESTS][32] = 00307 { 00308 "password", 00309 "password", 00310 "password", 00311 "passwordPASSWORDpassword", 00312 "pass\0word", 00313 }; 00314 00315 static const size_t slen[MAX_TESTS] = 00316 { 4, 4, 4, 36, 5 }; 00317 00318 static const unsigned char salt[MAX_TESTS][40] = 00319 { 00320 "salt", 00321 "salt", 00322 "salt", 00323 "saltSALTsaltSALTsaltSALTsaltSALTsalt", 00324 "sa\0lt", 00325 }; 00326 00327 static const uint32_t it_cnt[MAX_TESTS] = 00328 { 1, 2, 4096, 4096, 4096 }; 00329 00330 static const uint32_t key_len[MAX_TESTS] = 00331 { 20, 20, 20, 25, 16 }; 00332 00333 static const unsigned char result_key[MAX_TESTS][32] = 00334 { 00335 { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 00336 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, 00337 0x2f, 0xe0, 0x37, 0xa6 }, 00338 { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 00339 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, 00340 0xd8, 0xde, 0x89, 0x57 }, 00341 { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 00342 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, 00343 0x65, 0xa4, 0x29, 0xc1 }, 00344 { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 00345 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, 00346 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, 00347 0x38 }, 00348 { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 00349 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, 00350 }; 00351 00352 int pkcs5_self_test( int verbose ) 00353 { 00354 md_context_t sha1_ctx; 00355 const md_info_t *info_sha1; 00356 int ret, i; 00357 unsigned char key[64]; 00358 00359 md_init( &sha1_ctx ); 00360 00361 info_sha1 = md_info_from_type( POLARSSL_MD_SHA1 ); 00362 if( info_sha1 == NULL ) 00363 { 00364 ret = 1; 00365 goto exit; 00366 } 00367 00368 if( ( ret = md_init_ctx( &sha1_ctx, info_sha1 ) ) != 0 ) 00369 { 00370 ret = 1; 00371 goto exit; 00372 } 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 ret = 1; 00388 goto exit; 00389 } 00390 00391 if( verbose != 0 ) 00392 polarssl_printf( "passed\n" ); 00393 } 00394 00395 polarssl_printf( "\n" ); 00396 00397 exit: 00398 md_free( &sha1_ctx ); 00399 00400 return( ret ); 00401 } 00402 #endif /* POLARSSL_SHA1_C */ 00403 00404 #endif /* POLARSSL_SELF_TEST */ 00405 00406 #endif /* POLARSSL_PKCS5_C */ 00407
Generated on Tue Jul 12 2022 13:50:37 by 1.7.2