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 /**
14   Store a BIT STRING
15   @param in      The DER encoded BIT STRING
16   @param inlen   The size of the DER BIT STRING
17   @param out     [out] The array of bits stored (one per char)
18   @param outlen  [in/out] The number of bits stored
19   @return CRYPT_OK if successful
20 */
der_decode_bit_string(const unsigned char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen)21 int der_decode_bit_string(const unsigned char *in,  unsigned long inlen,
22                                 unsigned char *out, unsigned long *outlen)
23 {
24    unsigned long dlen, blen, x, y;
25    int err;
26 
27    LTC_ARGCHK(in     != NULL);
28    LTC_ARGCHK(out    != NULL);
29    LTC_ARGCHK(outlen != NULL);
30 
31    /* packet must be at least 4 bytes */
32    if (inlen < 4) {
33        return CRYPT_INVALID_ARG;
34    }
35 
36    /* check for 0x03 */
37    if ((in[0]&0x1F) != 0x03) {
38       return CRYPT_INVALID_PACKET;
39    }
40 
41    /* offset in the data */
42    x = 1;
43 
44    /* get the length of the data */
45    y = inlen - 1;
46    if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) {
47       return err;
48    }
49    x += y;
50    /* is the data len too long or too short? */
51    if ((dlen == 0) || (dlen > (inlen - x))) {
52        return CRYPT_INVALID_PACKET;
53    }
54 
55    /* get padding count */
56    blen = ((dlen - 1) << 3) - (in[x++] & 7);
57 
58    /* too many bits? */
59    if (blen > *outlen) {
60       *outlen = blen;
61       return CRYPT_BUFFER_OVERFLOW;
62    }
63 
64    /* decode/store the bits */
65    for (y = 0; y < blen; y++) {
66        out[y] = (in[x] & (1 << (7 - (y & 7)))) ? 1 : 0;
67        if ((y & 7) == 7) {
68           ++x;
69        }
70    }
71 
72    /* we done */
73    *outlen = blen;
74    return CRYPT_OK;
75 }
76 
77 #endif
78