1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file der_decode_integer.c
7   ASN.1 DER, decode an integer, Tom St Denis
8 */
9 
10 
11 #ifdef LTC_DER
12 
13 /**
14   Read a mp_int integer
15   @param in       The DER encoded data
16   @param inlen    Size of DER encoded data
17   @param num      The first mp_int to decode
18   @return CRYPT_OK if successful
19 */
der_decode_integer(const unsigned char * in,unsigned long inlen,void * num)20 int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num)
21 {
22    unsigned long x, y;
23    int           err;
24 
25    LTC_ARGCHK(num    != NULL);
26    LTC_ARGCHK(in     != NULL);
27 
28    /* min DER INTEGER is 0x02 01 00 == 0 */
29    if (inlen < (1 + 1 + 1)) {
30       return CRYPT_INVALID_PACKET;
31    }
32 
33    /* ok expect 0x02 when we AND with 0001 1111 [1F] */
34    x = 0;
35    if ((in[x++] & 0x1F) != 0x02) {
36       return CRYPT_INVALID_PACKET;
37    }
38 
39    /* get the length of the data */
40    inlen -= x;
41    if ((err = der_decode_asn1_length(in + x, &inlen, &y)) != CRYPT_OK) {
42       return err;
43    }
44    x += inlen;
45 
46    if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
47       return err;
48    }
49 
50    /* see if it's negative */
51    if (in[x] & 0x80) {
52       void *tmp;
53       if (mp_init(&tmp) != CRYPT_OK) {
54          return CRYPT_MEM;
55       }
56 
57       if (mp_2expt(tmp, mp_count_bits(num)) != CRYPT_OK || mp_sub(num, tmp, num) != CRYPT_OK) {
58          mp_clear(tmp);
59          return CRYPT_MEM;
60       }
61       mp_clear(tmp);
62    }
63 
64    return CRYPT_OK;
65 
66 }
67 
68 #endif
69