Commit 4098e89c authored by Ben Laurie's avatar Ben Laurie
Browse files

Fix incorrect DER encoding of SETs and all knock-ons from that.

parent 03f8b042
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -5,6 +5,15 @@

 Changes between 0.9.1c and 0.9.1d

  *) SETs were incorrectly DER encoded. This was a major pain, because they
     shared code with SEQUENCEs, which aren't coded the same. This means that
     almost everything to do with SETs or SEQUENCEs has either changed name or
     number of arguments.
     [Ben Laurie, based on a partial fix by GP Jayan <gp@nsj.co.jp>]

  *) Fix test data to work with the above.
     [Ben Laurie]

  *) Fix the RSA header declarations that hid a bug I fixed in 0.9.0b but
     was already fixed by Eric for 0.9.1 it seems.
     [Ben Laurie - pointed out by Ulf Möller <ulf@fitug.de>]
+75 −6
Original line number Diff line number Diff line
@@ -62,17 +62,43 @@

/* ASN1err(ASN1_F_ASN1_TYPE_NEW,ERR_R_MALLOC_FAILURE);
 */
typedef struct
    {
    unsigned char *pbData;
    int cbData;
    } MYBLOB;

/* SetBlobCmp
 * This function compares two elements of SET_OF block
 */
static int SetBlobCmp(const void *elem1, const void *elem2 )
    {
    MYBLOB *b1 = (MYBLOB *)elem1;
    MYBLOB *b2 = (MYBLOB *)elem2;
    int r;

int i2d_ASN1_SET(a,pp,func,ex_tag,ex_class)
    r = memcmp(b1->pbData, b2->pbData,
	       b1->cbData < b2->cbData ? b1->cbData : b2->cbData);
    if(r != 0)
	return r;
    return b1->cbData-b2->cbData;
    }

int i2d_ASN1_SET(a,pp,func,ex_tag,ex_class,is_set)
STACK *a;
unsigned char **pp;
int (*func)();
int ex_tag;
int ex_class;
int is_set;	/* if TRUE, then sort the contents (i.e. it isn't a SEQUENCE) */

	{
	int ret=0,r;
	int i;
	unsigned char *p;
        unsigned char *pStart, *pTempMem;
        MYBLOB *rgSetBlob;
        int totSize;

	if (a == NULL) return(0);
	for (i=sk_num(a)-1; i>=0; i--)
@@ -82,6 +108,13 @@ int ex_class;

	p= *pp;
	ASN1_put_object(&p,1,ret,ex_tag,ex_class);

/* Modified by gp@nsj.co.jp */
	/* And then again by Ben */
	/* And again by Steve */

	if(!is_set || (sk_num(a) < 2))
		{
		for (i=0; i<sk_num(a); i++)
                	func(sk_value(a,i),&p);

@@ -89,6 +122,42 @@ int ex_class;
		return(r);
		}

        pStart  = p; /* Catch the beg of Setblobs*/
        rgSetBlob = (MYBLOB *)Malloc( sk_num(a) * sizeof(MYBLOB)); /* In this array
we will store the SET blobs */

        for (i=0; i<sk_num(a); i++)
	        {
                rgSetBlob[i].pbData = p;  /* catch each set encode blob */
                func(sk_value(a,i),&p);
                rgSetBlob[i].cbData = p - rgSetBlob[i].pbData; /* Length of this
SetBlob
*/
		}
        *pp=p;
        totSize = p - pStart; /* This is the total size of all set blobs */

 /* Now we have to sort the blobs. I am using a simple algo.
    *Sort ptrs *Copy to temp-mem *Copy from temp-mem to user-mem*/
        qsort( rgSetBlob, sk_num(a), sizeof(MYBLOB), SetBlobCmp);
        pTempMem = Malloc(totSize);

/* Copy to temp mem */
        p = pTempMem;
        for(i=0; i<sk_num(a); ++i)
		{
                memcpy(p, rgSetBlob[i].pbData, rgSetBlob[i].cbData);
                p += rgSetBlob[i].cbData;
		}

/* Copy back to user mem*/
        memcpy(pStart, pTempMem, totSize);
        Free(pTempMem);
        Free(rgSetBlob);

        return(r);
        }

