]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
pkcs7: Order DER encoded attributes
authorTobias Brunner <tobias@strongswan.org>
Fri, 9 Oct 2020 15:42:08 +0000 (17:42 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 27 Oct 2020 10:21:09 +0000 (11:21 +0100)
The attributes are encoded as a SET OF, which means that in DER encoding
the encoded attributes have to be ordered lexicographically.

Fixes #3589.

src/libstrongswan/plugins/pkcs7/pkcs7_attributes.c

index 445dedcf79d91039c14016f38463915f0e3a4996..0ec6b0c35be3116bc37c5aaf4fe7c2a152d3d85e 100644 (file)
@@ -20,6 +20,7 @@
 #include <asn1/oid.h>
 #include <asn1/asn1.h>
 #include <asn1/asn1_parser.h>
+#include <collections/array.h>
 #include <collections/linked_list.h>
 
 #include "pkcs7_attributes.h"
@@ -92,6 +93,14 @@ static attribute_t *attribute_create(int oid, chunk_t value)
        return this;
 }
 
+/**
+ * Compare two encoded attributes
+ */
+static int cmp_attributes(const chunk_t *a, const chunk_t *b, void *unused)
+{
+       return chunk_compare(*a, *b);
+}
+
 /**
  * Build encoding of the attribute list
  */
@@ -100,31 +109,35 @@ static void build_encoding(private_pkcs7_attributes_t *this)
        enumerator_t *enumerator;
        attribute_t *attribute;
        u_int len = 0, count, i = 0;
-       chunk_t *chunks;
+       array_t *chunks;
+       chunk_t chunk;
        u_char *pos;
 
        count = this->attributes->get_count(this->attributes);
-       chunks = malloc(sizeof(chunk_t) * count);
+       chunks = array_create(sizeof(chunk_t), count);
 
        enumerator = this->attributes->create_enumerator(this->attributes);
        while (enumerator->enumerate(enumerator, &attribute))
        {
-               chunks[i] = asn1_wrap(ASN1_SEQUENCE, "mm",
-                                                               asn1_build_known_oid(attribute->oid),
-                                                               asn1_wrap(ASN1_SET, "c", attribute->value));
-               len += chunks[i].len;
-               i++;
+               chunk = asn1_wrap(ASN1_SEQUENCE, "mm",
+                                                 asn1_build_known_oid(attribute->oid),
+                                                 asn1_wrap(ASN1_SET, "c", attribute->value));
+               array_insert(chunks, ARRAY_TAIL, &chunk);
+               len += chunk.len;
        }
        enumerator->destroy(enumerator);
 
+       array_sort(chunks, (void*)cmp_attributes, NULL);
+
        pos = asn1_build_object(&this->encoding, ASN1_SET, len);
        for (i = 0; i < count; i++)
        {
-               memcpy(pos, chunks[i].ptr, chunks[i].len);
-               pos += chunks[i].len;
-               free(chunks[i].ptr);
+               array_get(chunks, i, &chunk);
+               memcpy(pos, chunk.ptr, chunk.len);
+               pos += chunk.len;
+               free(chunk.ptr);
        }
-       free(chunks);
+       array_destroy(chunks);
 }
 
 METHOD(pkcs7_attributes_t, get_encoding, chunk_t,