aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/asn1/a_object.c
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2005-11-20 13:07:47 +0000
committerDr. Stephen Henson <steve@openssl.org>2005-11-20 13:07:47 +0000
commit452ae49db5444f61fd643507fe71e4ac41ecfb1c (patch)
tree675545ea2056602925e6feccf4639183eb007303 /crypto/asn1/a_object.c
parent8c5c5b651725916cd690f7fabf04c4f7bfe4afbb (diff)
downloadopenssl-452ae49db5444f61fd643507fe71e4ac41ecfb1c.tar.gz
Extensive OID code enhancement and fixes.
Diffstat (limited to 'crypto/asn1/a_object.c')
-rw-r--r--crypto/asn1/a_object.c87
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);
}