a_bytes.c revision 109998
118579Sfenner/* crypto/asn1/a_bytes.c */
2100787Sfenner/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
318579Sfenner * All rights reserved.
418579Sfenner *
518579Sfenner * This package is an SSL implementation written
618579Sfenner * by Eric Young (eay@cryptsoft.com).
718579Sfenner * The implementation was written so as to conform with Netscapes SSL.
818579Sfenner *
918579Sfenner * This library is free for commercial and non-commercial use as long as
1018579Sfenner * the following conditions are aheared to.  The following conditions
1118579Sfenner * apply to all code found in this distribution, be it the RC4, RSA,
1218579Sfenner * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1318579Sfenner * included with this distribution is covered by the same copyright terms
1418579Sfenner * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1518579Sfenner *
1618579Sfenner * Copyright remains Eric Young's, and as such any Copyright notices in
1718579Sfenner * the code are not to be removed.
1818579Sfenner * If this package is used in a product, Eric Young should be given attribution
1918579Sfenner * as the author of the parts of the library used.
2018579Sfenner * This can be in the form of a textual message at program startup or
2118579Sfenner * in documentation (online or textual) provided with the package.
2218579Sfenner *
2318579Sfenner * Redistribution and use in source and binary forms, with or without
24100787Sfenner * modification, are permitted provided that the following conditions
2518579Sfenner * are met:
2658835Sshin * 1. Redistributions of source code must retain the copyright
2718579Sfenner *    notice, this list of conditions and the following disclaimer.
28100787Sfenner * 2. Redistributions in binary form must reproduce the above copyright
2918579Sfenner *    notice, this list of conditions and the following disclaimer in the
3058835Sshin *    documentation and/or other materials provided with the distribution.
3158835Sshin * 3. All advertising materials mentioning features or use of this software
3258835Sshin *    must display the following acknowledgement:
3318579Sfenner *    "This product includes cryptographic software written by
3418579Sfenner *     Eric Young (eay@cryptsoft.com)"
3518579Sfenner *    The word 'cryptographic' can be left out if the rouines from the library
3618579Sfenner *    being used are not cryptographic related :-).
3718579Sfenner * 4. If you include any Windows specific code (or a derivative thereof) from
3818579Sfenner *    the apps directory (application code) you must include an acknowledgement:
3918579Sfenner *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4018579Sfenner *
4118579Sfenner * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4218579Sfenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4377816Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4477816Sru * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4577816Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4618579Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4718579Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4818579Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4918579Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5018579Sfenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5118579Sfenner * SUCH DAMAGE.
5218579Sfenner *
5318579Sfenner * The licence and distribution terms for any publically available version or
5418579Sfenner * derivative of this code cannot be changed.  i.e. this code cannot simply be
5518579Sfenner * copied and put under another distribution licence
5618579Sfenner * [including the GNU Public Licence.]
5718579Sfenner */
5818579Sfenner
5918579Sfenner#include <stdio.h>
6077816Sru#include "cryptlib.h"
6118579Sfenner#include <openssl/asn1.h>
6218579Sfenner
6318579Sfennerstatic int asn1_collate_primitive(ASN1_STRING *a, ASN1_CTX *c);
6418579Sfenner/* type is a 'bitmap' of acceptable string types.
6518579Sfenner */
6618579SfennerASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, unsigned char **pp,
6718579Sfenner	     long length, int type)
6818579Sfenner	{
6918579Sfenner	ASN1_STRING *ret=NULL;
7018579Sfenner	unsigned char *p,*s;
7118579Sfenner	long len;
7218579Sfenner	int inf,tag,xclass;
7318579Sfenner	int i=0;
7418579Sfenner
7518579Sfenner	p= *pp;
7618579Sfenner	inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
7718579Sfenner	if (inf & 0x80) goto err;
7818579Sfenner
7918579Sfenner	if (tag >= 32)
8077816Sru		{
8118579Sfenner		i=ASN1_R_TAG_VALUE_TOO_HIGH;;
8218579Sfenner		goto err;
8318579Sfenner		}
8418579Sfenner	if (!(ASN1_tag2bit(tag) & type))
8518579Sfenner		{
8618579Sfenner		i=ASN1_R_WRONG_TYPE;
8718579Sfenner		goto err;
8818579Sfenner		}
8918579Sfenner
9018579Sfenner	/* If a bit-string, exit early */
9118579Sfenner	if (tag == V_ASN1_BIT_STRING)
9218579Sfenner		return(d2i_ASN1_BIT_STRING(a,pp,length));
9318579Sfenner
9418579Sfenner	if ((a == NULL) || ((*a) == NULL))
9518579Sfenner		{
9618579Sfenner		if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
9718579Sfenner		}
9818579Sfenner	else
9918579Sfenner		ret=(*a);
10018579Sfenner
10118579Sfenner	if (len != 0)
10218579Sfenner		{
10318579Sfenner		s=(unsigned char *)OPENSSL_malloc((int)len+1);
10418579Sfenner		if (s == NULL)
10518579Sfenner			{
10618579Sfenner			i=ERR_R_MALLOC_FAILURE;
10718579Sfenner			goto err;
10818579Sfenner			}
10918579Sfenner		memcpy(s,p,(int)len);
11018579Sfenner		s[len]='\0';
11118579Sfenner		p+=len;
11218579Sfenner		}
11318579Sfenner	else
11418579Sfenner		s=NULL;
11518579Sfenner
11618579Sfenner	if (ret->data != NULL) OPENSSL_free(ret->data);
11718579Sfenner	ret->length=(int)len;
11818579Sfenner	ret->data=s;
11918579Sfenner	ret->type=tag;
12018579Sfenner	if (a != NULL) (*a)=ret;
12118579Sfenner	*pp=p;
12218579Sfenner	return(ret);
12318579Sfennererr:
12418579Sfenner	ASN1err(ASN1_F_D2I_ASN1_TYPE_BYTES,i);
12518579Sfenner	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
12618579Sfenner		ASN1_STRING_free(ret);
12718579Sfenner	return(NULL);
12818579Sfenner	}
12918579Sfenner
13018579Sfennerint i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
13118579Sfenner	{
13218579Sfenner	int ret,r,constructed;
13318579Sfenner	unsigned char *p;
13418579Sfenner
13518579Sfenner	if (a == NULL)  return(0);
13618579Sfenner
13718579Sfenner	if (tag == V_ASN1_BIT_STRING)
13818579Sfenner		return(i2d_ASN1_BIT_STRING(a,pp));
13918579Sfenner
14018579Sfenner	ret=a->length;
14118579Sfenner	r=ASN1_object_size(0,ret,tag);
14218579Sfenner	if (pp == NULL) return(r);
14318579Sfenner	p= *pp;
14418579Sfenner
14518579Sfenner	if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET))
14618579Sfenner		constructed=1;
14718579Sfenner	else
14818579Sfenner		constructed=0;
14918579Sfenner	ASN1_put_object(&p,constructed,ret,tag,xclass);
15018579Sfenner	memcpy(p,a->data,a->length);
15118579Sfenner	p+=a->length;
15218579Sfenner	*pp= p;
15318579Sfenner	return(r);
15418579Sfenner	}
15518579Sfenner
15618579SfennerASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, unsigned char **pp, long length,
15718579Sfenner	     int Ptag, int Pclass)
15818579Sfenner	{
15918579Sfenner	ASN1_STRING *ret=NULL;
16018579Sfenner	unsigned char *p,*s;
16118579Sfenner	long len;
16218579Sfenner	int inf,tag,xclass;
16318579Sfenner	int i=0;
16418579Sfenner
16518579Sfenner	if ((a == NULL) || ((*a) == NULL))
16618579Sfenner		{
16718579Sfenner		if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
16818579Sfenner		}
16918579Sfenner	else
17018579Sfenner		ret=(*a);
17118579Sfenner
17218579Sfenner	p= *pp;
17318579Sfenner	inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
17418579Sfenner	if (inf & 0x80)
17518579Sfenner		{
17618579Sfenner		i=ASN1_R_BAD_OBJECT_HEADER;
17718579Sfenner		goto err;
17818579Sfenner		}
17918579Sfenner
18018579Sfenner	if (tag != Ptag)
18118579Sfenner		{
18218579Sfenner		i=ASN1_R_WRONG_TAG;
18318579Sfenner		goto err;
18418579Sfenner		}
18518579Sfenner
18618579Sfenner	if (inf & V_ASN1_CONSTRUCTED)
18718579Sfenner		{
18818579Sfenner		ASN1_CTX c;
18918579Sfenner
19018579Sfenner		c.pp=pp;
19118579Sfenner		c.p=p;
19218579Sfenner		c.inf=inf;
19318579Sfenner		c.slen=len;
19418579Sfenner		c.tag=Ptag;
19518579Sfenner		c.xclass=Pclass;
19618579Sfenner		c.max=(length == 0)?0:(p+length);
19718579Sfenner		if (!asn1_collate_primitive(ret,&c))
19818579Sfenner			goto err;
19918579Sfenner		else
20018579Sfenner			{
20118579Sfenner			p=c.p;
20218579Sfenner			}
20318579Sfenner		}
20418579Sfenner	else
20518579Sfenner		{
20618579Sfenner		if (len != 0)
20718579Sfenner			{
20818579Sfenner			if ((ret->length < len) || (ret->data == NULL))
20918579Sfenner				{
21018579Sfenner				if (ret->data != NULL) OPENSSL_free(ret->data);
21118579Sfenner				s=(unsigned char *)OPENSSL_malloc((int)len + 1);
21277816Sru				if (s == NULL)
21377816Sru					{
21477816Sru					i=ERR_R_MALLOC_FAILURE;
21518579Sfenner					goto err;
21618579Sfenner					}
21718579Sfenner				}
21818579Sfenner			else
21918579Sfenner				s=ret->data;
22018579Sfenner			memcpy(s,p,(int)len);
22118579Sfenner			s[len] = '\0';
22218579Sfenner			p+=len;
22346542Sarchie			}
224100789Sfenner		else
22518579Sfenner			{
22618579Sfenner			s=NULL;
22718579Sfenner			if (ret->data != NULL) OPENSSL_free(ret->data);
22858804Sshin			}
22958804Sshin
230171135Sgnn		ret->length=(int)len;
23158804Sshin		ret->data=s;
23258804Sshin		ret->type=Ptag;
23318579Sfenner		}
234100787Sfenner
23518579Sfenner	if (a != NULL) (*a)=ret;
236100787Sfenner	*pp=p;
23718579Sfenner	return(ret);
23818579Sfennererr:
23918579Sfenner	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
24018579Sfenner		ASN1_STRING_free(ret);
24118579Sfenner	ASN1err(ASN1_F_D2I_ASN1_BYTES,i);
24218579Sfenner	return(NULL);
24318579Sfenner	}
24418579Sfenner
24518579Sfenner
24618579Sfenner/* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse
247100787Sfenner * them into the one structure that is then returned */
248100787Sfenner/* There have been a few bug fixes for this function from
249100787Sfenner * Paul Keogh <paul.keogh@sse.ie>, many thanks to him */
250100787Sfennerstatic int asn1_collate_primitive(ASN1_STRING *a, ASN1_CTX *c)
251100787Sfenner	{
252100787Sfenner	ASN1_STRING *os=NULL;
253100787Sfenner	BUF_MEM b;
254100787Sfenner	int num;
255100787Sfenner
256100787Sfenner	b.length=0;
257100787Sfenner	b.max=0;
258100787Sfenner	b.data=NULL;
259100787Sfenner
260176428Srpaulo	if (a == NULL)
261100787Sfenner		{
262100787Sfenner		c->error=ERR_R_PASSED_NULL_PARAMETER;
26318579Sfenner		goto err;
26418579Sfenner		}
26518579Sfenner
26618579Sfenner	num=0;
26718579Sfenner	for (;;)
26818579Sfenner		{
26918579Sfenner		if (c->inf & 1)
27018579Sfenner			{
27118579Sfenner			c->eos=ASN1_check_infinite_end(&c->p,
27218579Sfenner				(long)(c->max-c->p));
27346542Sarchie			if (c->eos) break;
27446542Sarchie			}
27546542Sarchie		else
27646542Sarchie			{
27746542Sarchie			if (c->slen <= 0) break;
27846542Sarchie			}
27946542Sarchie
28046542Sarchie		c->q=c->p;
28146542Sarchie		if (d2i_ASN1_bytes(&os,&c->p,c->max-c->p,c->tag,c->xclass)
28246542Sarchie			== NULL)
28346542Sarchie			{
28446542Sarchie			c->error=ERR_R_ASN1_LIB;
28546542Sarchie			goto err;
28646542Sarchie			}
287100787Sfenner
288100787Sfenner		if (!BUF_MEM_grow_clean(&b,num+os->length))
289100787Sfenner			{
290100787Sfenner			c->error=ERR_R_BUF_LIB;
291100787Sfenner			goto err;
292100787Sfenner			}
293100787Sfenner		memcpy(&(b.data[num]),os->data,os->length);
29418579Sfenner		if (!(c->inf & 1))
29518579Sfenner			c->slen-=(c->p-c->q);
29618579Sfenner		num+=os->length;
29718579Sfenner		}
29818579Sfenner
29918579Sfenner	if (!asn1_Finish(c)) goto err;
30018579Sfenner
301100787Sfenner	a->length=num;
302100787Sfenner	if (a->data != NULL) OPENSSL_free(a->data);
303100787Sfenner	a->data=(unsigned char *)b.data;
304100787Sfenner	if (os != NULL) ASN1_STRING_free(os);
305100787Sfenner	return(1);
30646542Sarchieerr:
307100787Sfenner	ASN1err(ASN1_F_ASN1_COLLATE_PRIMITIVE,c->error);
30846542Sarchie	if (os != NULL) ASN1_STRING_free(os);
30918579Sfenner	if (b.data != NULL) OPENSSL_free(b.data);
31018579Sfenner	return(0);
31146542Sarchie	}
312100787Sfenner
31318579Sfenner