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