GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/dh/dh_pmeth.c Lines: 48 88 54.5 %
Date: 2017-11-07 Branches: 14 52 26.9 %

Line Branch Exec Source
1
/* $OpenBSD: dh_pmeth.c,v 1.10 2017/01/29 17:49:22 beck Exp $ */
2
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3
 * project 2006.
4
 */
5
/* ====================================================================
6
 * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. All advertising materials mentioning features or use of this
21
 *    software must display the following acknowledgment:
22
 *    "This product includes software developed by the OpenSSL Project
23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24
 *
25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26
 *    endorse or promote products derived from this software without
27
 *    prior written permission. For written permission, please contact
28
 *    licensing@OpenSSL.org.
29
 *
30
 * 5. Products derived from this software may not be called "OpenSSL"
31
 *    nor may "OpenSSL" appear in their names without prior written
32
 *    permission of the OpenSSL Project.
33
 *
34
 * 6. Redistributions of any form whatsoever must retain the following
35
 *    acknowledgment:
36
 *    "This product includes software developed by the OpenSSL Project
37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38
 *
39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
51
 * ====================================================================
52
 *
53
 * This product includes cryptographic software written by Eric Young
54
 * (eay@cryptsoft.com).  This product includes software written by Tim
55
 * Hudson (tjh@cryptsoft.com).
56
 *
57
 */
58
59
#include <limits.h>
60
#include <stdio.h>
61
#include <string.h>
62
63
#include <openssl/asn1t.h>
64
#include <openssl/bn.h>
65
#include <openssl/dh.h>
66
#include <openssl/err.h>
67
#include <openssl/evp.h>
68
#include <openssl/x509.h>
69
70
#include "evp_locl.h"
71
72
/* DH pkey context structure */
73
74
typedef struct {
75
	/* Parameter gen parameters */
76
	int prime_len;
77
	int generator;
78
	int use_dsa;
79
	/* Keygen callback info */
80
	int gentmp[2];
81
	/* message digest */
82
} DH_PKEY_CTX;
83
84
static int
85
pkey_dh_init(EVP_PKEY_CTX *ctx)
86
{
87
	DH_PKEY_CTX *dctx;
88
89
8
	dctx = malloc(sizeof(DH_PKEY_CTX));
90
4
	if (!dctx)
91
		return 0;
92
4
	dctx->prime_len = 1024;
93
4
	dctx->generator = 2;
94
4
	dctx->use_dsa = 0;
95
96
4
	ctx->data = dctx;
97
4
	ctx->keygen_info = dctx->gentmp;
98
4
	ctx->keygen_info_count = 2;
99
100
4
	return 1;
101
4
}
102
103
static int
104
pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
105
{
106
	DH_PKEY_CTX *dctx, *sctx;
107
108
	if (!pkey_dh_init(dst))
109
		return 0;
110
       	sctx = src->data;
111
	dctx = dst->data;
112
	dctx->prime_len = sctx->prime_len;
113
	dctx->generator = sctx->generator;
114
	dctx->use_dsa = sctx->use_dsa;
115
	return 1;
116
}
117
118
static void
119
pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
120
{
121
8
	DH_PKEY_CTX *dctx = ctx->data;
122
123
4
	free(dctx);
124
4
}
125
126
static int
127
pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
128
{
129
4
	DH_PKEY_CTX *dctx = ctx->data;
130
131

2
	switch (type) {
132
	case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
133
2
		if (p1 < 256)
134
			return -2;
135
2
		dctx->prime_len = p1;
136
2
		return 1;
137
138
	case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
139
		dctx->generator = p1;
140
		return 1;
141
142
	case EVP_PKEY_CTRL_PEER_KEY:
143
		/* Default behaviour is OK */
144
		return 1;
145
146
	default:
147
		return -2;
148
	}
149
2
}
150
151
static int
152
pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
153
{
154
 	long lval;
155
4
	char *ep;
156
	int len;
157
158
2
	if (!strcmp(type, "dh_paramgen_prime_len")) {
159
2
		errno = 0;
160
2
		lval = strtol(value, &ep, 10);
161

4
		if (value[0] == '\0' || *ep != '\0')
162
			goto not_a_number;
163
2
		if ((errno == ERANGE &&
164
		    (lval == LONG_MAX || lval == LONG_MIN)) ||
165
2
		    (lval > INT_MAX || lval < INT_MIN))
166
			goto out_of_range;
167
2
		len = lval;
168
2
		return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
169
	} else if (!strcmp(type, "dh_paramgen_generator")) {
170
		errno = 0;
171
		lval = strtol(value, &ep, 10);
172
		if (value[0] == '\0' || *ep != '\0')
173
			goto not_a_number;
174
		if ((errno == ERANGE &&
175
		    (lval == LONG_MAX || lval == LONG_MIN)) ||
176
		    (lval > INT_MAX || lval < INT_MIN))
177
			goto out_of_range;
178
		len = lval;
179
		return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
180
	}
181
182
not_a_number:
183
out_of_range:
184
	return -2;
185
2
}
186
187
static int
188
pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
189
{
190
	DH *dh = NULL;
191
4
	DH_PKEY_CTX *dctx = ctx->data;
192
2
	BN_GENCB *pcb, cb;
193
	int ret;
194
195
2
	if (ctx->pkey_gencb) {
196
		pcb = &cb;
197
2
		evp_pkey_set_cb_translate(pcb, ctx);
198
2
	} else
199
		pcb = NULL;
200
2
	dh = DH_new();
201
2
	if (!dh)
202
		return 0;
203
2
	ret = DH_generate_parameters_ex(dh, dctx->prime_len, dctx->generator,
204
	    pcb);
205
2
	if (ret)
206
2
		EVP_PKEY_assign_DH(pkey, dh);
207
	else
208
		DH_free(dh);
209
2
	return ret;
210
2
}
211
212
static int
213
pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
214
{
215
	DH *dh = NULL;
216
217
4
	if (ctx->pkey == NULL) {
218
		DHerror(DH_R_NO_PARAMETERS_SET);
219
		return 0;
220
	}
221
2
	dh = DH_new();
222
2
	if (!dh)
223
		return 0;
224
2
	EVP_PKEY_assign_DH(pkey, dh);
225
	/* Note: if error return, pkey is freed by parent routine */
226
2
	if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
227
		return 0;
228
2
	return DH_generate_key(pkey->pkey.dh);
229
2
}
230
231
static int
232
pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
233
{
234
	int ret;
235
236
	if (!ctx->pkey || !ctx->peerkey) {
237
		DHerror(DH_R_KEYS_NOT_SET);
238
		return 0;
239
	}
240
	ret = DH_compute_key(key, ctx->peerkey->pkey.dh->pub_key,
241
	    ctx->pkey->pkey.dh);
242
	if (ret < 0)
243
		return ret;
244
	*keylen = ret;
245
	return 1;
246
}
247
248
const EVP_PKEY_METHOD dh_pkey_meth = {
249
	.pkey_id = EVP_PKEY_DH,
250
	.flags = EVP_PKEY_FLAG_AUTOARGLEN,
251
252
	.init = pkey_dh_init,
253
	.copy = pkey_dh_copy,
254
	.cleanup = pkey_dh_cleanup,
255
256
	.paramgen = pkey_dh_paramgen,
257
258
	.keygen = pkey_dh_keygen,
259
260
	.derive = pkey_dh_derive,
261
262
	.ctrl = pkey_dh_ctrl,
263
	.ctrl_str = pkey_dh_ctrl_str
264
};