X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fasn1%2Fx_name.c;h=681e5d110fada8917aa77eb49eb1051201e9a7a1;hp=15d9aa4ea00039aae32ee6d6c43ebdb491361637;hb=8afca8d9c60c3d7db6f9bc94a97c77f016fc139d;hpb=ec577822f95a8bca0023c5c77cef1a4916822d4a diff --git a/crypto/asn1/x_name.c b/crypto/asn1/x_name.c index 15d9aa4ea0..681e5d110f 100644 --- a/crypto/asn1/x_name.c +++ b/crypto/asn1/x_name.c @@ -58,221 +58,206 @@ #include #include "cryptlib.h" -#include -#include +#include +#include -/* - * ASN1err(ASN1_F_D2I_X509_NAME,ERR_R_ASN1_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_NAME_NEW,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE); - * ASN1err(ASN1_F_D2I_X509_NAME_ENTRY,ERR_R_ASN1_LENGTH_MISMATCH); - * ASN1err(ASN1_F_X509_NAME_ENTRY_NEW,ASN1_R_UNKNOWN_ATTRIBUTE_TYPE); - */ - -#ifndef NOPROTO -static int i2d_X509_NAME_entries(X509_NAME *a); -#else -static int i2d_X509_NAME_entries(); -#endif - -int i2d_X509_NAME_ENTRY(X509_NAME_ENTRY *a, unsigned char **pp) - { - M_ASN1_I2D_vars(a); +static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); - M_ASN1_I2D_len(a->object,i2d_ASN1_OBJECT); - M_ASN1_I2D_len(a->value,i2d_ASN1_PRINTABLE); +static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); +static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it); +static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it); - M_ASN1_I2D_seq_total(); +static int x509_name_encode(X509_NAME *a); - M_ASN1_I2D_put(a->object,i2d_ASN1_OBJECT); - M_ASN1_I2D_put(a->value,i2d_ASN1_PRINTABLE); +ASN1_SEQUENCE(X509_NAME_ENTRY) = { + ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT), + ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE) +} ASN1_SEQUENCE_END(X509_NAME_ENTRY) - M_ASN1_I2D_finish(); - } - -X509_NAME_ENTRY *d2i_X509_NAME_ENTRY(X509_NAME_ENTRY **a, unsigned char **pp, - long length) - { - M_ASN1_D2I_vars(a,X509_NAME_ENTRY *,X509_NAME_ENTRY_new); +IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY) - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - M_ASN1_D2I_get(ret->object,d2i_ASN1_OBJECT); - M_ASN1_D2I_get(ret->value,d2i_ASN1_PRINTABLE); - ret->set=0; - M_ASN1_D2I_Finish(a,X509_NAME_ENTRY_free,ASN1_F_D2I_X509_NAME_ENTRY); - } +/* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } + * so declare two template wrappers for this + */ -int i2d_X509_NAME(X509_NAME *a, unsigned char **pp) - { - int ret; +ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY) +ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES) - if (a == NULL) return(0); - if (a->modified) - { - ret=i2d_X509_NAME_entries(a); - if (ret < 0) return(ret); - } +ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES) +ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL) - ret=a->bytes->length; - if (pp != NULL) - { - memcpy(*pp,a->bytes->data,ret); - *pp+=ret; - } - return(ret); - } +/* Normally that's where it would end: we'd have two nested STACK structures + * representing the ASN1. Unfortunately X509_NAME uses a completely different + * form and caches encodings so we have to process the internal form and convert + * to the external form. + */ -static int i2d_X509_NAME_entries(X509_NAME *a) - { - X509_NAME_ENTRY *ne,*fe=NULL; - STACK *sk; - BUF_MEM *buf=NULL; - int set=0,r,ret=0; - int i; - unsigned char *p; - int size=0; +const ASN1_EXTERN_FUNCS x509_name_ff = { + NULL, + x509_name_ex_new, + x509_name_ex_free, + 0, /* Default clear behaviour is OK */ + x509_name_ex_d2i, + x509_name_ex_i2d +}; + +IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff) + +IMPLEMENT_ASN1_FUNCTIONS(X509_NAME) +IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME) + +static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) +{ + X509_NAME *ret = NULL; + ret = OPENSSL_malloc(sizeof(X509_NAME)); + if(!ret) goto memerr; + if ((ret->entries=sk_X509_NAME_ENTRY_new_null()) == NULL) + goto memerr; + if((ret->bytes = BUF_MEM_new()) == NULL) goto memerr; + ret->modified=1; + *val = (ASN1_VALUE *)ret; + return 1; - sk=a->entries; - for (i=0; iset != set) - { - ret+=ASN1_object_size(1,size,V_ASN1_SET); - fe->size=size; - fe=ne; - size=0; - set=ne->set; - } - size+=i2d_X509_NAME_ENTRY(ne,NULL); + if (ret->entries) + sk_X509_NAME_ENTRY_free(ret->entries); + OPENSSL_free(ret); } + return 0; +} - ret+=ASN1_object_size(1,size,V_ASN1_SET); - if (fe != NULL) - fe->size=size; - - r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); - - buf=a->bytes; - if (!BUF_MEM_grow(buf,r)) goto err; - p=(unsigned char *)buf->data; - - ASN1_put_object(&p,1,ret,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); - - set= -1; - for (i=0; iset) - { - set=ne->set; - ASN1_put_object(&p,1,ne->size, - V_ASN1_SET,V_ASN1_UNIVERSAL); - } - i2d_X509_NAME_ENTRY(ne,&p); - } - a->modified=0; - return(r); -err: - return(-1); - } - -X509_NAME *d2i_X509_NAME(X509_NAME **a, unsigned char **pp, long length) - { - int set=0,i; - int idx=0; - unsigned char *orig; - M_ASN1_D2I_vars(a,X509_NAME *,X509_NAME_new); +static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ + X509_NAME *a; + if(!pval || !*pval) + return; + a = (X509_NAME *)*pval; - orig= *pp; - if (sk_num(ret->entries) > 0) - { - while (sk_num(ret->entries) > 0) - X509_NAME_ENTRY_free((X509_NAME_ENTRY *) - sk_pop(ret->entries)); - } + BUF_MEM_free(a->bytes); + sk_X509_NAME_ENTRY_pop_free(a->entries,X509_NAME_ENTRY_free); + OPENSSL_free(a); + *pval = NULL; +} + +/* Used with sk_pop_free() to free up the internal representation. + * NB: we only free the STACK and not its contents because it is + * already present in the X509_NAME structure. + */ - M_ASN1_D2I_Init(); - M_ASN1_D2I_start_sequence(); - for (;;) - { - if (M_ASN1_D2I_end_sequence()) break; - M_ASN1_D2I_get_set(ret->entries,d2i_X509_NAME_ENTRY, - X509_NAME_ENTRY_free); - for (; idx < sk_num(ret->entries); idx++) - { - ((X509_NAME_ENTRY *)sk_value(ret->entries,idx))->set= - set; - } - set++; +static void sk_internal_free(void *a) +{ + sk_free(a); +} + +static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + const unsigned char *p = *in, *q; + STACK *intname = NULL, **intname_pp = &intname; + int i, j, ret; + X509_NAME *nm = NULL, **nm_pp = &nm; + STACK_OF(X509_NAME_ENTRY) *entries; + X509_NAME_ENTRY *entry; + q = p; + + /* Get internal representation of Name */ + ret = ASN1_item_ex_d2i((ASN1_VALUE **)intname_pp, + &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL), + tag, aclass, opt, ctx); + + if(ret <= 0) return ret; + + if(*val) x509_name_ex_free(val, NULL); + if(!x509_name_ex_new((ASN1_VALUE **)nm_pp, NULL)) goto err; + /* We've decoded it: now cache encoding */ + if(!BUF_MEM_grow(nm->bytes, p - q)) goto err; + memcpy(nm->bytes->data, q, p - q); + + /* Convert internal representation to X509_NAME structure */ + for(i = 0; i < sk_num(intname); i++) { + entries = (STACK_OF(X509_NAME_ENTRY) *)sk_value(intname, i); + for(j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { + entry = sk_X509_NAME_ENTRY_value(entries, j); + entry->set = i; + if(!sk_X509_NAME_ENTRY_push(nm->entries, entry)) + goto err; } - - i=(int)(c.p-orig); - if (!BUF_MEM_grow(ret->bytes,i)) goto err; - memcpy(ret->bytes->data,orig,i); - ret->bytes->length=i; - ret->modified=0; - - M_ASN1_D2I_Finish(a,X509_NAME_free,ASN1_F_D2I_X509_NAME); + sk_X509_NAME_ENTRY_free(entries); } - -X509_NAME *X509_NAME_new(void) - { - X509_NAME *ret=NULL; - ASN1_CTX c; - - M_ASN1_New_Malloc(ret,X509_NAME); - if ((ret->entries=sk_new(NULL)) == NULL) - { c.line=__LINE__; goto err2; } - M_ASN1_New(ret->bytes,BUF_MEM_new); - ret->modified=1; - return(ret); - M_ASN1_New_Error(ASN1_F_X509_NAME_NEW); + sk_free(intname); + nm->modified = 0; + *val = (ASN1_VALUE *)nm; + *in = p; + return ret; + err: + ASN1err(ASN1_F_X509_NAME_EX_D2I, ERR_R_NESTED_ASN1_ERROR); + return 0; +} + +static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) +{ + int ret; + X509_NAME *a = (X509_NAME *)*val; + if(a->modified) { + ret = x509_name_encode((X509_NAME *)a); + if(ret < 0) return ret; } - -X509_NAME_ENTRY *X509_NAME_ENTRY_new(void) - { - X509_NAME_ENTRY *ret=NULL; - ASN1_CTX c; - - M_ASN1_New_Malloc(ret,X509_NAME_ENTRY); -/* M_ASN1_New(ret->object,ASN1_OBJECT_new);*/ - ret->object=NULL; - ret->set=0; - M_ASN1_New(ret->value,ASN1_STRING_new); - return(ret); - M_ASN1_New_Error(ASN1_F_X509_NAME_ENTRY_NEW); + ret = a->bytes->length; + if(out != NULL) { + memcpy(*out,a->bytes->data,ret); + *out+=ret; } + return ret; +} -void X509_NAME_free(X509_NAME *a) - { - if(a == NULL) - return; - - BUF_MEM_free(a->bytes); - sk_pop_free(a->entries,X509_NAME_ENTRY_free); - Free((char *)a); +static int x509_name_encode(X509_NAME *a) +{ + STACK *intname = NULL, **intname_pp = &intname; + int len; + unsigned char *p; + STACK_OF(X509_NAME_ENTRY) *entries = NULL; + X509_NAME_ENTRY *entry; + int i, set = -1; + intname = sk_new_null(); + if(!intname) goto memerr; + for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + entry = sk_X509_NAME_ENTRY_value(a->entries, i); + if(entry->set != set) { + entries = sk_X509_NAME_ENTRY_new_null(); + if(!entries) goto memerr; + if(!sk_push(intname, (char *)entries)) goto memerr; + set = entry->set; + } + if(!sk_X509_NAME_ENTRY_push(entries, entry)) goto memerr; } + len = ASN1_item_ex_i2d((ASN1_VALUE **)intname_pp, NULL, + ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); + if (!BUF_MEM_grow(a->bytes,len)) goto memerr; + p=(unsigned char *)a->bytes->data; + ASN1_item_ex_i2d((ASN1_VALUE **)intname_pp, + &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); + sk_pop_free(intname, sk_internal_free); + a->modified = 0; + return len; + memerr: + sk_pop_free(intname, sk_internal_free); + ASN1err(ASN1_F_X509_NAME_ENCODE, ERR_R_MALLOC_FAILURE); + return -1; +} -void X509_NAME_ENTRY_free(X509_NAME_ENTRY *a) - { - if (a == NULL) return; - ASN1_OBJECT_free(a->object); - ASN1_BIT_STRING_free(a->value); - Free((char *)a); - } int X509_NAME_set(X509_NAME **xn, X509_NAME *name) { X509_NAME *in; - if (*xn == NULL) return(0); + if (!xn || !name) return(0); if (*xn != name) { @@ -286,3 +271,5 @@ int X509_NAME_set(X509_NAME **xn, X509_NAME *name) return(*xn != NULL); } +IMPLEMENT_STACK_OF(X509_NAME_ENTRY) +IMPLEMENT_ASN1_SET_OF(X509_NAME_ENTRY)