X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fasn1%2Fx_name.c;h=5da066949236ea104c6a38fe8dd05c8375b4a460;hp=3b8bc5191f0ae07d8df46dab701f7ef319d58e29;hb=9d6b1ce6441c7cc6aed344f02d9f676ab5e04217;hpb=dfeab0689f69c0b4bd3480ffd37a9cacc2f17d9c diff --git a/crypto/asn1/x_name.c b/crypto/asn1/x_name.c index 3b8bc5191f..5da0669492 100644 --- a/crypto/asn1/x_name.c +++ b/crypto/asn1/x_name.c @@ -58,228 +58,190 @@ #include #include "cryptlib.h" -#include "objects.h" -#include "asn1_mac.h" +#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 +static int x509_name_ex_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); -int i2d_X509_NAME_ENTRY(a,pp) -X509_NAME_ENTRY *a; -unsigned char **pp; - { - M_ASN1_I2D_vars(a); +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_len(a->object,i2d_ASN1_OBJECT); - M_ASN1_I2D_len(a->value,i2d_ASN1_PRINTABLE); +static int x509_name_encode(X509_NAME *a); - M_ASN1_I2D_seq_total(); +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_put(a->object,i2d_ASN1_OBJECT); - M_ASN1_I2D_put(a->value,i2d_ASN1_PRINTABLE); - - M_ASN1_I2D_finish(); - } - -X509_NAME_ENTRY *d2i_X509_NAME_ENTRY(a,pp,length) -X509_NAME_ENTRY **a; -unsigned char **pp; -long length; - { - M_ASN1_D2I_vars(a,X509_NAME_ENTRY *,X509_NAME_ENTRY_new); - - 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); - } +IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY) -int i2d_X509_NAME(a,pp) -X509_NAME *a; -unsigned char **pp; - { - int ret; - - if (a == NULL) return(0); - if (a->modified) - { - ret=i2d_X509_NAME_entries(a); - if (ret < 0) return(ret); - } - - ret=a->bytes->length; - if (pp != NULL) - { - memcpy(*pp,a->bytes->data,ret); - *pp+=ret; - } - return(ret); - } - -static int i2d_X509_NAME_entries(a) -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; - - 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); - } - - ret+=ASN1_object_size(1,size,V_ASN1_SET); - if (fe != NULL) - fe->size=size; - - r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); +/* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } + * so declare two template wrappers for this + */ - buf=a->bytes; - if (!BUF_MEM_grow(buf,r)) goto err; - p=(unsigned char *)buf->data; +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); - ASN1_put_object(&p,1,ret,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); +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); - 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); - } +/* 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. + */ -X509_NAME *d2i_X509_NAME(a,pp,length) -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); +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) + +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; + memerr: + ASN1err(ASN1_F_X509_NAME_NEW, ERR_R_MALLOC_FAILURE); + return 0; +} + +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, unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx) +{ + unsigned char *p = *in, *q; + STACK *intname = NULL; + int i, j, ret; + X509_NAME *nm = NULL; + 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, &p, len, &X509_NAME_INTERNAL_it, + 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, 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() - { - 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); - } - -X509_NAME_ENTRY *X509_NAME_ENTRY_new() - { - 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); + sk_free(intname); + nm->modified = 0; + *val = (ASN1_VALUE *)nm; + *in = p; + return ret; + err: + ASN1err(ASN1_F_D2I_X509_NAME, 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; } - -void X509_NAME_free(a) -X509_NAME *a; - { - BUF_MEM_free(a->bytes); - sk_pop_free(a->entries,X509_NAME_ENTRY_free); - Free((char *)a); + ret = a->bytes->length; + if(out != NULL) { + memcpy(*out,a->bytes->data,ret); + *out+=ret; } + return ret; +} -void X509_NAME_ENTRY_free(a) -X509_NAME_ENTRY *a; - { - if (a == NULL) return; - ASN1_OBJECT_free(a->object); - ASN1_BIT_STRING_free(a->value); - Free((char *)a); +static int x509_name_encode(X509_NAME *a) +{ + STACK *intname = NULL; + 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; } - -int X509_NAME_set(xn,name) -X509_NAME **xn; -X509_NAME *name; + len = ASN1_item_ex_i2d((ASN1_VALUE **)&intname, NULL, &X509_NAME_INTERNAL_it, -1, -1); + if (!BUF_MEM_grow(a->bytes,len)) goto memerr; + p=(unsigned char *)a->bytes->data; + ASN1_item_ex_i2d((ASN1_VALUE **)&intname, &p, &X509_NAME_INTERNAL_it, -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_D2I_X509_NAME, ERR_R_MALLOC_FAILURE); + return -1; +} + + +int X509_NAME_set(X509_NAME **xn, X509_NAME *name) { X509_NAME *in; @@ -297,3 +259,5 @@ X509_NAME *name; return(*xn != NULL); } +IMPLEMENT_STACK_OF(X509_NAME_ENTRY) +IMPLEMENT_ASN1_SET_OF(X509_NAME_ENTRY)