1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 /**
6   @file der_decode_bit_string.c
7   ASN.1 DER, encode a BIT STRING, Tom St Denis
8 */
9 
10 
11 #ifdef LTC_DER
12 
13 #define SETBIT(v, n)    (v=((unsigned char)(v) | (1U << (unsigned char)(n))))
14 #define CLRBIT(v, n)    (v=((unsigned char)(v) & ~(1U << (unsigned char)(n))))
15 
16 /**
17   Store a BIT STRING
18   @param in      The DER encoded BIT STRING
19   @param inlen   The size of the DER BIT STRING
20   @param out     [out] The array of bits stored (8 per char)
21   @param outlen  [in/out] The number of bits stored
22   @return CRYPT_OK if successful
23 */
der_decode_raw_bit_string(const unsigned char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen)24 int der_decode_raw_bit_string(const unsigned char *in,  unsigned long inlen,
25                                 unsigned char *out, unsigned long *outlen)
26 {
27    unsigned long dlen, blen, x, y;
28    int err;
29 
30    LTC_ARGCHK(in     != NULL);
31    LTC_ARGCHK(out    != NULL);
32    LTC_ARGCHK(outlen != NULL);
33 
34    /* packet must be at least 4 bytes */
35    if (inlen < 4) {
36        return CRYPT_INVALID_ARG;
37    }
38 
39    /* check for 0x03 */
40    if ((in[0]&0x1F) != 0x03) {
41       return CRYPT_INVALID_PACKET;
42    }
43 
44    /* offset in the data */
45    x = 1;
46 
47    /* get the length of the data */
48    y = inlen - 1;
49    if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) {
50       return err;
51    }
52    x += y;
53    /* is the data len too long or too short? */
54    if ((dlen == 0) || (dlen > (inlen - x))) {
55        return CRYPT_INVALID_PACKET;
56    }
57 
58    /* get padding count */
59    blen = ((dlen - 1) << 3) - (in[x++] & 7);
60 
61    /* too many bits? */
62    if (blen > *outlen) {
63       *outlen = blen;
64       return CRYPT_BUFFER_OVERFLOW;
65    }
66 
67    /* decode/store the bits */
68    for (y = 0; y < blen; y++) {
69       if (in[x] & (1 << (7 - (y & 7)))) {
70          SETBIT(out[y/8], 7-(y%8));
71       } else {
72          CLRBIT(out[y/8], 7-(y%8));
73       }
74       if ((y & 7) == 7) {
75          ++x;
76       }
77    }
78 
79    /* we done */
80    *outlen = blen;
81    return CRYPT_OK;
82 }
83 
84 #endif
85