p5_crpt2.c 7.8 KB
Newer Older
1
/*
R
Rich Salz 已提交
2
 * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
8
 */
R
Rich Salz 已提交
9

10 11
#include <stdio.h>
#include <stdlib.h>
12
#include "internal/cryptlib.h"
13 14 15
# include <openssl/x509.h>
# include <openssl/evp.h>
# include <openssl/hmac.h>
16
# include "evp_local.h"
17

18
/* set this to print out info about the keygen algorithm */
R
Rich Salz 已提交
19
/* #define OPENSSL_DEBUG_PKCS5V2 */
20

R
Rich Salz 已提交
21
# ifdef OPENSSL_DEBUG_PKCS5V2
22 23
static void h__dump(const unsigned char *p, int len);
# endif
24

25 26 27
/*
 * This is an implementation of PKCS#5 v2.0 password based encryption key
 * derivation function PBKDF2. SHA1 version verified against test vectors
28
 * posted by Peter Gutmann to the PKCS-TNG mailing list.
29 30
 */

31
int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
32 33 34
                      const unsigned char *salt, int saltlen, int iter,
                      const EVP_MD *digest, int keylen, unsigned char *out)
{
35
    const char *empty = "";
36 37 38
    unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
    int cplen, j, k, tkeylen, mdlen;
    unsigned long i = 1;
39
    HMAC_CTX *hctx_tpl = NULL, *hctx = NULL;
40 41 42 43 44

    mdlen = EVP_MD_size(digest);
    if (mdlen < 0)
        return 0;

45 46 47
    hctx_tpl = HMAC_CTX_new();
    if (hctx_tpl == NULL)
        return 0;
48 49
    p = out;
    tkeylen = keylen;
50 51
    if (pass == NULL) {
        pass = empty;
52
        passlen = 0;
53
    } else if (passlen == -1) {
54
        passlen = strlen(pass);
55
    }
56 57 58 59 60 61 62
    if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL)) {
        HMAC_CTX_free(hctx_tpl);
        return 0;
    }
    hctx = HMAC_CTX_new();
    if (hctx == NULL) {
        HMAC_CTX_free(hctx_tpl);
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
        return 0;
    }
    while (tkeylen) {
        if (tkeylen > mdlen)
            cplen = mdlen;
        else
            cplen = tkeylen;
        /*
         * We are unlikely to ever use more than 256 blocks (5120 bits!) but
         * just in case...
         */
        itmp[0] = (unsigned char)((i >> 24) & 0xff);
        itmp[1] = (unsigned char)((i >> 16) & 0xff);
        itmp[2] = (unsigned char)((i >> 8) & 0xff);
        itmp[3] = (unsigned char)(i & 0xff);
78 79 80
        if (!HMAC_CTX_copy(hctx, hctx_tpl)) {
            HMAC_CTX_free(hctx);
            HMAC_CTX_free(hctx_tpl);
81 82
            return 0;
        }
83 84 85 86 87
        if (!HMAC_Update(hctx, salt, saltlen)
            || !HMAC_Update(hctx, itmp, 4)
            || !HMAC_Final(hctx, digtmp, NULL)) {
            HMAC_CTX_free(hctx);
            HMAC_CTX_free(hctx_tpl);
88 89 90 91
            return 0;
        }
        memcpy(p, digtmp, cplen);
        for (j = 1; j < iter; j++) {
92 93 94
            if (!HMAC_CTX_copy(hctx, hctx_tpl)) {
                HMAC_CTX_free(hctx);
                HMAC_CTX_free(hctx_tpl);
95 96
                return 0;
            }
97 98 99 100
            if (!HMAC_Update(hctx, digtmp, mdlen)
                || !HMAC_Final(hctx, digtmp, NULL)) {
                HMAC_CTX_free(hctx);
                HMAC_CTX_free(hctx_tpl);
101 102 103 104 105 106 107 108 109
                return 0;
            }
            for (k = 0; k < cplen; k++)
                p[k] ^= digtmp[k];
        }
        tkeylen -= cplen;
        i++;
        p += cplen;
    }
110 111
    HMAC_CTX_free(hctx);
    HMAC_CTX_free(hctx_tpl);
R
Rich Salz 已提交
112
# ifdef OPENSSL_DEBUG_PKCS5V2
113 114 115 116 117 118 119 120 121 122
    fprintf(stderr, "Password:\n");
    h__dump(pass, passlen);
    fprintf(stderr, "Salt:\n");
    h__dump(salt, saltlen);
    fprintf(stderr, "Iteration count %d\n", iter);
    fprintf(stderr, "Key:\n");
    h__dump(out, keylen);