STACK *d2i_ASN1_SET(a,pp,length,func,free_func,ex_tag,ex_class)
STACK **a;
unsigned char **pp;
+4 −1
Original line number Diff line number Diff line
@@ -430,8 +430,11 @@ int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a,unsigned char **pp);
ASN1_UTCTIME *	d2i_ASN1_UTCTIME(ASN1_UTCTIME **a,unsigned char **pp,
			long length);

  /* for the is_set parameter to i2d_ASN1_SET */
#define IS_SEQUENCE	0
#define IS_SET		1
int		i2d_ASN1_SET(STACK *a, unsigned char **pp,
			int (*func)(), int ex_tag, int ex_class);
			int (*func)(), int ex_tag, int ex_class, int is_set);
STACK *		d2i_ASN1_SET(STACK **a, unsigned char **pp, long length,
			char *(*func)(), void (*free_func)(),
			int ex_tag, int ex_class);
+60 −22
Original line number Diff line number Diff line
@@ -162,6 +162,10 @@ err:\
	if ((a != NULL) && (sk_num(a) != 0)) \
		M_ASN1_I2D_put_SET(a,f);

#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
	if ((a != NULL) && (sk_num(a) != 0)) \
		M_ASN1_I2D_put_SEQUENCE(a,f);

#define M_ASN1_D2I_get_IMP_set_opt(b,func,free_func,tag) \
	if ((c.slen != 0) && \
		(M_ASN1_next == \
@@ -262,21 +266,32 @@ err:\
#define M_ASN1_I2D_len_IMP_opt(a,f)	if (a != NULL) M_ASN1_I2D_len(a,f)

#define M_ASN1_I2D_len_SET(a,f) \
		ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL);
		ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET);

#define M_ASN1_I2D_len_SEQUENCE(a,f) \
		ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \
				  IS_SEQUENCE);

#define M_ASN1_I2D_len_SEQUENCE_opt(a,f) \
		if ((a != NULL) && (sk_num(a) != 0)) \
			M_ASN1_I2D_len_SEQUENCE(a,f);

#define M_ASN1_I2D_len_SEQ(a,f) \
		ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL);
#define M_ASN1_I2D_len_IMP_SET(a,f,x) \
		ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET);

#define M_ASN1_I2D_len_SEQ_opt(a,f) \
#define M_ASN1_I2D_len_IMP_SET_opt(a,f,x) \
		if ((a != NULL) && (sk_num(a) != 0)) \
			M_ASN1_I2D_len_SEQ(a,f);
			ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
					  IS_SET);

#define M_ASN1_I2D_len_IMP_set(a,f,x) \
		ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC);
#define M_ASN1_I2D_len_IMP_SEQUENCE(a,f,x) \
		ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
				  IS_SEQUENCE);

#define M_ASN1_I2D_len_IMP_set_opt(a,f,x) \
#define M_ASN1_I2D_len_IMP_SEQUENCE_opt(a,f,x) \
		if ((a != NULL) && (sk_num(a) != 0)) \
			ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC);
			ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \
					  IS_SEQUENCE);

#define M_ASN1_I2D_len_EXP_opt(a,f,mtag,v) \
		if (a != NULL)\
@@ -285,10 +300,18 @@ err:\
			ret+=ASN1_object_size(1,v,mtag); \
			}

#define M_ASN1_I2D_len_EXP_set_opt(a,f,mtag,tag,v) \
#define M_ASN1_I2D_len_EXP_SET_opt(a,f,mtag,tag,v) \
		if ((a != NULL) && (sk_num(a) != 0))\
			{ \
			v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL); \
			v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
			ret+=ASN1_object_size(1,v,mtag); \
			}

#define M_ASN1_I2D_len_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
		if ((a != NULL) && (sk_num(a) != 0))\
			{ \
			v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL, \
				       IS_SEQUENCE); \
			ret+=ASN1_object_size(1,v,mtag); \
			}

@@ -304,20 +327,28 @@ err:\
			}

#define M_ASN1_I2D_put_SET(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SET,\
			V_ASN1_UNIVERSAL)
#define M_ASN1_I2D_put_IMP_set(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
			V_ASN1_CONTEXT_SPECIFIC)
			V_ASN1_UNIVERSAL,IS_SET)
