| OLD | NEW |
| 1 /* p5_crpt2.c */ | 1 /* p5_crpt2.c */ |
| 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
| 3 * project 1999. | 3 * project 1999. |
| 4 */ | 4 */ |
| 5 /* ==================================================================== | 5 /* ==================================================================== |
| 6 * Copyright (c) 1999 The OpenSSL Project. All rights reserved. | 6 * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved. |
| 7 * | 7 * |
| 8 * Redistribution and use in source and binary forms, with or without | 8 * Redistribution and use in source and binary forms, with or without |
| 9 * modification, are permitted provided that the following conditions | 9 * modification, are permitted provided that the following conditions |
| 10 * are met: | 10 * are met: |
| 11 * | 11 * |
| 12 * 1. Redistributions of source code must retain the above copyright | 12 * 1. Redistributions of source code must retain the above copyright |
| 13 * notice, this list of conditions and the following disclaimer. | 13 * notice, this list of conditions and the following disclaimer. |
| 14 * | 14 * |
| 15 * 2. Redistributions in binary form must reproduce the above copyright | 15 * 2. Redistributions in binary form must reproduce the above copyright |
| 16 * notice, this list of conditions and the following disclaimer in | 16 * notice, this list of conditions and the following disclaimer in |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 #include <openssl/hmac.h> | 64 #include <openssl/hmac.h> |
| 65 | 65 |
| 66 /* set this to print out info about the keygen algorithm */ | 66 /* set this to print out info about the keygen algorithm */ |
| 67 /* #define DEBUG_PKCS5V2 */ | 67 /* #define DEBUG_PKCS5V2 */ |
| 68 | 68 |
| 69 #ifdef DEBUG_PKCS5V2 | 69 #ifdef DEBUG_PKCS5V2 |
| 70 static void h__dump (const unsigned char *p, int len); | 70 static void h__dump (const unsigned char *p, int len); |
| 71 #endif | 71 #endif |
| 72 | 72 |
| 73 /* This is an implementation of PKCS#5 v2.0 password based encryption key | 73 /* This is an implementation of PKCS#5 v2.0 password based encryption key |
| 74 * derivation function PBKDF2 using the only currently defined function HMAC | 74 * derivation function PBKDF2. |
| 75 * with SHA1. Verified against test vectors posted by Peter Gutmann | 75 * SHA1 version verified against test vectors posted by Peter Gutmann |
| 76 * <pgut001@cs.auckland.ac.nz> to the PKCS-TNG <pkcs-tng@rsa.com> mailing list. | 76 * <pgut001@cs.auckland.ac.nz> to the PKCS-TNG <pkcs-tng@rsa.com> mailing list. |
| 77 */ | 77 */ |
| 78 | 78 |
| 79 int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, | 79 int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, |
| 80 const unsigned char *salt, int saltlen, int iter, | 80 const unsigned char *salt, int saltlen, int iter, |
| 81 const EVP_MD *digest, |
| 81 int keylen, unsigned char *out) | 82 int keylen, unsigned char *out) |
| 82 { | 83 » { |
| 83 » unsigned char digtmp[SHA_DIGEST_LENGTH], *p, itmp[4]; | 84 » unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; |
| 84 » int cplen, j, k, tkeylen; | 85 » int cplen, j, k, tkeylen, mdlen; |
| 85 unsigned long i = 1; | 86 unsigned long i = 1; |
| 86 HMAC_CTX hctx; | 87 HMAC_CTX hctx; |
| 87 | 88 |
| 89 mdlen = EVP_MD_size(digest); |
| 90 if (mdlen < 0) |
| 91 return 0; |
| 92 |
| 88 HMAC_CTX_init(&hctx); | 93 HMAC_CTX_init(&hctx); |
| 89 p = out; | 94 p = out; |
| 90 tkeylen = keylen; | 95 tkeylen = keylen; |
| 91 » if(!pass) passlen = 0; | 96 » if(!pass) |
| 92 » else if(passlen == -1) passlen = strlen(pass); | 97 » » passlen = 0; |
| 93 » while(tkeylen) { | 98 » else if(passlen == -1) |
| 94 » » if(tkeylen > SHA_DIGEST_LENGTH) cplen = SHA_DIGEST_LENGTH; | 99 » » passlen = strlen(pass); |
| 95 » » else cplen = tkeylen; | 100 » while(tkeylen) |
| 101 » » { |
| 102 » » if(tkeylen > mdlen) |
| 103 » » » cplen = mdlen; |
| 104 » » else |
| 105 » » » cplen = tkeylen; |
| 96 /* We are unlikely to ever use more than 256 blocks (5120 bits!) | 106 /* We are unlikely to ever use more than 256 blocks (5120 bits!) |
| 97 * but just in case... | 107 * but just in case... |
| 98 */ | 108 */ |
| 99 itmp[0] = (unsigned char)((i >> 24) & 0xff); | 109 itmp[0] = (unsigned char)((i >> 24) & 0xff); |
| 100 itmp[1] = (unsigned char)((i >> 16) & 0xff); | 110 itmp[1] = (unsigned char)((i >> 16) & 0xff); |
| 101 itmp[2] = (unsigned char)((i >> 8) & 0xff); | 111 itmp[2] = (unsigned char)((i >> 8) & 0xff); |
| 102 itmp[3] = (unsigned char)(i & 0xff); | 112 itmp[3] = (unsigned char)(i & 0xff); |
| 103 » » HMAC_Init_ex(&hctx, pass, passlen, EVP_sha1(), NULL); | 113 » » HMAC_Init_ex(&hctx, pass, passlen, digest, NULL); |
| 104 HMAC_Update(&hctx, salt, saltlen); | 114 HMAC_Update(&hctx, salt, saltlen); |
| 105 HMAC_Update(&hctx, itmp, 4); | 115 HMAC_Update(&hctx, itmp, 4); |
| 106 HMAC_Final(&hctx, digtmp, NULL); | 116 HMAC_Final(&hctx, digtmp, NULL); |
| 107 memcpy(p, digtmp, cplen); | 117 memcpy(p, digtmp, cplen); |
| 108 » » for(j = 1; j < iter; j++) { | 118 » » for(j = 1; j < iter; j++) |
| 109 » » » HMAC(EVP_sha1(), pass, passlen, | 119 » » » { |
| 110 » » » » digtmp, SHA_DIGEST_LENGTH, digtmp, NULL); | 120 » » » HMAC(digest, pass, passlen, |
| 111 » » » for(k = 0; k < cplen; k++) p[k] ^= digtmp[k]; | 121 » » » » digtmp, mdlen, digtmp, NULL); |
| 112 » » } | 122 » » » for(k = 0; k < cplen; k++) |
| 123 » » » » p[k] ^= digtmp[k]; |
| 124 » » » } |
| 113 tkeylen-= cplen; | 125 tkeylen-= cplen; |
| 114 i++; | 126 i++; |
| 115 p+= cplen; | 127 p+= cplen; |
| 116 » } | 128 » » } |
| 117 HMAC_CTX_cleanup(&hctx); | 129 HMAC_CTX_cleanup(&hctx); |
| 118 #ifdef DEBUG_PKCS5V2 | 130 #ifdef DEBUG_PKCS5V2 |
| 119 fprintf(stderr, "Password:\n"); | 131 fprintf(stderr, "Password:\n"); |
| 120 h__dump (pass, passlen); | 132 h__dump (pass, passlen); |
| 121 fprintf(stderr, "Salt:\n"); | 133 fprintf(stderr, "Salt:\n"); |
| 122 h__dump (salt, saltlen); | 134 h__dump (salt, saltlen); |
| 123 fprintf(stderr, "Iteration count %d\n", iter); | 135 fprintf(stderr, "Iteration count %d\n", iter); |
| 124 fprintf(stderr, "Key:\n"); | 136 fprintf(stderr, "Key:\n"); |
| 125 h__dump (out, keylen); | 137 h__dump (out, keylen); |
| 126 #endif | 138 #endif |
| 127 return 1; | 139 return 1; |
| 128 } | 140 » } |
| 141 |
| 142 int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, |
| 143 » » » const unsigned char *salt, int saltlen, int iter, |
| 144 » » » int keylen, unsigned char *out) |
| 145 » { |
| 146 » return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, EVP_sha1(), |
| 147 » » » » » keylen, out); |
| 148 » } |
| 129 | 149 |
| 130 #ifdef DO_TEST | 150 #ifdef DO_TEST |
| 131 main() | 151 main() |
| 132 { | 152 { |
| 133 unsigned char out[4]; | 153 unsigned char out[4]; |
| 134 unsigned char salt[] = {0x12, 0x34, 0x56, 0x78}; | 154 unsigned char salt[] = {0x12, 0x34, 0x56, 0x78}; |
| 135 PKCS5_PBKDF2_HMAC_SHA1("password", -1, salt, 4, 5, 4, out); | 155 PKCS5_PBKDF2_HMAC_SHA1("password", -1, salt, 4, 5, 4, out); |
| 136 fprintf(stderr, "Out %02X %02X %02X %02X\n", | 156 fprintf(stderr, "Out %02X %02X %02X %02X\n", |
| 137 out[0], out[1], out[2], out[3]); | 157 out[0], out[1], out[2], out[3]); |
| 138 } | 158 } |
| 139 | 159 |
| 140 #endif | 160 #endif |
| 141 | 161 |
| 142 /* Now the key derivation function itself. This is a bit evil because | 162 /* Now the key derivation function itself. This is a bit evil because |
| 143 * it has to check the ASN1 parameters are valid: and there are quite a | 163 * it has to check the ASN1 parameters are valid: and there are quite a |
| 144 * few of them... | 164 * few of them... |
| 145 */ | 165 */ |
| 146 | 166 |
| 147 int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, | 167 int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, |
| 148 ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md
, | 168 ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md
, |
| 149 int en_de) | 169 int en_de) |
| 150 { | 170 { |
| 151 unsigned char *salt, key[EVP_MAX_KEY_LENGTH]; | 171 unsigned char *salt, key[EVP_MAX_KEY_LENGTH]; |
| 152 const unsigned char *pbuf; | 172 const unsigned char *pbuf; |
| 153 int saltlen, iter, plen; | 173 int saltlen, iter, plen; |
| 154 unsigned int keylen; | 174 unsigned int keylen; |
| 155 PBE2PARAM *pbe2 = NULL; | 175 PBE2PARAM *pbe2 = NULL; |
| 156 const EVP_CIPHER *cipher; | 176 const EVP_CIPHER *cipher; |
| 157 PBKDF2PARAM *kdf = NULL; | 177 PBKDF2PARAM *kdf = NULL; |
| 178 const EVP_MD *prfmd; |
| 179 int prf_nid, hmac_md_nid; |
| 158 | 180 |
| 159 if (param == NULL || param->type != V_ASN1_SEQUENCE || | 181 if (param == NULL || param->type != V_ASN1_SEQUENCE || |
| 160 param->value.sequence == NULL) { | 182 param->value.sequence == NULL) { |
| 161 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,EVP_R_DECODE_ERROR); | 183 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,EVP_R_DECODE_ERROR); |
| 162 return 0; | 184 return 0; |
| 163 } | 185 } |
| 164 | 186 |
| 165 pbuf = param->value.sequence->data; | 187 pbuf = param->value.sequence->data; |
| 166 plen = param->value.sequence->length; | 188 plen = param->value.sequence->length; |
| 167 if(!(pbe2 = d2i_PBE2PARAM(NULL, &pbuf, plen))) { | 189 if(!(pbe2 = d2i_PBE2PARAM(NULL, &pbuf, plen))) { |
| 168 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,EVP_R_DECODE_ERROR); | 190 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,EVP_R_DECODE_ERROR); |
| 169 return 0; | 191 return 0; |
| 170 } | 192 } |
| 171 | 193 |
| 172 /* See if we recognise the key derivation function */ | 194 /* See if we recognise the key derivation function */ |
| 173 | 195 |
| 174 if(OBJ_obj2nid(pbe2->keyfunc->algorithm) != NID_id_pbkdf2) { | 196 if(OBJ_obj2nid(pbe2->keyfunc->algorithm) != NID_id_pbkdf2) { |
| 175 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, | 197 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, |
| 176 EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION); | 198 EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION); |
| 177 goto err; | 199 goto err; |
| 178 } | 200 } |
| 179 | 201 |
| 180 /* lets see if we recognise the encryption algorithm. | 202 /* lets see if we recognise the encryption algorithm. |
| 181 */ | 203 */ |
| 182 | 204 |
| 183 » cipher = EVP_get_cipherbyname( | 205 » cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm); |
| 184 » » » OBJ_nid2sn(OBJ_obj2nid(pbe2->encryption->algorithm))); | |
| 185 | 206 |
| 186 if(!cipher) { | 207 if(!cipher) { |
| 187 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, | 208 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, |
| 188 EVP_R_UNSUPPORTED_CIPHER); | 209 EVP_R_UNSUPPORTED_CIPHER); |
| 189 goto err; | 210 goto err; |
| 190 } | 211 } |
| 191 | 212 |
| 192 /* Fixup cipher based on AlgorithmIdentifier */ | 213 /* Fixup cipher based on AlgorithmIdentifier */ |
| 193 EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de); | 214 EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de); |
| 194 if(EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) { | 215 if(EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 219 pbe2 = NULL; | 240 pbe2 = NULL; |
| 220 | 241 |
| 221 /* Now check the parameters of the kdf */ | 242 /* Now check the parameters of the kdf */ |
| 222 | 243 |
| 223 if(kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)){ | 244 if(kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)){ |
| 224 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, | 245 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, |
| 225 EVP_R_UNSUPPORTED_KEYLENGTH); | 246 EVP_R_UNSUPPORTED_KEYLENGTH); |
| 226 goto err; | 247 goto err; |
| 227 } | 248 } |
| 228 | 249 |
| 229 » if(kdf->prf && (OBJ_obj2nid(kdf->prf->algorithm) != NID_hmacWithSHA1)) { | 250 » if (kdf->prf) |
| 251 » » prf_nid = OBJ_obj2nid(kdf->prf->algorithm); |
| 252 » else |
| 253 » » prf_nid = NID_hmacWithSHA1; |
| 254 |
| 255 » if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0)) |
| 256 » » { |
| 230 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); | 257 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); |
| 231 goto err; | 258 goto err; |
| 232 » } | 259 » » } |
| 260 |
| 261 » prfmd = EVP_get_digestbynid(hmac_md_nid); |
| 262 » if (prfmd == NULL) |
| 263 » » { |
| 264 » » EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); |
| 265 » » goto err; |
| 266 » » } |
| 233 | 267 |
| 234 if(kdf->salt->type != V_ASN1_OCTET_STRING) { | 268 if(kdf->salt->type != V_ASN1_OCTET_STRING) { |
| 235 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, | 269 EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, |
| 236 EVP_R_UNSUPPORTED_SALT_TYPE); | 270 EVP_R_UNSUPPORTED_SALT_TYPE); |
| 237 goto err; | 271 goto err; |
| 238 } | 272 } |
| 239 | 273 |
| 240 /* it seems that its all OK */ | 274 /* it seems that its all OK */ |
| 241 salt = kdf->salt->value.octet_string->data; | 275 salt = kdf->salt->value.octet_string->data; |
| 242 saltlen = kdf->salt->value.octet_string->length; | 276 saltlen = kdf->salt->value.octet_string->length; |
| 243 iter = ASN1_INTEGER_get(kdf->iter); | 277 iter = ASN1_INTEGER_get(kdf->iter); |
| 244 » PKCS5_PBKDF2_HMAC_SHA1(pass, passlen, salt, saltlen, iter, keylen, key); | 278 » if(!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd, |
| 279 » » » » » » keylen, key)) |
| 280 » » goto err; |
| 245 EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); | 281 EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); |
| 246 OPENSSL_cleanse(key, keylen); | 282 OPENSSL_cleanse(key, keylen); |
| 247 PBKDF2PARAM_free(kdf); | 283 PBKDF2PARAM_free(kdf); |
| 248 return 1; | 284 return 1; |
| 249 | 285 |
| 250 err: | 286 err: |
| 251 PBE2PARAM_free(pbe2); | 287 PBE2PARAM_free(pbe2); |
| 252 PBKDF2PARAM_free(kdf); | 288 PBKDF2PARAM_free(kdf); |
| 253 return 0; | 289 return 0; |
| 254 } | 290 } |
| 255 | 291 |
| 256 #ifdef DEBUG_PKCS5V2 | 292 #ifdef DEBUG_PKCS5V2 |
| 257 static void h__dump (const unsigned char *p, int len) | 293 static void h__dump (const unsigned char *p, int len) |
| 258 { | 294 { |
| 259 for (; len --; p++) fprintf(stderr, "%02X ", *p); | 295 for (; len --; p++) fprintf(stderr, "%02X ", *p); |
| 260 fprintf(stderr, "\n"); | 296 fprintf(stderr, "\n"); |
| 261 } | 297 } |
| 262 #endif | 298 #endif |
| 263 #endif | 299 #endif |
| OLD | NEW |