Commit 452ae49d authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Extensive OID code enhancement and fixes.

parent 8c5c5b65
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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]
+75 −12
Original line number Diff line number Diff line
@@ -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,6 +138,21 @@ 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;
				}
			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,15 +162,43 @@ 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;
		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++] = BN_div_word(bl, 0x80L);
			}
		else
			{
					
			for (;;)
				{
				tmp[i++]=(unsigned char)l&0x7f;
				l>>=7L;
				if (l == 0L) break;
				}

			}
		if (out != NULL)
			{
			if (len+i > olen)
@@ -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);
	}

+125 −45
Original line number Diff line number Diff line
@@ -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) {

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


	len=a->length;
	p=a->data;

		idx=0;
	first = 1;
	bl = NULL;

	while (len > 0)
		{
		l=0;
		while (idx < a->length) {
			l|=(p[idx]&0x7f);
			if (!(p[idx] & 0x80)) break;
		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;
			idx++;
			}
		idx++;

		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);
		if (i > 2) i=2;
				l-=(long)(i*40);
				}
			if (buf && (buf_len > 0))
				{
				*buf++ = i + '0';
				buf_len--;
				}
			n++;
			}

		BIO_snprintf(tbuf,sizeof tbuf,"%d.%lu",i,l);
		i=strlen(tbuf);
		BUF_strlcpy(buf,tbuf,buf_len);
		buf_len-=i;
		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;

		l=0;
		for (; idx<len; idx++) {
			l|=p[idx]&0x7f;
			if (!(p[idx] & 0x80)) {
			buf_len -= i;
			OPENSSL_free(bndec);
			}
		else
			{
			BIO_snprintf(tbuf,sizeof tbuf,".%lu",l);
			i=strlen(tbuf);
				if (buf_len > 0)
			if (buf && (buf_len > 0))
				{
				BUF_strlcpy(buf,tbuf,buf_len);
				buf_len-=i;
				buf+=i;
				}
			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)