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