1 /* $OpenBSD: a_object.c,v 1.25 2016/03/06 18:05:00 beck 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 <limits.h>
60 #include <stdio.h>
61 #include <string.h>
62 
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>
68 
69 int
70 i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
71 {
72 	unsigned char *p;
73 	int objsize;
74 
75 	if ((a == NULL) || (a->data == NULL))
76 		return (0);
77 
78 	objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
79 	if (pp == NULL)
80 		return objsize;
81 
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;
86 
87 	*pp = p;
88 	return (objsize);
89 }
90 
91 int
92 a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
93 {
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;
100 
101 	if (num == 0)
102 		return (0);
103 	else if (num == -1)
104 		num = strlen(buf);
105 
106 	p = buf;
107 	c = *(p++);
108 	num--;
109 	if ((c >= '0') && (c <= '2')) {
110 		first= c-'0';
111 	} else {
112 		ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE);
113 		goto err;
114 	}
115 
116 	if (num <= 0) {
117 		ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER);
118 		goto err;
119 	}
120 	c = *(p++);
121 	num--;
122 	for (;;) {
123 		if (num <= 0)
124 			break;
125 		if ((c != '.') && (c != ' ')) {
126 			ASN1err(ASN1_F_A2D_ASN1_OBJECT,
127 			    ASN1_R_INVALID_SEPARATOR);
128 			goto err;
129 		}
130 		l = 0;
131 		use_bn = 0;
132 		for (;;) {
133 			if (num <= 0)
134 				break;
135 			num--;
136 			c = *(p++);
137 			if ((c == ' ') || (c == '.'))
138 				break;
139 			if ((c < '0') || (c > '9')) {
140 				ASN1err(ASN1_F_A2D_ASN1_OBJECT,
141 				    ASN1_R_INVALID_DIGIT);
142 				goto err;
143 			}
144 			if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
145 				use_bn = 1;
146 				if (!bl)
147 					bl = BN_new();
148 				if (!bl || !BN_set_word(bl, l))
149 					goto err;
150 			}
151 			if (use_bn) {
152 				if (!BN_mul_word(bl, 10L) ||
153 				    !BN_add_word(bl, c-'0'))
154 					goto err;
155 			} else
156 				l = l * 10L + (long)(c - '0');
157 		}
158 		if (len == 0) {
159 			if ((first < 2) && (l >= 40)) {
160 				ASN1err(ASN1_F_A2D_ASN1_OBJECT,
161 				    ASN1_R_SECOND_NUMBER_TOO_LARGE);
162 				goto err;
163 			}
164 			if (use_bn) {
165 				if (!BN_add_word(bl, first * 40))
166 					goto err;
167 			} else
168 				l += (long)first * 40;
169 		}
170 		i = 0;
171 		if (use_bn) {
172 			int blsize;
173 			blsize = BN_num_bits(bl);
174 			blsize = (blsize + 6) / 7;
175 			if (blsize > tmpsize) {
176 				if (tmp != ftmp)
177 					free(tmp);
178 				tmpsize = blsize + 32;
179 				tmp = malloc(tmpsize);
180 				if (!tmp)
181 					goto err;
182 			}
183 			while (blsize--)
184 				tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
185 		} else {
186 
187 			for (;;) {
188 				tmp[i++] = (unsigned char)l & 0x7f;
189 				l >>= 7L;
190 				if (l == 0L)
191 					break;
192 			}
193 
194 		}
195 		if (out != NULL) {
196 			if (len + i > olen) {
197 				ASN1err(ASN1_F_A2D_ASN1_OBJECT,
198 				    ASN1_R_BUFFER_TOO_SMALL);
199 				goto err;
200 			}
201 			while (--i > 0)
202 				out[len++] = tmp[i]|0x80;
203 			out[len++] = tmp[0];
204 		} else
205 			len += i;
206 	}
207 	if (tmp != ftmp)
208 		free(tmp);
209 	BN_free(bl);
210 	return (len);
211 
212 err:
213 	if (tmp != ftmp)
214 		free(tmp);
215 	BN_free(bl);
216 	return (0);
217 }
218 
219 int
220 i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
221 {
222 	return OBJ_obj2txt(buf, buf_len, a, 0);
223 }
224 
225 int
226 i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
227 {
228 	char *tmp = NULL;
229 	size_t tlen = 256;
230 	int i = -1;
231 
232 	if ((a == NULL) || (a->data == NULL))
233 		return(BIO_write(bp, "NULL", 4));
234 	if ((tmp = malloc(tlen)) == NULL)
235 		return -1;
236 	i = i2t_ASN1_OBJECT(tmp, tlen, a);
237 	if (i > (int)(tlen - 1)) {
238 		explicit_bzero(tmp, tlen);
239 		free(tmp);
240 		if ((tmp = malloc(i + 1)) == NULL)
241 			return -1;
242 		tlen = i + 1;
243 		i = i2t_ASN1_OBJECT(tmp, tlen, a);
244 	}
245 	if (i <= 0)
246 		i = BIO_write(bp, "<INVALID>", 9);
247 	else
248 		i = BIO_write(bp, tmp, i);
249 	explicit_bzero(tmp, tlen);
250 	free(tmp);
251 	return (i);
252 }
253 
254 ASN1_OBJECT *
255 d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long length)
256 {
257 	const unsigned char *p;
258 	long len;
259 	int tag, xclass;
260 	int inf, i;
261 	ASN1_OBJECT *ret = NULL;
262 
263 	p = *pp;
264 	inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
265 	if (inf & 0x80) {
266 		i = ASN1_R_BAD_OBJECT_HEADER;
267 		goto err;
268 	}
269 
270 	if (tag != V_ASN1_OBJECT) {
271 		i = ASN1_R_EXPECTING_AN_OBJECT;
272 		goto err;
273 	}
274 	ret = c2i_ASN1_OBJECT(a, &p, len);
275 	if (ret)
276 		*pp = p;
277 	return ret;
278 
279 err:
280 	ASN1err(ASN1_F_D2I_ASN1_OBJECT, i);
281 	return (NULL);
282 }
283 
284 ASN1_OBJECT *
285 c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len)
286 {
287 	ASN1_OBJECT *ret = NULL;
288 	const unsigned char *p;
289 	unsigned char *data;
290 	int i, length;
291 
292 	/*
293 	 * Sanity check OID encoding:
294 	 * - need at least one content octet
295 	 * - MSB must be clear in the last octet
296 	 * - can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
297 	 */
298 	if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
299 	    p[len - 1] & 0x80) {
300 		ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
301 		return (NULL);
302 	}
303 
304 	/* Now 0 < len <= INT_MAX, so the cast is safe. */
305 	length = (int)len;
306 	for (i = 0; i < length; i++, p++) {
307 		if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
308 			ASN1err(ASN1_F_C2I_ASN1_OBJECT,
309 			    ASN1_R_INVALID_OBJECT_ENCODING);
310 			return NULL;
311 		}
312 	}
313 
314 	/* only the ASN1_OBJECTs from the 'table' will have values
315 	 * for ->sn or ->ln */
316 	if ((a == NULL) || ((*a) == NULL) ||
317 	    !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
318 		if ((ret = ASN1_OBJECT_new()) == NULL)
319 			return (NULL);
320 	} else
321 		ret = (*a);
322 
323 	p = *pp;
324 	/* detach data from object */
325 	data = (unsigned char *)ret->data;
326 	if (data != NULL)
327 		explicit_bzero(data, ret->length);
328 	free(data);
329 	data = malloc(length);
330 	if (data == NULL) {
331 		i = ERR_R_MALLOC_FAILURE;
332 		goto err;
333 	}
334 	ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
335 	memcpy(data, p, length);
336 	/* reattach data to object, after which it remains const */
337 	ret->data = data;
338 	ret->length = length;
339 	ret->sn = NULL;
340 	ret->ln = NULL;
341 	/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
342 	p += length;
343 
344 	if (a != NULL)
345 		(*a) = ret;
346 	*pp = p;
347 	return (ret);
348 
349 err:
350 	ASN1err(ASN1_F_C2I_ASN1_OBJECT, i);
351 	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
352 		ASN1_OBJECT_free(ret);
353 	return (NULL);
354 }
355 
356 ASN1_OBJECT *
357 ASN1_OBJECT_new(void)
358 {
359 	ASN1_OBJECT *ret;
360 
361 	ret = malloc(sizeof(ASN1_OBJECT));
362 	if (ret == NULL) {
363 		ASN1err(ASN1_F_ASN1_OBJECT_NEW, ERR_R_MALLOC_FAILURE);
364 		return (NULL);
365 	}
366 	ret->length = 0;
367 	ret->data = NULL;
368 	ret->nid = 0;
369 	ret->sn = NULL;
370 	ret->ln = NULL;
371 	ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
372 	return (ret);
373 }
374 
375 void
376 ASN1_OBJECT_free(ASN1_OBJECT *a)
377 {
378 	if (a == NULL)
379 		return;
380 	if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
381 		free((void *)a->sn);
382 		free((void *)a->ln);
383 		a->sn = a->ln = NULL;
384 	}
385 	if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
386 		if (a->data != NULL)
387 			explicit_bzero((void *)a->data, a->length);
388 		free((void *)a->data);
389 		a->data = NULL;
390 		a->length = 0;
391 	}
392 	if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
393 		free(a);
394 }
395 
396 ASN1_OBJECT *
397 ASN1_OBJECT_create(int nid, unsigned char *data, int len,
398     const char *sn, const char *ln)
399 {
400 	ASN1_OBJECT o;
401 
402 	o.sn = sn;
403 	o.ln = ln;
404 	o.data = data;
405 	o.nid = nid;
406 	o.length = len;
407 	o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
408 	    ASN1_OBJECT_FLAG_DYNAMIC_DATA;
409 	return (OBJ_dup(&o));
410 }
411