Allow subject of CMP -oldcert as sender unless protection cert is given
[openssl.git] / crypto / cmp / cmp_hdr.c
index 29f477f1b5dce1c31ebafb3827724284a6e2c231..38b3bce3f5ddccc791f4580dc86fa37c8ae22073 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright Nokia 2007-2019
  * Copyright Siemens AG 2015-2019
  *
@@ -20,6 +20,9 @@
 #include <openssl/cmp.h>
 #include <openssl/err.h>
 
+DEFINE_STACK_OF(ASN1_UTF8STRING)
+DEFINE_STACK_OF(OSSL_CMP_ITAV)
+
 int ossl_cmp_hdr_set_pvno(OSSL_CMP_PKIHEADER *hdr, int pvno)
 {
     if (!ossl_assert(hdr != NULL))
@@ -38,7 +41,8 @@ int ossl_cmp_hdr_get_pvno(const OSSL_CMP_PKIHEADER *hdr)
     return (int)pvno;
 }
 
-ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const OSSL_CMP_PKIHEADER *hdr)
+ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const
+                                                   OSSL_CMP_PKIHEADER *hdr)
 {
     if (hdr == NULL) {
         CMPerr(0, CMP_R_NULL_ARGUMENT);
@@ -63,31 +67,42 @@ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr)
     return hdr->recipNonce;
 }
 
+int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name)
+{
+    X509_NAME *null = X509_NAME_new();
+    int res = name == NULL || null == NULL
+        || (name->type == GEN_DIRNAME
+                && X509_NAME_cmp(name->d.directoryName, null) == 0);
+
+    X509_NAME_free(null);
+    return res;
+}
+
 /* assign to *tgt a copy of src (which may be NULL to indicate an empty DN) */
 static int set1_general_name(GENERAL_NAME **tgt, const X509_NAME *src)
 {
-    GENERAL_NAME *gen;
+    GENERAL_NAME *name;
 
     if (!ossl_assert(tgt != NULL))
         return 0;
-    if ((gen = GENERAL_NAME_new()) == NULL)
+    if ((name = GENERAL_NAME_new()) == NULL)
         goto err;
-    gen->type = GEN_DIRNAME;
+    name->type = GEN_DIRNAME;
 
     if (src == NULL) { /* NULL-DN */
-        if ((gen->d.directoryName = X509_NAME_new()) == NULL)
+        if ((name->d.directoryName = X509_NAME_new()) == NULL)
             goto err;
-    } else if (!X509_NAME_set(&gen->d.directoryName, src)) {
+    } else if (!X509_NAME_set(&name->d.directoryName, src)) {
         goto err;
     }
 
     GENERAL_NAME_free(*tgt);
-    *tgt = gen;
+    *tgt = name;
 
     return 1;
 
  err:
-    GENERAL_NAME_free(gen);
+    GENERAL_NAME_free(name);
     return 0;
 }
 
@@ -153,25 +168,6 @@ int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr,
 }
 
 /* push the given text string to the given PKIFREETEXT ft */
-int ossl_cmp_pkifreetext_push_str(OSSL_CMP_PKIFREETEXT *ft, const char *text)
-{
-    ASN1_UTF8STRING *utf8string;
-
-    if (!ossl_assert(ft != NULL && text != NULL))
-        return 0;
-    if ((utf8string = ASN1_UTF8STRING_new()) == NULL)
-        return 0;
-    if (!ASN1_STRING_set(utf8string, text, -1))
-        goto err;
-    if (!sk_ASN1_UTF8STRING_push(ft, utf8string))
-        goto err;
-    return 1;
-
- err:
-    ASN1_UTF8STRING_free(utf8string);
-    return 0;
-}
-
 int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text)
 {
     if (!ossl_assert(hdr != NULL && text != NULL))
@@ -193,7 +189,8 @@ int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text)
             && (hdr->freeText = sk_ASN1_UTF8STRING_new_null()) == NULL)
         return 0;
 
-    return ossl_cmp_pkifreetext_push_str(hdr->freeText, (char *)text->data);
+    return
+        ossl_cmp_sk_ASN1_UTF8STRING_push_str(hdr->freeText, (char *)text->data);
 }
 
 int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr,
@@ -205,7 +202,7 @@ int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr,
 }
 
 int ossl_cmp_hdr_generalInfo_push1_items(OSSL_CMP_PKIHEADER *hdr,
-                                         STACK_OF(OSSL_CMP_ITAV) *itavs)
+                                         const STACK_OF(OSSL_CMP_ITAV) *itavs)
 {
     int i;
     OSSL_CMP_ITAV *itav;
@@ -250,7 +247,7 @@ int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr)
 }
 
 /* return 1 if implicitConfirm in the generalInfo field of the header is set */
-int ossl_cmp_hdr_check_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr)
+int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr)
 {
     int itavCount;
     int i;
@@ -270,11 +267,30 @@ int ossl_cmp_hdr_check_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr)
     return 0;
 }
 
