[openssl] master update

Matt Caswell matt at openssl.org
Tue Dec 8 14:43:48 UTC 2020


The branch master has been updated
       via  1e13198fa72943dd7e5154d7250a86b93a8f7e47 (commit)
       via  22b88fc9c0e22545401c0b34d24843883ea73fec (commit)
       via  97ab3c4b538840037812c8d9164d09a1f4bf11a1 (commit)
       via  3db2c9f3e5fb9f649ebb4a55918398756310af43 (commit)
       via  43a7033a010feaf72c79d39df65ca733fb9dcd4c (commit)
       via  b33c48b75aaf33c93aeda42d7138616b9e6a64cb (commit)
       via  198b11683568452282bd48828fcf60d4835bf327 (commit)
      from  c1131e6a0e4a9a9734559f7a58b278c027d76711 (commit)


- Log -----------------------------------------------------------------
commit 1e13198fa72943dd7e5154d7250a86b93a8f7e47
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Dec 8 11:19:41 2020 +0000

    Update CHANGES and NEWS for new release
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 22b88fc9c0e22545401c0b34d24843883ea73fec
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Nov 30 14:46:47 2020 +0000

    Add a test for encoding/decoding using an invalid ASN.1 Template
    
    If you have a CHOICE type that it must use explicit tagging - otherwise
    the template is invalid. We add tests for this.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>

commit 97ab3c4b538840037812c8d9164d09a1f4bf11a1
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Nov 30 13:50:52 2020 +0000

    Add a test for GENERAL_NAME_cmp
    
    Based on a boringssl test contributed by David Benjamin
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>

commit 3db2c9f3e5fb9f649ebb4a55918398756310af43
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 12 14:55:31 2020 +0000

    Complain if we are attempting to encode with an invalid ASN.1 template
    
    It never makes sense for multi-string or CHOICE types to have implicit
    tagging. If we have a template that uses the in this way then we
    should immediately fail.
    
    Thanks to David Benjamin from Google for reporting this issue.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>

commit 43a7033a010feaf72c79d39df65ca733fb9dcd4c
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 12 11:58:12 2020 +0000

    Check that multi-strings/CHOICE types don't use implicit tagging
    
    It never makes sense for multi-string or CHOICE types to use implicit
    tagging since the content would be ambiguous. It is an error in the
    template if this ever happens. If we detect it we should stop parsing.
    
    Thanks to David Benjamin from Google for reporting this issue.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>

commit b33c48b75aaf33c93aeda42d7138616b9e6a64cb
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Nov 11 16:12:58 2020 +0000

    Correctly compare EdiPartyName in GENERAL_NAME_cmp()
    
    If a GENERAL_NAME field contained EdiPartyName data then it was
    incorrectly being handled as type "other". This could lead to a
    segmentation fault.
    
    Many thanks to David Benjamin from Google for reporting this issue.
    
    CVE-2020-1971
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>

commit 198b11683568452282bd48828fcf60d4835bf327
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Nov 11 15:19:34 2020 +0000

    DirectoryString is a CHOICE type and therefore uses explicit tagging
    
    EDIPartyName has 2 fields that use a DirectoryString. However they were
    marked as implicit tagging - which is not correct for a CHOICE type.
    
    Additionally the partyName field was marked as Optional when, according to
    RFC5280 it is not.
    
    Many thanks to github user @filipnavara for reporting this issue. Also to
    David Benjamin from Google who independently identified and reported it.
    
    Fixes #6859
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>

-----------------------------------------------------------------------

