]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/dh/dh_pmeth.c
Copyright consolidation 05/10
[thirdparty/openssl.git] / crypto / dh / dh_pmeth.c
CommitLineData
0f113f3e 1/*
aa6bb135 2 * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
3ba0885a 3 *
aa6bb135
RS
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
3ba0885a
DSH
8 */
9
10#include <stdio.h>
b39fc560 11#include "internal/cryptlib.h"
3ba0885a
DSH
12#include <openssl/asn1t.h>
13#include <openssl/x509.h>
3ba0885a 14#include <openssl/evp.h>
0aeddcfa 15#include "dh_locl.h"
1e26a8ba 16#include <openssl/bn.h>
3c27208f 17#include <openssl/dsa.h>
bd59f2b9 18#include <openssl/objects.h>
27af42f9 19#include "internal/evp_int.h"
3ba0885a
DSH
20
21/* DH pkey context structure */
22
0f113f3e
MC
23typedef struct {
24 /* Parameter gen parameters */
25 int prime_len;
26 int generator;
27 int use_dsa;
28 int subprime_len;
29 /* message digest used for parameter generation */
30 const EVP_MD *md;
31 int rfc5114_param;
32 /* Keygen callback info */
33 int gentmp[2];
34 /* KDF (if any) to use for DH */
35 char kdf_type;
36 /* OID to use for KDF */
37 ASN1_OBJECT *kdf_oid;
38 /* Message digest to use for key derivation */
39 const EVP_MD *kdf_md;
40 /* User key material */
41 unsigned char *kdf_ukm;
42 size_t kdf_ukmlen;
43 /* KDF output length */
44 size_t kdf_outlen;
45} DH_PKEY_CTX;
3ba0885a
DSH
46
47static int pkey_dh_init(EVP_PKEY_CTX *ctx)
0f113f3e
MC
48{
49 DH_PKEY_CTX *dctx;
64b25758
RS
50
51 dctx = OPENSSL_zalloc(sizeof(*dctx));
90945fa3 52 if (dctx == NULL)
0f113f3e
MC
53 return 0;
54 dctx->prime_len = 1024;
55 dctx->subprime_len = -1;
56 dctx->generator = 2;
0f113f3e 57 dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
0f113f3e
MC
58
59 ctx->data = dctx;
60 ctx->keygen_info = dctx->gentmp;
61 ctx->keygen_info_count = 2;
62
63 return 1;
64}
3ba0885a 65
edeb3fd2
IY
66static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
67{
68 DH_PKEY_CTX *dctx = ctx->data;
69 if (dctx != NULL) {
70 OPENSSL_free(dctx->kdf_ukm);
71 ASN1_OBJECT_free(dctx->kdf_oid);
72 OPENSSL_free(dctx);
73 }
74}
75
76
8bdcef40 77static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
0f113f3e
MC
78{
79 DH_PKEY_CTX *dctx, *sctx;
80 if (!pkey_dh_init(dst))
81 return 0;
82 sctx = src->data;
83 dctx = dst->data;
84 dctx->prime_len = sctx->prime_len;
85 dctx->subprime_len = sctx->subprime_len;
86 dctx->generator = sctx->generator;
87 dctx->use_dsa = sctx->use_dsa;
88 dctx->md = sctx->md;
89 dctx->rfc5114_param = sctx->rfc5114_param;
90
91 dctx->kdf_type = sctx->kdf_type;
92 dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
edeb3fd2 93 if (dctx->kdf_oid == NULL)
0f113f3e
MC
94 return 0;
95 dctx->kdf_md = sctx->kdf_md;
edeb3fd2 96 if (sctx->kdf_ukm != NULL) {
7644a9ae 97 dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
edeb3fd2
IY
98 if (dctx->kdf_ukm == NULL)
99 return 0;
0f113f3e
MC
100 dctx->kdf_ukmlen = sctx->kdf_ukmlen;
101 }
102 dctx->kdf_outlen = sctx->kdf_outlen;
103 return 1;
104}
8bdcef40 105
3ba0885a 106static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
0f113f3e
MC
107{
108 DH_PKEY_CTX *dctx = ctx->data;
109 switch (type) {
110 case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
111 if (p1 < 256)
112 return -2;
113 dctx->prime_len = p1;
114 return 1;
115
116 case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
117 if (dctx->use_dsa == 0)
118 return -2;
119 dctx->subprime_len = p1;
120 return 1;
121
122 case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
123 if (dctx->use_dsa)
124 return -2;
125 dctx->generator = p1;
126 return 1;
127
128 case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
39090878 129#ifdef OPENSSL_NO_DSA
0f113f3e
MC
130 if (p1 != 0)
131 return -2;
39090878 132#else
0f113f3e
MC
133 if (p1 < 0 || p1 > 2)
134 return -2;
39090878 135#endif
0f113f3e
MC
136 dctx->use_dsa = p1;
137 return 1;
138
139 case EVP_PKEY_CTRL_DH_RFC5114:
140 if (p1 < 1 || p1 > 3)
141 return -2;
142 dctx->rfc5114_param = p1;
143 return 1;
144
145 case EVP_PKEY_CTRL_PEER_KEY:
146 /* Default behaviour is OK */
147 return 1;
148
149 case EVP_PKEY_CTRL_DH_KDF_TYPE:
150 if (p1 == -2)
151 return dctx->kdf_type;
e968561d
DB
152#ifdef OPENSSL_NO_CMS
153 if (p1 != EVP_PKEY_DH_KDF_NONE)
154#else
0f113f3e 155 if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
e968561d 156#endif
0f113f3e
MC
157 return -2;
158 dctx->kdf_type = p1;
159 return 1;
160
161 case EVP_PKEY_CTRL_DH_KDF_MD:
162 dctx->kdf_md = p2;
163 return 1;
164
165 case EVP_PKEY_CTRL_GET_DH_KDF_MD:
166 *(const EVP_MD **)p2 = dctx->kdf_md;
167 return 1;
168
169 case EVP_PKEY_CTRL_DH_KDF_OUTLEN:
170 if (p1 <= 0)
171 return -2;
172 dctx->kdf_outlen = (size_t)p1;
173 return 1;
174
175 case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN:
176 *(int *)p2 = dctx->kdf_outlen;
177 return 1;
178
179 case EVP_PKEY_CTRL_DH_KDF_UKM:
b548a1f1 180 OPENSSL_free(dctx->kdf_ukm);
0f113f3e
MC
181 dctx->kdf_ukm = p2;
182 if (p2)
183 dctx->kdf_ukmlen = p1;
184 else
185 dctx->kdf_ukmlen = 0;
186 return 1;
187
188 case EVP_PKEY_CTRL_GET_DH_KDF_UKM:
189 *(unsigned char **)p2 = dctx->kdf_ukm;
190 return dctx->kdf_ukmlen;
191
192 case EVP_PKEY_CTRL_DH_KDF_OID:
0dfb9398 193 ASN1_OBJECT_free(dctx->kdf_oid);
0f113f3e
MC
194 dctx->kdf_oid = p2;
195 return 1;
196
197 case EVP_PKEY_CTRL_GET_DH_KDF_OID:
198 *(ASN1_OBJECT **)p2 = dctx->kdf_oid;
199 return 1;
200
201 default:
202 return -2;
203
204 }
205}
39090878 206
3ba0885a 207static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
0f113f3e
MC
208 const char *type, const char *value)
209{
86885c28 210 if (strcmp(type, "dh_paramgen_prime_len") == 0) {
0f113f3e
MC
211 int len;
212 len = atoi(value);
213 return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
214 }
86885c28 215 if (strcmp(type, "dh_rfc5114") == 0) {
0f113f3e
MC
216 DH_PKEY_CTX *dctx = ctx->data;
217 int len;
218 len = atoi(value);
219 if (len < 0 || len > 3)
220 return -2;
221 dctx->rfc5114_param = len;
222 return 1;
223 }
86885c28 224 if (strcmp(type, "dh_paramgen_generator") == 0) {
0f113f3e
MC
225 int len;
226 len = atoi(value);
227 return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
228 }
86885c28 229 if (strcmp(type, "dh_paramgen_subprime_len") == 0) {
0f113f3e
MC
230 int len;
231 len = atoi(value);
232 return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len);
233 }
86885c28 234 if (strcmp(type, "dh_paramgen_type") == 0) {
0f113f3e
MC
235 int typ;
236 typ = atoi(value);
237 return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ);
238 }
239 return -2;
240}
3ba0885a 241
39090878
DSH
242#ifndef OPENSSL_NO_DSA
243
244extern int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
0f113f3e
MC
245 const EVP_MD *evpmd,
246 const unsigned char *seed_in, size_t seed_len,
247 unsigned char *seed_out, int *counter_ret,
248 unsigned long *h_ret, BN_GENCB *cb);
39090878
DSH
249
250extern int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
0f113f3e
MC
251 const EVP_MD *evpmd,
252 const unsigned char *seed_in,
253 size_t seed_len, int idx,
254 unsigned char *seed_out, int *counter_ret,
255 unsigned long *h_ret, BN_GENCB *cb);
39090878
DSH
256
257static DSA *dsa_dh_generate(DH_PKEY_CTX *dctx, BN_GENCB *pcb)
0f113f3e
MC
258{
259 DSA *ret;
260 int rv = 0;
261 int prime_len = dctx->prime_len;
262 int subprime_len = dctx->subprime_len;
263 const EVP_MD *md = dctx->md;
264 if (dctx->use_dsa > 2)
265 return NULL;
266 ret = DSA_new();
90945fa3 267 if (ret == NULL)
0f113f3e
MC
268 return NULL;
269 if (subprime_len == -1) {
270 if (prime_len >= 2048)
271 subprime_len = 256;
272 else
273 subprime_len = 160;
274 }
275 if (md == NULL) {
276 if (prime_len >= 2048)
277 md = EVP_sha256();
278 else
279 md = EVP_sha1();
280 }
281 if (dctx->use_dsa == 1)
282 rv = dsa_builtin_paramgen(ret, prime_len, subprime_len, md,
283 NULL, 0, NULL, NULL, NULL, pcb);
284 else if (dctx->use_dsa == 2)
285 rv = dsa_builtin_paramgen2(ret, prime_len, subprime_len, md,
286 NULL, 0, -1, NULL, NULL, NULL, pcb);
287 if (rv <= 0) {
288 DSA_free(ret);
289 return NULL;
290 }
291 return ret;
292}
39090878
DSH
293
294#endif
295
3ba0885a 296static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e
MC
297{
298 DH *dh = NULL;
299 DH_PKEY_CTX *dctx = ctx->data;
300 BN_GENCB *pcb;
301 int ret;
302 if (dctx->rfc5114_param) {
303 switch (dctx->rfc5114_param) {
304 case 1:
305 dh = DH_get_1024_160();
306 break;
307
308 case 2:
309 dh = DH_get_2048_224();
310 break;
311
312 case 3:
313 dh = DH_get_2048_256();
314 break;
315
316 default:
317 return -2;
318 }
319 EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
320 return 1;
321 }
322
323 if (ctx->pkey_gencb) {
324 pcb = BN_GENCB_new();
90945fa3
MC
325 if (pcb == NULL)
326 return 0;
0f113f3e
MC
327 evp_pkey_set_cb_translate(pcb, ctx);
328 } else
329 pcb = NULL;
39090878 330#ifndef OPENSSL_NO_DSA
0f113f3e
MC
331 if (dctx->use_dsa) {
332 DSA *dsa_dh;
333 dsa_dh = dsa_dh_generate(dctx, pcb);
23a1d5e9 334 BN_GENCB_free(pcb);
90945fa3 335 if (dsa_dh == NULL)
0f113f3e
MC
336 return 0;
337 dh = DSA_dup_DH(dsa_dh);
338 DSA_free(dsa_dh);
339 if (!dh)
340 return 0;
341 EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
342 return 1;
343 }
39090878 344#endif
0f113f3e 345 dh = DH_new();
90945fa3 346 if (dh == NULL) {
23a1d5e9 347 BN_GENCB_free(pcb);
0f113f3e
MC
348 return 0;
349 }
350 ret = DH_generate_parameters_ex(dh,
351 dctx->prime_len, dctx->generator, pcb);
23a1d5e9 352 BN_GENCB_free(pcb);
0f113f3e
MC
353 if (ret)
354 EVP_PKEY_assign_DH(pkey, dh);
355 else
356 DH_free(dh);
357 return ret;
358}
3ba0885a
DSH
359
360static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e
MC
361{
362 DH *dh = NULL;
363 if (ctx->pkey == NULL) {
364 DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET);
365 return 0;
366 }
367 dh = DH_new();
90945fa3 368 if (dh == NULL)
0f113f3e
MC
369 return 0;
370 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh);
371 /* Note: if error return, pkey is freed by parent routine */
372 if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
373 return 0;
374 return DH_generate_key(pkey->pkey.dh);
375}
376
377static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
378 size_t *keylen)
379{
380 int ret;
381 DH *dh;
382 DH_PKEY_CTX *dctx = ctx->data;
383 BIGNUM *dhpub;
384 if (!ctx->pkey || !ctx->peerkey) {
385 DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET);
386 return 0;
387 }
388 dh = ctx->pkey->pkey.dh;
389 dhpub = ctx->peerkey->pkey.dh->pub_key;
390 if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) {
391 if (key == NULL) {
392 *keylen = DH_size(dh);
393 return 1;
394 }
395 ret = DH_compute_key(key, dhpub, dh);
396 if (ret < 0)
397 return ret;
398 *keylen = ret;
399 return 1;
e968561d
DB
400 }
401#ifndef OPENSSL_NO_CMS
402 else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
403
0f113f3e
MC
404 unsigned char *Z = NULL;
405 size_t Zlen = 0;
406 if (!dctx->kdf_outlen || !dctx->kdf_oid)
407 return 0;
408 if (key == NULL) {
409 *keylen = dctx->kdf_outlen;
410 return 1;
411 }
412 if (*keylen != dctx->kdf_outlen)
413 return 0;
414 ret = 0;
415 Zlen = DH_size(dh);
416 Z = OPENSSL_malloc(Zlen);
90945fa3 417 if (Z == NULL) {
918bb865
MC
418 goto err;
419 }
0f113f3e
MC
420 if (DH_compute_key_padded(Z, dhpub, dh) <= 0)
421 goto err;
422 if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
423 dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
424 goto err;
425 *keylen = dctx->kdf_outlen;
426 ret = 1;
427 err:
4b45c6e5 428 OPENSSL_clear_free(Z, Zlen);
0f113f3e
MC
429 return ret;
430 }
e968561d
DB
431#endif
432 return 0;
0f113f3e
MC
433}
434
435const EVP_PKEY_METHOD dh_pkey_meth = {
436 EVP_PKEY_DH,
437 0,
438 pkey_dh_init,
439 pkey_dh_copy,
440 pkey_dh_cleanup,
441
442 0,
443 pkey_dh_paramgen,
444
445 0,
446 pkey_dh_keygen,
447
448 0,
449 0,
450
451 0,
452 0,
453
454 0, 0,
455
456 0, 0, 0, 0,
457
458 0, 0,
459
460 0, 0,
461
462 0,
463 pkey_dh_derive,
464
465 pkey_dh_ctrl,
466 pkey_dh_ctrl_str
467};
468
469const EVP_PKEY_METHOD dhx_pkey_meth = {
470 EVP_PKEY_DHX,
471 0,
472 pkey_dh_init,
473 pkey_dh_copy,
474 pkey_dh_cleanup,
475
476 0,
477 pkey_dh_paramgen,
478
479 0,
480 pkey_dh_keygen,
481
482 0,
483 0,
484
485 0,
486 0,
487
488 0, 0,
489
490 0, 0, 0, 0,
491
492 0, 0,
493
494 0, 0,
495
496 0,
497 pkey_dh_derive,
498
499 pkey_dh_ctrl,
500 pkey_dh_ctrl_str
501};