diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2005-11-20 13:07:47 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2005-11-20 13:07:47 +0000 |
commit | 452ae49db5444f61fd643507fe71e4ac41ecfb1c (patch) | |
tree | 675545ea2056602925e6feccf4639183eb007303 /crypto/asn1/a_object.c | |
parent | 8c5c5b651725916cd690f7fabf04c4f7bfe4afbb (diff) | |
download | openssl-452ae49db5444f61fd643507fe71e4ac41ecfb1c.tar.gz |
Extensive OID code enhancement and fixes.
Diffstat (limited to 'crypto/asn1/a_object.c')
-rw-r--r-- | crypto/asn1/a_object.c | 87 |
1 files changed, 75 insertions, 12 deletions
diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c index 3e6531481b..a11d25e1fb 100644 --- a/crypto/asn1/a_object.c +++ b/crypto/asn1/a_object.c @@ -57,6 +57,7 @@ */ #include <stdio.h> +#include <limits.h> #include "cryptlib.h" #include <openssl/buffer.h> #include <openssl/asn1.h> @@ -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); } |