X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fdh%2Fdh_group_params.c;h=1f5a58ed87acbc939042a66f24d46a40e4dc5ec7;hp=4996e854f59c86dc65ece92623bc12ff68c1212f;hb=7165593ce5a07a6860d4d408ad640ee707172936;hpb=ca2bf555cd64bc9624af1259ce3cd27f95a5763e diff --git a/crypto/dh/dh_group_params.c b/crypto/dh/dh_group_params.c index 4996e854f5..1f5a58ed87 100644 --- a/crypto/dh/dh_group_params.c +++ b/crypto/dh/dh_group_params.c @@ -9,121 +9,261 @@ /* DH parameters from RFC7919 and RFC3526 */ +/* + * DH low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + #include #include "internal/cryptlib.h" +#include "internal/ffc.h" #include "dh_local.h" #include #include #include "crypto/bn_dh.h" +#include "crypto/dh.h" +#include "crypto/security_bits.h" +#include "e_os.h" /* strcasecmp */ + +#define FFDHE(sz) { \ + SN_ffdhe##sz, NID_ffdhe##sz, \ + sz, \ + &_bignum_ffdhe##sz##_p, NULL, &_bignum_const_2 \ +} + +#define MODP(sz) { \ + SN_modp_##sz, NID_modp_##sz, \ + sz, \ + &_bignum_modp_##sz##_p, NULL, &_bignum_const_2 \ +} + +#define RFC5114(name, uid, sz, tag) { \ + name, uid, \ + sz, \ + &_bignum_dh##tag##_p, &_bignum_dh##tag##_q, &_bignum_dh##tag##_g \ +} -static DH *dh_param_init(int nid, const BIGNUM *p, int32_t nbits) +typedef struct dh_named_group_st { + const char *name; + int uid; + int32_t nbits; + const BIGNUM *p; + const BIGNUM *q; + const BIGNUM *g; +} DH_NAMED_GROUP; + + +static const DH_NAMED_GROUP dh_named_groups[] = { + FFDHE(2048), + FFDHE(3072), + FFDHE(4096), + FFDHE(6144), + FFDHE(8192), +#ifndef FIPS_MODE + 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_MODE + 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 +}; + +int ffc_named_group_to_uid(const char *name) { - BIGNUM *q = NULL; - DH *dh = DH_new(); + 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].uid; + } + return NID_undef; +} + +const char *ffc_named_group_from_uid(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].name; + } + return NULL; +} + +static DH *dh_param_init(OPENSSL_CTX *libctx, int uid, const BIGNUM *p, + const BIGNUM *q, const BIGNUM *g, + int32_t nbits) +{ + BIGNUM *qtmp = NULL; + DH *dh = dh_new_with_libctx(libctx); if (dh == NULL) return NULL; - q = BN_dup(p); - /* Set q = (p - 1) / 2 (p is known to be odd so just shift right ) */ - if (q == NULL || !BN_rshift1(q, q)) { - BN_free(q); - DH_free(dh); - return NULL; + if (q == NULL) { + qtmp = BN_dup(p); + /* Set q = (p - 1) / 2 (p is known to be odd so just shift right ) */ + if (qtmp == NULL || !BN_rshift1(qtmp, qtmp)) { + BN_free(qtmp); + DH_free(dh); + return NULL; + } } - dh->params.nid = nid; + dh->params.nid = uid; dh->params.p = (BIGNUM *)p; - dh->params.q = (BIGNUM *)q; - dh->params.g = (BIGNUM *)&_bignum_const_2; + dh->params.q = (q != NULL ? (BIGNUM *)q : qtmp); + dh->params.g = (BIGNUM *)g; /* Private key length = 2 * max_target_security_strength */ dh->length = nbits; dh->dirty_cnt++; return dh; } -DH *DH_new_by_nid(int nid) +static DH *dh_new_by_group_name(OPENSSL_CTX *libctx, const char *name) { - /* - * The last parameter specified in these fields is - * 2 * max_target_security_strength. - * See SP800-56Ar3 Table(s) 25 & 26. - */ - switch (nid) { - case NID_ffdhe2048: - return dh_param_init(nid, &_bignum_ffdhe2048_p, 225); - case NID_ffdhe3072: - return dh_param_init(nid, &_bignum_ffdhe3072_p, 275); - case NID_ffdhe4096: - return dh_param_init(nid, &_bignum_ffdhe4096_p, 325); - case NID_ffdhe6144: - return dh_param_init(nid, &_bignum_ffdhe6144_p, 375); - case NID_ffdhe8192: - return dh_param_init(nid, &_bignum_ffdhe8192_p, 400); -#ifndef FIPS_MODE - case NID_modp_1536: - return dh_param_init(nid, &_bignum_modp_1536_p, 190); -#endif - case NID_modp_2048: - return dh_param_init(nid, &_bignum_modp_2048_p, 225); - case NID_modp_3072: - return dh_param_init(nid, &_bignum_modp_3072_p, 275); - case NID_modp_4096: - return dh_param_init(nid, &_bignum_modp_4096_p, 325); - case NID_modp_6144: - return dh_param_init(nid, &_bignum_modp_6144_p, 375); - case NID_modp_8192: - return dh_param_init(nid, &_bignum_modp_8192_p, 400); - default: - DHerr(DH_F_DH_NEW_BY_NID, DH_R_INVALID_PARAMETER_NID); + int i; + + if (name == NULL) return NULL; + + for (i = 0; i < (int)OSSL_NELEM(dh_named_groups); ++i) { + if (strcasecmp(dh_named_groups[i].name, name) == 0) { + int max_target_security_strength = + ifc_ffc_compute_security_bits(dh_named_groups[i].nbits); + + /* + * The last parameter specified here is + * 2 * max_target_security_strength. + * See SP800-56Ar3 Table(s) 25 & 26. + */ + return dh_param_init(libctx, dh_named_groups[i].uid, + dh_named_groups[i].p, + dh_named_groups[i].q, + dh_named_groups[i].g, + 2 * max_target_security_strength); + } + } + DHerr(0, DH_R_INVALID_PARAMETER_NID); + return NULL; +} + +DH *dh_new_by_nid_with_libctx(OPENSSL_CTX *libctx, int nid) +{ + const char *name = ffc_named_group_from_uid(nid); + + return dh_new_by_group_name(libctx, name); +} + +DH *DH_new_by_nid(int nid) +{ + return dh_new_by_nid_with_libctx(NULL, nid); +} + +int ffc_set_group_pqg(FFC_PARAMS *ffc, const char *group_name) +{ + int i; + BIGNUM *q = NULL; + + if (ffc == NULL) + return 0; + + for (i = 0; i < (int)OSSL_NELEM(dh_named_groups); ++i) { + if (strcasecmp(dh_named_groups[i].name, group_name) == 0) { + if (dh_named_groups[i].q != NULL) { + /* For groups with a q */ + ffc_params_set0_pqg(ffc, + (BIGNUM *)dh_named_groups[i].p, + (BIGNUM *)dh_named_groups[i].q, + (BIGNUM *)dh_named_groups[i].g); + } else { + /* For SAFE PRIME GROUPS */ + /* Set q = (p - 1) / 2 (p is known to be odd so just shift right) */ + q = BN_dup(dh_named_groups[i].p); + if (q == NULL || !BN_rshift1(q, q)) + break; /* exit with failure */ + + ffc_params_set0_pqg(ffc, + (BIGNUM *)dh_named_groups[i].p, q, + (BIGNUM *)dh_named_groups[i].g); + } + /* flush the cached nid, The DH layer is responsible for caching */ + ffc->nid = NID_undef; + return 1; + } } + /* gets here on error or if the name was not found */ + BN_free(q); + return 0; } int DH_get_nid(DH *dh) { - int nid = dh->params.nid; + BIGNUM *q = NULL; + int i, nid; + + if (dh == NULL) + return NID_undef; + nid = dh->params.nid; + /* Just return if it is already cached */ if (nid != NID_undef) return nid; - if (BN_get_word(dh->params.g) != 2) - return NID_undef; - if (!BN_cmp(dh->params.p, &_bignum_ffdhe2048_p)) - nid = NID_ffdhe2048; - else if (!BN_cmp(dh->params.p, &_bignum_ffdhe3072_p)) - nid = NID_ffdhe3072; - else if (!BN_cmp(dh->params.p, &_bignum_ffdhe4096_p)) - nid = NID_ffdhe4096; - else if (!BN_cmp(dh->params.p, &_bignum_ffdhe6144_p)) - nid = NID_ffdhe6144; - else if (!BN_cmp(dh->params.p, &_bignum_ffdhe8192_p)) - nid = NID_ffdhe8192; -#ifndef FIPS_MODE - else if (!BN_cmp(dh->params.p, &_bignum_modp_1536_p)) - nid = NID_modp_1536; -#endif - else if (!BN_cmp(dh->params.p, &_bignum_modp_2048_p)) - nid = NID_modp_2048; - else if (!BN_cmp(dh->params.p, &_bignum_modp_3072_p)) - nid = NID_modp_3072; - else if (!BN_cmp(dh->params.p, &_bignum_modp_4096_p)) - nid = NID_modp_4096; - else if (!BN_cmp(dh->params.p, &_bignum_modp_6144_p)) - nid = NID_modp_6144; - else if (!BN_cmp(dh->params.p, &_bignum_modp_8192_p)) - nid = NID_modp_8192; - else - return NID_undef; + for (i = 0; i < (int)OSSL_NELEM(dh_named_groups); ++i) { + /* Keep searching until a matching p is found */ + if (BN_cmp(dh->params.p, dh_named_groups[i].p) != 0) + continue; + + /* Return an error if g is not matching */ + if (BN_cmp(dh->params.g, dh_named_groups[i].g) != 0) + break; + if (dh_named_groups[i].q != NULL) { + /* RFC5114 NAMED GROUPS have q defined */ + + /* Verify q is correct if it exists */ + if (dh->params.q != NULL) { + if (BN_cmp(dh->params.q, dh_named_groups[i].q) != 0) + break; /* returns nid = NID_undef if q does not match */ + } else { + dh->params.q = (BIGNUM *)dh_named_groups[i].q; + } + } else { + /* For SAFE PRIME GROUPS */ + + /* Set q = (p - 1) / 2 (p is known to be odd so just shift right) */ + q = BN_dup(dh->params.p); - /* Verify q is correct if it exists - reset the nid if it is not correct */ - if (dh->params.q != NULL) { - BIGNUM *q = BN_dup(dh->params.p); + if (q == NULL || !BN_rshift1(q, q)) + break; /* returns nid = NID_undef on failure */ - /* Check q = p * 2 + 1 we already know q is odd, so just shift right */ - if (q == NULL || !BN_rshift1(q, q) || (BN_cmp(dh->params.q, q) != 0)) - nid = NID_undef; - BN_free(q); + /* Verify q is correct if it exists */ + if (dh->params.q != NULL) { + if (BN_cmp(dh->params.q, q) != 0) + break; /* returns nid = NID_undef if q does not match */ + } else { + /* assign the calculated q */ + dh->params.q = q; + q = NULL; /* set to NULL so it is not freed */ + } + } + nid = dh->params.nid = dh_named_groups[i].uid; /* cache the nid */ + dh->length = + 2 * ifc_ffc_compute_security_bits(dh_named_groups[i].nbits); + dh->dirty_cnt++; + /* A matching p was found so break out of the loop */ + break; } - dh->params.nid = nid; /* cache the nid */ + BN_free(q); return nid; }