Summary of changes:
 CHANGES.md                |  15 +-
 NEWS.md                   |   3 +-
 crypto/asn1/asn1_err.c    |   1 +
 crypto/asn1/tasn_dec.c    |  19 +++
 crypto/asn1/tasn_enc.c    |  16 +++
 crypto/err/openssl.txt    |   1 +
 crypto/x509/v3_genn.c     |  50 ++++++-
 include/openssl/asn1err.h |   1 +
 test/asn1_decode_test.c   |  36 +++++
 test/asn1_encode_test.c   |  33 +++++
 test/v3nametest.c         | 344 ++++++++++++++++++++++++++++++++++++++++++++++
 11 files changed, 512 insertions(+), 7 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index e3ab1c5562..b099baa27a 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1339,7 +1339,19 @@ OpenSSL 1.1.1
 
 ### Changes between 1.1.1h and 1.1.1i [xx XXX xxxx]
 
- *
+ * Fixed NULL pointer deref in the GENERAL_NAME_cmp function
+   This function could crash if both GENERAL_NAMEs contain an EDIPARTYNAME.
+    If an attacker can control both items being compared  then this could lead
+    to a possible denial of service attack. OpenSSL itself uses the
+    GENERAL_NAME_cmp function for two purposes:
+    1) Comparing CRL distribution point names between an available CRL and a
+       CRL distribution point embedded in an X509 certificate
+    2) When verifying that a timestamp response token signer matches the
+       timestamp authority name (exposed via the API functions
+       TS_RESP_verify_response and TS_RESP_verify_token)
+   ([CVE-2020-1971])
+
+   *Matt Caswell*
 
 ### Changes between 1.1.1g and 1.1.1h [22 Sep 2020]
 
@@ -18662,6 +18674,7 @@ ndif
 
 <!-- Links -->
 
+[CVE-2020-1971]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1971
 [CVE-2020-1967]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1967
 [CVE-2019-1563]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1563
 [CVE-2019-1559]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1559
diff --git a/NEWS.md b/NEWS.md
index 6cd797badf..d02e00b8df 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -77,7 +77,7 @@ OpenSSL 1.1.1
 
 ### Major changes between OpenSSL 1.1.1h and OpenSSL 1.1.1i [under development]
 
-  *
+  * Fixed NULL pointer deref in GENERAL_NAME_cmp ([CVE-2020-1971])
 
 ### Major changes between OpenSSL 1.1.1g and OpenSSL 1.1.1h [22 Sep 2020]
 
@@ -1328,6 +1328,7 @@ OpenSSL 0.9.x
 
 <!-- Links -->
 
+[CVE-2020-1971]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1971
 [CVE-2020-1967]: https://www.openssl.org/news/vulnerabilities.html#CVE-2020-1967
 [CVE-2019-1563]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1563
 [CVE-2019-1559]: https://www.openssl.org/news/vulnerabilities.html#CVE-2019-1559
diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c
index d202094e27..8957519cb2 100644
--- a/crypto/asn1/asn1_err.c
+++ b/crypto/asn1/asn1_err.c
@@ -21,6 +21,7 @@ static const ERR_STRING_DATA ASN1_str_reasons[] = {
     "asn1 sig parse error"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_AUX_ERROR), "aux error"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_OBJECT_HEADER), "bad object header"},
+    {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BAD_TEMPLATE), "bad template"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BMPSTRING_IS_WRONG_LENGTH),
     "bmpstring is wrong length"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_BN_LIB), "bn lib"},
diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c
index 09adbf5d07..9a210e221f 100644
--- a/crypto/asn1/tasn_dec.c
+++ b/crypto/asn1/tasn_dec.c
@@ -183,6 +183,15 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
                                      tag, aclass, opt, ctx);
 
     case ASN1_ITYPE_MSTRING:
+        /*
+         * It never makes sense for multi-strings to have implicit tagging, so
+         * if tag != -1, then this looks like an error in the template.
+         */
+        if (tag != -1) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
+            goto err;
+        }
+
         p = *in;
         /* Just read in tag and class */
         ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,
@@ -200,6 +209,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
             ERR_raise(ERR_LIB_ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL);
             goto err;
         }
+
         /* Check tag matches bit map */
         if (!(ASN1_tag2bit(otag) & it->utype)) {
             /* If OPTIONAL, assume this is OK */
@@ -216,6 +226,15 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
         return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx);
 
     case ASN1_ITYPE_CHOICE:
