Hannes Tschofenig
/
aes-gcm-test-program
Example program to test AES-GCM functionality. Used for a workshop
Embed:
(wiki syntax)
Show/hide line numbers
pkcs5.c
Go to the documentation of this file.
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