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