Import LibreSSL v2.4.2 to vendor branch
[dragonfly.git] / crypto / libressl / crypto / asn1 / a_bytes.c
1 /* $OpenBSD: a_bytes.c,v 1.17 2014/07/10 13:58:22 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/buffer.h>
64 #include <openssl/err.h>
65
66 static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c);
67 /* type is a 'bitmap' of acceptable string types.
68  */
69 ASN1_STRING *
70 d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp,
71     long length, int type)
72 {
73         ASN1_STRING *ret = NULL;
74         const unsigned char *p;
75         unsigned char *s;
76         long len;
77         int inf, tag, xclass;
78         int i = 0;
79
80         p = *pp;
81         inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
82         if (inf & 0x80)
83                 goto err;
84
85         if (tag >= 32) {
86                 i = ASN1_R_TAG_VALUE_TOO_HIGH;
87                 goto err;
88         }
89         if (!(ASN1_tag2bit(tag) & type)) {
90                 i = ASN1_R_WRONG_TYPE;
91                 goto err;
92         }
93
94         /* If a bit-string, exit early */
95         if (tag == V_ASN1_BIT_STRING)
96                 return (d2i_ASN1_BIT_STRING(a, pp, length));
97
98         if ((a == NULL) || ((*a) == NULL)) {
99                 if ((ret = ASN1_STRING_new()) == NULL)
100                         return (NULL);
101         } else
102                 ret = (*a);
103
104         if (len != 0) {
105                 s = malloc(len + 1);
106                 if (s == NULL) {
107                         i = ERR_R_MALLOC_FAILURE;
108                         goto err;
109                 }
110                 memcpy(s, p, len);
111                 s[len]='\0';
112                 p += len;
113         } else
114                 s = NULL;
115
116         free(ret->data);
117         ret->length = (int)len;
118         ret->data = s;
119         ret->type = tag;
120         if (a != NULL)
121                 (*a) = ret;
122         *pp = p;
123         return (ret);
124
125 err:
126         ASN1err(ASN1_F_D2I_ASN1_TYPE_BYTES, i);
127         if (a == NULL || *a != ret)
128                 ASN1_STRING_free(ret);
129         return (NULL);
130 }
131
132 int
133 i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
134 {
135         int ret, r, constructed;
136         unsigned char *p;
137
138         if (a == NULL)
139                 return (0);
140
141         if (tag == V_ASN1_BIT_STRING)
142                 return (i2d_ASN1_BIT_STRING(a, pp));
143
144         ret = a->length;
145         r = ASN1_object_size(0, ret, tag);
146         if (pp == NULL)
147                 return (r);
148         p = *pp;
149
150         if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET))
151                 constructed = 1;
152         else
153                 constructed = 0;
154         ASN1_put_object(&p, constructed, ret, tag, xclass);
155         memcpy(p, a->data, a->length);
156         p += a->length;
157         *pp = p;
158         return (r);
159 }
160
161 ASN1_STRING *
162 d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
163     long length, int Ptag, int Pclass)
164 {
165         ASN1_STRING *ret = NULL;
166         const unsigned char *p;
167         unsigned char *s;
168         long len;
169         int inf, tag, xclass;
170         int i = 0;
171
172         if ((a == NULL) || ((*a) == NULL)) {
173                 if ((ret = ASN1_STRING_new()) == NULL)
174                         return (NULL);
175         } else
176                 ret = (*a);
177
178         p= *pp;
179         inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
180         if (inf & 0x80) {
181                 i = ASN1_R_BAD_OBJECT_HEADER;
182                 goto err;
183         }
184
185         if (tag != Ptag) {
186                 i = ASN1_R_WRONG_TAG;
187                 goto err;
188         }
189
190         if (inf & V_ASN1_CONSTRUCTED) {
191                 ASN1_const_CTX c;
192
193                 c.pp = pp;
194                 c.p = p;
195                 c.inf = inf;
196                 c.slen = len;
197                 c.tag = Ptag;
198                 c.xclass = Pclass;
199                 c.max = (length == 0) ? 0 : (p + length);
200                 if (!asn1_collate_primitive(ret, &c))
201                         goto err;
202                 else {
203                         p = c.p;
204                 }
205         } else {
206                 if (len != 0) {
207                         if ((ret->length < len) || (ret->data == NULL)) {
208                                 free(ret->data);
209                                 ret->data = NULL;
210                                 s = malloc(len + 1);
211                                 if (s == NULL) {
212                                         i = ERR_R_MALLOC_FAILURE;
213                                         goto err;
214                                 }
215                         } else
216                                 s = ret->data;
217                         memcpy(s, p, len);
218                         s[len] = '\0';
219                         p += len;
220                 } else {
221                         s = NULL;
222                         free(ret->data);
223                 }
224
225                 ret->length = (int)len;
226                 ret->data = s;
227                 ret->type = Ptag;
228         }
229
230         if (a != NULL)
231                 (*a) = ret;
232         *pp = p;
233         return (ret);
234
235 err:
236         if (a == NULL || *a != ret)
237                 ASN1_STRING_free(ret);
238         ASN1err(ASN1_F_D2I_ASN1_BYTES, i);
239         return (NULL);
240 }
241
242
243 /* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse
244  * them into the one structure that is then returned */
245 /* There have been a few bug fixes for this function from
246  * Paul Keogh <paul.keogh@sse.ie>, many thanks to him */
247 static int
248 asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
249 {
250         ASN1_STRING *os = NULL;
251         BUF_MEM b;
252         int num;
253
254         b.length = 0;
255         b.max = 0;
256         b.data = NULL;
257
258         if (a == NULL) {
259                 c->error = ERR_R_PASSED_NULL_PARAMETER;
260                 goto err;
261         }
262
263         num = 0;
264         for (;;) {
265                 if (c->inf & 1) {
266                         c->eos = ASN1_const_check_infinite_end(&c->p,
267                             (long)(c->max - c->p));
268                         if (c->eos)
269                                 break;
270                 } else {
271                         if (c->slen <= 0)
272                                 break;
273                 }
274
275                 c->q = c->p;
276                 if (d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag,
277                     c->xclass) == NULL) {
278                         c->error = ERR_R_ASN1_LIB;
279                         goto err;
280                 }
281
282                 if (!BUF_MEM_grow_clean(&b, num + os->length)) {
283                         c->error = ERR_R_BUF_LIB;
284                         goto err;
285                 }
286                 memcpy(&(b.data[num]), os->data, os->length);
287                 if (!(c->inf & 1))
288                         c->slen -= (c->p - c->q);
289                 num += os->length;
290         }
291
292         if (!asn1_const_Finish(c))
293                 goto err;
294
295         a->length = num;
296         free(a->data);
297         a->data = (unsigned char *)b.data;
298         ASN1_STRING_free(os);
299         return (1);
300
301 err:
302         ASN1err(ASN1_F_ASN1_COLLATE_PRIMITIVE, c->error);
303         ASN1_STRING_free(os);
304         free(b.data);
305         return (0);
306 }