155714Skris/* p5_crpt2.c */
2280304Sjkim/*
3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4280304Sjkim * 1999.
555714Skris */
655714Skris/* ====================================================================
7238405Sjkim * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
855714Skris *
955714Skris * Redistribution and use in source and binary forms, with or without
1055714Skris * modification, are permitted provided that the following conditions
1155714Skris * are met:
1255714Skris *
1355714Skris * 1. Redistributions of source code must retain the above copyright
14280304Sjkim *    notice, this list of conditions and the following disclaimer.
1555714Skris *
1655714Skris * 2. Redistributions in binary form must reproduce the above copyright
1755714Skris *    notice, this list of conditions and the following disclaimer in
1855714Skris *    the documentation and/or other materials provided with the
1955714Skris *    distribution.
2055714Skris *
2155714Skris * 3. All advertising materials mentioning features or use of this
2255714Skris *    software must display the following acknowledgment:
2355714Skris *    "This product includes software developed by the OpenSSL Project
2455714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2555714Skris *
2655714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2755714Skris *    endorse or promote products derived from this software without
2855714Skris *    prior written permission. For written permission, please contact
2955714Skris *    licensing@OpenSSL.org.
3055714Skris *
3155714Skris * 5. Products derived from this software may not be called "OpenSSL"
3255714Skris *    nor may "OpenSSL" appear in their names without prior written
3355714Skris *    permission of the OpenSSL Project.
3455714Skris *
3555714Skris * 6. Redistributions of any form whatsoever must retain the following
3655714Skris *    acknowledgment:
3755714Skris *    "This product includes software developed by the OpenSSL Project
3855714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3955714Skris *
4055714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4155714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4255714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4355714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4455714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4555714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4655714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4755714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5055714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5155714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5255714Skris * ====================================================================
5355714Skris *
5455714Skris * This product includes cryptographic software written by Eric Young
5555714Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5655714Skris * Hudson (tjh@cryptsoft.com).
5755714Skris *
5855714Skris */
5955714Skris#include <stdio.h>
6055714Skris#include <stdlib.h>
61109998Smarkm#include "cryptlib.h"
62160814Ssimon#if !defined(OPENSSL_NO_HMAC) && !defined(OPENSSL_NO_SHA)
63280304Sjkim# include <openssl/x509.h>
64280304Sjkim# include <openssl/evp.h>
65280304Sjkim# include <openssl/hmac.h>
66280304Sjkim# include "evp_locl.h"
6755714Skris
6855714Skris/* set this to print out info about the keygen algorithm */
6955714Skris/* #define DEBUG_PKCS5V2 */
7055714Skris
71280304Sjkim# ifdef DEBUG_PKCS5V2
72280304Sjkimstatic void h__dump(const unsigned char *p, int len);
73280304Sjkim# endif
7455714Skris
75280304Sjkim/*
76280304Sjkim * This is an implementation of PKCS#5 v2.0 password based encryption key
77280304Sjkim * derivation function PBKDF2. SHA1 version verified against test vectors
78280304Sjkim * posted by Peter Gutmann <pgut001@cs.auckland.ac.nz> to the PKCS-TNG
79280304Sjkim * <pkcs-tng@rsa.com> mailing list.
8055714Skris */
8155714Skris
82238405Sjkimint PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
83280304Sjkim                      const unsigned char *salt, int saltlen, int iter,
84280304Sjkim                      const EVP_MD *digest, int keylen, unsigned char *out)
85280304Sjkim{
86280304Sjkim    unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
87280304Sjkim    int cplen, j, k, tkeylen, mdlen;
88280304Sjkim    unsigned long i = 1;
89280304Sjkim    HMAC_CTX hctx_tpl, hctx;
90109998Smarkm
91280304Sjkim    mdlen = EVP_MD_size(digest);
92280304Sjkim    if (mdlen < 0)
93280304Sjkim        return 0;
94238405Sjkim
95280304Sjkim    HMAC_CTX_init(&hctx_tpl);
96280304Sjkim    p = out;
97280304Sjkim    tkeylen = keylen;
98280304Sjkim    if (!pass)
99280304Sjkim        passlen = 0;
100280304Sjkim    else if (passlen == -1)
101280304Sjkim        passlen = strlen(pass);
102280304Sjkim    if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL)) {
103280304Sjkim        HMAC_CTX_cleanup(&hctx_tpl);
104280304Sjkim        return 0;
105280304Sjkim    }
106280304Sjkim    while (tkeylen) {
107280304Sjkim        if (tkeylen > mdlen)
108280304Sjkim            cplen = mdlen;
109280304Sjkim        else
110280304Sjkim            cplen = tkeylen;
111280304Sjkim        /*
112280304Sjkim         * We are unlikely to ever use more than 256 blocks (5120 bits!) but
113280304Sjkim         * just in case...
114280304Sjkim         */
115280304Sjkim        itmp[0] = (unsigned char)((i >> 24) & 0xff);
116280304Sjkim        itmp[1] = (unsigned char)((i >> 16) & 0xff);
117280304Sjkim        itmp[2] = (unsigned char)((i >> 8) & 0xff);
118280304Sjkim        itmp[3] = (unsigned char)(i & 0xff);
119280304Sjkim        if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
120280304Sjkim            HMAC_CTX_cleanup(&hctx_tpl);
121280304Sjkim            return 0;
122280304Sjkim        }
123280304Sjkim        if (!HMAC_Update(&hctx, salt, saltlen)
124280304Sjkim            || !HMAC_Update(&hctx, itmp, 4)
125280304Sjkim            || !HMAC_Final(&hctx, digtmp, NULL)) {
126280304Sjkim            HMAC_CTX_cleanup(&hctx_tpl);
127280304Sjkim            HMAC_CTX_cleanup(&hctx);
128280304Sjkim            return 0;
129280304Sjkim        }
130280304Sjkim        HMAC_CTX_cleanup(&hctx);
131280304Sjkim        memcpy(p, digtmp, cplen);
132280304Sjkim        for (j = 1; j < iter; j++) {
133280304Sjkim            if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
134280304Sjkim                HMAC_CTX_cleanup(&hctx_tpl);
135280304Sjkim                return 0;
136280304Sjkim            }
137280304Sjkim            if (!HMAC_Update(&hctx, digtmp, mdlen)
138280304Sjkim                || !HMAC_Final(&hctx, digtmp, NULL)) {
139280304Sjkim                HMAC_CTX_cleanup(&hctx_tpl);
140280304Sjkim                HMAC_CTX_cleanup(&hctx);
141280304Sjkim                return 0;
142280304Sjkim            }
143280304Sjkim            HMAC_CTX_cleanup(&hctx);
144280304Sjkim            for (k = 0; k < cplen; k++)
145280304Sjkim                p[k] ^= digtmp[k];
146280304Sjkim        }
147280304Sjkim        tkeylen -= cplen;
148280304Sjkim        i++;
149280304Sjkim        p += cplen;
150280304Sjkim    }
151280304Sjkim    HMAC_CTX_cleanup(&hctx_tpl);
152280304Sjkim# ifdef DEBUG_PKCS5V2
153280304Sjkim    fprintf(stderr, "Password:\n");
154280304Sjkim    h__dump(pass, passlen);
155280304Sjkim    fprintf(stderr, "Salt:\n");
156280304Sjkim    h__dump(salt, saltlen);
157280304Sjkim    fprintf(stderr, "Iteration count %d\n", iter);
158280304Sjkim    fprintf(stderr, "Key:\n");
159280304Sjkim    h__dump(out, keylen);
160280304Sjkim# endif
161280304Sjkim    return 1;
162280304Sjkim}
16355714Skris
164238405Sjkimint PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
165280304Sjkim                           const unsigned char *salt, int saltlen, int iter,
166280304Sjkim                           int keylen, unsigned char *out)
167280304Sjkim{
168280304Sjkim    return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, EVP_sha1(),
169280304Sjkim                             keylen, out);
170280304Sjkim}
171238405Sjkim
172280304Sjkim# ifdef DO_TEST
17355714Skrismain()
17455714Skris{
175280304Sjkim    unsigned char out[4];
176280304Sjkim    unsigned char salt[] = { 0x12, 0x34, 0x56, 0x78 };
177280304Sjkim    PKCS5_PBKDF2_HMAC_SHA1("password", -1, salt, 4, 5, 4, out);
178280304Sjkim    fprintf(stderr, "Out %02X %02X %02X %02X\n",
179280304Sjkim            out[0], out[1], out[2], out[3]);
18055714Skris}
18155714Skris
182280304Sjkim# endif
18355714Skris
184280304Sjkim/*
185280304Sjkim * Now the key derivation function itself. This is a bit evil because it has
186280304Sjkim * to check the ASN1 parameters are valid: and there are quite a few of
187280304Sjkim * them...
18855714Skris */
18955714Skris
19055714Skrisint PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
191280304Sjkim                          ASN1_TYPE *param, const EVP_CIPHER *c,
192280304Sjkim                          const EVP_MD *md, int en_de)
19355714Skris{
194280304Sjkim    const unsigned char *pbuf;
195280304Sjkim    int plen;
196280304Sjkim    PBE2PARAM *pbe2 = NULL;
197280304Sjkim    const EVP_CIPHER *cipher;
19855714Skris
199280304Sjkim    int rv = 0;
200238405Sjkim
201280304Sjkim    if (param == NULL || param->type != V_ASN1_SEQUENCE ||
202280304Sjkim        param->value.sequence == NULL) {
203280304Sjkim        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_DECODE_ERROR);
204280304Sjkim        goto err;
205280304Sjkim    }
206160814Ssimon
207280304Sjkim    pbuf = param->value.sequence->data;
208280304Sjkim    plen = param->value.sequence->length;
209280304Sjkim    if (!(pbe2 = d2i_PBE2PARAM(NULL, &pbuf, plen))) {
210280304Sjkim        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_DECODE_ERROR);
211280304Sjkim        goto err;
212280304Sjkim    }
21355714Skris
214280304Sjkim    /* See if we recognise the key derivation function */
21555714Skris
216280304Sjkim    if (OBJ_obj2nid(pbe2->keyfunc->algorithm) != NID_id_pbkdf2) {
217280304Sjkim        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,
218280304Sjkim               EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
219280304Sjkim        goto err;
220280304Sjkim    }
22155714Skris
222280304Sjkim    /*
223280304Sjkim     * lets see if we recognise the encryption algorithm.
224280304Sjkim     */
22555714Skris
226280304Sjkim    cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm);
22755714Skris
228280304Sjkim    if (!cipher) {
229280304Sjkim        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_UNSUPPORTED_CIPHER);
230280304Sjkim        goto err;
231280304Sjkim    }
23255714Skris
233280304Sjkim    /* Fixup cipher based on AlgorithmIdentifier */
234280304Sjkim    if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de))
235280304Sjkim        goto err;
236280304Sjkim    if (EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) {
237280304Sjkim        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_CIPHER_PARAMETER_ERROR);
238280304Sjkim        goto err;
239280304Sjkim    }
240280304Sjkim    rv = PKCS5_v2_PBKDF2_keyivgen(ctx, pass, passlen,
241280304Sjkim                                  pbe2->keyfunc->parameter, c, md, en_de);
242280304Sjkim err:
243280304Sjkim    PBE2PARAM_free(pbe2);
244280304Sjkim    return rv;
245238405Sjkim}
246238405Sjkim
247280304Sjkimint PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
248280304Sjkim                             int passlen, ASN1_TYPE *param,
249280304Sjkim                             const EVP_CIPHER *c, const EVP_MD *md, int en_de)
250238405Sjkim{
251280304Sjkim    unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
252280304Sjkim    const unsigned char *pbuf;
253280304Sjkim    int saltlen, iter, plen;
254280304Sjkim    int rv = 0;
255280304Sjkim    unsigned int keylen = 0;
256280304Sjkim    int prf_nid, hmac_md_nid;
257280304Sjkim    PBKDF2PARAM *kdf = NULL;
258280304Sjkim    const EVP_MD *prfmd;
259238405Sjkim
260280304Sjkim    if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
261280304Sjkim        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_NO_CIPHER_SET);
262280304Sjkim        goto err;
263280304Sjkim    }
264280304Sjkim    keylen = EVP_CIPHER_CTX_key_length(ctx);
265280304Sjkim    OPENSSL_assert(keylen <= sizeof key);
26655714Skris
267280304Sjkim    /* Decode parameter */
26855714Skris
269280304Sjkim    if (!param || (param->type != V_ASN1_SEQUENCE)) {
270280304Sjkim        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_DECODE_ERROR);
271280304Sjkim        goto err;
272280304Sjkim    }
273160814Ssimon
274280304Sjkim    pbuf = param->value.sequence->data;
275280304Sjkim    plen = param->value.sequence->length;
276238405Sjkim
277280304Sjkim    if (!(kdf = d2i_PBKDF2PARAM(NULL, &pbuf, plen))) {
278280304Sjkim        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_DECODE_ERROR);
279280304Sjkim        goto err;
280280304Sjkim    }
28155714Skris
282280304Sjkim    keylen = EVP_CIPHER_CTX_key_length(ctx);
28355714Skris
284280304Sjkim    /* Now check the parameters of the kdf */
28555714Skris
286280304Sjkim    if (kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)) {
287280304Sjkim        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_KEYLENGTH);
288280304Sjkim        goto err;
289280304Sjkim    }
29055714Skris
291280304Sjkim    if (kdf->prf)
292280304Sjkim        prf_nid = OBJ_obj2nid(kdf->prf->algorithm);
293280304Sjkim    else
294280304Sjkim        prf_nid = NID_hmacWithSHA1;
295238405Sjkim
296280304Sjkim    if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0)) {
297280304Sjkim        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF);
298280304Sjkim        goto err;
299280304Sjkim    }
30055714Skris
301280304Sjkim    prfmd = EVP_get_digestbynid(hmac_md_nid);
302280304Sjkim    if (prfmd == NULL) {
303280304Sjkim        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF);
304280304Sjkim        goto err;
305280304Sjkim    }
306238405Sjkim
307280304Sjkim    if (kdf->salt->type != V_ASN1_OCTET_STRING) {
308280304Sjkim        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_SALT_TYPE);
309280304Sjkim        goto err;
310280304Sjkim    }
31155714Skris
312280304Sjkim    /* it seems that its all OK */
313280304Sjkim    salt = kdf->salt->value.octet_string->data;
314280304Sjkim    saltlen = kdf->salt->value.octet_string->length;
315280304Sjkim    iter = ASN1_INTEGER_get(kdf->iter);
316280304Sjkim    if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd,
317280304Sjkim                           keylen, key))
318280304Sjkim        goto err;
319280304Sjkim    rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
320280304Sjkim err:
321280304Sjkim    OPENSSL_cleanse(key, keylen);
322280304Sjkim    PBKDF2PARAM_free(kdf);
323280304Sjkim    return rv;
32455714Skris}
32555714Skris
326280304Sjkim# ifdef DEBUG_PKCS5V2
327280304Sjkimstatic void h__dump(const unsigned char *p, int len)
32855714Skris{
329280304Sjkim    for (; len--; p++)
330280304Sjkim        fprintf(stderr, "%02X ", *p);
331280304Sjkim    fprintf(stderr, "\n");
33255714Skris}
333280304Sjkim# endif
33455714Skris#endif
335