Coverage Report

Created: 2018-08-29 13:53

/src/openssl/crypto/evp/p5_crpt2.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the OpenSSL license (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include "internal/cryptlib.h"
13
# include <openssl/x509.h>
14
# include <openssl/evp.h>
15
# include <openssl/hmac.h>
16
# include "evp_locl.h"
17
18
/* set this to print out info about the keygen algorithm */
19
/* #define OPENSSL_DEBUG_PKCS5V2 */
20
21
# ifdef OPENSSL_DEBUG_PKCS5V2
22
static void h__dump(const unsigned char *p, int len);
23
# endif
24
25
/*
26
 * This is an implementation of PKCS#5 v2.0 password based encryption key
27
 * 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
                      const unsigned char *salt, int saltlen, int iter,
33
                      const EVP_MD *digest, int keylen, unsigned char *out)
34
0
{
35
0
    const char *empty = "";
36
0
    unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
37
0
    int cplen, j, k, tkeylen, mdlen;
38
0
    unsigned long i = 1;
39
0
    HMAC_CTX *hctx_tpl = NULL, *hctx = NULL;
40
0
41
0
    mdlen = EVP_MD_size(digest);
42
0
    if (mdlen < 0)
43
0
        return 0;
44
0
45
0
    hctx_tpl = HMAC_CTX_new();
46
0
    if (hctx_tpl == NULL)
47
0
        return 0;
48
0
    p = out;
49
0
    tkeylen = keylen;
50
0
    if (pass == NULL) {
51
0
        pass = empty;
52
0
        passlen = 0;
53
0
    } else if (passlen == -1) {
54
0
        passlen = strlen(pass);
55
0
    }
56
0
    if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL)) {
57
0
        HMAC_CTX_free(hctx_tpl);
58
0
        return 0;
59
0
    }
60
0
    hctx = HMAC_CTX_new();
61
0
    if (hctx == NULL) {
62
0
        HMAC_CTX_free(hctx_tpl);
63
0
        return 0;
64
0
    }
65
0
    while (tkeylen) {
66
0
        if (tkeylen > mdlen)
67
0
            cplen = mdlen;
68
0
        else
69
0
            cplen = tkeylen;
70
0
        /*
71
0
         * We are unlikely to ever use more than 256 blocks (5120 bits!) but
72
0
         * just in case...
73
0
         */
74
0
        itmp[0] = (unsigned char)((i >> 24) & 0xff);
75
0
        itmp[1] = (unsigned char)((i >> 16) & 0xff);
76
0
        itmp[2] = (unsigned char)((i >> 8) & 0xff);
77
0
        itmp[3] = (unsigned char)(i & 0xff);
78
0
        if (!HMAC_CTX_copy(hctx, hctx_tpl)) {
79
0
            HMAC_CTX_free(hctx);
80
0
            HMAC_CTX_free(hctx_tpl);
81
0
            return 0;
82
0
        }
83
0
        if (!HMAC_Update(hctx, salt, saltlen)
84
0
            || !HMAC_Update(hctx, itmp, 4)
85
0
            || !HMAC_Final(hctx, digtmp, NULL)) {
86
0
            HMAC_CTX_free(hctx);
87
0
            HMAC_CTX_free(hctx_tpl);
88
0
            return 0;
89
0
        }
90
0
        memcpy(p, digtmp, cplen);
91
0
        for (j = 1; j < iter; j++) {
92
0
            if (!HMAC_CTX_copy(hctx, hctx_tpl)) {
93
0
                HMAC_CTX_free(hctx);
94
0
                HMAC_CTX_free(hctx_tpl);
95
0
                return 0;
96
0
            }
97
0
            if (!HMAC_Update(hctx, digtmp, mdlen)
98
0
                || !HMAC_Final(hctx, digtmp, NULL)) {
99
0
                HMAC_CTX_free(hctx);
100
0
                HMAC_CTX_free(hctx_tpl);
101
0
                return 0;
102
0
            }
103
0
            for (k = 0; k < cplen; k++)
104
0
                p[k] ^= digtmp[k];
105
0
        }
106
0
        tkeylen -= cplen;
107
0
        i++;
108
0
        p += cplen;
109
0
    }
110
0
    HMAC_CTX_free(hctx);
111
0
    HMAC_CTX_free(hctx_tpl);
112
# ifdef OPENSSL_DEBUG_PKCS5V2
113
    fprintf(stderr, "Password:\n");
114
    h__dump(pass, passlen);
115
    fprintf(stderr, "Salt:\n");
116
    h__dump(salt, saltlen);
117
    fprintf(stderr, "Iteration count %d\n", iter);
118
    fprintf(stderr, "Key:\n");
119
    h__dump(out, keylen);
120
# endif
121
    return 1;
122
0
}
123
124
int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
125
                           const unsigned char *salt, int saltlen, int iter,
