1/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2 * All rights reserved. 3 * 4 * This package is an SSL implementation written 5 * by Eric Young (eay@cryptsoft.com). 6 * The implementation was written so as to conform with Netscapes SSL. 7 * 8 * This library is free for commercial and non-commercial use as long as 9 * the following conditions are aheared to. The following conditions 10 * apply to all code found in this distribution, be it the RC4, RSA, 11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 12 * included with this distribution is covered by the same copyright terms 13 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 14 * 15 * Copyright remains Eric Young's, and as such any Copyright notices in 16 * the code are not to be removed. 17 * If this package is used in a product, Eric Young should be given attribution 18 * as the author of the parts of the library used. 19 * This can be in the form of a textual message at program startup or 20 * in documentation (online or textual) provided with the package. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 3. All advertising materials mentioning features or use of this software 31 * must display the following acknowledgement: 32 * "This product includes cryptographic software written by 33 * Eric Young (eay@cryptsoft.com)" 34 * The word 'cryptographic' can be left out if the rouines from the library 35 * being used are not cryptographic related :-). 36 * 4. If you include any Windows specific code (or a derivative thereof) from 37 * the apps directory (application code) you must include an acknowledgement: 38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * SUCH DAMAGE. 51 * 52 * The licence and distribution terms for any publically available version or 53 * derivative of this code cannot be changed. i.e. this code cannot simply be 54 * copied and put under another distribution licence 55 * [including the GNU Public Licence.] */ 56 57#include <ctype.h> 58#include <string.h> 59 60#include <openssl/asn1.h> 61#include <openssl/asn1t.h> 62#include <openssl/buf.h> 63#include <openssl/err.h> 64#include <openssl/mem.h> 65#include <openssl/obj.h> 66#include <openssl/stack.h> 67#include <openssl/x509.h> 68 69#include "../asn1/asn1_locl.h" 70 71 72typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY; 73DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY) 74 75static int x509_name_ex_d2i(ASN1_VALUE **val, 76 const unsigned char **in, long len, 77 const ASN1_ITEM *it, 78 int tag, int aclass, char opt, ASN1_TLC *ctx); 79 80static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, 81 const ASN1_ITEM *it, int tag, int aclass); 82static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it); 83static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it); 84 85static int x509_name_encode(X509_NAME *a); 86static int x509_name_canon(X509_NAME *a); 87static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in); 88static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname, 89 unsigned char **in); 90 91 92static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, 93 int indent, 94 const char *fname, 95 const ASN1_PCTX *pctx); 96 97ASN1_SEQUENCE(X509_NAME_ENTRY) = { 98 ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT), 99 ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE) 100} ASN1_SEQUENCE_END(X509_NAME_ENTRY) 101 102IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY) 103IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY) 104 105/* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } 106 * so declare two template wrappers for this 107 */ 108 109ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) = 110 ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY) 111ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES) 112 113ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) = 114 ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES) 115ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL) 116 117/* Normally that's where it would end: we'd have two nested STACK structures 118 * representing the ASN1. Unfortunately X509_NAME uses a completely different 119 * form and caches encodings so we have to process the internal form and convert 120 * to the external form. 121 */ 122 123const ASN1_EXTERN_FUNCS x509_name_ff = { 124 NULL, 125 x509_name_ex_new, 126 x509_name_ex_free, 127 0, /* Default clear behaviour is OK */ 128 x509_name_ex_d2i, 129 x509_name_ex_i2d, 130 x509_name_ex_print 131}; 132 133IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff) 134 135IMPLEMENT_ASN1_FUNCTIONS(X509_NAME) 136IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME) 137 138static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) 139{ 140 X509_NAME *ret = NULL; 141 ret = OPENSSL_malloc(sizeof(X509_NAME)); 142 if(!ret) goto memerr; 143 if ((ret->entries=sk_X509_NAME_ENTRY_new_null()) == NULL) 144 goto memerr; 145 if((ret->bytes = BUF_MEM_new()) == NULL) goto memerr; 146 ret->canon_enc = NULL; 147 ret->canon_enclen = 0; 148 ret->modified=1; 149 *val = (ASN1_VALUE *)ret; 150 return 1; 151 152 memerr: 153 OPENSSL_PUT_ERROR(X509, x509_name_ex_new, ERR_R_MALLOC_FAILURE); 154 if (ret) 155 { 156 if (ret->entries) 157 sk_X509_NAME_ENTRY_free(ret->entries); 158 OPENSSL_free(ret); 159 } 160 return 0; 161} 162 163static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) 164{ 165 X509_NAME *a; 166 if(!pval || !*pval) 167 return; 168 a = (X509_NAME *)*pval; 169 170 BUF_MEM_free(a->bytes); 171 sk_X509_NAME_ENTRY_pop_free(a->entries,X509_NAME_ENTRY_free); 172 if (a->canon_enc) 173 OPENSSL_free(a->canon_enc); 174 OPENSSL_free(a); 175 *pval = NULL; 176} 177 178static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne) 179{ 180 sk_X509_NAME_ENTRY_free(ne); 181} 182 183static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne) 184{ 185 sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free); 186} 187 188static int x509_name_ex_d2i(ASN1_VALUE **val, 189 const unsigned char **in, long len, const ASN1_ITEM *it, 190 int tag, int aclass, char opt, ASN1_TLC *ctx) 191{ 192 const unsigned char *p = *in, *q; 193 union { STACK_OF(STACK_OF_X509_NAME_ENTRY) *s; 194 ASN1_VALUE *a; } intname = {NULL}; 195 union { X509_NAME *x; ASN1_VALUE *a; } nm = {NULL}; 196 size_t i, j; 197 int ret; 198 STACK_OF(X509_NAME_ENTRY) *entries; 199 X509_NAME_ENTRY *entry; 200 q = p; 201 202 /* Get internal representation of Name */ 203 ret = ASN1_item_ex_d2i(&intname.a, 204 &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL), 205 tag, aclass, opt, ctx); 206 207 if(ret <= 0) return ret; 208 209 if(*val) x509_name_ex_free(val, NULL); 210 /* We've decoded it: now cache encoding */ 211 if (!x509_name_ex_new(&nm.a, NULL) || 212 !BUF_MEM_grow(nm.x->bytes, p - q)) 213 { 214 sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, 215 local_sk_X509_NAME_ENTRY_pop_free); 216 goto err; 217 } 218 memcpy(nm.x->bytes->data, q, p - q); 219 220 /* Convert internal representation to X509_NAME structure */ 221 for(i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) { 222 entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i); 223 for(j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) { 224 entry = sk_X509_NAME_ENTRY_value(entries, j); 225 entry->set = i; 226 if(!sk_X509_NAME_ENTRY_push(nm.x->entries, entry)) 227 goto err; 228 } 229 sk_X509_NAME_ENTRY_free(entries); 230 } 231 sk_STACK_OF_X509_NAME_ENTRY_free(intname.s); 232 ret = x509_name_canon(nm.x); 233 if (!ret) 234 goto err; 235 nm.x->modified = 0; 236 *val = nm.a; 237 *in = p; 238 return ret; 239err: 240 if (nm.x != NULL) 241 X509_NAME_free(nm.x); 242 OPENSSL_PUT_ERROR(X509, x509_name_ex_d2i, ERR_R_ASN1_LIB); 243 return 0; 244} 245 246static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass) 247{ 248 int ret; 249 X509_NAME *a = (X509_NAME *)*val; 250 if(a->modified) { 251 ret = x509_name_encode(a); 252 if(ret < 0) 253 return ret; 254 ret = x509_name_canon(a); 255 if(ret < 0) 256 return ret; 257 } 258 ret = a->bytes->length; 259 if(out != NULL) { 260 memcpy(*out,a->bytes->data,ret); 261 *out+=ret; 262 } 263 return ret; 264} 265 266static int x509_name_encode(X509_NAME *a) 267{ 268 union { STACK_OF(STACK_OF_X509_NAME_ENTRY) *s; 269 ASN1_VALUE *a; } intname = {NULL}; 270 int len; 271 unsigned char *p; 272 STACK_OF(X509_NAME_ENTRY) *entries = NULL; 273 X509_NAME_ENTRY *entry; 274 int set = -1; 275 size_t i; 276 intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null(); 277 if(!intname.s) goto memerr; 278 for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { 279 entry = sk_X509_NAME_ENTRY_value(a->entries, i); 280 if(entry->set != set) { 281 entries = sk_X509_NAME_ENTRY_new_null(); 282 if(!entries) goto memerr; 283 if(!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, 284 entries)) 285 goto memerr; 286 set = entry->set; 287 } 288 if(!sk_X509_NAME_ENTRY_push(entries, entry)) goto memerr; 289 } 290 len = ASN1_item_ex_i2d(&intname.a, NULL, 291 ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); 292 if (!BUF_MEM_grow(a->bytes,len)) goto memerr; 293 p=(unsigned char *)a->bytes->data; 294 ASN1_item_ex_i2d(&intname.a, 295 &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); 296 sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, 297 local_sk_X509_NAME_ENTRY_free); 298 a->modified = 0; 299 return len; 300memerr: 301 sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, 302 local_sk_X509_NAME_ENTRY_free); 303 OPENSSL_PUT_ERROR(X509, x509_name_encode, ERR_R_MALLOC_FAILURE); 304 return -1; 305} 306 307static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, 308 int indent, 309 const char *fname, 310 const ASN1_PCTX *pctx) 311 { 312 if (X509_NAME_print_ex(out, (X509_NAME *)*pval, 313 indent, pctx->nm_flags) <= 0) 314 return 0; 315 return 2; 316 } 317 318/* This function generates the canonical encoding of the Name structure. 319 * In it all strings are converted to UTF8, leading, trailing and 320 * multiple spaces collapsed, converted to lower case and the leading 321 * SEQUENCE header removed. 322 * 323 * In future we could also normalize the UTF8 too. 324 * 325 * By doing this comparison of Name structures can be rapidly 326 * perfomed by just using memcmp() of the canonical encoding. 327 * By omitting the leading SEQUENCE name constraints of type 328 * dirName can also be checked with a simple memcmp(). 329 */ 330 331static int x509_name_canon(X509_NAME *a) 332 { 333 unsigned char *p; 334 STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL; 335 STACK_OF(X509_NAME_ENTRY) *entries = NULL; 336 X509_NAME_ENTRY *entry, *tmpentry = NULL; 337 int set = -1, ret = 0; 338 size_t i; 339 340 if (a->canon_enc) 341 { 342 OPENSSL_free(a->canon_enc); 343 a->canon_enc = NULL; 344 } 345 /* Special case: empty X509_NAME => null encoding */ 346 if (sk_X509_NAME_ENTRY_num(a->entries) == 0) 347 { 348 a->canon_enclen = 0; 349 return 1; 350 } 351 intname = sk_STACK_OF_X509_NAME_ENTRY_new_null(); 352 if(!intname) 353 goto err; 354 for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) 355 { 356 entry = sk_X509_NAME_ENTRY_value(a->entries, i); 357 if(entry->set != set) 358 { 359 entries = sk_X509_NAME_ENTRY_new_null(); 360 if(!entries) 361 goto err; 362 if(!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) 363 { 364 sk_X509_NAME_ENTRY_free(entries); 365 goto err; 366 } 367 set = entry->set; 368 } 369 tmpentry = X509_NAME_ENTRY_new(); 370 if (tmpentry == NULL) 371 goto err; 372 tmpentry->object = OBJ_dup(entry->object); 373 if (!asn1_string_canon(tmpentry->value, entry->value)) 374 goto err; 375 if(!sk_X509_NAME_ENTRY_push(entries, tmpentry)) 376 goto err; 377 tmpentry = NULL; 378 } 379 380 /* Finally generate encoding */ 381 382 a->canon_enclen = i2d_name_canon(intname, NULL); 383 384 p = OPENSSL_malloc(a->canon_enclen); 385 386 if (!p) 387 goto err; 388 389 a->canon_enc = p; 390 391 i2d_name_canon(intname, &p); 392 393 ret = 1; 394 395 err: 396 397 if (tmpentry) 398 X509_NAME_ENTRY_free(tmpentry); 399 if (intname) 400 sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname, 401 local_sk_X509_NAME_ENTRY_pop_free); 402 return ret; 403 } 404 405/* Bitmap of all the types of string that will be canonicalized. */ 406 407#define ASN1_MASK_CANON \ 408 (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \ 409 | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \ 410 | B_ASN1_VISIBLESTRING) 411 412 413static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in) 414 { 415 unsigned char *to, *from; 416 int len, i; 417 418 /* If type not in bitmask just copy string across */ 419 if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) 420 { 421 if (!ASN1_STRING_copy(out, in)) 422 return 0; 423 return 1; 424 } 425 426 out->type = V_ASN1_UTF8STRING; 427 out->length = ASN1_STRING_to_UTF8(&out->data, in); 428 if (out->length == -1) 429 return 0; 430 431 to = out->data; 432 from = to; 433 434 len = out->length; 435 436 /* Convert string in place to canonical form. 437 * Ultimately we may need to handle a wider range of characters 438 * but for now ignore anything with MSB set and rely on the 439 * isspace() and tolower() functions. 440 */ 441 442 /* Ignore leading spaces */ 443 while((len > 0) && !(*from & 0x80) && isspace(*from)) 444 { 445 from++; 446 len--; 447 } 448 449 to = from + len - 1; 450 451 /* Ignore trailing spaces */ 452 while ((len > 0) && !(*to & 0x80) && isspace(*to)) 453 { 454 to--; 455 len--; 456 } 457 458 to = out->data; 459 460 i = 0; 461 while(i < len) 462 { 463 /* If MSB set just copy across */ 464 if (*from & 0x80) 465 { 466 *to++ = *from++; 467 i++; 468 } 469 /* Collapse multiple spaces */ 470 else if (isspace(*from)) 471 { 472 /* Copy one space across */ 473 *to++ = ' '; 474 /* Ignore subsequent spaces. Note: don't need to 475 * check len here because we know the last 476 * character is a non-space so we can't overflow. 477 */ 478 do 479 { 480 from++; 481 i++; 482 } 483 while(!(*from & 0x80) && isspace(*from)); 484 } 485 else 486 { 487 *to++ = tolower(*from); 488 from++; 489 i++; 490 } 491 } 492 493 out->length = to - out->data; 494 495 return 1; 496 497 } 498 499static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *_intname, 500 unsigned char **in) 501 { 502 int len, ltmp; 503 size_t i; 504 ASN1_VALUE *v; 505 STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname; 506 507 len = 0; 508 for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) 509 { 510 v = sk_ASN1_VALUE_value(intname, i); 511 ltmp = ASN1_item_ex_i2d(&v, in, 512 ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1); 513 if (ltmp < 0) 514 return ltmp; 515 len += ltmp; 516 } 517 return len; 518 } 519 520int X509_NAME_set(X509_NAME **xn, X509_NAME *name) 521 { 522 X509_NAME *in; 523 524 if (!xn || !name) return(0); 525 526 if (*xn != name) 527 { 528 in=X509_NAME_dup(name); 529 if (in != NULL) 530 { 531 X509_NAME_free(*xn); 532 *xn=in; 533 } 534 } 535 return(*xn != NULL); 536 } 537 538IMPLEMENT_ASN1_SET_OF(X509_NAME_ENTRY) 539