# endif
    return 1;
}
123 124

int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
125 126 127 128 129 130 131 132 133 134 135
                           const unsigned char *salt, int saltlen, int iter,
                           int keylen, unsigned char *out)
{
    return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, EVP_sha1(),
                             keylen, out);
}

/*
 * Now the key derivation function itself. This is a bit evil because it has
 * to check the ASN1 parameters are valid: and there are quite a few of
 * them...
136 137 138
 */

int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
139 140
                          ASN1_TYPE *param, const EVP_CIPHER *c,
                          const EVP_MD *md, int en_de)
141
{
142 143
    PBE2PARAM *pbe2 = NULL;
    const EVP_CIPHER *cipher;
144
    EVP_PBE_KEYGEN *kdf;
145 146 147

    int rv = 0;

D
Dr. Stephen Henson 已提交
148 149
    pbe2 = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBE2PARAM), param);
    if (pbe2 == NULL) {
150 151 152 153 154
        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_DECODE_ERROR);
        goto err;
    }

    /* See if we recognise the key derivation function */
155
    if (!EVP_PBE_find(EVP_PBE_TYPE_KDF, OBJ_obj2nid(pbe2->keyfunc->algorithm),
F
FdaSilvaYY 已提交
156
                        NULL, NULL, &kdf)) {
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,
               EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
        goto err;
    }

    /*
     * lets see if we recognise the encryption algorithm.
     */

    cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm);

    if (!cipher) {
        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_UNSUPPORTED_CIPHER);
        goto err;
    }

    /* Fixup cipher based on AlgorithmIdentifier */
    if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de))
        goto err;
    if (EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) {
        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_CIPHER_PARAMETER_ERROR);
        goto err;
    }
180
    rv = kdf(ctx, pass, passlen, pbe2->keyfunc->parameter, NULL, NULL, en_de);
181 182 183
 err:
    PBE2PARAM_free(pbe2);
    return rv;
184 185
}

186 187 188
int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
                             int passlen, ASN1_TYPE *param,
                             const EVP_CIPHER *c, const EVP_MD *md, int en_de)
189
{
190
    unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
D
Dr. Stephen Henson 已提交
191
    int saltlen, iter;
192 193 194 195 196 197 198 199 200 201 202
    int rv = 0;
    unsigned int keylen = 0;
    int prf_nid, hmac_md_nid;
    PBKDF2PARAM *kdf = NULL;
    const EVP_MD *prfmd;

    if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_NO_CIPHER_SET);
        goto err;
    }
    keylen = EVP_CIPHER_CTX_key_length(ctx);
R
Rich Salz 已提交
203
    OPENSSL_assert(keylen <= sizeof(key));
204 205 206

    /* Decode parameter */

D
Dr. Stephen Henson 已提交
207
    kdf = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), param);
208

D
Dr. Stephen Henson 已提交
209
    if (kdf == NULL) {
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_DECODE_ERROR);
        goto err;
    }

    keylen = EVP_CIPHER_CTX_key_length(ctx);

    /* Now check the parameters of the kdf */

    if (kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)) {
        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_KEYLENGTH);
        goto err;
    }

    if (kdf->prf)
        prf_nid = OBJ_obj2nid(kdf->prf->algorithm);
    else
        prf_nid = NID_hmacWithSHA1;

    if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0)) {
        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF);
        goto err;
    }

    prfmd = EVP_get_digestbynid(hmac_md_nid);
    if (prfmd == NULL) {
        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF);
        goto err;
    }

    if (kdf->salt->type != V_ASN1_OCTET_STRING) {
        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_SALT_TYPE);
        goto err;
    }

    /* it seems that its all OK */
    salt = kdf->salt->value.octet_string->data;
    saltlen = kdf->salt->value.octet_string->length;
    iter = ASN1_INTEGER_get(kdf->iter);
    if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd,
                           keylen, key))
        goto err;
    rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
 err:
    OPENSSL_cleanse(key, keylen);
    PBKDF2PARAM_free(kdf);
    return rv;
256
}
257

R
Rich Salz 已提交
258
# ifdef OPENSSL_DEBUG_PKCS5V2
259
static void h__dump(const unsigned char *p, int len)
260
{
261 262 263
    for (; len--; p++)
        fprintf(stderr, "%02X ", *p);
    fprintf(stderr, "\n");
264
}
265
# endif