asn1_lib.c revision 68651
1142215Sglebius/* crypto/asn1/asn1_lib.c */
2142215Sglebius/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3142215Sglebius * All rights reserved.
4142215Sglebius *
5142215Sglebius * This package is an SSL implementation written
6142215Sglebius * by Eric Young (eay@cryptsoft.com).
7142215Sglebius * The implementation was written so as to conform with Netscapes SSL.
8142215Sglebius *
9142215Sglebius * This library is free for commercial and non-commercial use as long as
10142215Sglebius * the following conditions are aheared to.  The following conditions
11142215Sglebius * apply to all code found in this distribution, be it the RC4, RSA,
12142215Sglebius * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13142215Sglebius * included with this distribution is covered by the same copyright terms
14142215Sglebius * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15142215Sglebius *
16142215Sglebius * Copyright remains Eric Young's, and as such any Copyright notices in
17142215Sglebius * the code are not to be removed.
18142215Sglebius * If this package is used in a product, Eric Young should be given attribution
19142215Sglebius * as the author of the parts of the library used.
20142215Sglebius * This can be in the form of a textual message at program startup or
21142215Sglebius * in documentation (online or textual) provided with the package.
22142215Sglebius *
23142215Sglebius * Redistribution and use in source and binary forms, with or without
24142215Sglebius * modification, are permitted provided that the following conditions
25142215Sglebius * are met:
26142215Sglebius * 1. Redistributions of source code must retain the copyright
27172467Ssilby *    notice, this list of conditions and the following disclaimer.
28172467Ssilby * 2. Redistributions in binary form must reproduce the above copyright
29172467Ssilby *    notice, this list of conditions and the following disclaimer in the
30142215Sglebius *    documentation and/or other materials provided with the distribution.
31142215Sglebius * 3. All advertising materials mentioning features or use of this software
32142215Sglebius *    must display the following acknowledgement:
33142215Sglebius *    "This product includes cryptographic software written by
34142215Sglebius *     Eric Young (eay@cryptsoft.com)"
35142215Sglebius *    The word 'cryptographic' can be left out if the rouines from the library
36142215Sglebius *    being used are not cryptographic related :-).
37142215Sglebius * 4. If you include any Windows specific code (or a derivative thereof) from
38142215Sglebius *    the apps directory (application code) you must include an acknowledgement:
39142215Sglebius *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40142215Sglebius *
41142215Sglebius * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42142215Sglebius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43142215Sglebius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44142215Sglebius * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45164033Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46142215Sglebius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47142215Sglebius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48142215Sglebius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49142215Sglebius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50142215Sglebius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51142215Sglebius * SUCH DAMAGE.
52142215Sglebius *
53142215Sglebius * The licence and distribution terms for any publically available version or
54142215Sglebius * derivative of this code cannot be changed.  i.e. this code cannot simply be
55181803Sbz * copied and put under another distribution licence
56142215Sglebius * [including the GNU Public Licence.]
57142215Sglebius */
58142215Sglebius
59142215Sglebius#include <stdio.h>
60142215Sglebius#include "cryptlib.h"
61142215Sglebius#include <openssl/asn1.h>
62142215Sglebius#include <openssl/asn1_mac.h>
63142215Sglebius
64142215Sglebiusstatic int asn1_get_length(unsigned char **pp,int *inf,long *rl,int max);
65152410Srustatic void asn1_put_length(unsigned char **pp, int length);
66142215Sglebiusconst char *ASN1_version="ASN.1" OPENSSL_VERSION_PTEXT;
67142215Sglebius
68142215Sglebiusint ASN1_check_infinite_end(unsigned char **p, long len)
69142215Sglebius	{
70142215Sglebius	/* If there is 0 or 1 byte left, the length check should pick
71142215Sglebius	 * things up */
72142215Sglebius	if (len <= 0)
73142215Sglebius		return(1);
74142215Sglebius	else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0))
75142215Sglebius		{
76142215Sglebius		(*p)+=2;
77142215Sglebius		return(1);
78142215Sglebius		}
79142215Sglebius	return(0);
80142215Sglebius	}
81142215Sglebius
82142215Sglebius
83148387Sumeint ASN1_get_object(unsigned char **pp, long *plength, int *ptag, int *pclass,
84142215Sglebius	     long omax)
85142215Sglebius	{
86142215Sglebius	int i,ret;
87142215Sglebius	long l;
88142215Sglebius	unsigned char *p= *pp;
89142215Sglebius	int tag,xclass,inf;
90142215Sglebius	long max=omax;
91142215Sglebius
92142215Sglebius	if (!max) goto err;
93142215Sglebius	ret=(*p&V_ASN1_CONSTRUCTED);
94142215Sglebius	xclass=(*p&V_ASN1_PRIVATE);
95147256Sbrooks	i= *p&V_ASN1_PRIMITIVE_TAG;
96142901Sglebius	if (i == V_ASN1_PRIMITIVE_TAG)
97142215Sglebius		{		/* high-tag */
98142215Sglebius		p++;
99142215Sglebius		if (--max == 0) goto err;
100142215Sglebius		l=0;
101142215Sglebius		while (*p&0x80)
102142215Sglebius			{
103142215Sglebius			l<<=7L;
104142215Sglebius			l|= *(p++)&0x7f;
105142215Sglebius			if (--max == 0) goto err;
106142215Sglebius			}
107142215Sglebius		l<<=7L;
108142215Sglebius		l|= *(p++)&0x7f;
109142215Sglebius		tag=(int)l;
110142215Sglebius		}
111142215Sglebius	else
112142215Sglebius		{
113142215Sglebius		tag=i;
114142215Sglebius		p++;
115142215Sglebius		if (--max == 0) goto err;
116142215Sglebius		}
117142215Sglebius	*ptag=tag;
118142215Sglebius	*pclass=xclass;
119142215Sglebius	if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err;
120142215Sglebius
121142215Sglebius#if 0
122142215Sglebius	fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d  (%d > %d)\n",
123142215Sglebius		(int)p,*plength,omax,(int)*pp,(int)(p+ *plength),
124142215Sglebius		(int)(omax+ *pp));
125142215Sglebius
126142215Sglebius#endif
127142215Sglebius#if 0
128142215Sglebius	if ((p+ *plength) > (omax+ *pp))
129142215Sglebius		{
130142215Sglebius		ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_TOO_LONG);
131142215Sglebius		/* Set this so that even if things are not long enough
132142215Sglebius		 * the values are set correctly */
133142215Sglebius		ret|=0x80;
134142215Sglebius		}
135147256Sbrooks#endif
136142215Sglebius	*pp=p;
137142215Sglebius	return(ret|inf);
138142215Sglebiuserr:
139142215Sglebius	ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_HEADER_TOO_LONG);
140142215Sglebius	return(0x80);
141142215Sglebius	}
142142215Sglebius
143142215Sglebiusstatic int asn1_get_length(unsigned char **pp, int *inf, long *rl, int max)
144142215Sglebius	{
145142215Sglebius	unsigned char *p= *pp;
146142215Sglebius	long ret=0;
147146226Sglebius	int i;
148146226Sglebius
149142215Sglebius	if (max-- < 1) return(0);
150142215Sglebius	if (*p == 0x80)
151142215Sglebius		{
152142215Sglebius		*inf=1;
153142215Sglebius		ret=0;
154142215Sglebius		p++;
155142215Sglebius		}
156142215Sglebius	else
157142215Sglebius		{
158142215Sglebius		*inf=0;
159142215Sglebius		i= *p&0x7f;
160142215Sglebius		if (*(p++) & 0x80)
161142215Sglebius			{
162142914Sglebius			if (max-- == 0) return(0);
163142914Sglebius			while (i-- > 0)
164142914Sglebius				{
165142914Sglebius				ret<<=8L;
166142215Sglebius				ret|= *(p++);
167142914Sglebius				if (max-- == 0) return(0);
168142215Sglebius				}
169142914Sglebius			}
170142215Sglebius		else
171142215Sglebius			ret=i;
172142215Sglebius		}
173142215Sglebius	*pp=p;
174142914Sglebius	*rl=ret;
175142914Sglebius	return(1);
176142914Sglebius	}
177142914Sglebius
178142451Sglebius/* class 0 is constructed
179142446Sglebius * constructed == 2 for indefinite length constructed */
180142446Sglebiusvoid ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
181142451Sglebius	     int xclass)
182142215Sglebius	{
183142451Sglebius	unsigned char *p= *pp;
184142446Sglebius	int i, ttag;
185142446Sglebius
186142451Sglebius	i=(constructed)?V_ASN1_CONSTRUCTED:0;
187142446Sglebius	i|=(xclass&V_ASN1_PRIVATE);
188142559Sglebius	if (tag < 31)
189142559Sglebius		*(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG);
190142559Sglebius	else
191142559Sglebius		{
192142559Sglebius		*(p++)=i|V_ASN1_PRIMITIVE_TAG;
193142559Sglebius		for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7;
194142559Sglebius		ttag = i;
195160195Ssam		while(i-- > 0)
196142559Sglebius			{
197166228Sglebius			p[i] = tag & 0x7f;
198142559Sglebius			if(i != (ttag - 1)) p[i] |= 0x80;
199142559Sglebius			tag >>= 7;
200142559Sglebius			}
201142559Sglebius		p += ttag;
202142914Sglebius		}
203142559Sglebius	if ((constructed == 2) && (length == 0))
204142559Sglebius		*(p++)=0x80; /* der_put_length would output 0 instead */
205142914Sglebius	else
206142559Sglebius		asn1_put_length(&p,length);
207142559Sglebius	*pp=p;
208191148Skmacy	}
209142559Sglebius
210142559Sglebiusstatic void asn1_put_length(unsigned char **pp, int length)
211142559Sglebius	{
212142559Sglebius	unsigned char *p= *pp;
213142215Sglebius	int i,l;
214142215Sglebius	if (length <= 127)
215156947Sglebius		*(p++)=(unsigned char)length;
216142559Sglebius	else
217142559Sglebius		{
218142914Sglebius		l=length;
219144329Sglebius		for (i=0; l > 0; i++)
220142215Sglebius			l>>=8;
221142559Sglebius		*(p++)=i|0x80;
222142559Sglebius		l=i;
223142559Sglebius		while (i-- > 0)
224166423Sglebius			{
225142215Sglebius			p[i]=length&0xff;
226142215Sglebius			length>>=8;
227142215Sglebius			}
228142911Sglebius		p+=l;
229142215Sglebius		}
230142215Sglebius	*pp=p;
231156947Sglebius	}
232156947Sglebius
233142215Sglebiusint ASN1_object_size(int constructed, int length, int tag)
234142215Sglebius	{
235142215Sglebius	int ret;
236142215Sglebius
237142215Sglebius	ret=length;
238142215Sglebius	ret++;
239142559Sglebius	if (tag >= 31)
240142215Sglebius		{
241142215Sglebius		while (tag > 0)
242142215Sglebius			{
243142215Sglebius			tag>>=7;
244142215Sglebius			ret++;
245179490Smlaier			}
246179490Smlaier		}
247179490Smlaier	if ((length == 0) && (constructed == 2))
248179490Smlaier		ret+=2;
249142215Sglebius	ret++;
250179490Smlaier	if (length > 127)
251142215Sglebius		{
252142215Sglebius		while (length > 0)
253142914Sglebius			{
254142914Sglebius			length>>=8;
255142914Sglebius			ret++;
256142914Sglebius			}
257142914Sglebius		}
258142215Sglebius	return(ret);
259142215Sglebius	}
260142215Sglebius
261142215Sglebiusint asn1_Finish(ASN1_CTX *c)
262142215Sglebius	{
263142215Sglebius	if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos))
264142215Sglebius		{
265142215Sglebius		if (!ASN1_check_infinite_end(&c->p,c->slen))
266142215Sglebius			{
267142215Sglebius			c->error=ERR_R_MISSING_ASN1_EOS;
268142215Sglebius			return(0);
269142215Sglebius			}
270142215Sglebius		}
271179490Smlaier	if (	((c->slen != 0) && !(c->inf & 1)) ||
272179490Smlaier		((c->slen < 0) && (c->inf & 1)))
273179490Smlaier		{
274179490Smlaier		c->error=ERR_R_ASN1_LENGTH_MISMATCH;
275179490Smlaier		return(0);
276191528Srwatson		}
277179490Smlaier	return(1);
278179490Smlaier	}
279179490Smlaier
280179490Smlaierint asn1_GetSequence(ASN1_CTX *c, long *length)
281179490Smlaier	{
282179490Smlaier	unsigned char *q;
283179490Smlaier
284179490Smlaier	q=c->p;
285179490Smlaier	c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass),
286191528Srwatson		*length);
287179490Smlaier	if (c->inf & 0x80)
288179490Smlaier		{
289179490Smlaier		c->error=ERR_R_BAD_GET_ASN1_OBJECT_CALL;
290142215Sglebius		return(0);
291142215Sglebius		}
292179490Smlaier	if (c->tag != V_ASN1_SEQUENCE)
293179490Smlaier		{
294179490Smlaier		c->error=ERR_R_EXPECTING_AN_ASN1_SEQUENCE;
295179490Smlaier		return(0);
296179490Smlaier		}
297191528Srwatson	(*length)-=(c->p-q);
298179490Smlaier	if (c->max && (*length < 0))
299142215Sglebius		{
300179490Smlaier		c->error=ERR_R_ASN1_LENGTH_MISMATCH;
301179490Smlaier		return(0);
302179490Smlaier		}
303179490Smlaier	if (c->inf == (1|V_ASN1_CONSTRUCTED))
304179490Smlaier		c->slen= *length+ *(c->pp)-c->p;
305179490Smlaier	c->eos=0;
306179490Smlaier	return(1);
307179490Smlaier	}
308142215Sglebius
309191528SrwatsonASN1_STRING *ASN1_STRING_dup(ASN1_STRING *str)
310179490Smlaier	{
311179490Smlaier	ASN1_STRING *ret;
312179490Smlaier
313142215Sglebius	if (str == NULL) return(NULL);
314142215Sglebius	if ((ret=ASN1_STRING_type_new(str->type)) == NULL)
315142215Sglebius		return(NULL);
316142215Sglebius	if (!ASN1_STRING_set(ret,str->data,str->length))
317142215Sglebius		{
318142914Sglebius		ASN1_STRING_free(ret);
319142914Sglebius		return(NULL);
320142914Sglebius		}
321142215Sglebius	ret->flags = str->flags;
322142215Sglebius	return(ret);
323142559Sglebius	}
324142215Sglebius
325142215Sglebiusint ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
326142215Sglebius	{
327142215Sglebius	unsigned char *c;
328142215Sglebius	const char *data=_data;
329142215Sglebius
330142215Sglebius	if (len < 0)
331142215Sglebius		{
332142215Sglebius		if (data == NULL)
333142215Sglebius			return(0);
334142215Sglebius		else
335142215Sglebius			len=strlen(data);
336142215Sglebius		}
337142215Sglebius	if ((str->length < len) || (str->data == NULL))
338142215Sglebius		{
339142215Sglebius		c=str->data;
340142215Sglebius		if (c == NULL)
341142215Sglebius			str->data=OPENSSL_malloc(len+1);
342142559Sglebius		else
343142215Sglebius			str->data=OPENSSL_realloc(c,len+1);
344142215Sglebius
345142215Sglebius		if (str->data == NULL)
346142215Sglebius			{
347142215Sglebius			str->data=c;
348142914Sglebius			return(0);
349142914Sglebius			}
350142215Sglebius		}
351142215Sglebius	str->length=len;
352142215Sglebius	if (data != NULL)
353142215Sglebius		{
354142215Sglebius		memcpy(str->data,data,len);
355142559Sglebius		/* an allowance for strings :-) */
356142215Sglebius		str->data[len]='\0';
357142215Sglebius		}
358142215Sglebius	return(1);
359142215Sglebius	}
360142215Sglebius
361142914SglebiusASN1_STRING *ASN1_STRING_new(void)
362142914Sglebius	{
363142914Sglebius	return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
364142215Sglebius	}
365147256Sbrooks
366142914Sglebius
367142914SglebiusASN1_STRING *ASN1_STRING_type_new(int type)
368142215Sglebius	{
369142564Sglebius	ASN1_STRING *ret;
370142215Sglebius
371142215Sglebius	ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
372142215Sglebius	if (ret == NULL)
373142215Sglebius		{
374142215Sglebius		ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW,ERR_R_MALLOC_FAILURE);
375142215Sglebius		return(NULL);
376142215Sglebius		}
377142215Sglebius	ret->length=0;
378142215Sglebius	ret->type=type;
379142215Sglebius	ret->data=NULL;
380142559Sglebius	ret->flags=0;
381160195Ssam	return(ret);
382142215Sglebius	}
383142215Sglebius
384142215Sglebiusvoid ASN1_STRING_free(ASN1_STRING *a)
385142215Sglebius	{
386142215Sglebius	if (a == NULL) return;
387184205Sdes	if (a->data != NULL) OPENSSL_free(a->data);
388147256Sbrooks	OPENSSL_free(a);
389147256Sbrooks	}
390184205Sdes
391147256Sbrooksint ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b)
392147256Sbrooks	{
393142215Sglebius	int i;
394142215Sglebius
395142215Sglebius	i=(a->length-b->length);
396142215Sglebius	if (i == 0)
397142215Sglebius		{
398142215Sglebius		i=memcmp(a->data,b->data,a->length);
399142215Sglebius		if (i == 0)
400142215Sglebius			return(a->type-b->type);
401160164Smlaier		else
402160164Smlaier			return(i);
403160164Smlaier		}
404170613Sbms	else
405160164Smlaier		return(i);
406162627Sbms	}
407191672Sbms
408191672Sbmsvoid asn1_add_error(unsigned char *address, int offset)
409191672Sbms	{
410191672Sbms	char buf1[16],buf2[16];
411191672Sbms
412191672Sbms	sprintf(buf1,"%lu",(unsigned long)address);
413191672Sbms	sprintf(buf2,"%d",offset);
414191672Sbms	ERR_add_error_data(4,"address=",buf1," offset=",buf2);
415142215Sglebius	}
416171637Srwatson
417171637Srwatsonint ASN1_STRING_length(ASN1_STRING *x)
418171637Srwatson{ return M_ASN1_STRING_length(x); }
419142215Sglebius
420142215Sglebiusvoid ASN1_STRING_length_set(ASN1_STRING *x, int len)
421142215Sglebius{ M_ASN1_STRING_length_set(x, len); return; }
422142215Sglebius
423151688Syarint ASN1_STRING_type(ASN1_STRING *x)
424142215Sglebius{ return M_ASN1_STRING_type(x); }
425142215Sglebius
426142215Sglebiusunsigned char * ASN1_STRING_data(ASN1_STRING *x)
427142215Sglebius{ return M_ASN1_STRING_data(x); }
428142215Sglebius