+        /*
+         * It never makes sense for CHOICE types to have implicit tagging, so
+         * if tag != -1, then this looks like an error in the template.
+         */
+        if (tag != -1) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
+            goto err;
+        }
+
         if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
             goto auxerr;
         if (*pval) {
diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c
index 798dc69650..9d65f294db 100644
--- a/crypto/asn1/tasn_enc.c
+++ b/crypto/asn1/tasn_enc.c
@@ -106,9 +106,25 @@ int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
         return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
 
     case ASN1_ITYPE_MSTRING:
+        /*
+         * It never makes sense for multi-strings to have implicit tagging, so
+         * if tag != -1, then this looks like an error in the template.
+         */
+        if (tag != -1) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
+            return -1;
+        }
         return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
 
     case ASN1_ITYPE_CHOICE:
+        /*
+         * It never makes sense for CHOICE types to have implicit tagging, so
+         * if tag != -1, then this looks like an error in the template.
+         */
+        if (tag != -1) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
+            return -1;
+        }
         if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
             return 0;
         i = asn1_get_choice_selector_const(pval, it);
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 88b6168214..a19ca7ceb9 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -1901,6 +1901,7 @@ ASN1_R_ASN1_PARSE_ERROR:203:asn1 parse error
 ASN1_R_ASN1_SIG_PARSE_ERROR:204:asn1 sig parse error
 ASN1_R_AUX_ERROR:100:aux error
 ASN1_R_BAD_OBJECT_HEADER:102:bad object header
+ASN1_R_BAD_TEMPLATE:230:bad template
 ASN1_R_BMPSTRING_IS_WRONG_LENGTH:214:bmpstring is wrong length
 ASN1_R_BN_LIB:105:bn lib
 ASN1_R_BOOLEAN_IS_WRONG_LENGTH:106:boolean is wrong length
diff --git a/crypto/x509/v3_genn.c b/crypto/x509/v3_genn.c
index 867b9a9070..c0a7166cd0 100644
--- a/crypto/x509/v3_genn.c
+++ b/crypto/x509/v3_genn.c
@@ -22,8 +22,9 @@ ASN1_SEQUENCE(OTHERNAME) = {
 IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
 
 ASN1_SEQUENCE(EDIPARTYNAME) = {
-        ASN1_IMP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
-        ASN1_IMP_OPT(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
+        /* DirectoryString is a CHOICE type so use explicit tagging */
+        ASN1_EXP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
+        ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
 } ASN1_SEQUENCE_END(EDIPARTYNAME)
 
 IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME)
@@ -57,6 +58,37 @@ GENERAL_NAME *GENERAL_NAME_dup(const GENERAL_NAME *a)
                                     (char *)a);
 }
 
