1/*
2 * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (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/*
11 * DH & DSA low level APIs are deprecated for public use, but still ok for
12 * internal use.
13 */
14#include "internal/deprecated.h"
15
16#include <stdio.h>
17#include "internal/cryptlib.h"
18#include <openssl/asn1t.h>
19#include <openssl/x509.h>
20#include <openssl/evp.h>
21#include "dh_local.h"
22#include <openssl/bn.h>
23#include <openssl/dsa.h>
24#include <openssl/objects.h>
25#include "crypto/evp.h"
26
27/* DH pkey context structure */
28
29typedef struct {
30    /* Parameter gen parameters */
31    int prime_len;
32    int generator;
33    int paramgen_type;
34    int subprime_len;
35    int pad;
36    /* message digest used for parameter generation */
37    const EVP_MD *md;
38    int param_nid;
39    /* Keygen callback info */
40    int gentmp[2];
41    /* KDF (if any) to use for DH */
42    char kdf_type;
43    /* OID to use for KDF */
44    ASN1_OBJECT *kdf_oid;
45    /* Message digest to use for key derivation */
46    const EVP_MD *kdf_md;
47    /* User key material */
48    unsigned char *kdf_ukm;
49    size_t kdf_ukmlen;
50    /* KDF output length */
51    size_t kdf_outlen;
52} DH_PKEY_CTX;
53
54static int pkey_dh_init(EVP_PKEY_CTX *ctx)
55{
56    DH_PKEY_CTX *dctx;
57
58    if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
59        ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
60        return 0;
61    }
62    dctx->prime_len = 2048;
63    dctx->subprime_len = -1;
64    dctx->generator = 2;
65    dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
66
67    ctx->data = dctx;
68    ctx->keygen_info = dctx->gentmp;
69    ctx->keygen_info_count = 2;
70
71    return 1;
72}
73
74static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
75{
76    DH_PKEY_CTX *dctx = ctx->data;
77
78    if (dctx != NULL) {
79        OPENSSL_free(dctx->kdf_ukm);
80        ASN1_OBJECT_free(dctx->kdf_oid);
81        OPENSSL_free(dctx);
82    }
83}
84
85
86static int pkey_dh_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
87{
88    DH_PKEY_CTX *dctx, *sctx;
89
90    if (!pkey_dh_init(dst))
91        return 0;
92    sctx = src->data;
93    dctx = dst->data;
94    dctx->prime_len = sctx->prime_len;
95    dctx->subprime_len = sctx->subprime_len;
96    dctx->generator = sctx->generator;
97    dctx->paramgen_type = sctx->paramgen_type;
98    dctx->pad = sctx->pad;
99    dctx->md = sctx->md;
100    dctx->param_nid = sctx->param_nid;
101
102    dctx->kdf_type = sctx->kdf_type;
103    dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
104    if (dctx->kdf_oid == NULL)
105        return 0;
106    dctx->kdf_md = sctx->kdf_md;
107    if (sctx->kdf_ukm != NULL) {
108        dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
109        if (dctx->kdf_ukm == NULL)
110          return 0;
111        dctx->kdf_ukmlen = sctx->kdf_ukmlen;
112    }
113    dctx->kdf_outlen = sctx->kdf_outlen;
114    return 1;
115}
116
117static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
118{
119    DH_PKEY_CTX *dctx = ctx->data;
120    switch (type) {
121    case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
122        if (p1 < 256)
123            return -2;
124        dctx->prime_len = p1;
125        return 1;
126
127    case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
128        if (dctx->paramgen_type == DH_PARAMGEN_TYPE_GENERATOR)
129            return -2;
130        dctx->subprime_len = p1;
131        return 1;
132
133    case EVP_PKEY_CTRL_DH_PAD:
134        dctx->pad = p1;
135        return 1;
136
137    case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
138        if (dctx->paramgen_type != DH_PARAMGEN_TYPE_GENERATOR)
139            return -2;
140        dctx->generator = p1;
141        return 1;
142
143    case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
144#ifdef OPENSSL_NO_DSA
145        if (p1 != DH_PARAMGEN_TYPE_GENERATOR)
146            return -2;
147#else
148        if (p1 < 0 || p1 > 2)
149            return -2;
150#endif
151        dctx->paramgen_type = p1;
152        return 1;
153
154    case EVP_PKEY_CTRL_DH_RFC5114:
155        if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef)
156            return -2;
157        dctx->param_nid = p1;
158        return 1;
159
160    case EVP_PKEY_CTRL_DH_NID:
161        if (p1 <= 0 || dctx->param_nid != NID_undef)
162            return -2;
163        dctx->param_nid = p1;
164        return 1;
165
166    case EVP_PKEY_CTRL_PEER_KEY:
167        /* Default behaviour is OK */
168        return 1;
169
170    case EVP_PKEY_CTRL_DH_KDF_TYPE:
171        if (p1 == -2)
172            return dctx->kdf_type;
173        if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
174            return -2;
175        dctx->kdf_type = p1;
176        return 1;
177
178    case EVP_PKEY_CTRL_DH_KDF_MD:
179        dctx->kdf_md = p2;
180        return 1;
181
182    case EVP_PKEY_CTRL_GET_DH_KDF_MD:
183        *(const EVP_MD **)p2 = dctx->kdf_md;
184        return 1;
185
186    case EVP_PKEY_CTRL_DH_KDF_OUTLEN:
187        if (p1 <= 0)
188            return -2;
189        dctx->kdf_outlen = (size_t)p1;
190        return 1;
191
192    case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN:
193        *(int *)p2 = dctx->kdf_outlen;
194        return 1;
195
196    case EVP_PKEY_CTRL_DH_KDF_UKM:
197        OPENSSL_free(dctx->kdf_ukm);
198        dctx->kdf_ukm = p2;
199        if (p2)
200            dctx->kdf_ukmlen = p1;
201        else
202            dctx->kdf_ukmlen = 0;
203        return 1;
204
205    case EVP_PKEY_CTRL_GET_DH_KDF_UKM:
206        *(unsigned char **)p2 = dctx->kdf_ukm;
207        return dctx->kdf_ukmlen;
208
209    case EVP_PKEY_CTRL_DH_KDF_OID:
210        ASN1_OBJECT_free(dctx->kdf_oid);
211        dctx->kdf_oid = p2;
212        return 1;
213
214    case EVP_PKEY_CTRL_GET_DH_KDF_OID:
215        *(ASN1_OBJECT **)p2 = dctx->kdf_oid;
216        return 1;
217
218    default:
219        return -2;
220
221    }
222}
223
224static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
225                            const char *type, const char *value)
226{
227    if (strcmp(type, "dh_paramgen_prime_len") == 0) {
228        int len;
229        len = atoi(value);
230        return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
231    }
232    if (strcmp(type, "dh_rfc5114") == 0) {
233        DH_PKEY_CTX *dctx = ctx->data;
234        int id;
235
236        id = atoi(value);
237        if (id < 0 || id > 3)
238            return -2;
239        dctx->param_nid = id;
240        return 1;
241    }
242    if (strcmp(type, "dh_param") == 0) {
243        DH_PKEY_CTX *dctx = ctx->data;
244        int nid = OBJ_sn2nid(value);
245
246        if (nid == NID_undef) {
247            ERR_raise(ERR_LIB_DH, DH_R_INVALID_PARAMETER_NAME);
248            return -2;
249        }
250        dctx->param_nid = nid;
251        return 1;
252    }
253    if (strcmp(type, "dh_paramgen_generator") == 0) {
254        int len;
255        len = atoi(value);
256        return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
257    }
258    if (strcmp(type, "dh_paramgen_subprime_len") == 0) {
259        int len;
260        len = atoi(value);
261        return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len);
262    }
263    if (strcmp(type, "dh_paramgen_type") == 0) {
264        int typ;
265        typ = atoi(value);
266        return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ);
267    }
268    if (strcmp(type, "dh_pad") == 0) {
269        int pad;
270        pad = atoi(value);
271        return EVP_PKEY_CTX_set_dh_pad(ctx, pad);
272    }
273    return -2;
274}
275
276static DH *ffc_params_generate(OSSL_LIB_CTX *libctx, DH_PKEY_CTX *dctx,
277                               BN_GENCB *pcb)
278{
279    DH *ret;
280    int rv = 0;
281    int res;
282    int prime_len = dctx->prime_len;
283    int subprime_len = dctx->subprime_len;
284
285    if (dctx->paramgen_type > DH_PARAMGEN_TYPE_FIPS_186_4)
286        return NULL;
287    ret = DH_new();
288    if (ret == NULL)
289        return NULL;
290
291    if (subprime_len == -1) {
292        if (prime_len >= 2048)
293            subprime_len = 256;
294        else
295            subprime_len = 160;
296    }
297
298    if (dctx->md != NULL)
299        ossl_ffc_set_digest(&ret->params, EVP_MD_get0_name(dctx->md), NULL);
300
301# ifndef FIPS_MODULE
302    if (dctx->paramgen_type == DH_PARAMGEN_TYPE_FIPS_186_2)
303        rv = ossl_ffc_params_FIPS186_2_generate(libctx, &ret->params,
304                                                FFC_PARAM_TYPE_DH,
305                                                prime_len, subprime_len, &res,
306                                                pcb);
307    else
308# endif
309    /* For FIPS we always use the DH_PARAMGEN_TYPE_FIPS_186_4 generator */
310    if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2)
311        rv = ossl_ffc_params_FIPS186_4_generate(libctx, &ret->params,
312                                                FFC_PARAM_TYPE_DH,
313                                                prime_len, subprime_len, &res,
314                                                pcb);
315    if (rv <= 0) {
316        DH_free(ret);
317        return NULL;
318    }
319    return ret;
320}
321
322static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx,
323                            EVP_PKEY *pkey)
324{
325    DH *dh = NULL;
326    DH_PKEY_CTX *dctx = ctx->data;
327    BN_GENCB *pcb = NULL;
328    int ret;
329
330    /*
331     * Look for a safe prime group for key establishment. Which uses
332     * either RFC_3526 (modp_XXXX) or RFC_7919 (ffdheXXXX).
333     * RFC_5114 is also handled here for param_nid = (1..3)
334     */
335    if (dctx->param_nid != NID_undef) {
336        int type = dctx->param_nid <= 3 ? EVP_PKEY_DHX : EVP_PKEY_DH;
337
338        if ((dh = DH_new_by_nid(dctx->param_nid)) == NULL)
339            return 0;
340        EVP_PKEY_assign(pkey, type, dh);
341        return 1;
342    }
343
344    if (ctx->pkey_gencb != NULL) {
345        pcb = BN_GENCB_new();
346        if (pcb == NULL)
347            return 0;
348        evp_pkey_set_cb_translate(pcb, ctx);
349    }
350# ifdef FIPS_MODULE
351    dctx->paramgen_type = DH_PARAMGEN_TYPE_FIPS_186_4;
352# endif /* FIPS_MODULE */
353    if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2) {
354        dh = ffc_params_generate(NULL, dctx, pcb);
355        BN_GENCB_free(pcb);
356        if (dh == NULL)
357            return 0;
358        EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
359        return 1;
360    }
361    dh = DH_new();
362    if (dh == NULL) {
363        BN_GENCB_free(pcb);
364        return 0;
365    }
366    ret = DH_generate_parameters_ex(dh,
367                                    dctx->prime_len, dctx->generator, pcb);
368    BN_GENCB_free(pcb);
369    if (ret)
370        EVP_PKEY_assign_DH(pkey, dh);
371    else
372        DH_free(dh);
373    return ret;
374}
375
376static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
377{
378    DH_PKEY_CTX *dctx = ctx->data;
379    DH *dh = NULL;
380
381    if (ctx->pkey == NULL && dctx->param_nid == NID_undef) {
382        ERR_raise(ERR_LIB_DH, DH_R_NO_PARAMETERS_SET);
383        return 0;
384    }
385    if (dctx->param_nid != NID_undef)
386        dh = DH_new_by_nid(dctx->param_nid);
387    else
388        dh = DH_new();
389    if (dh == NULL)
390        return 0;
391    EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh);
392    /* Note: if error return, pkey is freed by parent routine */
393    if (ctx->pkey != NULL && !EVP_PKEY_copy_parameters(pkey, ctx->pkey))
394        return 0;
395    return DH_generate_key((DH *)EVP_PKEY_get0_DH(pkey));
396}
397
398static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
399                          size_t *keylen)
400{
401    int ret;
402    DH *dh;
403    const DH *dhpub;
404    DH_PKEY_CTX *dctx = ctx->data;
405    BIGNUM *dhpubbn;
406
407    if (ctx->pkey == NULL || ctx->peerkey == NULL) {
408        ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
409        return 0;
410    }
411    dh = (DH *)EVP_PKEY_get0_DH(ctx->pkey);
412    dhpub = EVP_PKEY_get0_DH(ctx->peerkey);
413    if (dhpub == NULL) {
414        ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
415        return 0;
416    }
417    dhpubbn = dhpub->pub_key;
418    if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) {
419        if (key == NULL) {
420            *keylen = DH_size(dh);
421            return 1;
422        }
423        if (dctx->pad)
424            ret = DH_compute_key_padded(key, dhpubbn, dh);
425        else
426            ret = DH_compute_key(key, dhpubbn, dh);
427        if (ret < 0)
428            return ret;
429        *keylen = ret;
430        return 1;
431    }
432    else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
433
434        unsigned char *Z = NULL;
435        int Zlen = 0;
436
437        if (!dctx->kdf_outlen || !dctx->kdf_oid)
438            return 0;
439        if (key == NULL) {
440            *keylen = dctx->kdf_outlen;
441            return 1;
442        }
443        if (*keylen != dctx->kdf_outlen)
444            return 0;
445        ret = 0;
446        if ((Zlen = DH_size(dh)) <= 0)
447            return 0;
448        if ((Z = OPENSSL_malloc(Zlen)) == NULL) {
449            ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
450            return 0;
451        }
452        if (DH_compute_key_padded(Z, dhpubbn, dh) <= 0)
453            goto err;
454        if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
455                          dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
456            goto err;
457        *keylen = dctx->kdf_outlen;
458        ret = 1;
459 err:
460        OPENSSL_clear_free(Z, Zlen);
461        return ret;
462    }
463    return 0;
464}
465
466static const EVP_PKEY_METHOD dh_pkey_meth = {
467    EVP_PKEY_DH,
468    0,
469    pkey_dh_init,
470    pkey_dh_copy,
471    pkey_dh_cleanup,
472
473    0,
474    pkey_dh_paramgen,
475
476    0,
477    pkey_dh_keygen,
478
479    0,
480    0,
481
482    0,
483    0,
484
485    0, 0,
486
487    0, 0, 0, 0,
488
489    0, 0,
490
491    0, 0,
492
493    0,
494    pkey_dh_derive,
495
496    pkey_dh_ctrl,
497    pkey_dh_ctrl_str
498};
499
500const EVP_PKEY_METHOD *ossl_dh_pkey_method(void)
501{
502    return &dh_pkey_meth;
503}
504
505static const EVP_PKEY_METHOD dhx_pkey_meth = {
506    EVP_PKEY_DHX,
507    0,
508    pkey_dh_init,
509    pkey_dh_copy,
510    pkey_dh_cleanup,
511
512    0,
513    pkey_dh_paramgen,
514
515    0,
516    pkey_dh_keygen,
517
518    0,
519    0,
520
521    0,
522    0,
523
524    0, 0,
525
526    0, 0, 0, 0,
527
528    0, 0,
529
530    0, 0,
531
532    0,
533    pkey_dh_derive,
534
535    pkey_dh_ctrl,
536    pkey_dh_ctrl_str
537};
538
539const EVP_PKEY_METHOD *ossl_dhx_pkey_method(void)
540{
541    return &dhx_pkey_meth;
542}
543