Invoke tear_down when exiting test_encode_tls_sct() prematurely
[openssl.git] / crypto / dh / dh_check.c
index 85ef17b36fa4531417df1c8960603fe4e3e712c1..ae23f61839eab39ef2106fd11e8d13950195e306 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 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
@@ -33,18 +33,18 @@ int DH_check_params_ex(const DH *dh)
         return 0;
 
     if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
-        DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_CHECK_P_NOT_PRIME);
+        ERR_raise(ERR_LIB_DH, DH_R_CHECK_P_NOT_PRIME);
     if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
-        DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_NOT_SUITABLE_GENERATOR);
+        ERR_raise(ERR_LIB_DH, DH_R_NOT_SUITABLE_GENERATOR);
     if ((errflags & DH_MODULUS_TOO_SMALL) != 0)
-        DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_MODULUS_TOO_SMALL);
+        ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL);
     if ((errflags & DH_MODULUS_TOO_LARGE) != 0)
-        DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_MODULUS_TOO_LARGE);
+        ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
 
     return errflags == 0;
 }
 
-#ifdef FIPS_MODE
+#ifdef FIPS_MODULE
 int DH_check_params(const DH *dh, int *ret)
 {
     int nid;
@@ -62,8 +62,8 @@ int DH_check_params(const DH *dh, int *ret)
      * (2b) FFC domain params conform to FIPS-186-4 explicit domain param
      * validity tests.
      */
-    return ffc_params_FIPS186_4_validate(&dh->params, FFC_PARAM_TYPE_DH, NULL,
-                                         FFC_PARAMS_VALIDATE_ALL, ret, NULL);
+    return ossl_ffc_params_FIPS186_4_validate(dh->libctx, &dh->params,
+                                              FFC_PARAM_TYPE_DH, ret, NULL);
 }
 #else
 int DH_check_params(const DH *dh, int *ret)
@@ -73,7 +73,7 @@ int DH_check_params(const DH *dh, int *ret)
     BN_CTX *ctx = NULL;
 
     *ret = 0;
-    ctx = BN_CTX_new();
+    ctx = BN_CTX_new_ex(dh->libctx);
     if (ctx == NULL)
         goto err;
     BN_CTX_start(ctx);
@@ -102,7 +102,7 @@ int DH_check_params(const DH *dh, int *ret)
     BN_CTX_free(ctx);
     return ok;
 }
