X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fasn1%2Fa_object.c;h=570aac71a742d254a6a4731bfe652b02674a9318;hp=9eff09509caa9789bb4886f799df10b530cd884e;hb=4d6e1e4f29de455b5e644ea9cae5d5f5a2dbef33;hpb=e778802f53c8d47e96a6e4cbc776eb6e1d4c461a diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c index 9eff09509c..570aac71a7 100644 --- a/crypto/asn1/a_object.c +++ b/crypto/asn1/a_object.c @@ -57,26 +57,22 @@ */ #include +#include #include "cryptlib.h" -#include "buffer.h" -#include "asn1.h" -#include "objects.h" +#include +#include +#include +#include -/* ASN1err(ASN1_F_ASN1_OBJECT_NEW,ASN1_R_EXPECTING_AN_OBJECT); - * ASN1err(ASN1_F_D2I_ASN1_OBJECT,ASN1_R_BAD_OBJECT_HEADER); - * ASN1err(ASN1_F_I2T_ASN1_OBJECT,ASN1_R_BAD_OBJECT_HEADER); - */ - -int i2d_ASN1_OBJECT(a, pp) -ASN1_OBJECT *a; -unsigned char **pp; +int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp) { unsigned char *p; + int objsize; if ((a == NULL) || (a->data == NULL)) return(0); - if (pp == NULL) - return(ASN1_object_size(0,a->length,V_ASN1_OBJECT)); + objsize = ASN1_object_size(0,a->length,V_ASN1_OBJECT); + if (pp == NULL) return objsize; p= *pp; ASN1_put_object(&p,0,a->length,V_ASN1_OBJECT,V_ASN1_UNIVERSAL); @@ -84,19 +80,19 @@ unsigned char **pp; p+=a->length; *pp=p; - return(a->length); + return(objsize); } -int a2d_ASN1_OBJECT(out,olen,buf,num) -unsigned char *out; -int olen; -const char *buf; -int num; +size_t a2d_ASN1_OBJECT(unsigned char *out, size_t olen, const char *buf, + int num) { - int i,first,len=0,c; - char tmp[24]; + int i,len=0,c, use_bn; + unsigned first; + char ftmp[24], *tmp = ftmp; + size_t tmpsize = sizeof ftmp; const char *p; unsigned long l; + BIGNUM *bl = NULL; if (num == 0) return(0); @@ -108,7 +104,7 @@ int num; num--; if ((c >= '0') && (c <= '2')) { - first=(c-'0')*40; + first= c-'0'; } else { @@ -132,6 +128,7 @@ int num; goto err; } l=0; + use_bn = 0; for (;;) { if (num <= 0) break; @@ -144,7 +141,22 @@ int num; ASN1err(ASN1_F_A2D_ASN1_OBJECT,ASN1_R_INVALID_DIGIT); goto err; } - l=l*10L+(long)(c-'0'); + if (!use_bn && l > (ULONG_MAX / 10L)) + { + use_bn = 1; + if (!bl) + bl = BN_new(); + if (!bl || !BN_set_word(bl, l)) + goto err; + } + if (use_bn) + { + if (!BN_mul_word(bl, 10L) + || !BN_add_signed_word(bl, c-'0')) + goto err; + } + else + l=l*10L+(c-'0'); } if (len == 0) { @@ -153,14 +165,42 @@ int num; ASN1err(ASN1_F_A2D_ASN1_OBJECT,ASN1_R_SECOND_NUMBER_TOO_LARGE); goto err; } - l+=(long)first; + if (use_bn) + { + if (!BN_add_word(bl, first * 40)) + goto err; + } + else + l+=(long)first*40; } i=0; - for (;;) + if (use_bn) + { + int blsize; + blsize = BN_num_bits(bl); + blsize = (blsize + 6)/7; + if (blsize > tmpsize) + { + if (tmp != ftmp) + OPENSSL_free(tmp); + tmpsize = blsize + 32; + tmp = OPENSSL_malloc(tmpsize); + if (!tmp) + goto err; + } + while(blsize--) + tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L); + } + else { - tmp[i++]=(unsigned char)l&0x7f; - l>>=7L; - if (l == 0L) break; + + for (;;) + { + tmp[i++]=(unsigned char)l&0x7f; + l>>=7L; + if (l == 0L) break; + } + } if (out != NULL) { @@ -176,124 +216,57 @@ int num; else len+=i; } + if (tmp != ftmp) + OPENSSL_free(tmp); + if (bl) + BN_free(bl); return(len); err: + if (tmp != ftmp) + OPENSSL_free(tmp); + if (bl) + BN_free(bl); return(0); } -int i2t_ASN1_OBJECT(buf,buf_len,a) -char *buf; -int buf_len; -ASN1_OBJECT *a; - { - int i,idx=0,n=0,len,nid; - unsigned long l; - unsigned char *p; - const char *s; - char tbuf[32]; - - if (buf_len <= 0) return(0); - - if ((a == NULL) || (a->data == NULL)) - { - buf[0]='\0'; - return(0); - } - - nid=OBJ_obj2nid(a); - if (nid == NID_undef) - { - len=a->length; - p=a->data; - - idx=0; - l=0; - while (idx < a->length) - { - l|=(p[idx]&0x7f); - if (!(p[idx] & 0x80)) break; - l<<=7L; - idx++; - } - idx++; - i=(int)(l/40); - if (i > 2) i=2; - l-=(long)(i*40); - - sprintf(tbuf,"%d.%ld",i,l); - i=strlen(tbuf); - strncpy(buf,tbuf,buf_len); - buf_len-=i; - buf+=i; - n+=i; - - l=0; - for (; idx 0) - strncpy(buf,tbuf,buf_len); - buf_len-=i; - buf+=i; - n+=i; - l=0; - } - l<<=7L; - } - } - else - { - s=OBJ_nid2ln(nid); - if (s == NULL) - s=OBJ_nid2sn(nid); - strncpy(buf,s,buf_len); - n=strlen(s); - } - buf[buf_len-1]='\0'; - return(n); - } +int i2t_ASN1_OBJECT(char *buf, size_t buf_len, ASN1_OBJECT *a) +{ + return OBJ_obj2txt(buf, buf_len, a, 0); +} -int i2a_ASN1_OBJECT(bp,a) -BIO *bp; -ASN1_OBJECT *a; +int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a) { - char buf[80]; - int i; + char buf[80], *p = buf; + size_t i; if ((a == NULL) || (a->data == NULL)) return(BIO_write(bp,"NULL",4)); - i=i2t_ASN1_OBJECT(buf,80,a); - if (i > 80) i=80; - BIO_write(bp,buf,i); + i=i2t_ASN1_OBJECT(buf,sizeof buf,a); + if (i > (int)(sizeof(buf) - 1)) + { + p = OPENSSL_malloc(i + 1); + if (!p) + return -1; + i2t_ASN1_OBJECT(p,i + 1,a); + } + if (i <= 0) + return BIO_write(bp, "", 9); + BIO_write(bp,p,i); + if (p != buf) + OPENSSL_free(p); return(i); } -ASN1_OBJECT *d2i_ASN1_OBJECT(a, pp, length) -ASN1_OBJECT **a; -unsigned char **pp; -long length; - { - ASN1_OBJECT *ret=NULL; - unsigned char *p; - long len; +ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + size_t length) +{ + const unsigned char *p; + size_t len; int tag,xclass; int inf,i; - - /* only the ASN1_OBJECTs from the 'table' will have values - * for ->sn or ->ln */ - if ((a == NULL) || ((*a) == NULL) || - !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) - { - if ((ret=ASN1_OBJECT_new()) == NULL) return(NULL); - } - else ret=(*a); + ASN1_OBJECT *ret = NULL; p= *pp; - inf=ASN1_get_object(&p,&len,&tag,&xclass,length); if (inf & 0x80) { @@ -306,16 +279,48 @@ long length; i=ASN1_R_EXPECTING_AN_OBJECT; goto err; } - if ((ret->data == NULL) || (ret->length < len)) + ret = c2i_ASN1_OBJECT(a, &p, len); + if(ret) *pp = p; + return ret; +err: + ASN1err(ASN1_F_D2I_ASN1_OBJECT,i); + return(NULL); +} +ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + size_t len) + { + ASN1_OBJECT *ret=NULL; + const unsigned char *p; + unsigned char *data; + int i; + + /* only the ASN1_OBJECTs from the 'table' will have values + * for ->sn or ->ln */ + if ((a == NULL) || ((*a) == NULL) || + !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) { - if (ret->data != NULL) Free((char *)ret->data); - ret->data=(unsigned char *)Malloc((int)len); - ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA; - if (ret->data == NULL) + if ((ret=ASN1_OBJECT_new()) == NULL) return(NULL); + } + else ret=(*a); + + p= *pp; + /* detach data from object */ + data = (unsigned char *)ret->data; + ret->data = NULL; + /* once detached we can change it */ + if ((data == NULL) || (ret->length < len)) + { + ret->length=0; + if (data != NULL) OPENSSL_free(data); + data=OPENSSL_malloc(len ? len : 1); + if (data == NULL) { i=ERR_R_MALLOC_FAILURE; goto err; } + ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA; } - memcpy(ret->data,p,(int)len); - ret->length=(int)len; + memcpy(data,p,len); + /* reattach data to object, after which it remains const */ + ret->data=data; + ret->length=len; ret->sn=NULL; ret->ln=NULL; /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */ @@ -325,17 +330,17 @@ long length; *pp=p; return(ret); err: - ASN1err(ASN1_F_D2I_ASN1_OBJECT,i); + ASN1err(ASN1_F_C2I_ASN1_OBJECT,i); if ((ret != NULL) && ((a == NULL) || (*a != ret))) ASN1_OBJECT_free(ret); return(NULL); } -ASN1_OBJECT *ASN1_OBJECT_new() +ASN1_OBJECT *ASN1_OBJECT_new(void) { ASN1_OBJECT *ret; - ret=(ASN1_OBJECT *)Malloc(sizeof(ASN1_OBJECT)); + ret=(ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT)); if (ret == NULL) { ASN1err(ASN1_F_ASN1_OBJECT_NEW,ERR_R_MALLOC_FAILURE); @@ -350,33 +355,29 @@ ASN1_OBJECT *ASN1_OBJECT_new() return(ret); } -void ASN1_OBJECT_free(a) -ASN1_OBJECT *a; +void ASN1_OBJECT_free(ASN1_OBJECT *a) { if (a == NULL) return; if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) { -#ifndef CONST_STRICT /* disable purely for compile-time strict const checking. Doing this on a "real" compile will cause mempory leaks */ - if (a->sn != NULL) Free((void *)a->sn); - if (a->ln != NULL) Free((void *)a->ln); +#ifndef CONST_STRICT /* disable purely for compile-time strict const checking. Doing this on a "real" compile will cause memory leaks */ + if (a->sn != NULL) OPENSSL_free((void *)a->sn); + if (a->ln != NULL) OPENSSL_free((void *)a->ln); #endif a->sn=a->ln=NULL; } if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) { - if (a->data != NULL) Free(a->data); + if (a->data != NULL) OPENSSL_free((void *)a->data); a->data=NULL; a->length=0; } if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC) - Free(a); + OPENSSL_free(a); } -ASN1_OBJECT *ASN1_OBJECT_create(nid,data,len,sn,ln) -int nid; -unsigned char *data; -int len; -char *sn,*ln; +ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, size_t len, + const char *sn, const char *ln) { ASN1_OBJECT o; @@ -390,3 +391,5 @@ char *sn,*ln; return(OBJ_dup(&o)); } +IMPLEMENT_STACK_OF(ASN1_OBJECT) +IMPLEMENT_ASN1_SET_OF(ASN1_OBJECT)