1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file der_encode_asn1_length.c
7   ASN.1 DER, encode the ASN.1 length field, Steffen Jaeckel
8 */
9 
10 #ifdef LTC_DER
11 /**
12   Encode the ASN.1 length field
13   @param len      The length to encode
14   @param out      Where to write the length field to
15   @param outlen   [in/out] The size of out available/written
16   @return CRYPT_OK if successful
17 */
der_encode_asn1_length(unsigned long len,unsigned char * out,unsigned long * outlen)18 int der_encode_asn1_length(unsigned long len, unsigned char *out, unsigned long *outlen)
19 {
20    unsigned long x, y;
21 
22    LTC_ARGCHK(outlen != NULL);
23 
24    x = len;
25    y = 0;
26 
27    while(x != 0) {
28       y++;
29       x >>= 8;
30    }
31    if (y == 0) {
32       return CRYPT_PK_ASN1_ERROR;
33    }
34 
35    if (out == NULL) {
36       if (len < 128) {
37          x = y;
38       } else {
39          x = y + 1;
40       }
41    } else {
42       if (*outlen < y) {
43          return CRYPT_BUFFER_OVERFLOW;
44       }
45       x = 0;
46       if (len < 128) {
47          out[x++] = (unsigned char)len;
48       } else if (len <= 0xffUL) {
49          out[x++] = 0x81;
50          out[x++] = (unsigned char)len;
51       } else if (len <= 0xffffUL) {
52          out[x++] = 0x82;
53          out[x++] = (unsigned char)((len>>8UL)&255);
54          out[x++] = (unsigned char)(len&255);
55       } else if (len <= 0xffffffUL) {
56          out[x++] = 0x83;
57          out[x++] = (unsigned char)((len>>16UL)&255);
58          out[x++] = (unsigned char)((len>>8UL)&255);
59          out[x++] = (unsigned char)(len&255);
60       #if ULONG_MAX != ULLONG_MAX
61       } else {
62          out[x++] = 0x84;
63          out[x++] = (unsigned char)((len>>24UL)&255);
64          out[x++] = (unsigned char)((len>>16UL)&255);
65          out[x++] = (unsigned char)((len>>8UL)&255);
66          out[x++] = (unsigned char)(len&255);
67       }
68       #else
69       } else if (len <= 0xffffffffUL) {
70          out[x++] = 0x84;
71          out[x++] = (unsigned char)((len>>24UL)&255);
72          out[x++] = (unsigned char)((len>>16UL)&255);
73          out[x++] = (unsigned char)((len>>8UL)&255);
74          out[x++] = (unsigned char)(len&255);
75       } else if (len <= 0xffffffffffULL) {
76          out[x++] = 0x85;
77          out[x++] = (unsigned char)((len>>32ULL)&255);
78          out[x++] = (unsigned char)((len>>24ULL)&255);
79          out[x++] = (unsigned char)((len>>16ULL)&255);
80          out[x++] = (unsigned char)((len>>8ULL)&255);
81          out[x++] = (unsigned char)(len&255);
82       } else if (len <= 0xffffffffffffULL) {
83          out[x++] = 0x86;
84          out[x++] = (unsigned char)((len>>40ULL)&255);
85          out[x++] = (unsigned char)((len>>32ULL)&255);
86          out[x++] = (unsigned char)((len>>24ULL)&255);
87          out[x++] = (unsigned char)((len>>16ULL)&255);
88          out[x++] = (unsigned char)((len>>8ULL)&255);
89          out[x++] = (unsigned char)(len&255);
90       } else if (len <= 0xffffffffffffffULL) {
91          out[x++] = 0x87;
92          out[x++] = (unsigned char)((len>>48ULL)&255);
93          out[x++] = (unsigned char)((len>>40ULL)&255);
94          out[x++] = (unsigned char)((len>>32ULL)&255);
95          out[x++] = (unsigned char)((len>>24ULL)&255);
96          out[x++] = (unsigned char)((len>>16ULL)&255);
97          out[x++] = (unsigned char)((len>>8ULL)&255);
98          out[x++] = (unsigned char)(len&255);
99       } else {
100          out[x++] = 0x88;
101          out[x++] = (unsigned char)((len>>56ULL)&255);
102          out[x++] = (unsigned char)((len>>48ULL)&255);
103          out[x++] = (unsigned char)((len>>40ULL)&255);
104          out[x++] = (unsigned char)((len>>32ULL)&255);
105          out[x++] = (unsigned char)((len>>24ULL)&255);
106          out[x++] = (unsigned char)((len>>16ULL)&255);
107          out[x++] = (unsigned char)((len>>8ULL)&255);
108          out[x++] = (unsigned char)(len&255);
109       }
110       #endif
111    }
112    *outlen = x;
113 
114    return CRYPT_OK;
115 }
116 
117 #endif
118