1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file der_encode_short_integer.c
7   ASN.1 DER, encode an integer, Tom St Denis
8 */
9 
10 
11 #ifdef LTC_DER
12 
13 /**
14   Store a short integer in the range (0,2^32-1)
15   @param num      The integer to encode
16   @param out      [out] The destination for the DER encoded integers
17   @param outlen   [in/out] The max size and resulting size of the DER encoded integers
18   @return CRYPT_OK if successful
19 */
der_encode_short_integer(unsigned long num,unsigned char * out,unsigned long * outlen)20 int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen)
21 {
22    unsigned long len, x, y, z;
23    int           err;
24 
25    LTC_ARGCHK(out    != NULL);
26    LTC_ARGCHK(outlen != NULL);
27 
28    /* force to 32 bits */
29    num &= 0xFFFFFFFFUL;
30 
31    /* find out how big this will be */
32    if ((err = der_length_short_integer(num, &len)) != CRYPT_OK) {
33       return err;
34    }
35 
36    if (*outlen < len) {
37       *outlen = len;
38       return CRYPT_BUFFER_OVERFLOW;
39    }
40 
41    /* get len of output */
42    z = 0;
43    y = num;
44    while (y) {
45      ++z;
46      y >>= 8;
47    }
48 
49    /* handle zero */
50    if (z == 0) {
51       z = 1;
52    }
53 
54    /* see if msb is set */
55    z += (num&(1UL<<((z<<3) - 1))) ? 1 : 0;
56 
57    /* adjust the number so the msB is non-zero */
58    for (x = 0; (z <= 4) && (x < (4 - z)); x++) {
59       num <<= 8;
60    }
61 
62    /* store header */
63    x = 0;
64    out[x++] = 0x02;
65    out[x++] = (unsigned char)z;
66 
67    /* if 31st bit is set output a leading zero and decrement count */
68    if (z == 5) {
69       out[x++] = 0;
70       --z;
71    }
72 
73    /* store values */
74    for (y = 0; y < z; y++) {
75       out[x++] = (unsigned char)((num >> 24) & 0xFF);
76       num    <<= 8;
77    }
78 
79    /* we good */
80    *outlen = x;
81 
82    return CRYPT_OK;
83 }
84 
85 #endif
86