155714Skris/* p5_crpt2.c */
2194206Ssimon/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
355714Skris * project 1999.
455714Skris */
555714Skris/* ====================================================================
6238405Sjkim * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
755714Skris *
855714Skris * Redistribution and use in source and binary forms, with or without
955714Skris * modification, are permitted provided that the following conditions
1055714Skris * are met:
1155714Skris *
1255714Skris * 1. Redistributions of source code must retain the above copyright
1355714Skris *    notice, this list of conditions and the following disclaimer.
1455714Skris *
1555714Skris * 2. Redistributions in binary form must reproduce the above copyright
1655714Skris *    notice, this list of conditions and the following disclaimer in
1755714Skris *    the documentation and/or other materials provided with the
1855714Skris *    distribution.
1955714Skris *
2055714Skris * 3. All advertising materials mentioning features or use of this
2155714Skris *    software must display the following acknowledgment:
2255714Skris *    "This product includes software developed by the OpenSSL Project
2355714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2455714Skris *
2555714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2655714Skris *    endorse or promote products derived from this software without
2755714Skris *    prior written permission. For written permission, please contact
2855714Skris *    licensing@OpenSSL.org.
2955714Skris *
3055714Skris * 5. Products derived from this software may not be called "OpenSSL"
3155714Skris *    nor may "OpenSSL" appear in their names without prior written
3255714Skris *    permission of the OpenSSL Project.
3355714Skris *
3455714Skris * 6. Redistributions of any form whatsoever must retain the following
3555714Skris *    acknowledgment:
3655714Skris *    "This product includes software developed by the OpenSSL Project
3755714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3855714Skris *
3955714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4055714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4155714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4255714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4355714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4455714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4555714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4655714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4755714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4855714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4955714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5055714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5155714Skris * ====================================================================
5255714Skris *
5355714Skris * This product includes cryptographic software written by Eric Young
5455714Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5555714Skris * Hudson (tjh@cryptsoft.com).
5655714Skris *
5755714Skris */
5855714Skris#include <stdio.h>
5955714Skris#include <stdlib.h>
60109998Smarkm#include "cryptlib.h"
61160814Ssimon#if !defined(OPENSSL_NO_HMAC) && !defined(OPENSSL_NO_SHA)
6255714Skris#include <openssl/x509.h>
6355714Skris#include <openssl/evp.h>
6455714Skris#include <openssl/hmac.h>
65238405Sjkim#include "evp_locl.h"
6655714Skris
6755714Skris/* set this to print out info about the keygen algorithm */
6855714Skris/* #define DEBUG_PKCS5V2 */
6955714Skris
7055714Skris#ifdef DEBUG_PKCS5V2
7155714Skris	static void h__dump (const unsigned char *p, int len);
7255714Skris#endif
7355714Skris
7455714Skris/* This is an implementation of PKCS#5 v2.0 password based encryption key
75238405Sjkim * derivation function PBKDF2.
76238405Sjkim * SHA1 version verified against test vectors posted by Peter Gutmann
7755714Skris * <pgut001@cs.auckland.ac.nz> to the PKCS-TNG <pkcs-tng@rsa.com> mailing list.
7855714Skris */
7955714Skris
80238405Sjkimint PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
81160814Ssimon			   const unsigned char *salt, int saltlen, int iter,
82238405Sjkim			   const EVP_MD *digest,
8355714Skris			   int keylen, unsigned char *out)
84238405Sjkim	{
85238405Sjkim	unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
86238405Sjkim	int cplen, j, k, tkeylen, mdlen;
8755714Skris	unsigned long i = 1;
88279264Sdelphij	HMAC_CTX hctx_tpl, hctx;
89109998Smarkm
90238405Sjkim	mdlen = EVP_MD_size(digest);
91238405Sjkim	if (mdlen < 0)
92238405Sjkim		return 0;
93238405Sjkim
94279264Sdelphij	HMAC_CTX_init(&hctx_tpl);
9555714Skris	p = out;
9655714Skris	tkeylen = keylen;
97238405Sjkim	if(!pass)
98238405Sjkim		passlen = 0;
99238405Sjkim	else if(passlen == -1)
100238405Sjkim		passlen = strlen(pass);
101279264Sdelphij	if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL))
102279264Sdelphij		{
103279264Sdelphij		HMAC_CTX_cleanup(&hctx_tpl);
104279264Sdelphij		return 0;
105279264Sdelphij		}
106238405Sjkim	while(tkeylen)
107238405Sjkim		{
108238405Sjkim		if(tkeylen > mdlen)
109238405Sjkim			cplen = mdlen;
110238405Sjkim		else
111238405Sjkim			cplen = tkeylen;
11255714Skris		/* We are unlikely to ever use more than 256 blocks (5120 bits!)
11355714Skris		 * but just in case...
11455714Skris		 */
11555714Skris		itmp[0] = (unsigned char)((i >> 24) & 0xff);
11655714Skris		itmp[1] = (unsigned char)((i >> 16) & 0xff);
11755714Skris		itmp[2] = (unsigned char)((i >> 8) & 0xff);
11855714Skris		itmp[3] = (unsigned char)(i & 0xff);
119279264Sdelphij		if (!HMAC_CTX_copy(&hctx, &hctx_tpl))
120238405Sjkim			{
121279264Sdelphij			HMAC_CTX_cleanup(&hctx_tpl);
122279264Sdelphij			return 0;
123279264Sdelphij			}
124279264Sdelphij		if (!HMAC_Update(&hctx, salt, saltlen)
125279264Sdelphij		    || !HMAC_Update(&hctx, itmp, 4)
126279264Sdelphij		    || !HMAC_Final(&hctx, digtmp, NULL))
127279264Sdelphij			{
128279264Sdelphij			HMAC_CTX_cleanup(&hctx_tpl);
129238405Sjkim			HMAC_CTX_cleanup(&hctx);
130238405Sjkim			return 0;
131238405Sjkim			}
132279264Sdelphij		HMAC_CTX_cleanup(&hctx);
13355714Skris		memcpy(p, digtmp, cplen);
134238405Sjkim		for(j = 1; j < iter; j++)
135238405Sjkim			{
136279264Sdelphij			if (!HMAC_CTX_copy(&hctx, &hctx_tpl))
137279264Sdelphij				{
138279264Sdelphij				HMAC_CTX_cleanup(&hctx_tpl);
139279264Sdelphij				return 0;
140279264Sdelphij				}
141279264Sdelphij			if (!HMAC_Update(&hctx, digtmp, mdlen)
142279264Sdelphij			    || !HMAC_Final(&hctx, digtmp, NULL))
143279264Sdelphij				{
144279264Sdelphij				HMAC_CTX_cleanup(&hctx_tpl);
145279264Sdelphij				HMAC_CTX_cleanup(&hctx);
146279264Sdelphij				return 0;
147279264Sdelphij				}
148279264Sdelphij			HMAC_CTX_cleanup(&hctx);
149238405Sjkim			for(k = 0; k < cplen; k++)
150238405Sjkim				p[k] ^= digtmp[k];
151238405Sjkim			}
15255714Skris		tkeylen-= cplen;
15355714Skris		i++;
15455714Skris		p+= cplen;
155238405Sjkim		}
156279264Sdelphij	HMAC_CTX_cleanup(&hctx_tpl);
15755714Skris#ifdef DEBUG_PKCS5V2
15855714Skris	fprintf(stderr, "Password:\n");
15955714Skris	h__dump (pass, passlen);
16055714Skris	fprintf(stderr, "Salt:\n");
16155714Skris	h__dump (salt, saltlen);
16255714Skris	fprintf(stderr, "Iteration count %d\n", iter);
16355714Skris	fprintf(stderr, "Key:\n");
16455714Skris	h__dump (out, keylen);
16555714Skris#endif
16655714Skris	return 1;
167238405Sjkim	}
16855714Skris
169238405Sjkimint PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
170238405Sjkim			   const unsigned char *salt, int saltlen, int iter,
171238405Sjkim			   int keylen, unsigned char *out)
172238405Sjkim	{
173238405Sjkim	return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, EVP_sha1(),
174238405Sjkim					keylen, out);
175238405Sjkim	}
176238405Sjkim
17755714Skris#ifdef DO_TEST
17855714Skrismain()
17955714Skris{
18055714Skris	unsigned char out[4];
18155714Skris	unsigned char salt[] = {0x12, 0x34, 0x56, 0x78};
18255714Skris	PKCS5_PBKDF2_HMAC_SHA1("password", -1, salt, 4, 5, 4, out);
18355714Skris	fprintf(stderr, "Out %02X %02X %02X %02X\n",
18455714Skris					 out[0], out[1], out[2], out[3]);
18555714Skris}
18655714Skris
18755714Skris#endif
18855714Skris
18955714Skris/* Now the key derivation function itself. This is a bit evil because
19055714Skris * it has to check the ASN1 parameters are valid: and there are quite a
19155714Skris * few of them...
19255714Skris */
19355714Skris
19455714Skrisint PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
195109998Smarkm                         ASN1_TYPE *param, const EVP_CIPHER *c, const EVP_MD *md,
19655714Skris                         int en_de)
19755714Skris{
198160814Ssimon	const unsigned char *pbuf;
199238405Sjkim	int plen;
20055714Skris	PBE2PARAM *pbe2 = NULL;
20155714Skris	const EVP_CIPHER *cipher;
20255714Skris
203238405Sjkim	int rv = 0;
204238405Sjkim
205160814Ssimon	if (param == NULL || param->type != V_ASN1_SEQUENCE ||
206160814Ssimon	    param->value.sequence == NULL) {
207160814Ssimon		EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,EVP_R_DECODE_ERROR);
208238405Sjkim		goto err;
209160814Ssimon	}
210160814Ssimon
21155714Skris	pbuf = param->value.sequence->data;
21255714Skris	plen = param->value.sequence->length;
213160814Ssimon	if(!(pbe2 = d2i_PBE2PARAM(NULL, &pbuf, plen))) {
21455714Skris		EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,EVP_R_DECODE_ERROR);
215238405Sjkim		goto err;
21655714Skris	}
21755714Skris
21855714Skris	/* See if we recognise the key derivation function */
21955714Skris
22055714Skris	if(OBJ_obj2nid(pbe2->keyfunc->algorithm) != NID_id_pbkdf2) {
22155714Skris		EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,
22255714Skris				EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
22355714Skris		goto err;
22455714Skris	}
22555714Skris
22655714Skris	/* lets see if we recognise the encryption algorithm.
22755714Skris	 */
22855714Skris
229238405Sjkim	cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm);
23055714Skris
23155714Skris	if(!cipher) {
23255714Skris		EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,
23355714Skris						EVP_R_UNSUPPORTED_CIPHER);
23455714Skris		goto err;
23555714Skris	}
23655714Skris
23755714Skris	/* Fixup cipher based on AlgorithmIdentifier */
238238405Sjkim	if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de))
239238405Sjkim		goto err;
24055714Skris	if(EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) {
24155714Skris		EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,
24255714Skris					EVP_R_CIPHER_PARAMETER_ERROR);
24355714Skris		goto err;
24455714Skris	}
245238405Sjkim	rv = PKCS5_v2_PBKDF2_keyivgen(ctx, pass, passlen,
246238405Sjkim					pbe2->keyfunc->parameter, c, md, en_de);
247238405Sjkim	err:
248238405Sjkim	PBE2PARAM_free(pbe2);
249238405Sjkim	return rv;
250238405Sjkim}
251238405Sjkim
252238405Sjkimint PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
253238405Sjkim                         ASN1_TYPE *param,
254238405Sjkim			 const EVP_CIPHER *c, const EVP_MD *md, int en_de)
255238405Sjkim{
256238405Sjkim	unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
257238405Sjkim	const unsigned char *pbuf;
258238405Sjkim	int saltlen, iter, plen;
259238405Sjkim	int rv = 0;
260238405Sjkim	unsigned int keylen = 0;
261238405Sjkim	int prf_nid, hmac_md_nid;
262238405Sjkim	PBKDF2PARAM *kdf = NULL;
263238405Sjkim	const EVP_MD *prfmd;
264238405Sjkim
265238405Sjkim	if (EVP_CIPHER_CTX_cipher(ctx) == NULL)
266238405Sjkim		{
267238405Sjkim		EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,EVP_R_NO_CIPHER_SET);
268238405Sjkim		goto err;
269238405Sjkim		}
27055714Skris	keylen = EVP_CIPHER_CTX_key_length(ctx);
271109998Smarkm	OPENSSL_assert(keylen <= sizeof key);
27255714Skris
273238405Sjkim	/* Decode parameter */
27455714Skris
275238405Sjkim	if(!param || (param->type != V_ASN1_SEQUENCE))
276160814Ssimon		{
277238405Sjkim		EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,EVP_R_DECODE_ERROR);
278160814Ssimon		goto err;
279160814Ssimon		}
280160814Ssimon
281238405Sjkim	pbuf = param->value.sequence->data;
282238405Sjkim	plen = param->value.sequence->length;
283238405Sjkim
284160814Ssimon	if(!(kdf = d2i_PBKDF2PARAM(NULL, &pbuf, plen)) ) {
285238405Sjkim		EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,EVP_R_DECODE_ERROR);
28655714Skris		goto err;
28755714Skris	}
28855714Skris
289238405Sjkim	keylen = EVP_CIPHER_CTX_key_length(ctx);
29055714Skris
29155714Skris	/* Now check the parameters of the kdf */
29255714Skris
293160814Ssimon	if(kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)){
294238405Sjkim		EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,
29555714Skris						EVP_R_UNSUPPORTED_KEYLENGTH);
29655714Skris		goto err;
29755714Skris	}
29855714Skris
299238405Sjkim	if (kdf->prf)
300238405Sjkim		prf_nid = OBJ_obj2nid(kdf->prf->algorithm);
301238405Sjkim	else
302238405Sjkim		prf_nid = NID_hmacWithSHA1;
303238405Sjkim
304238405Sjkim	if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0))
305238405Sjkim		{
306238405Sjkim		EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF);
30755714Skris		goto err;
308238405Sjkim		}
30955714Skris
310238405Sjkim	prfmd = EVP_get_digestbynid(hmac_md_nid);
311238405Sjkim	if (prfmd == NULL)
312238405Sjkim		{
313238405Sjkim		EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF);
314238405Sjkim		goto err;
315238405Sjkim		}
316238405Sjkim
31755714Skris	if(kdf->salt->type != V_ASN1_OCTET_STRING) {
318238405Sjkim		EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN,
31955714Skris						EVP_R_UNSUPPORTED_SALT_TYPE);
32055714Skris		goto err;
32155714Skris	}
32255714Skris
32355714Skris	/* it seems that its all OK */
32455714Skris	salt = kdf->salt->value.octet_string->data;
32555714Skris	saltlen = kdf->salt->value.octet_string->length;
32655714Skris	iter = ASN1_INTEGER_get(kdf->iter);
327238405Sjkim	if(!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd,
328238405Sjkim						   keylen, key))
329238405Sjkim		goto err;
330238405Sjkim	rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
331238405Sjkim	err:
332109998Smarkm	OPENSSL_cleanse(key, keylen);
33355714Skris	PBKDF2PARAM_free(kdf);
334238405Sjkim	return rv;
33555714Skris}
33655714Skris
33755714Skris#ifdef DEBUG_PKCS5V2
33855714Skrisstatic void h__dump (const unsigned char *p, int len)
33955714Skris{
34055714Skris        for (; len --; p++) fprintf(stderr, "%02X ", *p);
34155714Skris        fprintf(stderr, "\n");
34255714Skris}
34355714Skris#endif
34455714Skris#endif
345