version 0.3.33
[fms.git] / libs / libtomcrypt / 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  * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10  */
11 #include "tomcrypt.h"
12
13 /**
14   @file der_decode_integer.c
15   ASN.1 DER, decode an integer, Tom St Denis
16 */
17
18
19 #ifdef LTC_DER
20
21 /**
22   Read a mp_int integer
23   @param in       The DER encoded data
24   @param inlen    Size of DER encoded data
25   @param num      The first mp_int to decode
26   @return CRYPT_OK if successful
27 */
28 int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num)
29 {
30    unsigned long x, y, z;
31    int           err;
32
33    LTC_ARGCHK(num    != NULL);
34    LTC_ARGCHK(in     != NULL);
35
36    /* min DER INTEGER is 0x02 01 00 == 0 */
37    if (inlen < (1 + 1 + 1)) {
38       return CRYPT_INVALID_PACKET;
39    }
40
41    /* ok expect 0x02 when we AND with 0001 1111 [1F] */
42    x = 0;
43    if ((in[x++] & 0x1F) != 0x02) {
44       return CRYPT_INVALID_PACKET;
45    }
46
47    /* now decode the len stuff */
48    z = in[x++];
49
50    if ((z & 0x80) == 0x00) {
51       /* short form */
52
53       /* will it overflow? */
54       if (x + z > inlen) {
55          return CRYPT_INVALID_PACKET;
56       }
57      
58       /* no so read it */
59       if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, z)) != CRYPT_OK) {
60          return err;
61       }
62    } else {
63       /* long form */
64       z &= 0x7F;
65       
66       /* will number of length bytes overflow? (or > 4) */
67       if (((x + z) > inlen) || (z > 4) || (z == 0)) {
68          return CRYPT_INVALID_PACKET;
69       }
70
71       /* now read it in */
72       y = 0;
73       while (z--) {
74          y = ((unsigned long)(in[x++])) | (y << 8);
75       }
76
77       /* now will reading y bytes overrun? */
78       if ((x + y) > inlen) {
79          return CRYPT_INVALID_PACKET;
80       }
81
82       /* no so read it */
83       if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
84          return err;
85       }
86    }
87
88    /* see if it's negative */
89    if (in[x] & 0x80) {
90       void *tmp;
91       if (mp_init(&tmp) != CRYPT_OK) {
92          return CRYPT_MEM;
93       }
94
95       if (mp_2expt(tmp, mp_count_bits(num)) != CRYPT_OK || mp_sub(num, tmp, num) != CRYPT_OK) {
96          mp_clear(tmp);
97          return CRYPT_MEM;
98       }
99       mp_clear(tmp);
100    } 
101
102    return CRYPT_OK;
103
104 }
105
106 #endif
107
108 /* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c,v $ */
109 /* $Revision: 1.4 $ */
110 /* $Date: 2006/03/31 14:15:35 $ */