Home | History | Annotate | Download | only in integer
      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 (at) 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 $ */
    111