pkcs7: Order DER encoded attributes
The attributes are encoded as a SET OF, which means that in DER encoding the encoded attributes have to be ordered lexicographically. Fixes #3589.
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
#include <asn1/oid.h>
|
#include <asn1/oid.h>
|
||||||
#include <asn1/asn1.h>
|
#include <asn1/asn1.h>
|
||||||
#include <asn1/asn1_parser.h>
|
#include <asn1/asn1_parser.h>
|
||||||
|
#include <collections/array.h>
|
||||||
#include <collections/linked_list.h>
|
#include <collections/linked_list.h>
|
||||||
|
|
||||||
#include "pkcs7_attributes.h"
|
#include "pkcs7_attributes.h"
|
||||||
@@ -92,6 +93,14 @@ static attribute_t *attribute_create(int oid, chunk_t value)
|
|||||||
return this;
|
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
|
* Build encoding of the attribute list
|
||||||
*/
|
*/
|
||||||
@@ -100,31 +109,35 @@ static void build_encoding(private_pkcs7_attributes_t *this)
|
|||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
attribute_t *attribute;
|
attribute_t *attribute;
|
||||||
u_int len = 0, count, i = 0;
|
u_int len = 0, count, i = 0;
|
||||||
chunk_t *chunks;
|
array_t *chunks;
|
||||||
|
chunk_t chunk;
|
||||||
u_char *pos;
|
u_char *pos;
|
||||||
|
|
||||||
count = this->attributes->get_count(this->attributes);
|
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);
|
enumerator = this->attributes->create_enumerator(this->attributes);
|
||||||
while (enumerator->enumerate(enumerator, &attribute))
|
while (enumerator->enumerate(enumerator, &attribute))
|
||||||
{
|
{
|
||||||
chunks[i] = asn1_wrap(ASN1_SEQUENCE, "mm",
|
chunk = asn1_wrap(ASN1_SEQUENCE, "mm",
|
||||||
asn1_build_known_oid(attribute->oid),
|
asn1_build_known_oid(attribute->oid),
|
||||||
asn1_wrap(ASN1_SET, "c", attribute->value));
|
asn1_wrap(ASN1_SET, "c", attribute->value));
|
||||||
len += chunks[i].len;
|
array_insert(chunks, ARRAY_TAIL, &chunk);
|
||||||
i++;
|
len += chunk.len;
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
|
array_sort(chunks, (void*)cmp_attributes, NULL);
|
||||||
|
|
||||||
pos = asn1_build_object(&this->encoding, ASN1_SET, len);
|
pos = asn1_build_object(&this->encoding, ASN1_SET, len);
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
memcpy(pos, chunks[i].ptr, chunks[i].len);
|
array_get(chunks, i, &chunk);
|
||||||
pos += chunks[i].len;
|
memcpy(pos, chunk.ptr, chunk.len);
|
||||||
free(chunks[i].ptr);
|
pos += chunk.len;
|
||||||
|
free(chunk.ptr);
|
||||||
}
|
}
|
||||||
free(chunks);
|
array_destroy(chunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(pkcs7_attributes_t, get_encoding, chunk_t,
|
METHOD(pkcs7_attributes_t, get_encoding, chunk_t,
|
||||||
|
|||||||
Reference in New Issue
Block a user