Correct error reason of verify_signature() in cmp_vfy.c
[openssl.git] / crypto / cmp / cmp_vfy.c
index 8980d72..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).
@@ -32,7 +34,7 @@ static int verify_signature(const OSSL_CMP_CTX *cmp_ctx,
                             const OSSL_CMP_MSG *msg, X509 *cert)
 {
     EVP_MD_CTX *ctx = NULL;
-    CMP_PROTECTEDPART prot_part;
+    OSSL_CMP_PROTECTEDPART prot_part;
     int digest_nid, pk_nid;
     const EVP_MD *digest = NULL;
     EVP_PKEY *pubkey = NULL;
@@ -62,7 +64,7 @@ static int verify_signature(const OSSL_CMP_CTX *cmp_ctx,
     prot_part.header = msg->header;
     prot_part.body = msg->body;
 
-    len = i2d_CMP_PROTECTEDPART(&prot_part, &prot_part_der);
+    len = i2d_OSSL_CMP_PROTECTEDPART(&prot_part, &prot_part_der);
     if (len < 0 || prot_part_der == NULL)
         goto end;
     prot_part_der_len = (size_t) len;
@@ -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);
@@ -577,6 +599,11 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
     switch (nid) {
         /* 5.1.3.1.  Shared Secret Information */
     case NID_id_PasswordBasedMAC:
+        if (ctx->secretValue == 0) {
+            CMPerr(0, CMP_R_CHECKING_PBM_NO_SECRET_AVAILABLE);
+            break;
+        }
+
         if (verify_PBMAC(msg, ctx->secretValue)) {
             /*
              * RFC 4210, 5.3.2: 'Note that if the PKI Message Protection is
@@ -624,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))
@@ -695,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 */
@@ -722,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 */
@@ -731,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
     }
 
     /*
@@ -771,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;
 }