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