import libcrypto (LibreSSL 2.5.2)
[unleashed.git] / lib / libcrypto / asn1 / a_object.c
blob711b01f149e6bfaa65fff099675e7147a543ecb5
1 /* $OpenBSD: a_object.c,v 1.29 2017/01/29 17:49:22 beck Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
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.
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).
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.
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)"
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.
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.]
59 #include <limits.h>
60 #include <stdio.h>
61 #include <string.h>
63 #include <openssl/asn1.h>
64 #include <openssl/bn.h>
65 #include <openssl/err.h>
66 #include <openssl/buffer.h>
67 #include <openssl/objects.h>
69 int
70 i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
72 unsigned char *p;
73 int objsize;
75 if ((a == NULL) || (a->data == NULL))
76 return (0);
78 objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
79 if (pp == NULL)
80 return objsize;
82 p = *pp;
83 ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
84 memcpy(p, a->data, a->length);
85 p += a->length;
87 *pp = p;
88 return (objsize);
91 int
92 a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
94 int i, first, len = 0, c, use_bn;
95 char ftmp[24], *tmp = ftmp;
96 int tmpsize = sizeof ftmp;
97 const char *p;
98 unsigned long l;
99 BIGNUM *bl = NULL;
101 if (num == 0)
102 return (0);
103 else if (num == -1)
104 num = strlen(buf);
106 p = buf;
107 c = *(p++);
108 num--;
109 if ((c >= '0') && (c <= '2')) {
110 first= c-'0';
111 } else {
112 ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE);
113 goto err;
116 if (num <= 0) {
117 ASN1error(ASN1_R_MISSING_SECOND_NUMBER);
118 goto err;
120 c = *(p++);
121 num--;
122 for (;;) {
123 if (num <= 0)
124 break;
125 if ((c != '.') && (c != ' ')) {
126 ASN1error(ASN1_R_INVALID_SEPARATOR);
127 goto err;
129 l = 0;
130 use_bn = 0;
131 for (;;) {
132 if (num <= 0)
133 break;
134 num--;
135 c = *(p++);
136 if ((c == ' ') || (c == '.'))
137 break;
138 if ((c < '0') || (c > '9')) {
139 ASN1error(ASN1_R_INVALID_DIGIT);
140 goto err;
142 if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
143 use_bn = 1;
144 if (!bl)
145 bl = BN_new();
146 if (!bl || !BN_set_word(bl, l))
147 goto err;
149 if (use_bn) {
150 if (!BN_mul_word(bl, 10L) ||
151 !BN_add_word(bl, c-'0'))
152 goto err;
153 } else
154 l = l * 10L + (long)(c - '0');
156 if (len == 0) {
157 if ((first < 2) && (l >= 40)) {
158 ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE);
159 goto err;
161 if (use_bn) {
162 if (!BN_add_word(bl, first * 40))
163 goto err;
164 } else
165 l += (long)first * 40;
167 i = 0;
168 if (use_bn) {
169 int blsize;
170 blsize = BN_num_bits(bl);
171 blsize = (blsize + 6) / 7;
172 if (blsize > tmpsize) {
173 if (tmp != ftmp)
174 free(tmp);
175 tmpsize = blsize + 32;
176 tmp = malloc(tmpsize);
177 if (!tmp)
178 goto err;
180 while (blsize--)
181 tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
182 } else {
184 for (;;) {
185 tmp[i++] = (unsigned char)l & 0x7f;
186 l >>= 7L;
187 if (l == 0L)
188 break;
192 if (out != NULL) {
193 if (len + i > olen) {
194 ASN1error(ASN1_R_BUFFER_TOO_SMALL);
195 goto err;
197 while (--i > 0)
198 out[len++] = tmp[i]|0x80;
199 out[len++] = tmp[0];
200 } else
201 len += i;
203 if (tmp != ftmp)
204 free(tmp);
205 BN_free(bl);
206 return (len);
208 err:
209 if (tmp != ftmp)
210 free(tmp);
211 BN_free(bl);
212 return (0);
216 i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
218 return OBJ_obj2txt(buf, buf_len, a, 0);
222 i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
224 char *tmp = NULL;
225 size_t tlen = 256;
226 int i = -1;
228 if ((a == NULL) || (a->data == NULL))
229 return(BIO_write(bp, "NULL", 4));
230 if ((tmp = malloc(tlen)) == NULL)
231 return -1;
232 i = i2t_ASN1_OBJECT(tmp, tlen, a);
233 if (i > (int)(tlen - 1)) {
234 explicit_bzero(tmp, tlen);
235 free(tmp);
236 if ((tmp = malloc(i + 1)) == NULL)
237 return -1;
238 tlen = i + 1;
239 i = i2t_ASN1_OBJECT(tmp, tlen, a);
241 if (i <= 0)
242 i = BIO_write(bp, "<INVALID>", 9);
243 else
244 i = BIO_write(bp, tmp, i);
245 explicit_bzero(tmp, tlen);
246 free(tmp);
247 return (i);
250 ASN1_OBJECT *
251 d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long length)
253 const unsigned char *p;
254 long len;
255 int tag, xclass;
256 int inf, i;
257 ASN1_OBJECT *ret = NULL;
259 p = *pp;
260 inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
261 if (inf & 0x80) {
262 i = ASN1_R_BAD_OBJECT_HEADER;
263 goto err;
266 if (tag != V_ASN1_OBJECT) {
267 i = ASN1_R_EXPECTING_AN_OBJECT;
268 goto err;
270 ret = c2i_ASN1_OBJECT(a, &p, len);
271 if (ret)
272 *pp = p;
273 return ret;
275 err:
276 ASN1error(i);
277 return (NULL);
280 ASN1_OBJECT *
281 c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len)
283 ASN1_OBJECT *ret;
284 const unsigned char *p;
285 unsigned char *data;
286 int i, length;
289 * Sanity check OID encoding:
290 * - need at least one content octet
291 * - MSB must be clear in the last octet
292 * - can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
294 if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
295 p[len - 1] & 0x80) {
296 ASN1error(ASN1_R_INVALID_OBJECT_ENCODING);
297 return (NULL);
300 /* Now 0 < len <= INT_MAX, so the cast is safe. */
301 length = (int)len;
302 for (i = 0; i < length; i++, p++) {
303 if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
304 ASN1error(ASN1_R_INVALID_OBJECT_ENCODING);
305 return (NULL);
309 /* only the ASN1_OBJECTs from the 'table' will have values
310 * for ->sn or ->ln */
311 if ((a == NULL) || ((*a) == NULL) ||
312 !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
313 if ((ret = ASN1_OBJECT_new()) == NULL)
314 return (NULL);
315 } else
316 ret = *a;
318 p = *pp;
320 /* detach data from object */
321 data = (unsigned char *)ret->data;
322 if (data != NULL)
323 explicit_bzero(data, ret->length);
324 free(data);
326 data = malloc(length);
327 if (data == NULL) {
328 ASN1error(ERR_R_MALLOC_FAILURE);
329 goto err;
332 memcpy(data, p, length);
334 /* reattach data to object, after which it remains const */
335 ret->data = data;
336 ret->length = length;
337 ret->sn = NULL;
338 ret->ln = NULL;
339 ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
340 p += length;
342 if (a != NULL)
343 *a = ret;
344 *pp = p;
345 return (ret);
347 err:
348 if (a == NULL || ret != *a)
349 ASN1_OBJECT_free(ret);
350 return (NULL);
353 ASN1_OBJECT *
354 ASN1_OBJECT_new(void)
356 ASN1_OBJECT *ret;
358 ret = malloc(sizeof(ASN1_OBJECT));
359 if (ret == NULL) {
360 ASN1error(ERR_R_MALLOC_FAILURE);
361 return (NULL);
363 ret->length = 0;
364 ret->data = NULL;
365 ret->nid = 0;
366 ret->sn = NULL;
367 ret->ln = NULL;
368 ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
369 return (ret);
372 void
373 ASN1_OBJECT_free(ASN1_OBJECT *a)
375 if (a == NULL)
376 return;
377 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
378 free((void *)a->sn);
379 free((void *)a->ln);
380 a->sn = a->ln = NULL;
382 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
383 if (a->data != NULL)
384 explicit_bzero((void *)a->data, a->length);
385 free((void *)a->data);
386 a->data = NULL;
387 a->length = 0;
389 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
390 free(a);
393 ASN1_OBJECT *
394 ASN1_OBJECT_create(int nid, unsigned char *data, int len,
395 const char *sn, const char *ln)
397 ASN1_OBJECT o;
399 o.sn = sn;
400 o.ln = ln;
401 o.data = data;
402 o.nid = nid;
403 o.length = len;
404 o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
405 ASN1_OBJECT_FLAG_DYNAMIC_DATA;
406 return (OBJ_dup(&o));