#define M_ASN1_I2D_put_IMP_SET(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
			V_ASN1_CONTEXT_SPECIFIC,IS_SET)
#define M_ASN1_I2D_put_IMP_SEQUENCE(a,f,x) i2d_ASN1_SET(a,&p,f,x,\
			V_ASN1_CONTEXT_SPECIFIC,IS_SEQUENCE)

#define M_ASN1_I2D_put_SEQUENCE(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\
					     V_ASN1_UNIVERSAL,IS_SEQUENCE)

#define M_ASN1_I2D_put_SEQ(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\
			V_ASN1_UNIVERSAL)
#define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \
		if ((a != NULL) && (sk_num(a) != 0)) \
			M_ASN1_I2D_put_SEQUENCE(a,f);

#define M_ASN1_I2D_put_SEQ_opt(a,f) \
#define M_ASN1_I2D_put_IMP_SET_opt(a,f,x) \
		if ((a != NULL) && (sk_num(a) != 0)) \
			M_ASN1_I2D_put_SEQ(a,f);
			{ i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
				       IS_SET); }

#define M_ASN1_I2D_put_IMP_set_opt(a,f,x) \
#define M_ASN1_I2D_put_IMP_SEQUENCE_opt(a,f,x) \
		if ((a != NULL) && (sk_num(a) != 0)) \
			{ i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC); }
			{ i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \
				       IS_SEQUENCE); }

#define M_ASN1_I2D_put_EXP_opt(a,f,tag,v) \
		if (a != NULL) \
@@ -326,11 +357,18 @@ err:\
			f(a,&p); \
			}

#define M_ASN1_I2D_put_EXP_set_opt(a,f,mtag,tag,v) \
#define M_ASN1_I2D_put_EXP_SET_opt(a,f,mtag,tag,v) \
		if ((a != NULL) && (sk_num(a) != 0)) \
			{ \
			ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
			i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SET); \
			}

#define M_ASN1_I2D_put_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \
		if ((a != NULL) && (sk_num(a) != 0)) \
			{ \
			ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \
			i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL); \
			i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SEQUENCE); \
			}

#define M_ASN1_I2D_seq_total() \
+4 −4
Original line number Diff line number Diff line
@@ -76,8 +76,8 @@ unsigned char **pp;
	M_ASN1_I2D_len_SET(a->recipientinfo,i2d_PKCS7_RECIP_INFO);
	M_ASN1_I2D_len_SET(a->md_algs,i2d_X509_ALGOR);
	M_ASN1_I2D_len(a->enc_data,i2d_PKCS7_ENC_CONTENT);
	M_ASN1_I2D_len_IMP_set_opt(a->cert,i2d_X509,0);
	M_ASN1_I2D_len_IMP_set_opt(a->crl,i2d_X509_CRL,1);
	M_ASN1_I2D_len_IMP_SEQUENCE_opt(a->cert,i2d_X509,0);
	M_ASN1_I2D_len_IMP_SET_opt(a->crl,i2d_X509_CRL,1);
	M_ASN1_I2D_len_SET(a->signer_info,i2d_PKCS7_SIGNER_INFO);

	M_ASN1_I2D_seq_total();
@@ -86,8 +86,8 @@ unsigned char **pp;
	M_ASN1_I2D_put_SET(a->recipientinfo,i2d_PKCS7_RECIP_INFO);
	M_ASN1_I2D_put_SET(a->md_algs,i2d_X509_ALGOR);
	M_ASN1_I2D_put(a->enc_data,i2d_PKCS7_ENC_CONTENT);
	M_ASN1_I2D_put_IMP_set_opt(a->cert,i2d_X509,0);
	M_ASN1_I2D_put_IMP_set_opt(a->crl,i2d_X509_CRL,1);
	M_ASN1_I2D_put_IMP_SEQUENCE_opt(a->cert,i2d_X509,0);
	M_ASN1_I2D_put_IMP_SET_opt(a->crl,i2d_X509_CRL,1);
	M_ASN1_I2D_put_SET(a->signer_info,i2d_PKCS7_SIGNER_INFO);

	M_ASN1_I2D_finish();
Loading