xref: /aosp_15_r20/external/boringssl/src/crypto/asn1/a_bitstr.c (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
1 /* Copyright (C) 1995-1998 Eric Young ([email protected])
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young ([email protected]).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson ([email protected]).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young ([email protected])"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson ([email protected])"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.] */
56 
57 #include <openssl/asn1.h>
58 
59 #include <limits.h>
60 #include <string.h>
61 
62 #include <openssl/err.h>
63 #include <openssl/mem.h>
64 
65 #include "../internal.h"
66 #include "internal.h"
67 
68 
ASN1_BIT_STRING_set(ASN1_BIT_STRING * x,const unsigned char * d,ossl_ssize_t len)69 int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, const unsigned char *d,
70                         ossl_ssize_t len) {
71   return ASN1_STRING_set(x, d, len);
72 }
73 
asn1_bit_string_length(const ASN1_BIT_STRING * str,uint8_t * out_padding_bits)74 int asn1_bit_string_length(const ASN1_BIT_STRING *str,
75                            uint8_t *out_padding_bits) {
76   int len = str->length;
77   if (str->flags & ASN1_STRING_FLAG_BITS_LEFT) {
78     // If the string is already empty, it cannot have padding bits.
79     *out_padding_bits = len == 0 ? 0 : str->flags & 0x07;
80     return len;
81   }
82 
83   // TODO(https://crbug.com/boringssl/447): If we move this logic to
84   // |ASN1_BIT_STRING_set_bit|, can we remove this representation?
85   while (len > 0 && str->data[len - 1] == 0) {
86     len--;
87   }
88   uint8_t padding_bits = 0;
89   if (len > 0) {
90     uint8_t last = str->data[len - 1];
91     assert(last != 0);
92     for (; padding_bits < 7; padding_bits++) {
93       if (last & (1 << padding_bits)) {
94         break;
95       }
96     }
97   }
98   *out_padding_bits = padding_bits;
99   return len;
100 }
101 
ASN1_BIT_STRING_num_bytes(const ASN1_BIT_STRING * str,size_t * out)102 int ASN1_BIT_STRING_num_bytes(const ASN1_BIT_STRING *str, size_t *out) {
103   uint8_t padding_bits;
104   int len = asn1_bit_string_length(str, &padding_bits);
105   if (padding_bits != 0) {
106     return 0;
107   }
108   *out = len;
109   return 1;
110 }
111 
i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING * a,unsigned char ** pp)112 int i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING *a, unsigned char **pp) {
113   if (a == NULL) {
114     return 0;
115   }
116 
117   uint8_t bits;
118   int len = asn1_bit_string_length(a, &bits);
119   if (len > INT_MAX - 1) {
120     OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW);
121     return 0;
122   }
123   int ret = 1 + len;
124   if (pp == NULL) {
125     return ret;
126   }
127 
128   uint8_t *p = *pp;
129   *(p++) = bits;
130   OPENSSL_memcpy(p, a->data, len);
131   if (len > 0) {
132     p[len - 1] &= (0xff << bits);
133   }
134   p += len;
135   *pp = p;
136   return ret;
137 }
138 
c2i_ASN1_BIT_STRING(ASN1_BIT_STRING ** a,const unsigned char ** pp,long len)139 ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
140                                      const unsigned char **pp, long len) {
141   ASN1_BIT_STRING *ret = NULL;
142   const unsigned char *p;
143   unsigned char *s;
144   int padding;
145 
146   if (len < 1) {
147     OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
148     goto err;
149   }
150 
151   if (len > INT_MAX) {
152     OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
153     goto err;
154   }
155 
156   if ((a == NULL) || ((*a) == NULL)) {
157     if ((ret = ASN1_BIT_STRING_new()) == NULL) {
158       return NULL;
159     }
160   } else {
161     ret = (*a);
162   }
163 
164   p = *pp;
165   padding = *(p++);
166   len--;
167   if (padding > 7) {
168     OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
169     goto err;
170   }
171 
172   // Unused bits in a BIT STRING must be zero.
173   uint8_t padding_mask = (1 << padding) - 1;
174   if (padding != 0 && (len < 1 || (p[len - 1] & padding_mask) != 0)) {
175     OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING);
176     goto err;
177   }
178 
179   // We do this to preserve the settings.  If we modify the settings, via
180   // the _set_bit function, we will recalculate on output
181   ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);    // clear
182   ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding);  // set
183 
184   if (len > 0) {
185     s = OPENSSL_memdup(p, len);
186     if (s == NULL) {
187       goto err;
188     }
189     p += len;
190   } else {
191     s = NULL;
192   }
193 
194   ret->length = (int)len;
195   OPENSSL_free(ret->data);
196   ret->data = s;
197   ret->type = V_ASN1_BIT_STRING;
198   if (a != NULL) {
199     (*a) = ret;
200   }
201   *pp = p;
202   return ret;
203 err:
204   if ((ret != NULL) && ((a == NULL) || (*a != ret))) {
205     ASN1_BIT_STRING_free(ret);
206   }
207   return NULL;
208 }
209 
210 // These next 2 functions from Goetz Babin-Ebell <[email protected]>
ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING * a,int n,int value)211 int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) {
212   int w, v, iv;
213   unsigned char *c;
214 
215   w = n / 8;
216   v = 1 << (7 - (n & 0x07));
217   iv = ~v;
218   if (!value) {
219     v = 0;
220   }
221 
222   if (a == NULL) {
223     return 0;
224   }
225 
226   a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);  // clear, set on write
227 
228   if ((a->length < (w + 1)) || (a->data == NULL)) {
229     if (!value) {
230       return 1;  // Don't need to set
231     }
232     if (a->data == NULL) {
233       c = (unsigned char *)OPENSSL_malloc(w + 1);
234     } else {
235       c = (unsigned char *)OPENSSL_realloc(a->data, w + 1);
236     }
237     if (c == NULL) {
238       return 0;
239     }
240     if (w + 1 - a->length > 0) {
241       OPENSSL_memset(c + a->length, 0, w + 1 - a->length);
242     }
243     a->data = c;
244     a->length = w + 1;
245   }
246   a->data[w] = ((a->data[w]) & iv) | v;
247   while ((a->length > 0) && (a->data[a->length - 1] == 0)) {
248     a->length--;
249   }
250   return 1;
251 }
252 
ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING * a,int n)253 int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n) {
254   int w, v;
255 
256   w = n / 8;
257   v = 1 << (7 - (n & 0x07));
258   if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL)) {
259     return 0;
260   }
261   return ((a->data[w] & v) != 0);
262 }
263 
264 // Checks if the given bit string contains only bits specified by
265 // the flags vector. Returns 0 if there is at least one bit set in 'a'
266 // which is not specified in 'flags', 1 otherwise.
267 // 'len' is the length of 'flags'.
ASN1_BIT_STRING_check(const ASN1_BIT_STRING * a,const unsigned char * flags,int flags_len)268 int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, const unsigned char *flags,
269                           int flags_len) {
270   int i, ok;
271   // Check if there is one bit set at all.
272   if (!a || !a->data) {
273     return 1;
274   }
275 
276   // Check each byte of the internal representation of the bit string.
277   ok = 1;
278   for (i = 0; i < a->length && ok; ++i) {
279     unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
280     // We are done if there is an unneeded bit set.
281     ok = (a->data[i] & mask) == 0;
282   }
283   return ok;
284 }
285