diff --git a/CHANGES b/CHANGES index d5c02ee72b52351e4efb1a685658b8a22f8ceafe..33b98a418a9df01d4a6066ce7680a6f8e5198404 100644 --- a/CHANGES +++ b/CHANGES @@ -73,6 +73,12 @@ Changes between 0.9.8a and 0.9.8b [XX xxx XXXX] + *) Several fixes and enhancements to the OID generation code. The old code + sometimes allowed invalid OIDs (1.X for X >= 40 for example), couldn't + handle numbers larger than ULONG_MAX, truncated printing and had a + non standard OBJ_obj2txt() behaviour. + [Steve Henson] + *) Add support for building of engines under engine/ as shared libraries under VC++ build system. [Steve Henson] diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c index 3e6531481b39bbfbd86c4976a632b1b30290b58f..a11d25e1fb7a8b8ca172fb2a080e5a80e53dd969 100644 --- a/crypto/asn1/a_object.c +++ b/crypto/asn1/a_object.c @@ -57,6 +57,7 @@ */ #include +#include #include "cryptlib.h" #include #include @@ -83,10 +84,12 @@ int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp) int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) { - int i,first,len=0,c; - char tmp[24]; + int i,first,len=0,c, use_bn; + char ftmp[24], *tmp = ftmp; + int tmpsize = sizeof ftmp; const char *p; unsigned long l; + BIGNUM *bl = NULL; if (num == 0) return(0); @@ -98,7 +101,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) num--; if ((c >= '0') && (c <= '2')) { - first=(c-'0')*40; + first= c-'0'; } else { @@ -122,6 +125,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) goto err; } l=0; + use_bn = 0; for (;;) { if (num <= 0) break; @@ -134,7 +138,22 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, 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_word(bl, c-'0')) + goto err; + } + else + l=l*10L+(long)(c-'0'); } if (len == 0) { @@ -143,14 +162,42 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, 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) { - tmp[i++]=(unsigned char)l&0x7f; - l>>=7L; - if (l == 0L) break; + 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++] = BN_div_word(bl, 0x80L); + } + else + { + + for (;;) + { + tmp[i++]=(unsigned char)l&0x7f; + l>>=7L; + if (l == 0L) break; + } + } if (out != NULL) { @@ -166,8 +213,16 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, 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); } @@ -178,14 +233,22 @@ int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a) int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a) { - char buf[80]; + char buf[80], *p = buf; int i; if ((a == NULL) || (a->data == NULL)) return(BIO_write(bp,"NULL",4)); i=i2t_ASN1_OBJECT(buf,sizeof buf,a); - if (i > (int)sizeof(buf)) i=sizeof buf; - BIO_write(bp,buf,i); + if (i > (int)(sizeof(buf) - 1)) + { + p = OPENSSL_malloc(i + 1); + if (!p) + return -1; + i2t_ASN1_OBJECT(p,i + 1,a); + } + BIO_write(bp,p,i); + if (p != buf) + OPENSSL_free(p); return(i); } diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c index e56f3dea09a955f03efbf9b48435874f1b140f1e..9c61829c77dfefde057dd42eef9cc1b9b60983ab 100644 --- a/crypto/objects/obj_dat.c +++ b/crypto/objects/obj_dat.c @@ -58,6 +58,7 @@ #include #include +#include #include "cryptlib.h" #include #include @@ -413,8 +414,8 @@ ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name) /* Work out size of content octets */ i=a2d_ASN1_OBJECT(NULL,0,s,-1); if (i <= 0) { - /* Clear the error */ - ERR_clear_error(); + /* Don't clear the error */ + /*ERR_clear_error();*/ return NULL; } /* Work out total size */ @@ -436,66 +437,145 @@ ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name) int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) { - int i,idx=0,n=0,len,nid; + int i,n=0,len,nid, first, use_bn; + BIGNUM *bl; unsigned long l; unsigned char *p; - const char *s; char tbuf[DECIMAL_SIZE(i)+DECIMAL_SIZE(l)+2]; - if (buf_len <= 0) return(0); - if ((a == NULL) || (a->data == NULL)) { buf[0]='\0'; return(0); } - if (no_name || (nid=OBJ_obj2nid(a)) == 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++; + if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef) + { + const char *s; + s=OBJ_nid2ln(nid); + if (s == NULL) + s=OBJ_nid2sn(nid); + if (buf) + BUF_strlcpy(buf,s,buf_len); + n=strlen(s); + return n; } - idx++; - i=(int)(l/40); - if (i > 2) i=2; - l-=(long)(i*40); - - BIO_snprintf(tbuf,sizeof tbuf,"%d.%lu",i,l); - i=strlen(tbuf); - BUF_strlcpy(buf,tbuf,buf_len); - buf_len-=i; - buf+=i; - n+=i; + + len=a->length; + p=a->data; + + first = 1; + bl = NULL; + + while (len > 0) + { l=0; - for (; idx (ULONG_MAX >> 7L))) + { + if (!bl && !(bl = BN_new())) + goto err; + if (!BN_set_word(bl, l)) + goto err; + use_bn = 1; + } + if (use_bn) + { + if (!BN_lshift(bl, bl, 7)) + goto err; + } + else + l<<=7L; + } + + if (first) + { + first = 0; + if (l >= 80) + { + i = 2; + if (use_bn) + { + if (!BN_sub_word(bl, 80)) + goto err; + } + else + l -= 80; + } + else + { + i=(int)(l/40); + l-=(long)(i*40); + } + if (buf && (buf_len > 0)) + { + *buf++ = i + '0'; + buf_len--; + } + n++; + } + + if (use_bn) + { + char *bndec; + bndec = BN_bn2dec(bl); + if (!bndec) + goto err; + i = strlen(bndec); + if (buf) + { if (buf_len > 0) - BUF_strlcpy(buf,tbuf,buf_len); - buf_len-=i; + { + *buf++ = '.'; + buf_len--; + } + BUF_strlcpy(buf,bndec,buf_len); + buf += i; + } + n++; + n += i; + buf_len -= i; + OPENSSL_free(bndec); + } + else + { + BIO_snprintf(tbuf,sizeof tbuf,".%lu",l); + i=strlen(tbuf); + if (buf && (buf_len > 0)) + { + BUF_strlcpy(buf,tbuf,buf_len); buf+=i; - n+=i; - l=0; + } + buf_len-=i; + n+=i; + l=0; } - l<<=7L; } - } else { - s=OBJ_nid2ln(nid); - if (s == NULL) - s=OBJ_nid2sn(nid); - BUF_strlcpy(buf,s,buf_len); - n=strlen(s); - } - return(n); + + if (bl) + BN_free(bl); + return n; + + err: + if (bl) + BN_free(bl); + return -1; } int OBJ_txt2nid(const char *s)