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