asn1_lib.c revision 59191
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> 6055714Skris#include "cryptlib.h" 6155714Skris#include <openssl/asn1.h> 6255714Skris#include <openssl/asn1_mac.h> 6355714Skris 6455714Skrisstatic int asn1_get_length(unsigned char **pp,int *inf,long *rl,int max); 6555714Skrisstatic void asn1_put_length(unsigned char **pp, int length); 6655714Skrisconst char *ASN1_version="ASN.1" OPENSSL_VERSION_PTEXT; 6755714Skris 6855714Skrisint ASN1_check_infinite_end(unsigned char **p, long len) 6955714Skris { 7055714Skris /* If there is 0 or 1 byte left, the length check should pick 7155714Skris * things up */ 7255714Skris if (len <= 0) 7355714Skris return(1); 7455714Skris else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) 7555714Skris { 7655714Skris (*p)+=2; 7755714Skris return(1); 7855714Skris } 7955714Skris return(0); 8055714Skris } 8155714Skris 8255714Skris 8355714Skrisint ASN1_get_object(unsigned char **pp, long *plength, int *ptag, int *pclass, 8455714Skris long omax) 8555714Skris { 8655714Skris int i,ret; 8755714Skris long l; 8855714Skris unsigned char *p= *pp; 8955714Skris int tag,xclass,inf; 9055714Skris long max=omax; 9155714Skris 9255714Skris if (!max) goto err; 9355714Skris ret=(*p&V_ASN1_CONSTRUCTED); 9455714Skris xclass=(*p&V_ASN1_PRIVATE); 9555714Skris i= *p&V_ASN1_PRIMITIVE_TAG; 9655714Skris if (i == V_ASN1_PRIMITIVE_TAG) 9755714Skris { /* high-tag */ 9855714Skris p++; 9955714Skris if (--max == 0) goto err; 10055714Skris l=0; 10155714Skris while (*p&0x80) 10255714Skris { 10355714Skris l<<=7L; 10455714Skris l|= *(p++)&0x7f; 10555714Skris if (--max == 0) goto err; 10655714Skris } 10755714Skris l<<=7L; 10855714Skris l|= *(p++)&0x7f; 10955714Skris tag=(int)l; 11055714Skris } 11155714Skris else 11255714Skris { 11355714Skris tag=i; 11455714Skris p++; 11555714Skris if (--max == 0) goto err; 11655714Skris } 11755714Skris *ptag=tag; 11855714Skris *pclass=xclass; 11955714Skris if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err; 12055714Skris 12155714Skris#if 0 12255714Skris fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n", 12355714Skris (int)p,*plength,omax,(int)*pp,(int)(p+ *plength), 12455714Skris (int)(omax+ *pp)); 12555714Skris 12655714Skris#endif 12755714Skris#if 0 12855714Skris if ((p+ *plength) > (omax+ *pp)) 12955714Skris { 13055714Skris ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_TOO_LONG); 13155714Skris /* Set this so that even if things are not long enough 13255714Skris * the values are set correctly */ 13355714Skris ret|=0x80; 13455714Skris } 13555714Skris#endif 13655714Skris *pp=p; 13755714Skris return(ret|inf); 13855714Skriserr: 13955714Skris ASN1err(ASN1_F_ASN1_GET_OBJECT,ASN1_R_HEADER_TOO_LONG); 14055714Skris return(0x80); 14155714Skris } 14255714Skris 14355714Skrisstatic int asn1_get_length(unsigned char **pp, int *inf, long *rl, int max) 14455714Skris { 14555714Skris unsigned char *p= *pp; 14655714Skris long ret=0; 14755714Skris int i; 14855714Skris 14955714Skris if (max-- < 1) return(0); 15055714Skris if (*p == 0x80) 15155714Skris { 15255714Skris *inf=1; 15355714Skris ret=0; 15455714Skris p++; 15555714Skris } 15655714Skris else 15755714Skris { 15855714Skris *inf=0; 15955714Skris i= *p&0x7f; 16055714Skris if (*(p++) & 0x80) 16155714Skris { 16255714Skris if (max-- == 0) return(0); 16355714Skris while (i-- > 0) 16455714Skris { 16555714Skris ret<<=8L; 16655714Skris ret|= *(p++); 16755714Skris if (max-- == 0) return(0); 16855714Skris } 16955714Skris } 17055714Skris else 17155714Skris ret=i; 17255714Skris } 17355714Skris *pp=p; 17455714Skris *rl=ret; 17555714Skris return(1); 17655714Skris } 17755714Skris 17855714Skris/* class 0 is constructed 17959191Skris * constructed == 2 for indefinite length constructed */ 18055714Skrisvoid ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, 18155714Skris int xclass) 18255714Skris { 18355714Skris unsigned char *p= *pp; 18455714Skris int i; 18555714Skris 18655714Skris i=(constructed)?V_ASN1_CONSTRUCTED:0; 18755714Skris i|=(xclass&V_ASN1_PRIVATE); 18855714Skris if (tag < 31) 18955714Skris *(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG); 19055714Skris else 19155714Skris { 19255714Skris *(p++)=i|V_ASN1_PRIMITIVE_TAG; 19355714Skris while (tag > 0x7f) 19455714Skris { 19555714Skris *(p++)=(tag&0x7f)|0x80; 19655714Skris tag>>=7; 19755714Skris } 19855714Skris *(p++)=(tag&0x7f); 19955714Skris } 20055714Skris if ((constructed == 2) && (length == 0)) 20155714Skris *(p++)=0x80; /* der_put_length would output 0 instead */ 20255714Skris else 20355714Skris asn1_put_length(&p,length); 20455714Skris *pp=p; 20555714Skris } 20655714Skris 20755714Skrisstatic void asn1_put_length(unsigned char **pp, int length) 20855714Skris { 20955714Skris unsigned char *p= *pp; 21055714Skris int i,l; 21155714Skris if (length <= 127) 21255714Skris *(p++)=(unsigned char)length; 21355714Skris else 21455714Skris { 21555714Skris l=length; 21655714Skris for (i=0; l > 0; i++) 21755714Skris l>>=8; 21855714Skris *(p++)=i|0x80; 21955714Skris l=i; 22055714Skris while (i-- > 0) 22155714Skris { 22255714Skris p[i]=length&0xff; 22355714Skris length>>=8; 22455714Skris } 22555714Skris p+=l; 22655714Skris } 22755714Skris *pp=p; 22855714Skris } 22955714Skris 23055714Skrisint ASN1_object_size(int constructed, int length, int tag) 23155714Skris { 23255714Skris int ret; 23355714Skris 23455714Skris ret=length; 23555714Skris ret++; 23655714Skris if (tag >= 31) 23755714Skris { 23855714Skris while (tag > 0) 23955714Skris { 24055714Skris tag>>=7; 24155714Skris ret++; 24255714Skris } 24355714Skris } 24455714Skris if ((length == 0) && (constructed == 2)) 24555714Skris ret+=2; 24655714Skris ret++; 24755714Skris if (length > 127) 24855714Skris { 24955714Skris while (length > 0) 25055714Skris { 25155714Skris length>>=8; 25255714Skris ret++; 25355714Skris } 25455714Skris } 25555714Skris return(ret); 25655714Skris } 25755714Skris 25855714Skrisint asn1_Finish(ASN1_CTX *c) 25955714Skris { 26055714Skris if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos)) 26155714Skris { 26255714Skris if (!ASN1_check_infinite_end(&c->p,c->slen)) 26355714Skris { 26455714Skris c->error=ERR_R_MISSING_ASN1_EOS; 26555714Skris return(0); 26655714Skris } 26755714Skris } 26855714Skris if ( ((c->slen != 0) && !(c->inf & 1)) || 26955714Skris ((c->slen < 0) && (c->inf & 1))) 27055714Skris { 27155714Skris c->error=ERR_R_ASN1_LENGTH_MISMATCH; 27255714Skris return(0); 27355714Skris } 27455714Skris return(1); 27555714Skris } 27655714Skris 27755714Skrisint asn1_GetSequence(ASN1_CTX *c, long *length) 27855714Skris { 27955714Skris unsigned char *q; 28055714Skris 28155714Skris q=c->p; 28255714Skris c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass), 28355714Skris *length); 28455714Skris if (c->inf & 0x80) 28555714Skris { 28655714Skris c->error=ERR_R_BAD_GET_ASN1_OBJECT_CALL; 28755714Skris return(0); 28855714Skris } 28955714Skris if (c->tag != V_ASN1_SEQUENCE) 29055714Skris { 29155714Skris c->error=ERR_R_EXPECTING_AN_ASN1_SEQUENCE; 29255714Skris return(0); 29355714Skris } 29455714Skris (*length)-=(c->p-q); 29555714Skris if (c->max && (*length < 0)) 29655714Skris { 29755714Skris c->error=ERR_R_ASN1_LENGTH_MISMATCH; 29855714Skris return(0); 29955714Skris } 30055714Skris if (c->inf == (1|V_ASN1_CONSTRUCTED)) 30155714Skris c->slen= *length+ *(c->pp)-c->p; 30255714Skris c->eos=0; 30355714Skris return(1); 30455714Skris } 30555714Skris 30655714SkrisASN1_STRING *ASN1_STRING_dup(ASN1_STRING *str) 30755714Skris { 30855714Skris ASN1_STRING *ret; 30955714Skris 31055714Skris if (str == NULL) return(NULL); 31155714Skris if ((ret=ASN1_STRING_type_new(str->type)) == NULL) 31255714Skris return(NULL); 31355714Skris if (!ASN1_STRING_set(ret,str->data,str->length)) 31455714Skris { 31555714Skris ASN1_STRING_free(ret); 31655714Skris return(NULL); 31755714Skris } 31855714Skris ret->flags = str->flags; 31955714Skris return(ret); 32055714Skris } 32155714Skris 32255714Skrisint ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) 32355714Skris { 32455714Skris unsigned char *c; 32555714Skris const char *data=_data; 32655714Skris 32755714Skris if (len < 0) 32855714Skris { 32955714Skris if (data == NULL) 33055714Skris return(0); 33155714Skris else 33255714Skris len=strlen(data); 33355714Skris } 33455714Skris if ((str->length < len) || (str->data == NULL)) 33555714Skris { 33655714Skris c=str->data; 33755714Skris if (c == NULL) 33855714Skris str->data=Malloc(len+1); 33955714Skris else 34055714Skris str->data=Realloc(c,len+1); 34155714Skris 34255714Skris if (str->data == NULL) 34355714Skris { 34455714Skris str->data=c; 34555714Skris return(0); 34655714Skris } 34755714Skris } 34855714Skris str->length=len; 34955714Skris if (data != NULL) 35055714Skris { 35155714Skris memcpy(str->data,data,len); 35259191Skris /* an allowance for strings :-) */ 35355714Skris str->data[len]='\0'; 35455714Skris } 35555714Skris return(1); 35655714Skris } 35755714Skris 35855714SkrisASN1_STRING *ASN1_STRING_new(void) 35955714Skris { 36055714Skris return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); 36155714Skris } 36255714Skris 36355714Skris 36455714SkrisASN1_STRING *ASN1_STRING_type_new(int type) 36555714Skris { 36655714Skris ASN1_STRING *ret; 36755714Skris 36855714Skris ret=(ASN1_STRING *)Malloc(sizeof(ASN1_STRING)); 36955714Skris if (ret == NULL) 37055714Skris { 37155714Skris ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW,ERR_R_MALLOC_FAILURE); 37255714Skris return(NULL); 37355714Skris } 37455714Skris ret->length=0; 37555714Skris ret->type=type; 37655714Skris ret->data=NULL; 37755714Skris ret->flags=0; 37855714Skris return(ret); 37955714Skris } 38055714Skris 38155714Skrisvoid ASN1_STRING_free(ASN1_STRING *a) 38255714Skris { 38355714Skris if (a == NULL) return; 38459191Skris if (a->data != NULL) Free(a->data); 38559191Skris Free(a); 38655714Skris } 38755714Skris 38855714Skrisint ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b) 38955714Skris { 39055714Skris int i; 39155714Skris 39255714Skris i=(a->length-b->length); 39355714Skris if (i == 0) 39455714Skris { 39555714Skris i=memcmp(a->data,b->data,a->length); 39655714Skris if (i == 0) 39755714Skris return(a->type-b->type); 39855714Skris else 39955714Skris return(i); 40055714Skris } 40155714Skris else 40255714Skris return(i); 40355714Skris } 40455714Skris 40555714Skrisvoid asn1_add_error(unsigned char *address, int offset) 40655714Skris { 40755714Skris char buf1[16],buf2[16]; 40855714Skris 40955714Skris sprintf(buf1,"%lu",(unsigned long)address); 41055714Skris sprintf(buf2,"%d",offset); 41155714Skris ERR_add_error_data(4,"address=",buf1," offset=",buf2); 41255714Skris } 41355714Skris 41459191Skrisint ASN1_STRING_length(ASN1_STRING *x) 41559191Skris{ return M_ASN1_STRING_length(x); } 41659191Skris 41759191Skrisvoid ASN1_STRING_length_set(ASN1_STRING *x, int len) 41859191Skris{ M_ASN1_STRING_length_set(x, len); return; } 41959191Skris 42059191Skrisint ASN1_STRING_type(ASN1_STRING *x) 42159191Skris{ return M_ASN1_STRING_type(x); } 42259191Skris 42359191Skrisunsigned char * ASN1_STRING_data(ASN1_STRING *x) 42459191Skris{ return M_ASN1_STRING_data(x); } 425