+/*
+ * set ctx->transactionID in CMP header
+ * if ctx->transactionID is NULL, a random one is created with 128 bit
+ * according to section 5.1.1:
+ *
+ * It is RECOMMENDED that the clients fill the transactionID field with
+ * 128 bits of (pseudo-) random data for the start of a transaction to
+ * reduce the probability of having the transactionID in use at the server.
+ */
+int ossl_cmp_hdr_set_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
+{
+    if (ctx->transactionID == NULL
+            && !set1_aostr_else_random(&ctx->transactionID, NULL,
+                                       OSSL_CMP_TRANSACTIONID_LENGTH))
+        return 0;
+    return ossl_cmp_asn1_octet_string_set1(&hdr->transactionID,
+                                           ctx->transactionID);
+}
+
 /* fill in all fields of the hdr according to the info given in ctx */
 int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
 {
-    X509_NAME *sender;
-    X509_NAME *rcp = NULL;
+    const X509_NAME *sender;
+    const X509_NAME *rcp = NULL;
 
     if (!ossl_assert(ctx != NULL && hdr != NULL))
         return 0;
@@ -283,40 +299,33 @@ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
     if (!ossl_cmp_hdr_set_pvno(hdr, OSSL_CMP_PVNO))
         return 0;
 
-    sender = ctx->clCert != NULL ?
-        X509_get_subject_name(ctx->clCert) : ctx->subjectName;
     /*
-     * The sender name is copied from the subject of the client cert, if any,
-     * or else from the the subject name provided for certification requests.
-     * As required by RFC 4210 section 5.1.1., if the sender name is not known
-     * to the client it set to NULL-DN. In this case for identification at least
-     * the senderKID must be set, which we take from any referenceValue given.
+     * If neither protection cert nor oldCert nor subject are given,
+     * sender name is not known to the client and thus set to NULL-DN
      */
-    if (sender == NULL && ctx->referenceValue == NULL) {
-        CMPerr(0, CMP_R_MISSING_SENDER_IDENTIFICATION);
-        return 0;
-    }
+    sender = ctx->cert != NULL ? X509_get_subject_name(ctx->cert) :
+        ctx->oldCert != NULL ? X509_get_subject_name(ctx->oldCert) :
+        ctx->subjectName;
     if (!ossl_cmp_hdr_set1_sender(hdr, sender))
         return 0;
 
     /* determine recipient entry in PKIHeader */
-    if (ctx->srvCert != NULL) {
-        rcp = X509_get_subject_name(ctx->srvCert);
-        /* set also as expected_sender of responses unless set explicitly */
-        if (ctx->expected_sender == NULL && rcp != NULL
-                && !OSSL_CMP_CTX_set1_expected_sender(ctx, rcp))
-            return 0;
-    } else if (ctx->recipient != NULL) {
+    if (ctx->recipient != NULL)
         rcp = ctx->recipient;
-    } else if (ctx->issuer != NULL) {
+    else if (ctx->srvCert != NULL)
+        rcp = X509_get_subject_name(ctx->srvCert);
+    else if (ctx->issuer != NULL)
         rcp = ctx->issuer;
-    } else if (ctx->oldCert != NULL) {
+    else if (ctx->oldCert != NULL)
         rcp = X509_get_issuer_name(ctx->oldCert);
-    } else if (ctx->clCert != NULL) {
-        rcp = X509_get_issuer_name(ctx->clCert);
-    }
+    else if (ctx->cert != NULL)
+        rcp = X509_get_issuer_name(ctx->cert);
     if (!ossl_cmp_hdr_set1_recipient(hdr, rcp))
         return 0;
+    /* set also as expected_sender of responses unless set explicitly */
+    if (ctx->expected_sender == NULL && rcp != NULL
+        && !OSSL_CMP_CTX_set1_expected_sender(ctx, rcp))
+        return 0;
 
     /* set current time as message time */
     if (!ossl_cmp_hdr_update_messageTime(hdr))
@@ -327,21 +336,7 @@ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
                                                 ctx->recipNonce))
         return 0;
 
-    /*
-     * set ctx->transactionID in CMP header
-     * if ctx->transactionID is NULL, a random one is created with 128 bit
-     * according to section 5.1.1:
-     *
-     * It is RECOMMENDED that the clients fill the transactionID field with
-     * 128 bits of (pseudo-) random data for the start of a transaction to
-     * reduce the probability of having the transactionID in use at the server.
-     */
-    if (ctx->transactionID == NULL
-            && !set1_aostr_else_random(&ctx->transactionID, NULL,
-                                       OSSL_CMP_TRANSACTIONID_LENGTH))
-        return 0;
-    if (!ossl_cmp_asn1_octet_string_set1(&hdr->transactionID,
-                                         ctx->transactionID))
+    if (!ossl_cmp_hdr_set_transactionID(ctx, hdr))
         return 0;
 
     /*-