126
                           int keylen, unsigned char *out)
127
0
{
128
0
    return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, EVP_sha1(),
129
0
                             keylen, out);
130
0
}
131
132
/*
133
 * Now the key derivation function itself. This is a bit evil because it has
134
 * to check the ASN1 parameters are valid: and there are quite a few of
135
 * them...
136
 */
137
138
int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
139
                          ASN1_TYPE *param, const EVP_CIPHER *c,
140
                          const EVP_MD *md, int en_de)
141
0
{
142
0
    PBE2PARAM *pbe2 = NULL;
143
0
    const EVP_CIPHER *cipher;
144
0
    EVP_PBE_KEYGEN *kdf;
145
0
146
0
    int rv = 0;
147
0
148
0
    pbe2 = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBE2PARAM), param);
149
0
    if (pbe2 == NULL) {
150
0
        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_DECODE_ERROR);
151
0
        goto err;
152
0
    }
153
0
154
0
    /* See if we recognise the key derivation function */
155
0
    if (!EVP_PBE_find(EVP_PBE_TYPE_KDF, OBJ_obj2nid(pbe2->keyfunc->algorithm),
156
0
                        NULL, NULL, &kdf)) {
157
0
        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN,
158
0
               EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
159
0
        goto err;
160
0
    }
161
0
162
0
    /*
163
0
     * lets see if we recognise the encryption algorithm.
164
0
     */
165
0
166
0
    cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm);
167
0
168
0
    if (!cipher) {
169
0
        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_UNSUPPORTED_CIPHER);
170
0
        goto err;
171
0
    }
172
0
173
0
    /* Fixup cipher based on AlgorithmIdentifier */
174
0
    if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de))
175
0
        goto err;
176
0
    if (EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) {
177
0
        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_CIPHER_PARAMETER_ERROR);
178
0
        goto err;
179
0
    }
180
0
    rv = kdf(ctx, pass, passlen, pbe2->keyfunc->parameter, NULL, NULL, en_de);
181
0
 err:
182
0
    PBE2PARAM_free(pbe2);
183
0
    return rv;
184
0
}
185
186
int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
187
                             int passlen, ASN1_TYPE *param,
188
                             const EVP_CIPHER *c, const EVP_MD *md, int en_de)
189
0
{
190
0
    unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
191
0
    int saltlen, iter;
192
0
    int rv = 0;
193
0
    unsigned int keylen = 0;
194
0
    int prf_nid, hmac_md_nid;
195
0
    PBKDF2PARAM *kdf = NULL;
196
0
    const EVP_MD *prfmd;
197
0
198
0
    if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
199
0
        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_NO_CIPHER_SET);
200
0
        goto err;
201
0
    }
202
0
    keylen = EVP_CIPHER_CTX_key_length(ctx);
203
0
    OPENSSL_assert(keylen <= sizeof(key));
204
0
205
0
    /* Decode parameter */
206
0
207
0
    kdf = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), param);
208
0
209
0
    if (kdf == NULL) {
210
0
        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_DECODE_ERROR);
211
0
        goto err;
212
0
    }
213
0
214
0
    keylen = EVP_CIPHER_CTX_key_length(ctx);
215
0
216
0
    /* Now check the parameters of the kdf */
217
0
218
0
    if (kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)) {
219
0
        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_KEYLENGTH);
220
0
        goto err;
221
0
    }
222
0
223
0
    if (kdf->prf)
224
0
        prf_nid = OBJ_obj2nid(kdf->prf->algorithm);
225
0
    else
226
0
        prf_nid = NID_hmacWithSHA1;
227
0
228
0
    if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0)) {
229
0
        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF);
230
0
        goto err;
231
0
    }
232
0
233
0
    prfmd = EVP_get_digestbynid(hmac_md_nid);
234
0
    if (prfmd == NULL) {
235
0
        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF);
236
0
        goto err;
237
0
    }
238
0
239
0
    if (kdf->salt->type != V_ASN1_OCTET_STRING) {
240
0
        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_SALT_TYPE);
241
0
        goto err;
242
0
    }
243
0
244
0
    /* it seems that its all OK */
245
0
    salt = kdf->salt->value.octet_string->data;
246
0
    saltlen = kdf->salt->value.octet_string->length;
247
0
    iter = ASN1_INTEGER_get(kdf->iter);
248
0
    if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd,
249
0
                           keylen, key))
250
0
        goto err;
251
0
    rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
252
0
 err:
253
0
    OPENSSL_cleanse(key, keylen);
254
0
    PBKDF2PARAM_free(kdf);
255
0
    return rv;
256
0
}
257
258
# ifdef OPENSSL_DEBUG_PKCS5V2
259
static void h__dump(const unsigned char *p, int len)
260
{
261
    for (; len--; p++)
262
        fprintf(stderr, "%02X ", *p);
263
    fprintf(stderr, "\n");
264
}
265
# endif