asn1_lib.c revision 194206
155714Skris/* crypto/asn1/asn1_lib.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 60101613Snectar#include <limits.h> 6155714Skris#include "cryptlib.h" 6255714Skris#include <openssl/asn1.h> 6355714Skris#include <openssl/asn1_mac.h> 6455714Skris 65160814Ssimonstatic int asn1_get_length(const unsigned char **pp,int *inf,long *rl,int max); 6655714Skrisstatic void asn1_put_length(unsigned char **pp, int length); 67167612Ssimonconst char ASN1_version[]="ASN.1" OPENSSL_VERSION_PTEXT; 6855714Skris 69160814Ssimonstatic int _asn1_check_infinite_end(const unsigned char **p, long len) 7055714Skris { 7155714Skris /* If there is 0 or 1 byte left, the length check should pick 7255714Skris * things up */ 7355714Skris if (len <= 0) 7455714Skris return(1); 7555714Skris else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) 7655714Skris { 7755714Skris (*p)+=2; 7855714Skris return(1); 7955714Skris } 8055714Skris return(0); 8155714Skris } 8255714Skris 83160814Ssimonint ASN1_check_infinite_end(unsigned char **p, long len) 84160814Ssimon { 85160814Ssimon return _asn1_check_infinite_end((const unsigned char **)p, len); 86160814Ssimon } 8755714Skris 88160814Ssimonint ASN1_const_check_infinite_end(const unsigned char **p, long len) 8955714Skris { 90160814Ssimon return _asn1_check_infinite_end(p, len); 91160814Ssimon } 92160814Ssimon 93160814Ssimon 94160814Ssimonint ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, 95160814Ssimon int *pclass, long omax) 96160814Ssimon { 9755714Skris int i,ret; 9855714Skris long l; 99160814Ssimon const unsigned char *p= *pp; 10055714Skris int tag,xclass,inf; 10155714Skris long max=omax; 10255714Skris 10355714Skris if (!max) goto err; 10455714Skris ret=(*p&V_ASN1_CONSTRUCTED); 10555714Skris xclass=(*p&V_ASN1_PRIVATE); 10655714Skris i= *p&V_ASN1_PRIMITIVE_TAG; 10755714Skris if (i == V_ASN1_PRIMITIVE_TAG) 10855714Skris { /* high-tag */ 10955714Skris p++; 11055714Skris if (--max == 0) goto err; 11155714Skris l=0; 11255714Skris while (*p&0x80) 11355714Skris { 11455714Skris l<<=7L; 11555714Skris l|= *(p++)&0x7f; 11655714Skris if (--max == 0) goto err; 117120631Snectar if (l > (INT_MAX >> 7L)) goto err; 11855714Skris } 11955714Skris l<<=7L; 12055714Skris l|= *(p++)&0x7f; 12155714Skris tag=(int)l; 122120631Snectar if (--max == 0) goto err; 12355714Skris } 12455714Skris else 12555714Skris { 12655714Skris tag=i; 12755714Skris p++; 12855714Skris if (--max == 0) goto err; 12955714Skris } 13055714Skris *ptag=tag; 13155714Skris *pclass=xclass; 13255714Skris if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err; 13355714Skris 13455714Skris#if 0 13555714Skris fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n", 13655714Skris (int)p,*plength,omax,(int)*pp,(int)(p+ *plength), 13755714Skris (int)(omax+ *pp)); 13855714Skris 13955714Skris#endif 140101386Snectar if (*plength > (omax - (p - *pp))) 14155714Skris { 14255714Skris ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_TOO_LONG); 14355714Skris /* Set this so that even if things are not long enough 14455714Skris * the values are set correctly */ 14555714Skris ret|=0x80; 14655714Skris } 14755714Skris *pp=p; 14855714Skris return(ret|inf); 14955714Skriserr: 15055714Skris ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_HEADER_TOO_LONG); 15155714Skris return(0x80); 15255714Skris } 15355714Skris 154160814Ssimonstatic int asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max) 15555714Skris { 156160814Ssimon const unsigned char *p= *pp; 157101613Snectar unsigned long ret=0; 158160814Ssimon unsigned int i; 15955714Skris 16055714Skris if (max-- < 1) return(0); 16155714Skris if (*p == 0x80) 16255714Skris { 16355714Skris *inf=1; 16455714Skris ret=0; 16555714Skris p++; 16655714Skris } 16755714Skris else 16855714Skris { 16955714Skris *inf=0; 17055714Skris i= *p&0x7f; 17155714Skris if (*(p++) & 0x80) 17255714Skris { 173100936Snectar if (i > sizeof(long)) 174100936Snectar return 0; 17555714Skris if (max-- == 0) return(0); 17655714Skris while (i-- > 0) 17755714Skris { 17855714Skris ret<<=8L; 17955714Skris ret|= *(p++); 18055714Skris if (max-- == 0) return(0); 18155714Skris } 18255714Skris } 18355714Skris else 18455714Skris ret=i; 18555714Skris } 186101613Snectar if (ret > LONG_MAX) 187100936Snectar return 0; 18855714Skris *pp=p; 189101613Snectar *rl=(long)ret; 19055714Skris return(1); 19155714Skris } 19255714Skris 19355714Skris/* class 0 is constructed 19459191Skris * constructed == 2 for indefinite length constructed */ 19555714Skrisvoid ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, 19655714Skris int xclass) 19755714Skris { 19855714Skris unsigned char *p= *pp; 19968651Skris int i, ttag; 20055714Skris 20155714Skris i=(constructed)?V_ASN1_CONSTRUCTED:0; 20255714Skris i|=(xclass&V_ASN1_PRIVATE); 20355714Skris if (tag < 31) 20455714Skris *(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG); 20555714Skris else 20655714Skris { 20755714Skris *(p++)=i|V_ASN1_PRIMITIVE_TAG; 20868651Skris for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7; 20968651Skris ttag = i; 21068651Skris while(i-- > 0) 21155714Skris { 21268651Skris p[i] = tag & 0x7f; 21368651Skris if(i != (ttag - 1)) p[i] |= 0x80; 21468651Skris tag >>= 7; 21555714Skris } 21668651Skris p += ttag; 21755714Skris } 218160814Ssimon if (constructed == 2) 219160814Ssimon *(p++)=0x80; 22055714Skris else 22155714Skris asn1_put_length(&p,length); 22255714Skris *pp=p; 22355714Skris } 22455714Skris 225160814Ssimonint ASN1_put_eoc(unsigned char **pp) 226160814Ssimon { 227160814Ssimon unsigned char *p = *pp; 228160814Ssimon *p++ = 0; 229160814Ssimon *p++ = 0; 230160814Ssimon *pp = p; 231160814Ssimon return 2; 232160814Ssimon } 233160814Ssimon 23455714Skrisstatic void asn1_put_length(unsigned char **pp, int length) 23555714Skris { 23655714Skris unsigned char *p= *pp; 23755714Skris int i,l; 23855714Skris if (length <= 127) 23955714Skris *(p++)=(unsigned char)length; 24055714Skris else 24155714Skris { 24255714Skris l=length; 24355714Skris for (i=0; l > 0; i++) 24455714Skris l>>=8; 24555714Skris *(p++)=i|0x80; 24655714Skris l=i; 24755714Skris while (i-- > 0) 24855714Skris { 24955714Skris p[i]=length&0xff; 25055714Skris length>>=8; 25155714Skris } 25255714Skris p+=l; 25355714Skris } 25455714Skris *pp=p; 25555714Skris } 25655714Skris 25755714Skrisint ASN1_object_size(int constructed, int length, int tag) 25855714Skris { 25955714Skris int ret; 26055714Skris 26155714Skris ret=length; 26255714Skris ret++; 26355714Skris if (tag >= 31) 26455714Skris { 26555714Skris while (tag > 0) 26655714Skris { 26755714Skris tag>>=7; 26855714Skris ret++; 26955714Skris } 27055714Skris } 271160814Ssimon if (constructed == 2) 272160814Ssimon return ret + 3; 27355714Skris ret++; 27455714Skris if (length > 127) 27555714Skris { 27655714Skris while (length > 0) 27755714Skris { 27855714Skris length>>=8; 27955714Skris ret++; 28055714Skris } 28155714Skris } 28255714Skris return(ret); 28355714Skris } 28455714Skris 285160814Ssimonstatic int _asn1_Finish(ASN1_const_CTX *c) 28655714Skris { 28755714Skris if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos)) 28855714Skris { 289160814Ssimon if (!ASN1_const_check_infinite_end(&c->p,c->slen)) 29055714Skris { 29155714Skris c->error=ERR_R_MISSING_ASN1_EOS; 29255714Skris return(0); 29355714Skris } 29455714Skris } 29555714Skris if ( ((c->slen != 0) && !(c->inf & 1)) || 29655714Skris ((c->slen < 0) && (c->inf & 1))) 29755714Skris { 29855714Skris c->error=ERR_R_ASN1_LENGTH_MISMATCH; 29955714Skris return(0); 30055714Skris } 30155714Skris return(1); 30255714Skris } 30355714Skris 304160814Ssimonint asn1_Finish(ASN1_CTX *c) 30555714Skris { 306160814Ssimon return _asn1_Finish((ASN1_const_CTX *)c); 307160814Ssimon } 30855714Skris 309160814Ssimonint asn1_const_Finish(ASN1_const_CTX *c) 310160814Ssimon { 311160814Ssimon return _asn1_Finish(c); 312160814Ssimon } 313160814Ssimon 314160814Ssimonint asn1_GetSequence(ASN1_const_CTX *c, long *length) 315160814Ssimon { 316160814Ssimon const unsigned char *q; 317160814Ssimon 31855714Skris q=c->p; 31955714Skris c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass), 32055714Skris *length); 32155714Skris if (c->inf & 0x80) 32255714Skris { 32355714Skris c->error=ERR_R_BAD_GET_ASN1_OBJECT_CALL; 32455714Skris return(0); 32555714Skris } 32655714Skris if (c->tag != V_ASN1_SEQUENCE) 32755714Skris { 32855714Skris c->error=ERR_R_EXPECTING_AN_ASN1_SEQUENCE; 32955714Skris return(0); 33055714Skris } 33155714Skris (*length)-=(c->p-q); 33255714Skris if (c->max && (*length < 0)) 33355714Skris { 33455714Skris c->error=ERR_R_ASN1_LENGTH_MISMATCH; 33555714Skris return(0); 33655714Skris } 33755714Skris if (c->inf == (1|V_ASN1_CONSTRUCTED)) 338109998Smarkm c->slen= *length+ *(c->pp)-c->p; 33955714Skris c->eos=0; 34055714Skris return(1); 34155714Skris } 34255714Skris 34355714SkrisASN1_STRING *ASN1_STRING_dup(ASN1_STRING *str) 34455714Skris { 34555714Skris ASN1_STRING *ret; 34655714Skris 34755714Skris if (str == NULL) return(NULL); 34855714Skris if ((ret=ASN1_STRING_type_new(str->type)) == NULL) 34955714Skris return(NULL); 35055714Skris if (!ASN1_STRING_set(ret,str->data,str->length)) 35155714Skris { 35255714Skris ASN1_STRING_free(ret); 35355714Skris return(NULL); 35455714Skris } 35555714Skris ret->flags = str->flags; 35655714Skris return(ret); 35755714Skris } 35855714Skris 35955714Skrisint ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) 36055714Skris { 36155714Skris unsigned char *c; 36255714Skris const char *data=_data; 36355714Skris 36455714Skris if (len < 0) 36555714Skris { 36655714Skris if (data == NULL) 36755714Skris return(0); 36855714Skris else 36955714Skris len=strlen(data); 37055714Skris } 37155714Skris if ((str->length < len) || (str->data == NULL)) 37255714Skris { 37355714Skris c=str->data; 37455714Skris if (c == NULL) 37568651Skris str->data=OPENSSL_malloc(len+1); 37655714Skris else 37768651Skris str->data=OPENSSL_realloc(c,len+1); 37855714Skris 37955714Skris if (str->data == NULL) 38055714Skris { 381160814Ssimon ASN1err(ASN1_F_ASN1_STRING_SET,ERR_R_MALLOC_FAILURE); 38255714Skris str->data=c; 38355714Skris return(0); 38455714Skris } 38555714Skris } 38655714Skris str->length=len; 38755714Skris if (data != NULL) 38855714Skris { 38955714Skris memcpy(str->data,data,len); 39059191Skris /* an allowance for strings :-) */ 39155714Skris str->data[len]='\0'; 39255714Skris } 39355714Skris return(1); 39455714Skris } 39555714Skris 396194206Ssimonvoid ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) 397194206Ssimon { 398194206Ssimon if (str->data) 399194206Ssimon OPENSSL_free(str->data); 400194206Ssimon str->data = data; 401194206Ssimon str->length = len; 402194206Ssimon } 403194206Ssimon 40455714SkrisASN1_STRING *ASN1_STRING_new(void) 40555714Skris { 40655714Skris return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); 40755714Skris } 40855714Skris 40955714Skris 41055714SkrisASN1_STRING *ASN1_STRING_type_new(int type) 41155714Skris { 41255714Skris ASN1_STRING *ret; 41355714Skris 41468651Skris ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING)); 41555714Skris if (ret == NULL) 41655714Skris { 41755714Skris ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW,ERR_R_MALLOC_FAILURE); 41855714Skris return(NULL); 41955714Skris } 42055714Skris ret->length=0; 42155714Skris ret->type=type; 42255714Skris ret->data=NULL; 42355714Skris ret->flags=0; 42455714Skris return(ret); 42555714Skris } 42655714Skris 42755714Skrisvoid ASN1_STRING_free(ASN1_STRING *a) 42855714Skris { 42955714Skris if (a == NULL) return; 43068651Skris if (a->data != NULL) OPENSSL_free(a->data); 43168651Skris OPENSSL_free(a); 43255714Skris } 43355714Skris 43455714Skrisint ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b) 43555714Skris { 43655714Skris int i; 43755714Skris 43855714Skris i=(a->length-b->length); 43955714Skris if (i == 0) 44055714Skris { 44155714Skris i=memcmp(a->data,b->data,a->length); 44255714Skris if (i == 0) 44355714Skris return(a->type-b->type); 44455714Skris else 44555714Skris return(i); 44655714Skris } 44755714Skris else 44855714Skris return(i); 44955714Skris } 45055714Skris 451160814Ssimonvoid asn1_add_error(const unsigned char *address, int offset) 45255714Skris { 453100936Snectar char buf1[DECIMAL_SIZE(address)+1],buf2[DECIMAL_SIZE(offset)+1]; 45455714Skris 455127128Snectar BIO_snprintf(buf1,sizeof buf1,"%lu",(unsigned long)address); 456127128Snectar BIO_snprintf(buf2,sizeof buf2,"%d",offset); 45755714Skris ERR_add_error_data(4,"address=",buf1," offset=",buf2); 45855714Skris } 45955714Skris 46059191Skrisint ASN1_STRING_length(ASN1_STRING *x) 46159191Skris{ return M_ASN1_STRING_length(x); } 46259191Skris 46359191Skrisvoid ASN1_STRING_length_set(ASN1_STRING *x, int len) 46459191Skris{ M_ASN1_STRING_length_set(x, len); return; } 46559191Skris 46659191Skrisint ASN1_STRING_type(ASN1_STRING *x) 46759191Skris{ return M_ASN1_STRING_type(x); } 46859191Skris 46959191Skrisunsigned char * ASN1_STRING_data(ASN1_STRING *x) 47059191Skris{ return M_ASN1_STRING_data(x); } 471