+static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b)
+{
+    int res;
+
+    if (a == NULL || b == NULL) {
+        /*
+         * Shouldn't be possible in a valid GENERAL_NAME, but we handle it
+         * anyway. OTHERNAME_cmp treats NULL != NULL so we do the same here
+         */
+        return -1;
+    }
+    if (a->nameAssigner == NULL && b->nameAssigner != NULL)
+        return -1;
+    if (a->nameAssigner != NULL && b->nameAssigner == NULL)
+        return 1;
+    /* If we get here then both have nameAssigner set, or both unset */
+    if (a->nameAssigner != NULL) {
+        res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner);
+        if (res != 0)
+            return res;
+    }
+    /*
+     * partyName is required, so these should never be NULL. We treat it in
+     * the same way as the a == NULL || b == NULL case above
+     */
+    if (a->partyName == NULL || b->partyName == NULL)
+        return -1;
+
+    return ASN1_STRING_cmp(a->partyName, b->partyName);
+}
+
 /* Returns 0 if they are equal, != 0 otherwise. */
 int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
 {
@@ -66,8 +98,11 @@ int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
         return -1;
     switch (a->type) {
     case GEN_X400:
+        result = ASN1_TYPE_cmp(a->d.x400Address, b->d.x400Address);
+        break;
+
     case GEN_EDIPARTY:
-        result = ASN1_TYPE_cmp(a->d.other, b->d.other);
+        result = edipartyname_cmp(a->d.ediPartyName, b->d.ediPartyName);
         break;
 
     case GEN_OTHERNAME:
@@ -114,8 +149,11 @@ void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
 {
     switch (type) {
     case GEN_X400:
+        a->d.x400Address = value;
+        break;
+
     case GEN_EDIPARTY:
-        a->d.other = value;
+        a->d.ediPartyName = value;
         break;
 
     case GEN_OTHERNAME:
@@ -149,8 +187,10 @@ void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype)
         *ptype = a->type;
     switch (a->type) {
     case GEN_X400:
+        return a->d.x400Address;
+
     case GEN_EDIPARTY:
-        return a->d.other;
+        return a->d.ediPartyName;
 
     case GEN_OTHERNAME:
         return a->d.otherName;
diff --git a/include/openssl/asn1err.h b/include/openssl/asn1err.h
index 08281187ef..afae7c3a51 100644
--- a/include/openssl/asn1err.h
+++ b/include/openssl/asn1err.h
@@ -147,6 +147,7 @@
 # define ASN1_R_ASN1_SIG_PARSE_ERROR                      204
 # define ASN1_R_AUX_ERROR                                 100
 # define ASN1_R_BAD_OBJECT_HEADER                         102
+# define ASN1_R_BAD_TEMPLATE                              230
 # define ASN1_R_BMPSTRING_IS_WRONG_LENGTH                 214
 # define ASN1_R_BN_LIB                                    105
 # define ASN1_R_BOOLEAN_IS_WRONG_LENGTH                   106
diff --git a/test/asn1_decode_test.c b/test/asn1_decode_test.c
index b0c031a5a2..c6e1501fa1 100644
--- a/test/asn1_decode_test.c
+++ b/test/asn1_decode_test.c
@@ -160,6 +160,41 @@ static int test_uint64(void)
     return 1;
 }
 
+typedef struct {
+    ASN1_STRING *invalidDirString;
+} INVALIDTEMPLATE;
+
+ASN1_SEQUENCE(INVALIDTEMPLATE) = {
+    /*
+     * DirectoryString is a CHOICE type so it must use explicit tagging -
+     * but we deliberately use implicit here, which makes this template invalid.
+     */
+    ASN1_IMP(INVALIDTEMPLATE, invalidDirString, DIRECTORYSTRING, 12)
+} static_ASN1_SEQUENCE_END(INVALIDTEMPLATE)
+
+IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(INVALIDTEMPLATE)
+IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(INVALIDTEMPLATE)
+
+/* Empty sequence for invalid template test */
+static unsigned char t_invalid_template[] = {
+    0x30, 0x03,                  /* SEQUENCE tag + length */
+    0x0c, 0x01, 0x41             /* UTF8String, length 1, "A" */
+};
+
+static int test_invalid_template(void)
+{
+    const unsigned char *p = t_invalid_template;
+    INVALIDTEMPLATE *tmp = d2i_INVALIDTEMPLATE(NULL, &p,
+                                               sizeof(t_invalid_template));
+
+    /* We expect a NULL pointer return */
+    if (TEST_ptr_null(tmp))
+        return 1;
+
+    INVALIDTEMPLATE_free(tmp);
+    return 0;
+}
+
 int setup_tests(void)
 {
 #ifndef OPENSSL_NO_DEPRECATED_3_0
@@ -169,5 +204,6 @@ int setup_tests(void)
     ADD_TEST(test_uint32);
     ADD_TEST(test_int64);
     ADD_TEST(test_uint64);
+    ADD_TEST(test_invalid_template);
     return 1;
 }
diff --git a/test/asn1_encode_test.c b/test/asn1_encode_test.c
index 4ff8a20ff4..27f522b222 100644
--- a/test/asn1_encode_test.c
+++ b/test/asn1_encode_test.c
@@ -856,6 +856,38 @@ static int test_uint64(void)
     return test_intern(&uint64_test_package);
 }
 
+typedef struct {
+    ASN1_STRING *invalidDirString;
+} INVALIDTEMPLATE;
+
+ASN1_SEQUENCE(INVALIDTEMPLATE) = {
+    /*
+     * DirectoryString is a CHOICE type so it must use explicit tagging -
+     * but we deliberately use implicit here, which makes this template invalid.
+     */
+    ASN1_IMP(INVALIDTEMPLATE, invalidDirString, DIRECTORYSTRING, 12)
+} static_ASN1_SEQUENCE_END(INVALIDTEMPLATE)
+
+IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(INVALIDTEMPLATE)
+IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(INVALIDTEMPLATE)
+
+static int test_invalid_template(void)
+{
+    INVALIDTEMPLATE *temp = INVALIDTEMPLATE_new();
+    int ret;
+
+    if (!TEST_ptr(temp))
+        return 0;
+
+    ret = i2d_INVALIDTEMPLATE(temp, NULL);
+
+    INVALIDTEMPLATE_free(temp);
+
+    /* We expect the i2d operation to fail */
+    return ret < 0;
+}
+
+
 int setup_tests(void)
 {
 #ifndef OPENSSL_NO_DEPRECATED_3_0
@@ -866,5 +898,6 @@ int setup_tests(void)
     ADD_TEST(test_uint32);
     ADD_TEST(test_int64);
     ADD_TEST(test_uint64);
+    ADD_TEST(test_invalid_template);
     return 1;
 }
diff --git a/test/v3nametest.c b/test/v3nametest.c
index df12c15f09..cdf0472387 100644
--- a/test/v3nametest.c
+++ b/test/v3nametest.c
@@ -359,8 +359,352 @@ static int call_run_cert(int i)
     return failed == 0;
 }
 
+struct gennamedata {
+    const unsigned char der[22];
+    size_t derlen;
+} gennames[] = {
+    {
+        /*
+        * [0] {
+        *   OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
+        *   [0] {
+        *     SEQUENCE {}
+        *   }
+        * }
+        */
+        {
+            0xa0, 0x13, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
+            0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x02, 0x30, 0x00
+        },
+        21
+    }, {
+        /*
+        * [0] {
+        *   OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
+        *   [0] {
+        *     [APPLICATION 0] {}
+        *   }
+        * }
+        */
+        {
+            0xa0, 0x13, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
+            0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x02, 0x60, 0x00
+        },
+        21
+    }, {
+        /*
+        * [0] {
+        *   OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
+        *   [0] {
+        *     UTF8String { "a" }
+        *   }
+        * }
+        */
+        {
+            0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
+            0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x03, 0x0c, 0x01, 0x61
+        },
+        22
+    }, {
+        /*
+        * [0] {
+        *   OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.2 }
+        *   [0] {
+        *     UTF8String { "a" }
+        *   }
+        * }
+        */
+        {
+            0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
+            0x01, 0x84, 0xb7, 0x09, 0x02, 0x02, 0xa0, 0x03, 0x0c, 0x01, 0x61
+        },
+        22
+    }, {
+        /*
+        * [0] {
+        *   OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
+        *   [0] {
+        *     UTF8String { "b" }
+        *   }
+        * }
+        */
+        {
+            0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
+            0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x03, 0x0c, 0x01, 0x62
+        },
+        22
+    }, {
+        /*
+        * [0] {
+        *   OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
+        *   [0] {
+        *     BOOLEAN { TRUE }
+        *   }
+        * }
+        */
+        {
+            0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
+            0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x03, 0x01, 0x01, 0xff
+        },
+        22
+    }, {
+        /*
+        * [0] {
+        *   OBJECT_IDENTIFIER { 1.2.840.113554.4.1.72585.2.1 }
+        *   [0] {
+        *     BOOLEAN { FALSE }
+        *   }
+        * }
+        */
+        {
+            0xa0, 0x14, 0x06, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04,
+            0x01, 0x84, 0xb7, 0x09, 0x02, 0x01, 0xa0, 0x03, 0x01, 0x01, 0x00
+        },
+        22
+    }, {
+        /* [1 PRIMITIVE] { "a" } */
+        {
+            0x81, 0x01, 0x61
+        },
+        3
+    }, {
+        /* [1 PRIMITIVE] { "b" } */
+        {
+            0x81, 0x01, 0x62
+        },
+        3
+    }, {
+        /* [2 PRIMITIVE] { "a" } */
+        {
+            0x82, 0x01, 0x61
+        },
+        3
+    }, {
+        /* [2 PRIMITIVE] { "b" } */
+        {
+            0x82, 0x01, 0x62
+        },
+        3
+    }, {
+        /*
+        * [4] {
+        *   SEQUENCE {
+        *     SET {
+        *       SEQUENCE {
+        *         # commonName
+        *         OBJECT_IDENTIFIER { 2.5.4.3 }
+        *         UTF8String { "a" }
+        *       }
+        *     }
+        *   }
+        * }
+        */
+        {
+            0xa4, 0x0e, 0x30, 0x0c, 0x31, 0x0a, 0x30, 0x08, 0x06, 0x03, 0x55,
+            0x04, 0x03, 0x0c, 0x01, 0x61
+        },
+        16
+    }, {
+        /*
+        * [4] {
+        *   SEQUENCE {
+        *     SET {
+        *       SEQUENCE {
+        *         # commonName
+        *         OBJECT_IDENTIFIER { 2.5.4.3 }
+        *         UTF8String { "b" }
+        *       }
+        *     }
+        *   }
+        * }
+        */
+        {
+            0xa4, 0x0e, 0x30, 0x0c, 0x31, 0x0a, 0x30, 0x08, 0x06, 0x03, 0x55,
+            0x04, 0x03, 0x0c, 0x01, 0x62
+        },
+        16
+    }, {
+        /*
+        * [5] {
+        *   [1] {
+        *     UTF8String { "a" }
+        *   }
+        * }
+        */
+        {
+            0xa5, 0x05, 0xa1, 0x03, 0x0c, 0x01, 0x61
+        },
+        7
+    }, {
+        /*
+        * [5] {
+        *   [1] {
+        *     UTF8String { "b" }
+        *   }
+        * }
+        */
+        {
+            0xa5, 0x05, 0xa1, 0x03, 0x0c, 0x01, 0x62
+        },
+        7
+    }, {
+        /*
+        * [5] {
+        *   [0] {
+        *     UTF8String {}
+        *   }
+        *   [1] {
+        *     UTF8String { "a" }
+        *   }
+        * }
+        */
+        {
+            0xa5, 0x09, 0xa0, 0x02, 0x0c, 0x00, 0xa1, 0x03, 0x0c, 0x01, 0x61
+        },
+        11
+    }, {
+        /*
+        * [5] {
+        *   [0] {
+        *     UTF8String { "a" }
+        *   }
+        *   [1] {
+        *     UTF8String { "a" }
+        *   }
+        * }
+        */
+        {
+            0xa5, 0x0a, 0xa0, 0x03, 0x0c, 0x01, 0x61, 0xa1, 0x03, 0x0c, 0x01,
+            0x61
+        },
+        12
+    }, {
+        /*
+        * [5] {
+        *   [0] {
+        *     UTF8String { "b" }
+        *   }
+        *   [1] {
+        *     UTF8String { "a" }
+        *   }
+        * }
+        */
+        {
+            0xa5, 0x0a, 0xa0, 0x03, 0x0c, 0x01, 0x62, 0xa1, 0x03, 0x0c, 0x01,
+            0x61
+        },
+        12
+    }, {
+        /* [6 PRIMITIVE] { "a" } */
+        {
+            0x86, 0x01, 0x61
+        },
+        3
+    }, {
+        /* [6 PRIMITIVE] { "b" } */
+        {
+            0x86, 0x01, 0x62
+        },
+        3
+    }, {
+        /* [7 PRIMITIVE] { `11111111` } */
+        {
+            0x87, 0x04, 0x11, 0x11, 0x11, 0x11
+        },
+        6
+    }, {
+        /* [7 PRIMITIVE] { `22222222`} */
+        {
+            0x87, 0x04, 0x22, 0x22, 0x22, 0x22
+        },
+        6
+    }, {
+        /* [7 PRIMITIVE] { `11111111111111111111111111111111` } */
+        {
+            0x87, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+            0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+        },
+        18
+    }, {
+        /* [7 PRIMITIVE] { `22222222222222222222222222222222` } */
+        {
+            0x87, 0x10, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+            0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22
+        },
+        18
+    }, {
+        /* [8 PRIMITIVE] { 1.2.840.113554.4.1.72585.2.1 } */
+        {
+            0x88, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84,
+            0xb7, 0x09, 0x02, 0x01
+        },
+        15
+    }, {
+        /* [8 PRIMITIVE] { 1.2.840.113554.4.1.72585.2.2 } */
+        {
+            0x88, 0x0d, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84,
+            0xb7, 0x09, 0x02, 0x02
+        },
+        15
+    }
+};
+
+static int test_GENERAL_NAME_cmp(void)
+{
+    size_t i, j;
+    GENERAL_NAME **namesa = OPENSSL_malloc(sizeof(*namesa)
+                                           * OSSL_NELEM(gennames));
+    GENERAL_NAME **namesb = OPENSSL_malloc(sizeof(*namesb)
+                                           * OSSL_NELEM(gennames));
+    int testresult = 0;
+
+    if (!TEST_ptr(namesa) || !TEST_ptr(namesb))
+        goto end;
+
+    for (i = 0; i < OSSL_NELEM(gennames); i++) {
+        const unsigned char *derp = gennames[i].der;
+
+        /*
+         * We create two versions of each GENERAL_NAME so that we ensure when
+         * we compare them they are always different pointers.
+         */
+        namesa[i] = d2i_GENERAL_NAME(NULL, &derp, gennames[i].derlen);
+        derp = gennames[i].der;
+        namesb[i] = d2i_GENERAL_NAME(NULL, &derp, gennames[i].derlen);
+        if (!TEST_ptr(namesa[i]) || !TEST_ptr(namesb[i]))
+            goto end;
+    }
+
+    /* Every name should be equal to itself and not equal to any others. */
+    for (i = 0; i < OSSL_NELEM(gennames); i++) {
+        for (j = 0; j < OSSL_NELEM(gennames); j++) {
+            if (i == j) {
+                if (!TEST_int_eq(GENERAL_NAME_cmp(namesa[i], namesb[j]), 0))
+                    goto end;
+            } else {
+                if (!TEST_int_ne(GENERAL_NAME_cmp(namesa[i], namesb[j]), 0))
+                    goto end;
+            }
+        }
+    }
+    testresult = 1;
+
+ end:
+    for (i = 0; i < OSSL_NELEM(gennames); i++) {
+        if (namesa != NULL)
+            GENERAL_NAME_free(namesa[i]);
+        if (namesb != NULL)
+            GENERAL_NAME_free(namesb[i]);
+    }
+    OPENSSL_free(namesa);
+    OPENSSL_free(namesb);
+
+    return testresult;
+}
+
 int setup_tests(void)
 {
     ADD_ALL_TESTS(call_run_cert, OSSL_NELEM(name_fns));
+    ADD_TEST(test_GENERAL_NAME_cmp);
     return 1;
 }


More information about the openssl-commits mailing list