Coverage Report

Created: 2018-08-29 13:53

/src/openssl/crypto/dh/dh_key.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 1995-2018 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 "dh_locl.h"
13
#include "internal/bn_int.h"
14
15
static int generate_key(DH *dh);
16
static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
17
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
18
                         const BIGNUM *a, const BIGNUM *p,
19
                         const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
20
static int dh_init(DH *dh);
21
static int dh_finish(DH *dh);
22
23
int DH_generate_key(DH *dh)
24
0
{
25
0
    return dh->meth->generate_key(dh);
26
0
}
27
28
int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
29
0
{
30
0
    return dh->meth->compute_key(key, pub_key, dh);
31
0
}
32
33
int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh)
34
0
{
35
0
    int rv, pad;
36
0
    rv = dh->meth->compute_key(key, pub_key, dh);
37
0
    if (rv <= 0)
38
0
        return rv;
39
0
    pad = BN_num_bytes(dh->p) - rv;
40
0
    if (pad > 0) {
41
0
        memmove(key + pad, key, rv);
42
0
        memset(key, 0, pad);
43
0
    }
44
0
    return rv + pad;
45
0
}
46
47
static DH_METHOD dh_ossl = {
48
    "OpenSSL DH Method",
49
    generate_key,
50
    compute_key,
51
    dh_bn_mod_exp,
52
    dh_init,
53
    dh_finish,
54
    DH_FLAG_FIPS_METHOD,
55
    NULL,
56
    NULL
57
};
58
59
static const DH_METHOD *default_DH_method = &dh_ossl;
60
61
const DH_METHOD *DH_OpenSSL(void)
62
0
{
63
0
    return &dh_ossl;
64
0
}
65
66
void DH_set_default_method(const DH_METHOD *meth)
67
0
{
68
0
    default_DH_method = meth;
69
0
}
70
71
const DH_METHOD *DH_get_default_method(void)
72
0
{
73
0
    return default_DH_method;
74
0
}
75
76
static int generate_key(DH *dh)
77
0
{
78
0
    int ok = 0;
79
0
    int generate_new_key = 0;
80
0
    unsigned l;
81
0
    BN_CTX *ctx = NULL;
82
0
    BN_MONT_CTX *mont = NULL;
83
0
    BIGNUM *pub_key = NULL, *priv_key = NULL;
84
0
85
0
    if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
86
0
        DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE);
87
0
        return 0;
88
0
    }
89
0
90
0
    ctx = BN_CTX_new();
91
0
    if (ctx == NULL)
92
0
        goto err;
93
0
94
0
    if (dh->priv_key == NULL) {
95
0
        priv_key = BN_secure_new();
96
0
        if (priv_key == NULL)
97
0
            goto err;
98
0
        generate_new_key = 1;
99
0
    } else
100
0
        priv_key = dh->priv_key;
101
0
102
0
    if (dh->pub_key == NULL) {
103
0
        pub_key = BN_new();
104
0
        if (pub_key == NULL)
105
0
            goto err;
106
0
    } else
107
0
        pub_key = dh->pub_key;
108
0
109
0
    if (dh->flags & DH_FLAG_CACHE_MONT_P) {
110
0
        mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
111
0
                                      dh->lock, dh->p, ctx);
112
0
        if (!mont)
113
0
            goto err;
114
0
    }
115
0
116
0
    if (generate_new_key) {
117
0
        if (dh->q) {
118
0
            do {
119
0
                if (!BN_priv_rand_range(priv_key, dh->q))
120
0
                    goto err;
121
0
            }
122
0
            while (BN_is_zero(priv_key) || BN_is_one(priv_key));
123
0
        } else {
124
0
            /* secret exponent length */
125
0
            l = dh->length ? dh->length : BN_num_bits(dh->p) - 1;
126
0
            if (!BN_priv_rand(priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
127
0
                goto err;
128
0
        }
129
0
    }
130
0
131
0
    {
132
0
        BIGNUM *prk = BN_new();
133
0
134
0
        if (prk == NULL)
135
0
            goto err;
136
0
        BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
137
0
138
0
        if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) {
139
0
            BN_free(prk);
140
0
            goto err;
141
0
        }
142
0
        /* We MUST free prk before any further use of priv_key */
143
0
        BN_free(prk);
144
0
    }
145
0
146
0
    dh->pub_key = pub_key;
147
0
    dh->priv_key = priv_key;
148
0
    ok = 1;
149
0
 err:
150
0
    if (ok != 1)
151
0
        DHerr(DH_F_GENERATE_KEY, ERR_R_BN_LIB);
152
0
153
0
    if (pub_key != dh->pub_key)
154
0
        BN_free(pub_key);
155
0
    if (priv_key != dh->priv_key)
156
0
        BN_free(priv_key);
157
0
    BN_CTX_free(ctx);
158
0
    return ok;
159
0
}
160
161
static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
162
0
{
163
0
    BN_CTX *ctx = NULL;
164
0
    BN_MONT_CTX *mont = NULL;
165
0
    BIGNUM *tmp;
166
0
    int ret = -1;
167
0
    int check_result;
168
0
169
0
    if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
170
0
        DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE);
171
0
        goto err;
172
0
    }
173
0
174
0
    ctx = BN_CTX_new();
175
0
    if (ctx == NULL)
176
0
        goto err;
177
0
    BN_CTX_start(ctx);
178
0
    tmp = BN_CTX_get(ctx);
179
0
    if (tmp == NULL)
180
0
        goto err;
181
0
182
0
    if (dh->priv_key == NULL) {
183
0
        DHerr(DH_F_COMPUTE_KEY, DH_R_NO_PRIVATE_VALUE);
184
0
        goto err;
185
0
    }
186
0
187
0
    if (dh->flags & DH_FLAG_CACHE_MONT_P) {
188
0
        mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
189
0
                                      dh->lock, dh->p, ctx);
190
0
        BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
191
0
        if (!mont)
192
0
            goto err;
193
0
    }
194
0
195
0
    if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) {
196
0
        DHerr(DH_F_COMPUTE_KEY, DH_R_INVALID_PUBKEY);
197
0
        goto err;
198
0
    }
199
0
200
0
    if (!dh->
201
0
        meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx, mont)) {
202
0
        DHerr(DH_F_COMPUTE_KEY, ERR_R_BN_LIB);
203
0
        goto err;
204
0
    }
205
0
206
0
    ret = BN_bn2bin(tmp, key);
207
0
 err:
208
0
    if (ctx != NULL) {
209
0
        BN_CTX_end(ctx);
210
0
        BN_CTX_free(ctx);
211
0
    }
212
0
    return ret;
213
0
}
214
215
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
216
                         const BIGNUM *a, const BIGNUM *p,
217
                         const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
218
0
{
219
0
    return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
220
0
}
221
222
static int dh_init(DH *dh)
223
0
{
224
0
    dh->flags |= DH_FLAG_CACHE_MONT_P;
225
0
    return 1;
226
0
}
227
228
static int dh_finish(DH *dh)
229
0
{
230
0
    BN_MONT_CTX_free(dh->method_mont_p);
231
0
    return 1;
232
0
}