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