]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/dh/dh_pmeth.c
a760ff5390fc78f4d34a6475e581a55d52782097
[thirdparty/openssl.git] / crypto / dh / dh_pmeth.c
1 /*
2 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3 * 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 <stdio.h>
60 #include "internal/cryptlib.h"
61 #include <openssl/asn1t.h>
62 #include <openssl/x509.h>
63 #include <openssl/evp.h>
64 #include <openssl/dh.h>
65 #include <openssl/bn.h>
66 #ifndef OPENSSL_NO_DSA
67 # include <openssl/dsa.h>
68 #endif
69 #include <openssl/objects.h>
70 #include "internal/evp_int.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 int subprime_len;
80 /* message digest used for parameter generation */
81 const EVP_MD *md;
82 int rfc5114_param;
83 /* Keygen callback info */
84 int gentmp[2];
85 /* KDF (if any) to use for DH */
86 char kdf_type;
87 /* OID to use for KDF */
88 ASN1_OBJECT *kdf_oid;
89 /* Message digest to use for key derivation */
90 const EVP_MD *kdf_md;
91 /* User key material */
92 unsigned char *kdf_ukm;
93 size_t kdf_ukmlen;
94 /* KDF output length */
95 size_t kdf_outlen;
96 } DH_PKEY_CTX;
97
98 static int pkey_dh_init(EVP_PKEY_CTX *ctx)
99 {
100 DH_PKEY_CTX *dctx;
101
102 dctx = OPENSSL_zalloc(sizeof(*dctx));
103 if (dctx == NULL)
104 return 0;
105 dctx->prime_len = 1024;
106 dctx->subprime_len = -1;
107 dctx->generator = 2;
108 dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
109
110 ctx->data = dctx;
111 ctx->keygen_info = dctx->gentmp;
112 ctx->keygen_info_count = 2;
113
114 return 1;
115 }
116
117 static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
118 {
119 DH_PKEY_CTX *dctx, *sctx;
120 if (!pkey_dh_init(dst))
121 return 0;
122 sctx = src->data;
123 dctx = dst->data;
124 dctx->prime_len = sctx->prime_len;
125 dctx->subprime_len = sctx->subprime_len;
126 dctx->generator = sctx->generator;
127 dctx->use_dsa = sctx->use_dsa;
128 dctx->md = sctx->md;
129 dctx->rfc5114_param = sctx->rfc5114_param;
130
131 dctx->kdf_type = sctx->kdf_type;
132 dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
133 if (!dctx->kdf_oid)
134 return 0;
135 dctx->kdf_md = sctx->kdf_md;
136 if (dctx->kdf_ukm) {
137 dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
138 dctx->kdf_ukmlen = sctx->kdf_ukmlen;
139 }
140 dctx->kdf_outlen = sctx->kdf_outlen;
141 return 1;
142 }
143
144 static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
145 {
146 DH_PKEY_CTX *dctx = ctx->data;
147 if (dctx) {
148 OPENSSL_free(dctx->kdf_ukm);
149 ASN1_OBJECT_free(dctx->kdf_oid);
150 OPENSSL_free(dctx);
151 }
152 }
153
154 static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
155 {
156 DH_PKEY_CTX *dctx = ctx->data;
157 switch (type) {
158 case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
159 if (p1 < 256)
160 return -2;
161 dctx->prime_len = p1;
162 return 1;
163
164 case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
165 if (dctx->use_dsa == 0)
166 return -2;
167 dctx->subprime_len = p1;
168 return 1;
169
170 case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
171 if (dctx->use_dsa)
172 return -2;
173 dctx->generator = p1;
174 return 1;
175
176 case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
177 #ifdef OPENSSL_NO_DSA
178 if (p1 != 0)
179 return -2;
180 #else
181 if (p1 < 0 || p1 > 2)
182 return -2;
183 #endif
184 dctx->use_dsa = p1;
185 return 1;
186
187 case EVP_PKEY_CTRL_DH_RFC5114:
188 if (p1 < 1 || p1 > 3)
189 return -2;
190 dctx->rfc5114_param = p1;
191 return 1;
192
193 case EVP_PKEY_CTRL_PEER_KEY:
194 /* Default behaviour is OK */
195 return 1;
196
197 case EVP_PKEY_CTRL_DH_KDF_TYPE:
198 if (p1 == -2)
199 return dctx->kdf_type;
200 #ifdef OPENSSL_NO_CMS
201 if (p1 != EVP_PKEY_DH_KDF_NONE)
202 #else
203 if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
204 #endif
205 return -2;
206 dctx->kdf_type = p1;
207 return 1;
208
209 case EVP_PKEY_CTRL_DH_KDF_MD:
210 dctx->kdf_md = p2;
211 return 1;
212
213 case EVP_PKEY_CTRL_GET_DH_KDF_MD:
214 *(const EVP_MD **)p2 = dctx->kdf_md;
215 return 1;
216
217 case EVP_PKEY_CTRL_DH_KDF_OUTLEN:
218 if (p1 <= 0)
219 return -2;
220 dctx->kdf_outlen = (size_t)p1;
221 return 1;
222
223 case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN:
224 *(int *)p2 = dctx->kdf_outlen;
225 return 1;
226
227 case EVP_PKEY_CTRL_DH_KDF_UKM:
228 OPENSSL_free(dctx->kdf_ukm);
229 dctx->kdf_ukm = p2;
230 if (p2)
231 dctx->kdf_ukmlen = p1;
232 else
233 dctx->kdf_ukmlen = 0;
234 return 1;
235
236 case EVP_PKEY_CTRL_GET_DH_KDF_UKM:
237 *(unsigned char **)p2 = dctx->kdf_ukm;
238 return dctx->kdf_ukmlen;
239
240 case EVP_PKEY_CTRL_DH_KDF_OID:
241 ASN1_OBJECT_free(dctx->kdf_oid);
242 dctx->kdf_oid = p2;
243 return 1;
244
245 case EVP_PKEY_CTRL_GET_DH_KDF_OID:
246 *(ASN1_OBJECT **)p2 = dctx->kdf_oid;
247 return 1;
248
249 default:
250 return -2;
251
252 }
253 }
254
255 static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
256 const char *type, const char *value)
257 {
258 if (strcmp(type, "dh_paramgen_prime_len") == 0) {
259 int len;
260 len = atoi(value);
261 return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
262 }
263 if (strcmp(type, "dh_rfc5114") == 0) {
264 DH_PKEY_CTX *dctx = ctx->data;
265 int len;
266 len = atoi(value);
267 if (len < 0 || len > 3)
268 return -2;
269 dctx->rfc5114_param = len;
270 return 1;
271 }
272 if (strcmp(type, "dh_paramgen_generator") == 0) {
273 int len;
274 len = atoi(value);
275 return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
276 }
277 if (strcmp(type, "dh_paramgen_subprime_len") == 0) {
278 int len;
279 len = atoi(value);
280 return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len);
281 }
282 if (strcmp(type, "dh_paramgen_type") == 0) {
283 int typ;
284 typ = atoi(value);
285 return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ);
286 }
287 return -2;
288 }
289
290 #ifndef OPENSSL_NO_DSA
291
292 extern int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
293 const EVP_MD *evpmd,
294 const unsigned char *seed_in, size_t seed_len,
295 unsigned char *seed_out, int *counter_ret,
296 unsigned long *h_ret, BN_GENCB *cb);
297
298 extern int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
299 const EVP_MD *evpmd,
300 const unsigned char *seed_in,
301 size_t seed_len, int idx,
302 unsigned char *seed_out, int *counter_ret,
303 unsigned long *h_ret, BN_GENCB *cb);
304
305 static DSA *dsa_dh_generate(DH_PKEY_CTX *dctx, BN_GENCB *pcb)
306 {
307 DSA *ret;
308 int rv = 0;
309 int prime_len = dctx->prime_len;
310 int subprime_len = dctx->subprime_len;
311 const EVP_MD *md = dctx->md;
312 if (dctx->use_dsa > 2)
313 return NULL;
314 ret = DSA_new();
315 if (ret == NULL)
316 return NULL;
317 if (subprime_len == -1) {
318 if (prime_len >= 2048)
319 subprime_len = 256;
320 else
321 subprime_len = 160;
322 }
323 if (md == NULL) {
324 if (prime_len >= 2048)
325 md = EVP_sha256();
326 else
327 md = EVP_sha1();
328 }
329 if (dctx->use_dsa == 1)
330 rv = dsa_builtin_paramgen(ret, prime_len, subprime_len, md,
331 NULL, 0, NULL, NULL, NULL, pcb);
332 else if (dctx->use_dsa == 2)
333 rv = dsa_builtin_paramgen2(ret, prime_len, subprime_len, md,
334 NULL, 0, -1, NULL, NULL, NULL, pcb);
335 if (rv <= 0) {
336 DSA_free(ret);
337 return NULL;
338 }
339 return ret;
340 }
341
342 #endif
343
344 static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
345 {
346 DH *dh = NULL;
347 DH_PKEY_CTX *dctx = ctx->data;
348 BN_GENCB *pcb;
349 int ret;
350 if (dctx->rfc5114_param) {
351 switch (dctx->rfc5114_param) {
352 case 1:
353 dh = DH_get_1024_160();
354 break;
355
356 case 2:
357 dh = DH_get_2048_224();
358 break;
359
360 case 3:
361 dh = DH_get_2048_256();
362 break;
363
364 default:
365 return -2;
366 }
367 EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
368 return 1;
369 }
370
371 if (ctx->pkey_gencb) {
372 pcb = BN_GENCB_new();
373 if (pcb == NULL)
374 return 0;
375 evp_pkey_set_cb_translate(pcb, ctx);
376 } else
377 pcb = NULL;
378 #ifndef OPENSSL_NO_DSA
379 if (dctx->use_dsa) {
380 DSA *dsa_dh;
381 dsa_dh = dsa_dh_generate(dctx, pcb);
382 BN_GENCB_free(pcb);
383 if (dsa_dh == NULL)
384 return 0;
385 dh = DSA_dup_DH(dsa_dh);
386 DSA_free(dsa_dh);
387 if (!dh)
388 return 0;
389 EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
390 return 1;
391 }
392 #endif
393 dh = DH_new();
394 if (dh == NULL) {
395 BN_GENCB_free(pcb);
396 return 0;
397 }
398 ret = DH_generate_parameters_ex(dh,
399 dctx->prime_len, dctx->generator, pcb);
400 BN_GENCB_free(pcb);
401 if (ret)
402 EVP_PKEY_assign_DH(pkey, dh);
403 else
404 DH_free(dh);
405 return ret;
406 }
407
408 static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
409 {
410 DH *dh = NULL;
411 if (ctx->pkey == NULL) {
412 DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET);
413 return 0;
414 }
415 dh = DH_new();
416 if (dh == NULL)
417 return 0;
418 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh);
419 /* Note: if error return, pkey is freed by parent routine */
420 if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
421 return 0;
422 return DH_generate_key(pkey->pkey.dh);
423 }
424
425 static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
426 size_t *keylen)
427 {
428 int ret;
429 DH *dh;
430 DH_PKEY_CTX *dctx = ctx->data;
431 BIGNUM *dhpub;
432 if (!ctx->pkey || !ctx->peerkey) {
433 DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET);
434 return 0;
435 }
436 dh = ctx->pkey->pkey.dh;
437 dhpub = ctx->peerkey->pkey.dh->pub_key;
438 if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) {
439 if (key == NULL) {
440 *keylen = DH_size(dh);
441 return 1;
442 }
443 ret = DH_compute_key(key, dhpub, dh);
444 if (ret < 0)
445 return ret;
446 *keylen = ret;
447 return 1;
448 }
449 #ifndef OPENSSL_NO_CMS
450 else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
451
452 unsigned char *Z = NULL;
453 size_t Zlen = 0;
454 if (!dctx->kdf_outlen || !dctx->kdf_oid)
455 return 0;
456 if (key == NULL) {
457 *keylen = dctx->kdf_outlen;
458 return 1;
459 }
460 if (*keylen != dctx->kdf_outlen)
461 return 0;
462 ret = 0;
463 Zlen = DH_size(dh);
464 Z = OPENSSL_malloc(Zlen);
465 if (Z == NULL) {
466 goto err;
467 }
468 if (DH_compute_key_padded(Z, dhpub, dh) <= 0)
469 goto err;
470 if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
471 dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
472 goto err;
473 *keylen = dctx->kdf_outlen;
474 ret = 1;
475 err:
476 OPENSSL_clear_free(Z, Zlen);
477 return ret;
478 }
479 #endif
480 return 0;
481 }
482
483 const EVP_PKEY_METHOD dh_pkey_meth = {
484 EVP_PKEY_DH,
485 0,
486 pkey_dh_init,
487 pkey_dh_copy,
488 pkey_dh_cleanup,
489
490 0,
491 pkey_dh_paramgen,
492
493 0,
494 pkey_dh_keygen,
495
496 0,
497 0,
498
499 0,
500 0,
501
502 0, 0,
503
504 0, 0, 0, 0,
505
506 0, 0,
507
508 0, 0,
509
510 0,
511 pkey_dh_derive,
512
513 pkey_dh_ctrl,
514 pkey_dh_ctrl_str
515 };
516
517 const EVP_PKEY_METHOD dhx_pkey_meth = {
518 EVP_PKEY_DHX,
519 0,
520 pkey_dh_init,
521 pkey_dh_copy,
522 pkey_dh_cleanup,
523
524 0,
525 pkey_dh_paramgen,
526
527 0,
528 pkey_dh_keygen,
529
530 0,
531 0,
532
533 0,
534 0,
535
536 0, 0,
537
538 0, 0, 0, 0,
539
540 0, 0,
541
542 0, 0,
543
544 0,
545 pkey_dh_derive,
546
547 pkey_dh_ctrl,
548 pkey_dh_ctrl_str
549 };