Correct error reason of verify_signature() in cmp_vfy.c
[openssl.git] / crypto / cmp / cmp_vfy.c
index 1ee1b33..f73a0a0 100644 (file)
@@ -22,6 +22,8 @@
 #include <openssl/x509.h>
 #include "crypto/x509.h"
 
+DEFINE_STACK_OF(X509)
+
 /*
  * Verify a message protected by signature according to section 5.1.3.3
  * (sha1+RSA/DSA or any other algorithm supported by OpenSSL).
@@ -93,7 +95,7 @@ static int verify_signature(const OSSL_CMP_CTX *cmp_ctx,
 
  sig_err:
     res = x509_print_ex_brief(bio, cert, X509_FLAG_NO_EXTENSIONS);
-    CMPerr(0, CMP_R_ERROR_VALIDATING_PROTECTION);
+    CMPerr(0, CMP_R_ERROR_VALIDATING_SIGNATURE);
     if (res)
         ERR_add_error_mem_bio("\n", bio);
     res = 0;
@@ -557,6 +559,7 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
     int nid = NID_undef, pk_nid = NID_undef;
     const ASN1_OBJECT *algorOID = NULL;
     X509 *scrt;
+    const X509_NAME *expected_sender;
 
     if (ctx == NULL || msg == NULL
             || msg->header == NULL || msg->body == NULL) {
@@ -564,6 +567,25 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
         return 0;
     }
 
+    /* validate sender name of received msg */
+    if (msg->header->sender->type != GEN_DIRNAME) {
+        CMPerr(0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
+        return 0; /* TODO FR#42: support for more than X509_NAME */
+    }
+    /*
+     * Compare actual sender name of response with expected sender name.
+     * Mitigates risk to accept misused PBM secret
+     * or misused certificate of an unauthorized entity of a trusted hierarchy.
+     */
+    expected_sender = ctx->expected_sender;
+    if (expected_sender == NULL && ctx->srvCert != NULL)
+        expected_sender = X509_get_subject_name(ctx->srvCert);
+    if (!check_name(ctx, "sender DN field",
+                    msg->header->sender->d.directoryName,
+                    "expected sender", expected_sender))
+        return 0;
+    /* Note: if recipient was NULL-DN it could be learned here if needed */
+
     if ((alg = msg->header->protectionAlg) == NULL /* unprotected message */
             || msg->protection == NULL || msg->protection->data == NULL) {
         CMPerr(0, CMP_R_MISSING_PROTECTION);
@@ -629,23 +651,6 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
             CMPerr(0, CMP_R_UNKNOWN_ALGORITHM_ID);
             break;
         }
-        /* validate sender name of received msg */
-        if (msg->header->sender->type != GEN_DIRNAME) {
-            CMPerr(0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
-            break; /* FR#42: support for more than X509_NAME */
-        }
-        /*
-         * Compare actual sender name of response with expected sender name.
-         * Expected name can be set explicitly or the subject of ctx->srvCert.
-         * Mitigates risk to accept misused certificate of an unauthorized
-         * entity of a trusted hierarchy.
-         */
-        if (!check_name(ctx, "sender DN field",
-                        msg->header->sender->d.directoryName,
-                        "expected sender", ctx->expected_sender))
-            break;
-        /* Note: if recipient was NULL-DN it could be learned here if needed */
-
         scrt = ctx->srvCert;
         if (scrt == NULL) {
             if (check_msg_find_cert(ctx, msg))
@@ -700,26 +705,34 @@ int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
         /* detect explicitly permitted exceptions for invalid protection */
         if (!OSSL_CMP_validate_msg(ctx, msg)
                 && (cb == NULL || (*cb)(ctx, msg, 1, cb_arg) <= 0)) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
             CMPerr(0, CMP_R_ERROR_VALIDATING_PROTECTION);
             return -1;
+#endif
         }
     } else {
         /* detect explicitly permitted exceptions for missing protection */
         if (cb == NULL || (*cb)(ctx, msg, 0, cb_arg) <= 0) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
             CMPerr(0, CMP_R_MISSING_PROTECTION);
             return -1;
+#endif
         }
     }
 
     /* check CMP version number in header */
     if (ossl_cmp_hdr_get_pvno(OSSL_CMP_MSG_get0_header(msg)) != OSSL_CMP_PVNO) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
         CMPerr(0, CMP_R_UNEXPECTED_PVNO);
         return -1;
+#endif
     }
 
     if ((rcvd_type = ossl_cmp_msg_get_bodytype(msg)) < 0) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
         CMPerr(0, CMP_R_PKIBODY_ERROR);
         return -1;
+#endif
     }
 
     /* compare received transactionID with the expected one in previous msg */
@@ -727,8 +740,10 @@ int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
             && (msg->header->transactionID == NULL
                 || ASN1_OCTET_STRING_cmp(ctx->transactionID,
                                          msg->header->transactionID) != 0)) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
         CMPerr(0, CMP_R_TRANSACTIONID_UNMATCHED);
         return -1;
+#endif
     }
 
     /* compare received nonce with the one we sent */
@@ -736,8 +751,10 @@ int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
             && (msg->header->recipNonce == NULL
                 || ASN1_OCTET_STRING_cmp(ctx->senderNonce,
                                          msg->header->recipNonce) != 0)) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
         CMPerr(0, CMP_R_RECIPNONCE_UNMATCHED);
         return -1;
+#endif
     }
 
     /*
@@ -776,19 +793,27 @@ int ossl_cmp_verify_popo(const OSSL_CMP_MSG *msg, int accept_RAVerified)
         {
             X509_REQ *req = msg->body->value.p10cr;
 
-            if (X509_REQ_verify(req, X509_REQ_get0_pubkey(req)) > 0)
-                return 1;
-            CMPerr(0, CMP_R_REQUEST_NOT_ACCEPTED);
-            return 0;
+            if (X509_REQ_verify(req, X509_REQ_get0_pubkey(req)) <= 0) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+                CMPerr(0, CMP_R_REQUEST_NOT_ACCEPTED);
+                return 0;
+#endif
+            }
         }
+        break;
     case OSSL_CMP_PKIBODY_IR:
     case OSSL_CMP_PKIBODY_CR:
     case OSSL_CMP_PKIBODY_KUR:
-        return OSSL_CRMF_MSGS_verify_popo(msg->body->value.ir,
-                                          OSSL_CMP_CERTREQID,
-                                          accept_RAVerified);
+        if (!OSSL_CRMF_MSGS_verify_popo(msg->body->value.ir, OSSL_CMP_CERTREQID,
+                                        accept_RAVerified)) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+            return 0;
+#endif
+        }
+        break;
     default:
         CMPerr(0, CMP_R_PKIBODY_ERROR);
         return 0;
     }
+    return 1;
 }