-#endif /* FIPS_MODE */
+#endif /* FIPS_MODULE */
 
 /*-
  * Check that p is a safe prime and
@@ -116,23 +116,23 @@ int DH_check_ex(const DH *dh)
         return 0;
 
     if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
-        DHerr(DH_F_DH_CHECK_EX, DH_R_NOT_SUITABLE_GENERATOR);
+        ERR_raise(ERR_LIB_DH, DH_R_NOT_SUITABLE_GENERATOR);
     if ((errflags & DH_CHECK_Q_NOT_PRIME) != 0)
-        DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_Q_NOT_PRIME);
+        ERR_raise(ERR_LIB_DH, DH_R_CHECK_Q_NOT_PRIME);
     if ((errflags & DH_CHECK_INVALID_Q_VALUE) != 0)
-        DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_Q_VALUE);
+        ERR_raise(ERR_LIB_DH, DH_R_CHECK_INVALID_Q_VALUE);
     if ((errflags & DH_CHECK_INVALID_J_VALUE) != 0)
-        DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_J_VALUE);
+        ERR_raise(ERR_LIB_DH, DH_R_CHECK_INVALID_J_VALUE);
     if ((errflags & DH_UNABLE_TO_CHECK_GENERATOR) != 0)
-        DHerr(DH_F_DH_CHECK_EX, DH_R_UNABLE_TO_CHECK_GENERATOR);
+        ERR_raise(ERR_LIB_DH, DH_R_UNABLE_TO_CHECK_GENERATOR);
     if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
-        DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_PRIME);
+        ERR_raise(ERR_LIB_DH, DH_R_CHECK_P_NOT_PRIME);
     if ((errflags & DH_CHECK_P_NOT_SAFE_PRIME) != 0)
-        DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_SAFE_PRIME);
+        ERR_raise(ERR_LIB_DH, DH_R_CHECK_P_NOT_SAFE_PRIME);
     if ((errflags & DH_MODULUS_TOO_SMALL) != 0)
-        DHerr(DH_F_DH_CHECK_EX, DH_R_MODULUS_TOO_SMALL);
+        ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL);
     if ((errflags & DH_MODULUS_TOO_LARGE) != 0)
-        DHerr(DH_F_DH_CHECK_EX, DH_R_MODULUS_TOO_LARGE);
+        ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
 
     return errflags == 0;
 }
@@ -140,10 +140,10 @@ int DH_check_ex(const DH *dh)
 /* Note: according to documentation - this only checks the params */
 int DH_check(const DH *dh, int *ret)
 {
-#ifdef FIPS_MODE
+#ifdef FIPS_MODULE
     return DH_check_params(dh, ret);
 #else
-    int ok = 0, r;
+    int ok = 0, r, q_good = 0;
     BN_CTX *ctx = NULL;
     BIGNUM *t1 = NULL, *t2 = NULL;
     int nid = DH_get_nid((DH *)dh);
@@ -152,10 +152,17 @@ int DH_check(const DH *dh, int *ret)
     if (nid != NID_undef)
         return 1;
 
+    /* Don't do any checks at all with an excessively large modulus */
+    if (BN_num_bits(dh->params.p) > OPENSSL_DH_CHECK_MAX_MODULUS_BITS) {
+        ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
+        *ret = DH_MODULUS_TOO_LARGE | DH_CHECK_P_NOT_PRIME;
+        return 0;
+    }
+
     if (!DH_check_params(dh, ret))
         return 0;
 
-    ctx = BN_CTX_new();
+    ctx = BN_CTX_new_ex(dh->libctx);
     if (ctx == NULL)
         goto err;
     BN_CTX_start(ctx);
@@ -165,6 +172,13 @@ int DH_check(const DH *dh, int *ret)
         goto err;
 
     if (dh->params.q != NULL) {
+        if (BN_ucmp(dh->params.p, dh->params.q) > 0)
+            q_good = 1;
+        else
+            *ret |= DH_CHECK_INVALID_Q_VALUE;
+    }
+
+    if (q_good) {
         if (BN_cmp(dh->params.g, BN_value_one()) <= 0)
             *ret |= DH_NOT_SUITABLE_GENERATOR;
         else if (BN_cmp(dh->params.g, dh->params.p) >= 0)
@@ -210,7 +224,7 @@ int DH_check(const DH *dh, int *ret)
     BN_CTX_end(ctx);
     BN_CTX_free(ctx);
     return ok;
-#endif /* FIPS_MODE */
+#endif /* FIPS_MODULE */
 }
 
 int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key)
@@ -221,11 +235,11 @@ int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key)
         return 0;
 
     if ((errflags & DH_CHECK_PUBKEY_TOO_SMALL) != 0)
-        DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_SMALL);
+        ERR_raise(ERR_LIB_DH, DH_R_CHECK_PUBKEY_TOO_SMALL);
     if ((errflags & DH_CHECK_PUBKEY_TOO_LARGE) != 0)
-        DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_LARGE);
+        ERR_raise(ERR_LIB_DH, DH_R_CHECK_PUBKEY_TOO_LARGE);
     if ((errflags & DH_CHECK_PUBKEY_INVALID) != 0)
-        DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_INVALID);
+        ERR_raise(ERR_LIB_DH, DH_R_CHECK_PUBKEY_INVALID);
 
     return errflags == 0;
 }
