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