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