]> pd.if.org Git - zpackage/blob - libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c
commit files needed for zpm-fetchurl
[zpackage] / libtomcrypt / src / pk / asn1 / der / bit / der_decode_bit_string.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_bit_string.c
13   ASN.1 DER, encode a BIT STRING, Tom St Denis
14 */
15
16
17 #ifdef LTC_DER
18
19 /**
20   Store a BIT STRING
21   @param in      The DER encoded BIT STRING
22   @param inlen   The size of the DER BIT STRING
23   @param out     [out] The array of bits stored (one per char)
24   @param outlen  [in/out] The number of bits stored
25   @return CRYPT_OK if successful
26 */
27 int der_decode_bit_string(const unsigned char *in,  unsigned long inlen,
28                                 unsigned char *out, unsigned long *outlen)
29 {
30    unsigned long dlen, blen, x, y;
31
32    LTC_ARGCHK(in     != NULL);
33    LTC_ARGCHK(out    != NULL);
34    LTC_ARGCHK(outlen != NULL);
35
36    /* packet must be at least 4 bytes */
37    if (inlen < 4) {
38        return CRYPT_INVALID_ARG;
39    }
40
41    /* check for 0x03 */
42    if ((in[0]&0x1F) != 0x03) {
43       return CRYPT_INVALID_PACKET;
44    }
45
46    /* offset in the data */
47    x = 1;
48
49    /* get the length of the data */
50    if (in[x] & 0x80) {
51       /* long format get number of length bytes */
52       y = in[x++] & 0x7F;
53
54       /* invalid if 0 or > 2 */
55       if (y == 0 || y > 2) {
56          return CRYPT_INVALID_PACKET;
57       }
58
59       /* read the data len */
60       dlen = 0;
61       while (y--) {
62          dlen = (dlen << 8) | (unsigned long)in[x++];
63       }
64    } else {
65       /* short format */
66       dlen = in[x++] & 0x7F;
67    }
68
69    /* is the data len too long or too short? */
70    if ((dlen == 0) || (dlen + x > inlen)) {
71        return CRYPT_INVALID_PACKET;
72    }
73
74    /* get padding count */
75    blen = ((dlen - 1) << 3) - (in[x++] & 7);
76
77    /* too many bits? */
78    if (blen > *outlen) {
79       *outlen = blen;
80       return CRYPT_BUFFER_OVERFLOW;
81    }
82
83    /* decode/store the bits */
84    for (y = 0; y < blen; y++) {
85        out[y] = (in[x] & (1 << (7 - (y & 7)))) ? 1 : 0;
86        if ((y & 7) == 7) {
87           ++x;
88        }
89    }
90
91    /* we done */
92    *outlen = blen;
93    return CRYPT_OK;
94 }
95
96 #endif
97
98 /* ref:         $Format:%D$ */
99 /* git commit:  $Format:%H$ */
100 /* commit time: $Format:%ai$ */