1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3  *
4  * LibTomCrypt is a library that provides various cryptographic
5  * algorithms in a highly modular and flexible manner.
6  *
7  * The library is free for all purposes without any express
8  * guarantee it works.
9  */
10 #include "tomcrypt_private.h"
11 
12 /**
13   @file der_encode_asn1_identifier.c
14   ASN.1 DER, encode the ASN.1 Identifier, Steffen Jaeckel
15 */
16 
17 #ifdef LTC_DER
18 /**
19   Encode the ASN.1 Identifier
20   @param id       The ASN.1 Identifer to encode
21   @param out      Where to write the identifier to
22   @param outlen   [in/out] The size of out available/written
23   @return CRYPT_OK if successful
24 */
der_encode_asn1_identifier(const ltc_asn1_list * id,unsigned char * out,unsigned long * outlen)25 int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen)
26 {
27    ulong64 tmp;
28    unsigned long tag_len;
29 
30    LTC_ARGCHK(id  != NULL);
31    LTC_ARGCHK(outlen != NULL);
32 
33    if (id->type != LTC_ASN1_CUSTOM_TYPE) {
34       if ((unsigned)id->type >= der_asn1_type_to_identifier_map_sz) {
35          return CRYPT_INVALID_ARG;
36       }
37       if (der_asn1_type_to_identifier_map[id->type] == -1) {
38          return CRYPT_INVALID_ARG;
39       }
40       if (out != NULL) {
41          *out = der_asn1_type_to_identifier_map[id->type];
42       }
43       *outlen = 1;
44       return CRYPT_OK;
45    }
46    if (id->klass < LTC_ASN1_CL_UNIVERSAL || id->klass > LTC_ASN1_CL_PRIVATE) {
47       return CRYPT_INVALID_ARG;
48    }
49    if (id->pc < LTC_ASN1_PC_PRIMITIVE || id->pc > LTC_ASN1_PC_CONSTRUCTED) {
50       return CRYPT_INVALID_ARG;
51    }
52    if (id->tag > (ULONG_MAX >> (8 + 7))) {
53       return CRYPT_INVALID_ARG;
54    }
55 
56    if (out != NULL) {
57       if (*outlen < 1) {
58          return CRYPT_BUFFER_OVERFLOW;
59       }
60 
61       out[0] = id->klass << 6 | id->pc << 5;
62    }
63 
64    if (id->tag < 0x1f) {
65       if (out != NULL) {
66          out[0] |= id->tag & 0x1f;
67       }
68       *outlen = 1;
69    } else {
70       tag_len = 0;
71       tmp = id->tag;
72       do {
73          tag_len++;
74          tmp >>= 7;
75       } while (tmp);
76 
77       if (out != NULL) {
78          if (*outlen < tag_len + 1) {
79             return CRYPT_BUFFER_OVERFLOW;
80          }
81          out[0] |= 0x1f;
82          for (tmp = 1; tmp <= tag_len; ++tmp) {
83             out[tmp] = ((id->tag >> (7 * (tag_len - tmp))) & 0x7f) | 0x80;
84          }
85          out[tag_len] &= ~0x80;
86       }
87       *outlen = tag_len + 1;
88    }
89 
90    return CRYPT_OK;
91 }
92 
93 #endif
94 
95 /* ref:         $Format:%D$ */
96 /* git commit:  $Format:%H$ */
97 /* commit time: $Format:%ai$ */
98