1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include "internal/ffc.h"
11e1051a39Sopenharmony_ci#include "internal/nelem.h"
12e1051a39Sopenharmony_ci#include "crypto/bn_dh.h"
13e1051a39Sopenharmony_ci
14e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DH
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci# define FFDHE(sz, keylength) {                                             \
17e1051a39Sopenharmony_ci        SN_ffdhe##sz, NID_ffdhe##sz,                                        \
18e1051a39Sopenharmony_ci        sz,                                                                 \
19e1051a39Sopenharmony_ci        keylength,                                                          \
20e1051a39Sopenharmony_ci        &ossl_bignum_ffdhe##sz##_p, &ossl_bignum_ffdhe##sz##_q,             \
21e1051a39Sopenharmony_ci        &ossl_bignum_const_2,                                               \
22e1051a39Sopenharmony_ci    }
23e1051a39Sopenharmony_ci
24e1051a39Sopenharmony_ci# define MODP(sz, keylength)  {                                             \
25e1051a39Sopenharmony_ci        SN_modp_##sz, NID_modp_##sz,                                        \
26e1051a39Sopenharmony_ci        sz,                                                                 \
27e1051a39Sopenharmony_ci        keylength,                                                          \
28e1051a39Sopenharmony_ci        &ossl_bignum_modp_##sz##_p, &ossl_bignum_modp_##sz##_q,             \
29e1051a39Sopenharmony_ci        &ossl_bignum_const_2                                                \
30e1051a39Sopenharmony_ci    }
31e1051a39Sopenharmony_ci
32e1051a39Sopenharmony_ci# define RFC5114(name, uid, sz, tag) {                                      \
33e1051a39Sopenharmony_ci        name, uid,                                                          \
34e1051a39Sopenharmony_ci        sz,                                                                 \
35e1051a39Sopenharmony_ci        0,                                                                  \
36e1051a39Sopenharmony_ci        &ossl_bignum_dh##tag##_p, &ossl_bignum_dh##tag##_q,                 \
37e1051a39Sopenharmony_ci        &ossl_bignum_dh##tag##_g                                            \
38e1051a39Sopenharmony_ci    }
39e1051a39Sopenharmony_ci
40e1051a39Sopenharmony_ci#else
41e1051a39Sopenharmony_ci
42e1051a39Sopenharmony_ci# define FFDHE(sz, keylength)           { SN_ffdhe##sz, NID_ffdhe##sz }
43e1051a39Sopenharmony_ci# define MODP(sz, keylength)            { SN_modp_##sz, NID_modp_##sz }
44e1051a39Sopenharmony_ci# define RFC5114(name, uid, sz, tag)    { name, uid }
45e1051a39Sopenharmony_ci
46e1051a39Sopenharmony_ci#endif
47e1051a39Sopenharmony_ci
48e1051a39Sopenharmony_cistruct dh_named_group_st {
49e1051a39Sopenharmony_ci    const char *name;
50e1051a39Sopenharmony_ci    int uid;
51e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DH
52e1051a39Sopenharmony_ci    int32_t nbits;
53e1051a39Sopenharmony_ci    int keylength;
54e1051a39Sopenharmony_ci    const BIGNUM *p;
55e1051a39Sopenharmony_ci    const BIGNUM *q;
56e1051a39Sopenharmony_ci    const BIGNUM *g;
57e1051a39Sopenharmony_ci#endif
58e1051a39Sopenharmony_ci};
59e1051a39Sopenharmony_ci
60e1051a39Sopenharmony_ci/*
61e1051a39Sopenharmony_ci * The private key length values are taken from RFC7919 with the values for
62e1051a39Sopenharmony_ci * MODP primes given the same lengths as the equivalent FFDHE.
63e1051a39Sopenharmony_ci * The MODP 1536 value is approximated.
64e1051a39Sopenharmony_ci */
65e1051a39Sopenharmony_cistatic const DH_NAMED_GROUP dh_named_groups[] = {
66e1051a39Sopenharmony_ci    FFDHE(2048, 225),
67e1051a39Sopenharmony_ci    FFDHE(3072, 275),
68e1051a39Sopenharmony_ci    FFDHE(4096, 325),
69e1051a39Sopenharmony_ci    FFDHE(6144, 375),
70e1051a39Sopenharmony_ci    FFDHE(8192, 400),
71e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
72e1051a39Sopenharmony_ci    MODP(1536, 200),
73e1051a39Sopenharmony_ci#endif
74e1051a39Sopenharmony_ci    MODP(2048, 225),
75e1051a39Sopenharmony_ci    MODP(3072, 275),
76e1051a39Sopenharmony_ci    MODP(4096, 325),
77e1051a39Sopenharmony_ci    MODP(6144, 375),
78e1051a39Sopenharmony_ci    MODP(8192, 400),
79e1051a39Sopenharmony_ci    /*
80e1051a39Sopenharmony_ci     * Additional dh named groups from RFC 5114 that have a different g.
81e1051a39Sopenharmony_ci     * The uid can be any unique identifier.
82e1051a39Sopenharmony_ci     */
83e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
84e1051a39Sopenharmony_ci    RFC5114("dh_1024_160", 1, 1024, 1024_160),
85e1051a39Sopenharmony_ci    RFC5114("dh_2048_224", 2, 2048, 2048_224),
86e1051a39Sopenharmony_ci    RFC5114("dh_2048_256", 3, 2048, 2048_256),
87e1051a39Sopenharmony_ci#endif
88e1051a39Sopenharmony_ci};
89e1051a39Sopenharmony_ci
90e1051a39Sopenharmony_ciconst DH_NAMED_GROUP *ossl_ffc_name_to_dh_named_group(const char *name)
91e1051a39Sopenharmony_ci{
92e1051a39Sopenharmony_ci    size_t i;
93e1051a39Sopenharmony_ci
94e1051a39Sopenharmony_ci    for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) {
95e1051a39Sopenharmony_ci        if (OPENSSL_strcasecmp(dh_named_groups[i].name, name) == 0)
96e1051a39Sopenharmony_ci            return &dh_named_groups[i];
97e1051a39Sopenharmony_ci    }
98e1051a39Sopenharmony_ci    return NULL;
99e1051a39Sopenharmony_ci}
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_ciconst DH_NAMED_GROUP *ossl_ffc_uid_to_dh_named_group(int uid)
102e1051a39Sopenharmony_ci{
103e1051a39Sopenharmony_ci    size_t i;
104e1051a39Sopenharmony_ci
105e1051a39Sopenharmony_ci    for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) {
106e1051a39Sopenharmony_ci        if (dh_named_groups[i].uid == uid)
107e1051a39Sopenharmony_ci            return &dh_named_groups[i];
108e1051a39Sopenharmony_ci    }
109e1051a39Sopenharmony_ci    return NULL;
110e1051a39Sopenharmony_ci}
111e1051a39Sopenharmony_ci
112e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DH
113e1051a39Sopenharmony_ciconst DH_NAMED_GROUP *ossl_ffc_numbers_to_dh_named_group(const BIGNUM *p,
114e1051a39Sopenharmony_ci                                                         const BIGNUM *q,
115e1051a39Sopenharmony_ci                                                         const BIGNUM *g)
116e1051a39Sopenharmony_ci{
117e1051a39Sopenharmony_ci    size_t i;
118e1051a39Sopenharmony_ci
119e1051a39Sopenharmony_ci    for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) {
120e1051a39Sopenharmony_ci        /* Keep searching until a matching p and g is found */
121e1051a39Sopenharmony_ci        if (BN_cmp(p, dh_named_groups[i].p) == 0
122e1051a39Sopenharmony_ci            && BN_cmp(g, dh_named_groups[i].g) == 0
123e1051a39Sopenharmony_ci            /* Verify q is correct if it exists */
124e1051a39Sopenharmony_ci            && (q == NULL || BN_cmp(q, dh_named_groups[i].q) == 0))
125e1051a39Sopenharmony_ci            return &dh_named_groups[i];
126e1051a39Sopenharmony_ci    }
127e1051a39Sopenharmony_ci    return NULL;
128e1051a39Sopenharmony_ci}
129e1051a39Sopenharmony_ci#endif
130e1051a39Sopenharmony_ci
131e1051a39Sopenharmony_ciint ossl_ffc_named_group_get_uid(const DH_NAMED_GROUP *group)
132e1051a39Sopenharmony_ci{
133e1051a39Sopenharmony_ci    if (group == NULL)
134e1051a39Sopenharmony_ci        return NID_undef;
135e1051a39Sopenharmony_ci    return group->uid;
136e1051a39Sopenharmony_ci}
137e1051a39Sopenharmony_ci
138e1051a39Sopenharmony_ciconst char *ossl_ffc_named_group_get_name(const DH_NAMED_GROUP *group)
139e1051a39Sopenharmony_ci{
140e1051a39Sopenharmony_ci    if (group == NULL)
141e1051a39Sopenharmony_ci        return NULL;
142e1051a39Sopenharmony_ci    return group->name;
143e1051a39Sopenharmony_ci}
144e1051a39Sopenharmony_ci
145e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DH
146e1051a39Sopenharmony_ciint ossl_ffc_named_group_get_keylength(const DH_NAMED_GROUP *group)
147e1051a39Sopenharmony_ci{
148e1051a39Sopenharmony_ci    if (group == NULL)
149e1051a39Sopenharmony_ci        return 0;
150e1051a39Sopenharmony_ci    return group->keylength;
151e1051a39Sopenharmony_ci}
152e1051a39Sopenharmony_ci
153e1051a39Sopenharmony_ciconst BIGNUM *ossl_ffc_named_group_get_q(const DH_NAMED_GROUP *group)
154e1051a39Sopenharmony_ci{
155e1051a39Sopenharmony_ci    if (group == NULL)
156e1051a39Sopenharmony_ci        return NULL;
157e1051a39Sopenharmony_ci    return group->q;
158e1051a39Sopenharmony_ci}
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_ciint ossl_ffc_named_group_set(FFC_PARAMS *ffc, const DH_NAMED_GROUP *group)
161e1051a39Sopenharmony_ci{
162e1051a39Sopenharmony_ci    if (ffc == NULL || group == NULL)
163e1051a39Sopenharmony_ci        return 0;
164e1051a39Sopenharmony_ci
165e1051a39Sopenharmony_ci    ossl_ffc_params_set0_pqg(ffc, (BIGNUM *)group->p, (BIGNUM *)group->q,
166e1051a39Sopenharmony_ci                             (BIGNUM *)group->g);
167e1051a39Sopenharmony_ci    ffc->keylength = group->keylength;
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci    /* flush the cached nid, The DH layer is responsible for caching */
170e1051a39Sopenharmony_ci    ffc->nid = NID_undef;
171e1051a39Sopenharmony_ci    return 1;
172e1051a39Sopenharmony_ci}
173e1051a39Sopenharmony_ci#endif
174