1*0Sstevel@tonic-gate /* crypto/asn1/x_name.c */ 2*0Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3*0Sstevel@tonic-gate * All rights reserved. 4*0Sstevel@tonic-gate * 5*0Sstevel@tonic-gate * This package is an SSL implementation written 6*0Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com). 7*0Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as 10*0Sstevel@tonic-gate * the following conditions are aheared to. The following conditions 11*0Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA, 12*0Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13*0Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms 14*0Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15*0Sstevel@tonic-gate * 16*0Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in 17*0Sstevel@tonic-gate * the code are not to be removed. 18*0Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution 19*0Sstevel@tonic-gate * as the author of the parts of the library used. 20*0Sstevel@tonic-gate * This can be in the form of a textual message at program startup or 21*0Sstevel@tonic-gate * in documentation (online or textual) provided with the package. 22*0Sstevel@tonic-gate * 23*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 24*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 25*0Sstevel@tonic-gate * are met: 26*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright 27*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 28*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 29*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 30*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 31*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 32*0Sstevel@tonic-gate * must display the following acknowledgement: 33*0Sstevel@tonic-gate * "This product includes cryptographic software written by 34*0Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)" 35*0Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library 36*0Sstevel@tonic-gate * being used are not cryptographic related :-). 37*0Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from 38*0Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement: 39*0Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40*0Sstevel@tonic-gate * 41*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51*0Sstevel@tonic-gate * SUCH DAMAGE. 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate * The licence and distribution terms for any publically available version or 54*0Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be 55*0Sstevel@tonic-gate * copied and put under another distribution licence 56*0Sstevel@tonic-gate * [including the GNU Public Licence.] 57*0Sstevel@tonic-gate */ 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate #include <stdio.h> 60*0Sstevel@tonic-gate #include "cryptlib.h" 61*0Sstevel@tonic-gate #include <openssl/asn1t.h> 62*0Sstevel@tonic-gate #include <openssl/x509.h> 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate static int x509_name_ex_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_ITEM *it, 65*0Sstevel@tonic-gate int tag, int aclass, char opt, ASN1_TLC *ctx); 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); 68*0Sstevel@tonic-gate static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it); 69*0Sstevel@tonic-gate static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it); 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate static int x509_name_encode(X509_NAME *a); 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate ASN1_SEQUENCE(X509_NAME_ENTRY) = { 74*0Sstevel@tonic-gate ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT), 75*0Sstevel@tonic-gate ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE) 76*0Sstevel@tonic-gate } ASN1_SEQUENCE_END(X509_NAME_ENTRY) 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY) 79*0Sstevel@tonic-gate IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY) 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate /* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } 82*0Sstevel@tonic-gate * so declare two template wrappers for this 83*0Sstevel@tonic-gate */ 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) = 86*0Sstevel@tonic-gate ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY) 87*0Sstevel@tonic-gate ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES) 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) = 90*0Sstevel@tonic-gate ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES) 91*0Sstevel@tonic-gate ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL) 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate /* Normally that's where it would end: we'd have two nested STACK structures 94*0Sstevel@tonic-gate * representing the ASN1. Unfortunately X509_NAME uses a completely different 95*0Sstevel@tonic-gate * form and caches encodings so we have to process the internal form and convert 96*0Sstevel@tonic-gate * to the external form. 97*0Sstevel@tonic-gate */ 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate const ASN1_EXTERN_FUNCS x509_name_ff = { 100*0Sstevel@tonic-gate NULL, 101*0Sstevel@tonic-gate x509_name_ex_new, 102*0Sstevel@tonic-gate x509_name_ex_free, 103*0Sstevel@tonic-gate 0, /* Default clear behaviour is OK */ 104*0Sstevel@tonic-gate x509_name_ex_d2i, 105*0Sstevel@tonic-gate x509_name_ex_i2d 106*0Sstevel@tonic-gate }; 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff) 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate IMPLEMENT_ASN1_FUNCTIONS(X509_NAME) 111*0Sstevel@tonic-gate IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME) 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) 114*0Sstevel@tonic-gate { 115*0Sstevel@tonic-gate X509_NAME *ret = NULL; 116*0Sstevel@tonic-gate ret = OPENSSL_malloc(sizeof(X509_NAME)); 117*0Sstevel@tonic-gate if(!ret) goto memerr; 118*0Sstevel@tonic-gate if ((ret->entries=sk_X509_NAME_ENTRY_new_null()) == NULL) 119*0Sstevel@tonic-gate goto memerr; 120*0Sstevel@tonic-gate if((ret->bytes = BUF_MEM_new()) == NULL) goto memerr; 121*0Sstevel@tonic-gate ret->modified=1; 122*0Sstevel@tonic-gate *val = (ASN1_VALUE *)ret; 123*0Sstevel@tonic-gate return 1; 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate memerr: 126*0Sstevel@tonic-gate ASN1err(ASN1_F_X509_NAME_NEW, ERR_R_MALLOC_FAILURE); 127*0Sstevel@tonic-gate if (ret) 128*0Sstevel@tonic-gate { 129*0Sstevel@tonic-gate if (ret->entries) 130*0Sstevel@tonic-gate sk_X509_NAME_ENTRY_free(ret->entries); 131*0Sstevel@tonic-gate OPENSSL_free(ret); 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate return 0; 134*0Sstevel@tonic-gate } 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) 137*0Sstevel@tonic-gate { 138*0Sstevel@tonic-gate X509_NAME *a; 139*0Sstevel@tonic-gate if(!pval || !*pval) 140*0Sstevel@tonic-gate return; 141*0Sstevel@tonic-gate a = (X509_NAME *)*pval; 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate BUF_MEM_free(a->bytes); 144*0Sstevel@tonic-gate sk_X509_NAME_ENTRY_pop_free(a->entries,X509_NAME_ENTRY_free); 145*0Sstevel@tonic-gate OPENSSL_free(a); 146*0Sstevel@tonic-gate *pval = NULL; 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate /* Used with sk_pop_free() to free up the internal representation. 150*0Sstevel@tonic-gate * NB: we only free the STACK and not its contents because it is 151*0Sstevel@tonic-gate * already present in the X509_NAME structure. 152*0Sstevel@tonic-gate */ 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate static void sk_internal_free(void *a) 155*0Sstevel@tonic-gate { 156*0Sstevel@tonic-gate sk_free(a); 157*0Sstevel@tonic-gate } 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate static int x509_name_ex_d2i(ASN1_VALUE **val, unsigned char **in, long len, const ASN1_ITEM *it, 160*0Sstevel@tonic-gate int tag, int aclass, char opt, ASN1_TLC *ctx) 161*0Sstevel@tonic-gate { 162*0Sstevel@tonic-gate unsigned char *p = *in, *q; 163*0Sstevel@tonic-gate STACK *intname = NULL; 164*0Sstevel@tonic-gate int i, j, ret; 165*0Sstevel@tonic-gate X509_NAME *nm = NULL; 166*0Sstevel@tonic-gate STACK_OF(X509_NAME_ENTRY) *entries; 167*0Sstevel@tonic-gate X509_NAME_ENTRY *entry; 168*0Sstevel@tonic-gate q = p; 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate /* Get internal representation of Name */ 171*0Sstevel@tonic-gate ret = ASN1_item_ex_d2i((ASN1_VALUE **)&intname, &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL), 172*0Sstevel@tonic-gate tag, aclass, opt, ctx); 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate if(ret <= 0) return ret; 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate if(*val) x509_name_ex_free(val, NULL); 177*0Sstevel@tonic-gate if(!x509_name_ex_new((ASN1_VALUE **)&nm, NULL)) goto err; 178*0Sstevel@tonic-gate /* We've decoded it: now cache encoding */ 179*0Sstevel@tonic-gate if(!BUF_MEM_grow(nm->bytes, p - q)) goto err; 180*0Sstevel@tonic-gate memcpy(nm->bytes->data, q, p - q); 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate /* Convert internal representation to X509_NAME structure */ 183*0Sstevel@tonic-gate for(i = 0; i < sk_num(intname); i++) { 184*0Sstevel@tonic-gate entries = (STACK_OF(X509_NAME_ENTRY) *)sk_value(intname, i); 185*0Sstevel@tonic-gate for(j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { 186*0Sstevel@tonic-gate entry = sk_X509_NAME_ENTRY_value(entries, j); 187*0Sstevel@tonic-gate entry->set = i; 188*0Sstevel@tonic-gate if(!sk_X509_NAME_ENTRY_push(nm->entries, entry)) 189*0Sstevel@tonic-gate goto err; 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate sk_X509_NAME_ENTRY_free(entries); 192*0Sstevel@tonic-gate } 193*0Sstevel@tonic-gate sk_free(intname); 194*0Sstevel@tonic-gate nm->modified = 0; 195*0Sstevel@tonic-gate *val = (ASN1_VALUE *)nm; 196*0Sstevel@tonic-gate *in = p; 197*0Sstevel@tonic-gate return ret; 198*0Sstevel@tonic-gate err: 199*0Sstevel@tonic-gate ASN1err(ASN1_F_D2I_X509_NAME, ERR_R_NESTED_ASN1_ERROR); 200*0Sstevel@tonic-gate return 0; 201*0Sstevel@tonic-gate } 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) 204*0Sstevel@tonic-gate { 205*0Sstevel@tonic-gate int ret; 206*0Sstevel@tonic-gate X509_NAME *a = (X509_NAME *)*val; 207*0Sstevel@tonic-gate if(a->modified) { 208*0Sstevel@tonic-gate ret = x509_name_encode((X509_NAME *)a); 209*0Sstevel@tonic-gate if(ret < 0) return ret; 210*0Sstevel@tonic-gate } 211*0Sstevel@tonic-gate ret = a->bytes->length; 212*0Sstevel@tonic-gate if(out != NULL) { 213*0Sstevel@tonic-gate memcpy(*out,a->bytes->data,ret); 214*0Sstevel@tonic-gate *out+=ret; 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate return ret; 217*0Sstevel@tonic-gate } 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate static int x509_name_encode(X509_NAME *a) 220*0Sstevel@tonic-gate { 221*0Sstevel@tonic-gate STACK *intname = NULL; 222*0Sstevel@tonic-gate int len; 223*0Sstevel@tonic-gate unsigned char *p; 224*0Sstevel@tonic-gate STACK_OF(X509_NAME_ENTRY) *entries = NULL; 225*0Sstevel@tonic-gate X509_NAME_ENTRY *entry; 226*0Sstevel@tonic-gate int i, set = -1; 227*0Sstevel@tonic-gate intname = sk_new_null(); 228*0Sstevel@tonic-gate if(!intname) goto memerr; 229*0Sstevel@tonic-gate for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { 230*0Sstevel@tonic-gate entry = sk_X509_NAME_ENTRY_value(a->entries, i); 231*0Sstevel@tonic-gate if(entry->set != set) { 232*0Sstevel@tonic-gate entries = sk_X509_NAME_ENTRY_new_null(); 233*0Sstevel@tonic-gate if(!entries) goto memerr; 234*0Sstevel@tonic-gate if(!sk_push(intname, (char *)entries)) goto memerr; 235*0Sstevel@tonic-gate set = entry->set; 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate if(!sk_X509_NAME_ENTRY_push(entries, entry)) goto memerr; 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate len = ASN1_item_ex_i2d((ASN1_VALUE **)&intname, NULL, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); 240*0Sstevel@tonic-gate if (!BUF_MEM_grow(a->bytes,len)) goto memerr; 241*0Sstevel@tonic-gate p=(unsigned char *)a->bytes->data; 242*0Sstevel@tonic-gate ASN1_item_ex_i2d((ASN1_VALUE **)&intname, &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); 243*0Sstevel@tonic-gate sk_pop_free(intname, sk_internal_free); 244*0Sstevel@tonic-gate a->modified = 0; 245*0Sstevel@tonic-gate return len; 246*0Sstevel@tonic-gate memerr: 247*0Sstevel@tonic-gate sk_pop_free(intname, sk_internal_free); 248*0Sstevel@tonic-gate ASN1err(ASN1_F_D2I_X509_NAME, ERR_R_MALLOC_FAILURE); 249*0Sstevel@tonic-gate return -1; 250*0Sstevel@tonic-gate } 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate int X509_NAME_set(X509_NAME **xn, X509_NAME *name) 254*0Sstevel@tonic-gate { 255*0Sstevel@tonic-gate X509_NAME *in; 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate if (!xn || !name) return(0); 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate if (*xn != name) 260*0Sstevel@tonic-gate { 261*0Sstevel@tonic-gate in=X509_NAME_dup(name); 262*0Sstevel@tonic-gate if (in != NULL) 263*0Sstevel@tonic-gate { 264*0Sstevel@tonic-gate X509_NAME_free(*xn); 265*0Sstevel@tonic-gate *xn=in; 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate return(*xn != NULL); 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate IMPLEMENT_STACK_OF(X509_NAME_ENTRY) 272*0Sstevel@tonic-gate IMPLEMENT_ASN1_SET_OF(X509_NAME_ENTRY) 273