Coverage Report

Created: 2018-08-29 13:53

/src/openssl/crypto/pkcs12/p12_key.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 "internal/cryptlib.h"
12
#include <openssl/pkcs12.h>
13
#include <openssl/bn.h>
14
15
/* Uncomment out this line to get debugging info about key generation */
16
/*
17
 * #define OPENSSL_DEBUG_KEYGEN
18
 */
19
#ifdef OPENSSL_DEBUG_KEYGEN
20
# include <openssl/bio.h>
21
extern BIO *bio_err;
22
void h__dump(unsigned char *p, int len);
23
#endif
24
25
/* PKCS12 compatible key/IV generation */
26
#ifndef min
27
0
# define min(a,b) ((a) < (b) ? (a) : (b))
28
#endif
29
30
int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
31
                       int saltlen, int id, int iter, int n,
32
                       unsigned char *out, const EVP_MD *md_type)
33
0
{
34
0
    int ret;
35
0
    unsigned char *unipass;
36
0
    int uniplen;
37
0
38
0
    if (!pass) {
39
0
        unipass = NULL;
40
0
        uniplen = 0;
41
0
    } else if (!OPENSSL_asc2uni(pass, passlen, &unipass, &uniplen)) {
42
0
        PKCS12err(PKCS12_F_PKCS12_KEY_GEN_ASC, ERR_R_MALLOC_FAILURE);
43
0
        return 0;
44
0
    }
45
0
    ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
46
0
                             id, iter, n, out, md_type);
47
0
    if (ret <= 0)
48
0
        return 0;
49
0
    OPENSSL_clear_free(unipass, uniplen);
50
0
    return ret;
51
0
}
52
53
int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
54
                        int saltlen, int id, int iter, int n,
55
                        unsigned char *out, const EVP_MD *md_type)
56
0
{
57
0
    int ret;
58
0
    unsigned char *unipass;
59
0
    int uniplen;
60
0
61
0
    if (!pass) {
62
0
        unipass = NULL;
63
0
        uniplen = 0;
64
0
    } else if (!OPENSSL_utf82uni(pass, passlen, &unipass, &uniplen)) {
65
0
        PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UTF8, ERR_R_MALLOC_FAILURE);
66
0
        return 0;
67
0
    }
68
0
    ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
69
0
                             id, iter, n, out, md_type);
70
0
    if (ret <= 0)
71
0
        return 0;
72
0
    OPENSSL_clear_free(unipass, uniplen);
73
0
    return ret;
74
0
}
75
76
int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
77
                       int saltlen, int id, int iter, int n,
78
                       unsigned char *out, const EVP_MD *md_type)
79
0
{
80
0
    unsigned char *B = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL;
81
0
    int Slen, Plen, Ilen;
82
0
    int i, j, u, v;
83
0
    int ret = 0;
84
0
    EVP_MD_CTX *ctx = NULL;
85
#ifdef  OPENSSL_DEBUG_KEYGEN
86
    unsigned char *tmpout = out;
87
    int tmpn = n;
88
#endif
89
90
0
    ctx = EVP_MD_CTX_new();
91
0
    if (ctx == NULL)
92
0
        goto err;
93
0
94
#ifdef  OPENSSL_DEBUG_KEYGEN
95
    fprintf(stderr, "KEYGEN DEBUG\n");
96
    fprintf(stderr, "ID %d, ITER %d\n", id, iter);
97
    fprintf(stderr, "Password (length %d):\n", passlen);
98
    h__dump(pass, passlen);
99
    fprintf(stderr, "Salt (length %d):\n", saltlen);
100
    h__dump(salt, saltlen);
101
#endif
102
0
    v = EVP_MD_block_size(md_type);
103
0
    u = EVP_MD_size(md_type);
104
0
    if (u < 0 || v <= 0)
105
0
        goto err;
106
0
    D = OPENSSL_malloc(v);
107
0
    Ai = OPENSSL_malloc(u);
108
0
    B = OPENSSL_malloc(v + 1);
109
0
    Slen = v * ((saltlen + v - 1) / v);
110
0
    if (passlen)
111
0
        Plen = v * ((passlen + v - 1) / v);
112
0
    else
113
0
        Plen = 0;
114
0
    Ilen = Slen + Plen;
115
0
    I = OPENSSL_malloc(Ilen);
116
0
    if (D == NULL || Ai == NULL || B == NULL || I == NULL)
117
0
        goto err;
118
0
    for (i = 0; i < v; i++)
119
0
        D[i] = id;
120
0
    p = I;
121
0
    for (i = 0; i < Slen; i++)
122
0
        *p++ = salt[i % saltlen];
123
0
    for (i = 0; i < Plen; i++)
124
0
        *p++ = pass[i % passlen];
125
0
    for (;;) {
126
0
        if (!EVP_DigestInit_ex(ctx, md_type, NULL)
127
0
            || !EVP_DigestUpdate(ctx, D, v)
128
0
            || !EVP_DigestUpdate(ctx, I, Ilen)
129
0
            || !EVP_DigestFinal_ex(ctx, Ai, NULL))
130
0
            goto err;
131
0
        for (j = 1; j < iter; j++) {
132
0
            if (!EVP_DigestInit_ex(ctx, md_type, NULL)
133
0
                || !EVP_DigestUpdate(ctx, Ai, u)
134
0
                || !EVP_DigestFinal_ex(ctx, Ai, NULL))
135
0
                goto err;
136
0
        }
137
0
        memcpy(out, Ai, min(n, u));
138
0
        if (u >= n) {
139
#ifdef OPENSSL_DEBUG_KEYGEN
140
            fprintf(stderr, "Output KEY (length %d)\n", tmpn);
141
            h__dump(tmpout, tmpn);
142
#endif
143
            ret = 1;
144
0
            goto end;
145
0
        }
146
0
        n -= u;
147
0
        out += u;
148
0
        for (j = 0; j < v; j++)
149
0
            B[j] = Ai[j % u];
150
0
        for (j = 0; j < Ilen; j += v) {
151
0
            int k;
152
0
            unsigned char *Ij = I + j;
153
0
            uint16_t c = 1;
154
0
155
0
            /* Work out Ij = Ij + B + 1 */
156
0
            for (k = v - 1; k >= 0; k--) {
157
0
                c += Ij[k] + B[k];
158
0
                Ij[k] = (unsigned char)c;
159
0
                c >>= 8;
160
0
            }
161
0
        }
162
0
    }
163
0
164
0
 err:
165
0
    PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI, ERR_R_MALLOC_FAILURE);
166
0
167
0
 end:
168
0
    OPENSSL_free(Ai);
169
0
    OPENSSL_free(B);
170
0
    OPENSSL_free(D);
171
0
    OPENSSL_free(I);
172
0
    EVP_MD_CTX_free(ctx);
173
0
    return ret;
174
0
}
175
176
#ifdef OPENSSL_DEBUG_KEYGEN
177
void h__dump(unsigned char *p, int len)
178
{
179
    for (; len--; p++)
180
        fprintf(stderr, "%02X", *p);
181
    fprintf(stderr, "\n");
182
}
183
#endif