Extensive OID code enhancement and fixes.

This commit is contained in:
Dr. Stephen Henson 2005-11-20 13:07:47 +00:00
parent 8c5c5b6517
commit 452ae49db5
3 changed files with 209 additions and 60 deletions

View file

@ -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]

View file

@ -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);
}

View file

@ -58,6 +58,7 @@
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include "cryptlib.h"
#include <openssl/lhash.h>
#include <openssl/asn1.h>
@ -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++;
}
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;
l=0;
for (; idx<len; idx++) {
l|=p[idx]&0x7f;
if (!(p[idx] & 0x80)) {
BIO_snprintf(tbuf,sizeof tbuf,".%lu",l);
i=strlen(tbuf);
if (buf_len > 0)
BUF_strlcpy(buf,tbuf,buf_len);
buf_len-=i;
buf+=i;
n+=i;
l=0;
}
l<<=7L;
}
} else {
if (!no_name && (nid=OBJ_obj2nid(a)) != NID_undef)
{
const char *s;
s=OBJ_nid2ln(nid);
if (s == NULL)
s=OBJ_nid2sn(nid);
BUF_strlcpy(buf,s,buf_len);
if (buf)
BUF_strlcpy(buf,s,buf_len);
n=strlen(s);
}
return(n);
return n;
}
len=a->length;
p=a->data;
first = 1;
bl = NULL;
while (len > 0)
{
l=0;
use_bn = 0;
for (;;)
{
unsigned char c = *p++;
len--;
if ((len == 0) && (c & 0x80))
goto err;
if (use_bn)
{
if (!BN_add_word(bl, c & 0x7f))
goto err;
}
else
l |= c & 0x7f;
if (!(c & 0x80))
break;
if (!use_bn && (l > (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++ = '.';
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;
}
buf_len-=i;
n+=i;
l=0;
}
}
if (bl)
BN_free(bl);
return n;
err:
if (bl)
BN_free(bl);
return -1;
}
int OBJ_txt2nid(const char *s)