]> pd.if.org Git - zpackage/blob - libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c
commit files needed for zpm-fetchurl
[zpackage] / libtomcrypt / src / pk / asn1 / der / integer / der_decode_integer.c
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2  *
3  * LibTomCrypt is a library that provides various cryptographic
4  * algorithms in a highly modular and flexible manner.
5  *
6  * The library is free for all purposes without any express
7  * guarantee it works.
8  */
9 #include "tomcrypt.h"
10
11 /**
12   @file der_decode_integer.c
13   ASN.1 DER, decode an integer, Tom St Denis
14 */
15
16
17 #ifdef LTC_DER
18
19 /**
20   Read a mp_int integer
21   @param in       The DER encoded data
22   @param inlen    Size of DER encoded data
23   @param num      The first mp_int to decode
24   @return CRYPT_OK if successful
25 */
26 int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num)
27 {
28    unsigned long x, y, z;
29    int           err;
30
31    LTC_ARGCHK(num    != NULL);
32    LTC_ARGCHK(in     != NULL);
33
34    /* min DER INTEGER is 0x02 01 00 == 0 */
35    if (inlen < (1 + 1 + 1)) {
36       return CRYPT_INVALID_PACKET;
37    }
38
39    /* ok expect 0x02 when we AND with 0001 1111 [1F] */
40    x = 0;
41    if ((in[x++] & 0x1F) != 0x02) {
42       return CRYPT_INVALID_PACKET;
43    }
44
45    /* now decode the len stuff */
46    z = in[x++];
47
48    if ((z & 0x80) == 0x00) {
49       /* short form */
50
51       /* will it overflow? */
52       if (x + z > inlen) {
53          return CRYPT_INVALID_PACKET;
54       }
55
56       /* no so read it */
57       if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, z)) != CRYPT_OK) {
58          return err;
59       }
60    } else {
61       /* long form */
62       z &= 0x7F;
63
64       /* will number of length bytes overflow? (or > 4) */
65       if (((x + z) > inlen) || (z > 4) || (z == 0)) {
66          return CRYPT_INVALID_PACKET;
67       }
68
69       /* now read it in */
70       y = 0;
71       while (z--) {
72          y = ((unsigned long)(in[x++])) | (y << 8);
73       }
74
75       /* now will reading y bytes overrun? */
76       if ((x + y) > inlen) {
77          return CRYPT_INVALID_PACKET;
78       }
79
80       /* no so read it */
81       if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
82          return err;
83       }
84    }
85
86    /* see if it's negative */
87    if (in[x] & 0x80) {
88       void *tmp;
89       if (mp_init(&tmp) != CRYPT_OK) {
90          return CRYPT_MEM;
91       }
92
93       if (mp_2expt(tmp, mp_count_bits(num)) != CRYPT_OK || mp_sub(num, tmp, num) != CRYPT_OK) {
94          mp_clear(tmp);
95          return CRYPT_MEM;
96       }
97       mp_clear(tmp);
98    }
99
100    return CRYPT_OK;
101
102 }
103
104 #endif
105
106 /* ref:         $Format:%D$ */
107 /* git commit:  $Format:%H$ */
108 /* commit time: $Format:%ai$ */