1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file der_encode_set.c
7   ASN.1 DER, Encode a SET, Tom St Denis
8 */
9 
10 #ifdef LTC_DER
11 
12 /* LTC define to ASN.1 TAG */
s_ltc_to_asn1(ltc_asn1_type v)13 static int s_ltc_to_asn1(ltc_asn1_type v)
14 {
15    return der_asn1_type_to_identifier_map[v];
16 }
17 
18 
s_qsort_helper(const void * a,const void * b)19 static int s_qsort_helper(const void *a, const void *b)
20 {
21    ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b;
22    int            r;
23 
24    r = s_ltc_to_asn1(A->type) - s_ltc_to_asn1(B->type);
25 
26    /* for QSORT the order is UNDEFINED if they are "equal" which means it is NOT DETERMINISTIC.  So we force it to be :-) */
27    if (r == 0) {
28       /* their order in the original list now determines the position */
29       return A->used - B->used;
30    }
31    return r;
32 }
33 
34 /*
35    Encode a SET type
36    @param list      The list of items to encode
37    @param inlen     The number of items in the list
38    @param out       [out] The destination
39    @param outlen    [in/out] The size of the output
40    @return CRYPT_OK on success
41 */
der_encode_set(const ltc_asn1_list * list,unsigned long inlen,unsigned char * out,unsigned long * outlen)42 int der_encode_set(const ltc_asn1_list *list, unsigned long inlen,
43                    unsigned char *out,        unsigned long *outlen)
44 {
45    ltc_asn1_list  *copy;
46    unsigned long   x;
47    int             err;
48 
49    /* make copy of list */
50    copy = XCALLOC(inlen, sizeof(*copy));
51    if (copy == NULL) {
52       return CRYPT_MEM;
53    }
54 
55    /* fill in used member with index so we can fully sort it */
56    for (x = 0; x < inlen; x++) {
57        copy[x]      = list[x];
58        copy[x].used = x;
59    }
60 
61    /* sort it by the "type" field */
62    XQSORT(copy, inlen, sizeof(*copy), &s_qsort_helper);
63 
64    /* call der_encode_sequence_ex() */
65    err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET);
66 
67    /* free list */
68    XFREE(copy);
69 
70    return err;
71 }
72 
73 
74 #endif
75