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