From 5d5d2e1f0265f590fb33dd354f8c603cd4fe6572 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 18 Nov 2020 18:16:22 +0100 Subject: [PATCH] Check that curves in set_groups functions are valid --- src/ssl.c | 433 ++++++++++++++++++++++++++++++++++++++---- src/tls13.c | 36 +++- wolfcrypt/src/asn.c | 12 +- wolfssl/openssl/ssl.h | 4 +- wolfssl/ssl.h | 6 + 5 files changed, 444 insertions(+), 47 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index b8d4135de..68187a0b6 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -133,6 +133,7 @@ int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi); int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi); int oid2nid(word32 oid, int grp); + word32 nid2oid(int nid, int grp); #endif #if defined(WOLFSSL_QT) @@ -2377,11 +2378,8 @@ int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, byte status_type, /* Elliptic Curves */ #if defined(HAVE_SUPPORTED_CURVES) && !defined(NO_WOLFSSL_CLIENT) -int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name) +static int isValidCurveGroup(word16 name) { - if (ssl == NULL) - return BAD_FUNC_ARG; - switch (name) { case WOLFSSL_ECC_SECP160K1: case WOLFSSL_ECC_SECP160R1: @@ -2405,11 +2403,17 @@ int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name) case WOLFSSL_FFDHE_4096: case WOLFSSL_FFDHE_6144: case WOLFSSL_FFDHE_8192: - break; + return 0; default: return BAD_FUNC_ARG; } +} + +int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name) +{ + if (ssl == NULL || isValidCurveGroup(name) != 0) + return BAD_FUNC_ARG; ssl->options.userCurves = 1; @@ -2419,42 +2423,72 @@ int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name) int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name) { - if (ctx == NULL) + if (ctx == NULL || isValidCurveGroup(name) != 0) return BAD_FUNC_ARG; - switch (name) { - case WOLFSSL_ECC_SECP160K1: - case WOLFSSL_ECC_SECP160R1: - case WOLFSSL_ECC_SECP160R2: - case WOLFSSL_ECC_SECP192K1: - case WOLFSSL_ECC_SECP192R1: - case WOLFSSL_ECC_SECP224K1: - case WOLFSSL_ECC_SECP224R1: - case WOLFSSL_ECC_SECP256K1: - case WOLFSSL_ECC_SECP256R1: - case WOLFSSL_ECC_SECP384R1: - case WOLFSSL_ECC_SECP521R1: - case WOLFSSL_ECC_BRAINPOOLP256R1: - case WOLFSSL_ECC_BRAINPOOLP384R1: - case WOLFSSL_ECC_BRAINPOOLP512R1: - case WOLFSSL_ECC_X25519: - case WOLFSSL_ECC_X448: - case WOLFSSL_FFDHE_2048: - case WOLFSSL_FFDHE_3072: - case WOLFSSL_FFDHE_4096: - case WOLFSSL_FFDHE_6144: - case WOLFSSL_FFDHE_8192: - break; - - default: - return BAD_FUNC_ARG; - } - ctx->userCurves = 1; return TLSX_UseSupportedCurve(&ctx->extensions, name, ctx->heap); } +#ifdef OPENSSL_EXTRA +int wolfSSL_CTX_set1_groups(WOLFSSL_CTX* ctx, int* groups, + int count) +{ + int i; + int _groups[WOLFSSL_MAX_GROUP_COUNT]; + WOLFSSL_ENTER("wolfSSL_CTX_set1_groups"); + if (count == 0) { + WOLFSSL_MSG("Group count is zero"); + return WOLFSSL_FAILURE; + } + for (i = 0; i < count; i++) { + if (isValidCurveGroup(groups[i]) == 0) { + _groups[i] = groups[i]; + } + else { + /* groups may be populated with curve NIDs */ + int oid = nid2oid(groups[i], oidCurveType); + int name = (int)GetCurveByOID(oid); + if (name == 0) { + WOLFSSL_MSG("Invalid group name"); + return WOLFSSL_FAILURE; + } + _groups[i] = name; + } + } + return wolfSSL_CTX_set_groups(ctx, _groups, count) == WOLFSSL_SUCCESS ? + WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} + +int wolfSSL_set1_groups(WOLFSSL* ssl, int* groups, int count) +{ + int i; + int _groups[WOLFSSL_MAX_GROUP_COUNT]; + WOLFSSL_ENTER("wolfSSL_CTX_set1_groups"); + if (count == 0) { + WOLFSSL_MSG("Group count is zero"); + return WOLFSSL_FAILURE; + } + for (i = 0; i < count; i++) { + if (isValidCurveGroup(groups[i]) == 0) { + _groups[i] = groups[i]; + } + else { + /* groups may be populated with curve NIDs */ + int oid = nid2oid(groups[i], oidCurveType); + int name = (int)GetCurveByOID(oid); + if (name == 0) { + WOLFSSL_MSG("Invalid group name"); + return WOLFSSL_FAILURE; + } + _groups[i] = name; + } + } + return wolfSSL_set_groups(ssl, _groups, count) == WOLFSSL_SUCCESS ? + WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} +#endif #endif /* HAVE_SUPPORTED_CURVES && !NO_WOLFSSL_CLIENT */ /* QSH quantum safe handshake */ @@ -48151,6 +48185,337 @@ int wolfSSL_set_alpn_protos(WOLFSSL* ssl, #include "src/bio.c" #endif +word32 nid2oid(int nid, int grp) +{ + /* get OID type */ + switch (grp) { + /* oidHashType */ + case oidHashType: + switch (nid) { + #ifdef WOLFSSL_MD2 + case NID_md2: + return MD2h; + #endif + #ifndef NO_MD5 + case NID_md5: + return MD5h; + #endif + #ifndef NO_SHA + case NID_sha1: + return SHAh; + #endif + case NID_sha224: + return SHA224h; + #ifndef NO_SHA256 + case NID_sha256: + return SHA256h; + #endif + #ifdef WOLFSSL_SHA384 + case NID_sha384: + return SHA384h; + #endif + #ifdef WOLFSSL_SHA512 + case NID_sha512: + return SHA512h; + #endif + } + break; + + /* oidSigType */ + case oidSigType: + switch (nid) { + #ifndef NO_DSA + case CTC_SHAwDSA: + return CTC_SHAwDSA; + #endif /* NO_DSA */ + #ifndef NO_RSA + case CTC_MD2wRSA: + return CTC_MD2wRSA; + case CTC_MD5wRSA: + return CTC_MD5wRSA; + case CTC_SHAwRSA: + return CTC_SHAwRSA; + case CTC_SHA224wRSA: + return CTC_SHA224wRSA; + case CTC_SHA256wRSA: + return CTC_SHA256wRSA; + case CTC_SHA384wRSA: + return CTC_SHA384wRSA; + case CTC_SHA512wRSA: + return CTC_SHA512wRSA; + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case CTC_SHAwECDSA: + return CTC_SHAwECDSA; + case CTC_SHA224wECDSA: + return CTC_SHA224wECDSA; + case CTC_SHA256wECDSA: + return CTC_SHA256wECDSA; + case CTC_SHA384wECDSA: + return CTC_SHA384wECDSA; + case CTC_SHA512wECDSA: + return CTC_SHA512wECDSA; + #endif /* HAVE_ECC */ + } + break; + + /* oidKeyType */ + case oidKeyType: + switch (nid) { + #ifndef NO_DSA + case DSAk: + return DSAk; + #endif /* NO_DSA */ + #ifndef NO_RSA + case RSAk: + return RSAk; + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + case NTRUk: + return NTRUk; + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ECDSAk: + return ECDSAk; + #endif /* HAVE_ECC */ + } + break; + + + #ifdef HAVE_ECC + case oidCurveType: + switch (nid) { + case NID_X9_62_prime192v1: + return ECC_SECP192R1_OID; + case NID_X9_62_prime192v2: + return ECC_PRIME192V2_OID; + case NID_X9_62_prime192v3: + return ECC_PRIME192V3_OID; + case NID_X9_62_prime239v1: + return ECC_PRIME239V1_OID; + case NID_X9_62_prime239v2: + return ECC_PRIME239V2_OID; + case NID_X9_62_prime239v3: + return ECC_PRIME239V3_OID; + case NID_X9_62_prime256v1: + return ECC_SECP256R1_OID; + case NID_secp112r1: + return ECC_SECP112R1_OID; + case NID_secp112r2: + return ECC_SECP112R2_OID; + case NID_secp128r1: + return ECC_SECP128R1_OID; + case NID_secp128r2: + return ECC_SECP128R2_OID; + case NID_secp160r1: + return ECC_SECP160R1_OID; + case NID_secp160r2: + return ECC_SECP160R2_OID; + case NID_secp224r1: + return ECC_SECP224R1_OID; + case NID_secp384r1: + return ECC_SECP384R1_OID; + case NID_secp521r1: + return ECC_SECP521R1_OID; + case NID_secp160k1: + return ECC_SECP160K1_OID; + case NID_secp192k1: + return ECC_SECP192K1_OID; + case NID_secp224k1: + return ECC_SECP224K1_OID; + case NID_secp256k1: + return ECC_SECP256K1_OID; + case NID_brainpoolP160r1: + return ECC_BRAINPOOLP160R1_OID; + case NID_brainpoolP192r1: + return ECC_BRAINPOOLP192R1_OID; + case NID_brainpoolP224r1: + return ECC_BRAINPOOLP224R1_OID; + case NID_brainpoolP256r1: + return ECC_BRAINPOOLP256R1_OID; + case NID_brainpoolP320r1: + return ECC_BRAINPOOLP320R1_OID; + case NID_brainpoolP384r1: + return ECC_BRAINPOOLP384R1_OID; + case NID_brainpoolP512r1: + return ECC_BRAINPOOLP512R1_OID; + } + break; + #endif /* HAVE_ECC */ + + /* oidBlkType */ + case oidBlkType: + switch (nid) { + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + return AES128CBCb; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + return AES192CBCb; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + return AES256CBCb; + #endif + #ifndef NO_DES3 + case NID_des: + return DESb; + case NID_des3: + return DES3b; + #endif + } + break; + + #ifdef HAVE_OCSP + case oidOcspType: + switch (nid) { + case NID_id_pkix_OCSP_basic: + return OCSP_BASIC_OID; + case OCSP_NONCE_OID: + return OCSP_NONCE_OID; + } + break; + #endif /* HAVE_OCSP */ + + /* oidCertExtType */ + case oidCertExtType: + switch (nid) { + case BASIC_CA_OID: + return BASIC_CA_OID; + case ALT_NAMES_OID: + return ALT_NAMES_OID; + case CRL_DIST_OID: + return CRL_DIST_OID; + case AUTH_INFO_OID: + return AUTH_INFO_OID; + case AUTH_KEY_OID: + return AUTH_KEY_OID; + case SUBJ_KEY_OID: + return SUBJ_KEY_OID; + case INHIBIT_ANY_OID: + return INHIBIT_ANY_OID; + case NID_key_usage: + return KEY_USAGE_OID; + case NID_name_constraints: + return NAME_CONS_OID; + case NID_certificate_policies: + return CERT_POLICY_OID; + } + break; + + /* oidCertAuthInfoType */ + case oidCertAuthInfoType: + switch (nid) { + case AIA_OCSP_OID: + return AIA_OCSP_OID; + case AIA_CA_ISSUER_OID: + return AIA_CA_ISSUER_OID; + } + break; + + /* oidCertPolicyType */ + case oidCertPolicyType: + switch (nid) { + case NID_any_policy: + return CP_ANY_OID; + } + break; + + /* oidCertAltNameType */ + case oidCertAltNameType: + switch (nid) { + case NID_hw_name_oid: + return HW_NAME_OID; + } + break; + + /* oidCertKeyUseType */ + case oidCertKeyUseType: + switch (nid) { + case NID_anyExtendedKeyUsage: + return EKU_ANY_OID; + case EKU_SERVER_AUTH_OID: + return EKU_SERVER_AUTH_OID; + case EKU_CLIENT_AUTH_OID: + return EKU_CLIENT_AUTH_OID; + case EKU_OCSP_SIGN_OID: + return EKU_OCSP_SIGN_OID; + } + break; + + /* oidKdfType */ + case oidKdfType: + switch (nid) { + case PBKDF2_OID: + return PBKDF2_OID; + } + break; + + /* oidPBEType */ + case oidPBEType: + switch (nid) { + case PBE_SHA1_RC4_128: + return PBE_SHA1_RC4_128; + case PBE_SHA1_DES: + return PBE_SHA1_DES; + case PBE_SHA1_DES3: + return PBE_SHA1_DES3; + } + break; + + /* oidKeyWrapType */ + case oidKeyWrapType: + switch (nid) { + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + return AES128_WRAP; + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + return AES192_WRAP; + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + return AES256_WRAP; + #endif + } + break; + + /* oidCmsKeyAgreeType */ + case oidCmsKeyAgreeType: + switch (nid) { + #ifndef NO_SHA + case dhSinglePass_stdDH_sha1kdf_scheme: + return dhSinglePass_stdDH_sha1kdf_scheme; + #endif + #ifdef WOLFSSL_SHA224 + case dhSinglePass_stdDH_sha224kdf_scheme: + return dhSinglePass_stdDH_sha224kdf_scheme; + #endif + #ifndef NO_SHA256 + case dhSinglePass_stdDH_sha256kdf_scheme: + return dhSinglePass_stdDH_sha256kdf_scheme; + #endif + #ifdef WOLFSSL_SHA384 + case dhSinglePass_stdDH_sha384kdf_scheme: + return dhSinglePass_stdDH_sha384kdf_scheme; + #endif + #ifdef WOLFSSL_SHA512 + case dhSinglePass_stdDH_sha512kdf_scheme: + return dhSinglePass_stdDH_sha512kdf_scheme; + #endif + } + break; + + default: + WOLFSSL_MSG("NID not in table"); + return -1; + } + + return -1; +} + int oid2nid(word32 oid, int grp) { size_t i; diff --git a/src/tls13.c b/src/tls13.c index 1ec927efe..027be809f 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -8063,15 +8063,26 @@ int wolfSSL_preferred_group(WOLFSSL* ssl) */ int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count) { - int i; + int ret, i; + WOLFSSL_ENTER("wolfSSL_CTX_set_groups"); if (ctx == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT) return BAD_FUNC_ARG; if (!IsAtLeastTLSv1_3(ctx->method->version)) return BAD_FUNC_ARG; - for (i = 0; i < count; i++) - ctx->group[i] = (word16)groups[i]; + ctx->numGroups = 0; + TLSX_Remove(&ctx->extensions, TLSX_SUPPORTED_GROUPS, ctx->heap); + for (i = 0; i < count; i++) { + /* Call to wolfSSL_CTX_UseSupportedCurve also checks if input groups + * are valid */ + if ((ret = wolfSSL_CTX_UseSupportedCurve(ctx, groups[i])) + != WOLFSSL_SUCCESS) { + TLSX_Remove(&ctx->extensions, TLSX_SUPPORTED_GROUPS, ctx->heap); + return ret; + } + ctx->group[i] = groups[i]; + } ctx->numGroups = (byte)count; return WOLFSSL_SUCCESS; @@ -8087,20 +8098,31 @@ int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count) */ int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count) { - int i; + int ret, i; + WOLFSSL_ENTER("wolfSSL_set_groups"); if (ssl == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT) return BAD_FUNC_ARG; if (!IsAtLeastTLSv1_3(ssl->version)) return BAD_FUNC_ARG; - for (i = 0; i < count; i++) - ssl->group[i] = (word16)groups[i]; + ssl->numGroups = 0; + TLSX_Remove(&ssl->extensions, TLSX_SUPPORTED_GROUPS, ssl->heap); + for (i = 0; i < count; i++) { + /* Call to wolfSSL_UseSupportedCurve also checks if input groups + * are valid */ + if ((ret = wolfSSL_UseSupportedCurve(ssl, groups[i])) + != WOLFSSL_SUCCESS) { + TLSX_Remove(&ssl->extensions, TLSX_SUPPORTED_GROUPS, ssl->heap); + return ret; + } + ssl->group[i] = groups[i]; + } ssl->numGroups = (byte)count; return WOLFSSL_SUCCESS; } -#endif +#endif /* HAVE_SUPPORTED_CURVES */ #ifndef NO_PSK void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX* ctx, diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index be73518e2..32dfd5896 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -5603,9 +5603,10 @@ int wc_OBJ_sn2nid(const char *sn) {WOLFSSL_ORGUNIT_NAME, NID_organizationalUnitName}, {WOLFSSL_EMAIL_ADDR, NID_emailAddress}, {NULL, -1}}; - int i; #ifdef HAVE_ECC + char curveName[16]; /* Same as MAX_CURVE_NAME_SZ but can't include that + * symbol in this file */ int eccEnum; #endif WOLFSSL_ENTER("OBJ_sn2nid"); @@ -5618,8 +5619,11 @@ int wc_OBJ_sn2nid(const char *sn) /* Nginx uses this OpenSSL string. */ if (XSTRNCMP(sn, "prime256v1", 10) == 0) sn = "SECP256R1"; - if (XSTRNCMP(sn, "secp384r1", 10) == 0) - sn = "SECP384R1"; + /* OpenSSL allows lowercase curve names */ + for (i = 0; i < (int)(sizeof(curveName) - 1) && *sn; i++) { + curveName[i] = XTOUPPER(*sn++); + } + curveName[i] = '\0'; /* find based on name and return NID */ for (i = 0; #ifndef WOLFSSL_ECC_CURVE_STATIC @@ -5628,7 +5632,7 @@ int wc_OBJ_sn2nid(const char *sn) ecc_sets[i].size != 0; #endif i++) { - if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) { + if (XSTRNCMP(curveName, ecc_sets[i].name, ECC_MAXNAME) == 0) { eccEnum = ecc_sets[i].id; /* Convert enum value in ecc_curve_id to OpenSSL NID */ return EccEnumToNID(eccEnum); diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 6475f705a..564263cdb 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -303,8 +303,8 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; /* wolfSSL does not support exporting keying material */ #define SSL_export_keying_material wolfSSL_export_keying_material -#define SSL_CTX_set1_groups wolfSSL_CTX_set_groups -#define SSL_set1_groups wolfSSL_set_groups +#define SSL_CTX_set1_groups wolfSSL_CTX_set1_groups +#define SSL_set1_groups wolfSSL_set1_groups #define SSL_CTX_set1_groups_list wolfSSL_CTX_set1_groups_list #define SSL_set1_groups_list wolfSSL_set1_groups_list diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index c02f5d9f1..cab58bc2e 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -921,6 +921,12 @@ WOLFSSL_API int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count); WOLFSSL_API int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count); +#ifdef OPENSSL_EXTRA +WOLFSSL_API int wolfSSL_CTX_set1_groups(WOLFSSL_CTX* ctx, int* groups, + int count); +WOLFSSL_API int wolfSSL_set1_groups(WOLFSSL* ssl, int* groups, int count); +#endif + WOLFSSL_API int wolfSSL_connect_TLSv13(WOLFSSL*); WOLFSSL_API int wolfSSL_accept_TLSv13(WOLFSSL*);