| /* |
| * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. |
| * |
| * Licensed under the Apache License 2.0 (the "License"). You may not use |
| * this file except in compliance with the License. You can obtain a copy |
| * in the file LICENSE in the source distribution or at |
| * https://www.openssl.org/source/license.html |
| */ |
| |
| #include "internal/ffc.h" |
| #include "internal/nelem.h" |
| #include "crypto/bn_dh.h" |
| #include "internal/e_os.h" /* strcasecmp */ |
| |
| #ifndef OPENSSL_NO_DH |
| |
| # define FFDHE(sz) { \ |
| SN_ffdhe##sz, NID_ffdhe##sz, \ |
| sz, \ |
| &ossl_bignum_ffdhe##sz##_p, &ossl_bignum_ffdhe##sz##_q, \ |
| &ossl_bignum_const_2, \ |
| } |
| |
| # define MODP(sz) { \ |
| SN_modp_##sz, NID_modp_##sz, \ |
| sz, \ |
| &ossl_bignum_modp_##sz##_p, &ossl_bignum_modp_##sz##_q, \ |
| &ossl_bignum_const_2 \ |
| } |
| |
| # define RFC5114(name, uid, sz, tag) { \ |
| name, uid, \ |
| sz, \ |
| &ossl_bignum_dh##tag##_p, &ossl_bignum_dh##tag##_q, \ |
| &ossl_bignum_dh##tag##_g \ |
| } |
| |
| #else |
| |
| # define FFDHE(sz) { SN_ffdhe##sz, NID_ffdhe##sz } |
| # define MODP(sz) { SN_modp_##sz, NID_modp_##sz } |
| # define RFC5114(name, uid, sz, tag) { name, uid } |
| |
| #endif |
| |
| struct dh_named_group_st { |
| const char *name; |
| int uid; |
| #ifndef OPENSSL_NO_DH |
| int32_t nbits; |
| const BIGNUM *p; |
| const BIGNUM *q; |
| const BIGNUM *g; |
| #endif |
| }; |
| |
| static const DH_NAMED_GROUP dh_named_groups[] = { |
| FFDHE(2048), |
| FFDHE(3072), |
| FFDHE(4096), |
| FFDHE(6144), |
| FFDHE(8192), |
| #ifndef FIPS_MODULE |
| MODP(1536), |
| #endif |
| MODP(2048), |
| MODP(3072), |
| MODP(4096), |
| MODP(6144), |
| MODP(8192), |
| /* |
| * Additional dh named groups from RFC 5114 that have a different g. |
| * The uid can be any unique identifier. |
| */ |
| #ifndef FIPS_MODULE |
| RFC5114("dh_1024_160", 1, 1024, 1024_160), |
| RFC5114("dh_2048_224", 2, 2048, 2048_224), |
| RFC5114("dh_2048_256", 3, 2048, 2048_256), |
| #endif |
| }; |
| |
| const DH_NAMED_GROUP *ossl_ffc_name_to_dh_named_group(const char *name) |
| { |
| size_t i; |
| |
| for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) { |
| if (strcasecmp(dh_named_groups[i].name, name) == 0) |
| return &dh_named_groups[i]; |
| } |
| return NULL; |
| } |
| |
| const DH_NAMED_GROUP *ossl_ffc_uid_to_dh_named_group(int uid) |
| { |
| size_t i; |
| |
| for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) { |
| if (dh_named_groups[i].uid == uid) |
| return &dh_named_groups[i]; |
| } |
| return NULL; |
| } |
| |
| #ifndef OPENSSL_NO_DH |
| const DH_NAMED_GROUP *ossl_ffc_numbers_to_dh_named_group(const BIGNUM *p, |
| const BIGNUM *q, |
| const BIGNUM *g) |
| { |
| size_t i; |
| |
| for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) { |
| /* Keep searching until a matching p and g is found */ |
| if (BN_cmp(p, dh_named_groups[i].p) == 0 |
| && BN_cmp(g, dh_named_groups[i].g) == 0 |
| /* Verify q is correct if it exists */ |
| && (q == NULL || BN_cmp(q, dh_named_groups[i].q) == 0)) |
| return &dh_named_groups[i]; |
| } |
| return NULL; |
| } |
| #endif |
| |
| int ossl_ffc_named_group_get_uid(const DH_NAMED_GROUP *group) |
| { |
| if (group == NULL) |
| return NID_undef; |
| return group->uid; |
| } |
| |
| const char *ossl_ffc_named_group_get_name(const DH_NAMED_GROUP *group) |
| { |
| if (group == NULL) |
| return NULL; |
| return group->name; |
| } |
| |
| #ifndef OPENSSL_NO_DH |
| const BIGNUM *ossl_ffc_named_group_get_q(const DH_NAMED_GROUP *group) |
| { |
| if (group == NULL) |
| return NULL; |
| return group->q; |
| } |
| |
| int ossl_ffc_named_group_set_pqg(FFC_PARAMS *ffc, const DH_NAMED_GROUP *group) |
| { |
| if (ffc == NULL || group == NULL) |
| return 0; |
| |
| ossl_ffc_params_set0_pqg(ffc, (BIGNUM *)group->p, (BIGNUM *)group->q, |
| (BIGNUM *)group->g); |
| |
| /* flush the cached nid, The DH layer is responsible for caching */ |
| ffc->nid = NID_undef; |
| return 1; |
| } |
| #endif |