@@ -235,7 +249,19 @@ int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key)
  */
 int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
 {
-    return ffc_validate_public_key(&dh->params, pub_key, ret);
+    /* Don't do any checks at all with an excessively large modulus */
+    if (BN_num_bits(dh->params.p) > OPENSSL_DH_CHECK_MAX_MODULUS_BITS) {
+        ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
+        *ret = DH_MODULUS_TOO_LARGE | DH_CHECK_PUBKEY_INVALID;
+        return 0;
+    }
+
+    if (dh->params.q != NULL && BN_ucmp(dh->params.p, dh->params.q) < 0) {
+        *ret |= DH_CHECK_INVALID_Q_VALUE | DH_CHECK_PUBKEY_INVALID;
+        return 1;
+    }
+
+    return ossl_ffc_validate_public_key(&dh->params, pub_key, ret);
 }
 
 /*
@@ -243,12 +269,13 @@ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
  * To only be used with ephemeral FFC public keys generated using the approved
  * safe-prime groups.
  */
-int dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret)
+int ossl_dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret)
 {
-    return ffc_validate_public_key_partial(&dh->params, pub_key, ret);
+    return ossl_ffc_validate_public_key_partial(&dh->params, pub_key, ret)
+           && *ret == 0;
 }
 
-int dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret)
+int ossl_dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret)
 {
     int ok = 0;
     BIGNUM *two_powN = NULL, *upper;
@@ -257,22 +284,43 @@ int dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret)
     two_powN = BN_new();
     if (two_powN == NULL)
         return 0;
-    if (dh->params.q == NULL)
-        goto err;
-    upper = dh->params.q;
+
+    if (dh->params.q != NULL) {
+        upper = dh->params.q;
+#ifndef FIPS_MODULE
+    } else if (dh->params.p != NULL) {
+        /*
+         * We do not have q so we just check the key is within some
+         * reasonable range, or the number of bits is equal to dh->length.
+         */
+        int length = dh->length;
+
+        if (length == 0) {
+            length = BN_num_bits(dh->params.p) - 1;
+            if (BN_num_bits(priv_key) <= length
+                && BN_num_bits(priv_key) > 1)
+                ok = 1;
+        } else if (BN_num_bits(priv_key) == length) {
+            ok = 1;
+        }
+        goto end;
+#endif
+    } else {
+        goto end;
+    }
 
     /* Is it from an approved Safe prime group ?*/
-    if (DH_get_nid((DH *)dh) != NID_undef) {
+    if (DH_get_nid((DH *)dh) != NID_undef && dh->length != 0) {
         if (!BN_lshift(two_powN, BN_value_one(), dh->length))
-            goto err;
+            goto end;
         if (BN_cmp(two_powN, dh->params.q) < 0)
             upper = two_powN;
     }
-    if (!ffc_validate_private_key(upper, priv_key, ret))
-        goto err;
+    if (!ossl_ffc_validate_private_key(upper, priv_key, ret))
+        goto end;
 
     ok = 1;
-err:
+end:
     BN_free(two_powN);
     return ok;
 }
@@ -281,7 +329,7 @@ err:
  * FFC pairwise check from SP800-56A R3.
  *    Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency
  */
-int dh_check_pairwise(DH *dh)
+int ossl_dh_check_pairwise(const DH *dh)
 {
     int ret = 0;
     BN_CTX *ctx = NULL;
@@ -301,9 +349,9 @@ int dh_check_pairwise(DH *dh)
         goto err;
 
     /* recalculate the public key = (g ^ priv) mod p */
-    if (!dh_generate_public_key(ctx, dh, dh->priv_key, pub_key))
+    if (!ossl_dh_generate_public_key(ctx, dh, dh->priv_key, pub_key))
         goto err;
-    /* check it matches the existing pubic_key */
+    /* check it matches the existing public_key */
     ret = BN_cmp(pub_key, dh->pub_key) == 0;
 err:
     BN_free(pub_key);