1/* v3_utl.c */ 2/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 3 * project 1999. 4 */ 5/* ==================================================================== 6 * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58/* X509 v3 extension utilities */ 59 60 61#include <stdio.h> 62#include <ctype.h> 63#include "cryptlib.h" 64#include <openssl/conf.h> 65#include <openssl/x509v3.h> 66 67static char *strip_spaces(char *name); 68static int sk_strcmp(const char * const *a, const char * const *b); 69static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens); 70static void str_free(void *str); 71static int append_ia5(STACK **sk, ASN1_IA5STRING *email); 72 73/* Add a CONF_VALUE name value pair to stack */ 74 75int X509V3_add_value(const char *name, const char *value, 76 STACK_OF(CONF_VALUE) **extlist) 77{ 78 CONF_VALUE *vtmp = NULL; 79 char *tname = NULL, *tvalue = NULL; 80 if(name && !(tname = BUF_strdup(name))) goto err; 81 if(value && !(tvalue = BUF_strdup(value))) goto err;; 82 if(!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) goto err; 83 if(!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) goto err; 84 vtmp->section = NULL; 85 vtmp->name = tname; 86 vtmp->value = tvalue; 87 if(!sk_CONF_VALUE_push(*extlist, vtmp)) goto err; 88 return 1; 89 err: 90 X509V3err(X509V3_F_X509V3_ADD_VALUE,ERR_R_MALLOC_FAILURE); 91 if(vtmp) OPENSSL_free(vtmp); 92 if(tname) OPENSSL_free(tname); 93 if(tvalue) OPENSSL_free(tvalue); 94 return 0; 95} 96 97int X509V3_add_value_uchar(const char *name, const unsigned char *value, 98 STACK_OF(CONF_VALUE) **extlist) 99 { 100 return X509V3_add_value(name,(const char *)value,extlist); 101 } 102 103/* Free function for STACK_OF(CONF_VALUE) */ 104 105void X509V3_conf_free(CONF_VALUE *conf) 106{ 107 if(!conf) return; 108 if(conf->name) OPENSSL_free(conf->name); 109 if(conf->value) OPENSSL_free(conf->value); 110 if(conf->section) OPENSSL_free(conf->section); 111 OPENSSL_free(conf); 112} 113 114int X509V3_add_value_bool(const char *name, int asn1_bool, 115 STACK_OF(CONF_VALUE) **extlist) 116{ 117 if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist); 118 return X509V3_add_value(name, "FALSE", extlist); 119} 120 121int X509V3_add_value_bool_nf(char *name, int asn1_bool, 122 STACK_OF(CONF_VALUE) **extlist) 123{ 124 if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist); 125 return 1; 126} 127 128 129char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a) 130{ 131 BIGNUM *bntmp = NULL; 132 char *strtmp = NULL; 133 if(!a) return NULL; 134 if(!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || 135 !(strtmp = BN_bn2dec(bntmp)) ) 136 X509V3err(X509V3_F_I2S_ASN1_ENUMERATED,ERR_R_MALLOC_FAILURE); 137 BN_free(bntmp); 138 return strtmp; 139} 140 141char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a) 142{ 143 BIGNUM *bntmp = NULL; 144 char *strtmp = NULL; 145 if(!a) return NULL; 146 if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || 147 !(strtmp = BN_bn2dec(bntmp)) ) 148 X509V3err(X509V3_F_I2S_ASN1_INTEGER,ERR_R_MALLOC_FAILURE); 149 BN_free(bntmp); 150 return strtmp; 151} 152 153ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) 154{ 155 BIGNUM *bn = NULL; 156 ASN1_INTEGER *aint; 157 int isneg, ishex; 158 int ret; 159 bn = BN_new(); 160 if (!value) { 161 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE); 162 return 0; 163 } 164 if (value[0] == '-') { 165 value++; 166 isneg = 1; 167 } else isneg = 0; 168 169 if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) { 170 value += 2; 171 ishex = 1; 172 } else ishex = 0; 173 174 if (ishex) ret = BN_hex2bn(&bn, value); 175 else ret = BN_dec2bn(&bn, value); 176 177 if (!ret) { 178 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR); 179 return 0; 180 } 181 182 if (isneg && BN_is_zero(bn)) isneg = 0; 183 184 aint = BN_to_ASN1_INTEGER(bn, NULL); 185 BN_free(bn); 186 if (!aint) { 187 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_TO_ASN1_INTEGER_ERROR); 188 return 0; 189 } 190 if (isneg) aint->type |= V_ASN1_NEG; 191 return aint; 192} 193 194int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, 195 STACK_OF(CONF_VALUE) **extlist) 196{ 197 char *strtmp; 198 int ret; 199 if(!aint) return 1; 200 if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0; 201 ret = X509V3_add_value(name, strtmp, extlist); 202 OPENSSL_free(strtmp); 203 return ret; 204} 205 206int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool) 207{ 208 char *btmp; 209 if(!(btmp = value->value)) goto err; 210 if(!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") 211 || !strcmp(btmp, "Y") || !strcmp(btmp, "y") 212 || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { 213 *asn1_bool = 0xff; 214 return 1; 215 } else if(!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") 216 || !strcmp(btmp, "N") || !strcmp(btmp, "n") 217 || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { 218 *asn1_bool = 0; 219 return 1; 220 } 221 err: 222 X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,X509V3_R_INVALID_BOOLEAN_STRING); 223 X509V3_conf_err(value); 224 return 0; 225} 226 227int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint) 228{ 229 ASN1_INTEGER *itmp; 230 if(!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { 231 X509V3_conf_err(value); 232 return 0; 233 } 234 *aint = itmp; 235 return 1; 236} 237 238#define HDR_NAME 1 239#define HDR_VALUE 2 240 241/*#define DEBUG*/ 242 243STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) 244{ 245 char *p, *q, c; 246 char *ntmp, *vtmp; 247 STACK_OF(CONF_VALUE) *values = NULL; 248 char *linebuf; 249 int state; 250 /* We are going to modify the line so copy it first */ 251 linebuf = BUF_strdup(line); 252 state = HDR_NAME; 253 ntmp = NULL; 254 /* Go through all characters */ 255 for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) { 256 257 switch(state) { 258 case HDR_NAME: 259 if(c == ':') { 260 state = HDR_VALUE; 261 *p = 0; 262 ntmp = strip_spaces(q); 263 if(!ntmp) { 264 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); 265 goto err; 266 } 267 q = p + 1; 268 } else if(c == ',') { 269 *p = 0; 270 ntmp = strip_spaces(q); 271 q = p + 1; 272#if 0 273 printf("%s\n", ntmp); 274#endif 275 if(!ntmp) { 276 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); 277 goto err; 278 } 279 X509V3_add_value(ntmp, NULL, &values); 280 } 281 break ; 282 283 case HDR_VALUE: 284 if(c == ',') { 285 state = HDR_NAME; 286 *p = 0; 287 vtmp = strip_spaces(q); 288#if 0 289 printf("%s\n", ntmp); 290#endif 291 if(!vtmp) { 292 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE); 293 goto err; 294 } 295 X509V3_add_value(ntmp, vtmp, &values); 296 ntmp = NULL; 297 q = p + 1; 298 } 299 300 } 301 } 302 303 if(state == HDR_VALUE) { 304 vtmp = strip_spaces(q); 305#if 0 306 printf("%s=%s\n", ntmp, vtmp); 307#endif 308 if(!vtmp) { 309 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE); 310 goto err; 311 } 312 X509V3_add_value(ntmp, vtmp, &values); 313 } else { 314 ntmp = strip_spaces(q); 315#if 0 316 printf("%s\n", ntmp); 317#endif 318 if(!ntmp) { 319 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); 320 goto err; 321 } 322 X509V3_add_value(ntmp, NULL, &values); 323 } 324OPENSSL_free(linebuf); 325return values; 326 327err: 328OPENSSL_free(linebuf); 329sk_CONF_VALUE_pop_free(values, X509V3_conf_free); 330return NULL; 331 332} 333 334/* Delete leading and trailing spaces from a string */ 335static char *strip_spaces(char *name) 336{ 337 char *p, *q; 338 /* Skip over leading spaces */ 339 p = name; 340 while(*p && isspace((unsigned char)*p)) p++; 341 if(!*p) return NULL; 342 q = p + strlen(p) - 1; 343 while((q != p) && isspace((unsigned char)*q)) q--; 344 if(p != q) q[1] = 0; 345 if(!*p) return NULL; 346 return p; 347} 348 349/* hex string utilities */ 350 351/* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its 352 * hex representation 353 * @@@ (Contents of buffer are always kept in ASCII, also on EBCDIC machines) 354 */ 355 356char *hex_to_string(unsigned char *buffer, long len) 357{ 358 char *tmp, *q; 359 unsigned char *p; 360 int i; 361 static char hexdig[] = "0123456789ABCDEF"; 362 if(!buffer || !len) return NULL; 363 if(!(tmp = OPENSSL_malloc(len * 3 + 1))) { 364 X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE); 365 return NULL; 366 } 367 q = tmp; 368 for(i = 0, p = buffer; i < len; i++,p++) { 369 *q++ = hexdig[(*p >> 4) & 0xf]; 370 *q++ = hexdig[*p & 0xf]; 371 *q++ = ':'; 372 } 373 q[-1] = 0; 374#ifdef CHARSET_EBCDIC 375 ebcdic2ascii(tmp, tmp, q - tmp - 1); 376#endif 377 378 return tmp; 379} 380 381/* Give a string of hex digits convert to 382 * a buffer 383 */ 384 385unsigned char *string_to_hex(char *str, long *len) 386{ 387 unsigned char *hexbuf, *q; 388 unsigned char ch, cl, *p; 389 if(!str) { 390 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_INVALID_NULL_ARGUMENT); 391 return NULL; 392 } 393 if(!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) goto err; 394 for(p = (unsigned char *)str, q = hexbuf; *p;) { 395 ch = *p++; 396#ifdef CHARSET_EBCDIC 397 ch = os_toebcdic[ch]; 398#endif 399 if(ch == ':') continue; 400 cl = *p++; 401#ifdef CHARSET_EBCDIC 402 cl = os_toebcdic[cl]; 403#endif 404 if(!cl) { 405 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS); 406 OPENSSL_free(hexbuf); 407 return NULL; 408 } 409 if(isupper(ch)) ch = tolower(ch); 410 if(isupper(cl)) cl = tolower(cl); 411 412 if((ch >= '0') && (ch <= '9')) ch -= '0'; 413 else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10; 414 else goto badhex; 415 416 if((cl >= '0') && (cl <= '9')) cl -= '0'; 417 else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10; 418 else goto badhex; 419 420 *q++ = (ch << 4) | cl; 421 } 422 423 if(len) *len = q - hexbuf; 424 425 return hexbuf; 426 427 err: 428 if(hexbuf) OPENSSL_free(hexbuf); 429 X509V3err(X509V3_F_STRING_TO_HEX,ERR_R_MALLOC_FAILURE); 430 return NULL; 431 432 badhex: 433 OPENSSL_free(hexbuf); 434 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ILLEGAL_HEX_DIGIT); 435 return NULL; 436 437} 438 439/* V2I name comparison function: returns zero if 'name' matches 440 * cmp or cmp.* 441 */ 442 443int name_cmp(const char *name, const char *cmp) 444{ 445 int len, ret; 446 char c; 447 len = strlen(cmp); 448 if((ret = strncmp(name, cmp, len))) return ret; 449 c = name[len]; 450 if(!c || (c=='.')) return 0; 451 return 1; 452} 453 454static int sk_strcmp(const char * const *a, const char * const *b) 455{ 456 return strcmp(*a, *b); 457} 458 459STACK *X509_get1_email(X509 *x) 460{ 461 GENERAL_NAMES *gens; 462 STACK *ret; 463 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 464 ret = get_email(X509_get_subject_name(x), gens); 465 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 466 return ret; 467} 468 469STACK *X509_REQ_get1_email(X509_REQ *x) 470{ 471 GENERAL_NAMES *gens; 472 STACK_OF(X509_EXTENSION) *exts; 473 STACK *ret; 474 exts = X509_REQ_get_extensions(x); 475 gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); 476 ret = get_email(X509_REQ_get_subject_name(x), gens); 477 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 478 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 479 return ret; 480} 481 482 483static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens) 484{ 485 STACK *ret = NULL; 486 X509_NAME_ENTRY *ne; 487 ASN1_IA5STRING *email; 488 GENERAL_NAME *gen; 489 int i; 490 /* Now add any email address(es) to STACK */ 491 i = -1; 492 /* First supplied X509_NAME */ 493 while((i = X509_NAME_get_index_by_NID(name, 494 NID_pkcs9_emailAddress, i)) >= 0) { 495 ne = X509_NAME_get_entry(name, i); 496 email = X509_NAME_ENTRY_get_data(ne); 497 if(!append_ia5(&ret, email)) return NULL; 498 } 499 for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) 500 { 501 gen = sk_GENERAL_NAME_value(gens, i); 502 if(gen->type != GEN_EMAIL) continue; 503 if(!append_ia5(&ret, gen->d.ia5)) return NULL; 504 } 505 return ret; 506} 507 508static void str_free(void *str) 509{ 510 OPENSSL_free(str); 511} 512 513static int append_ia5(STACK **sk, ASN1_IA5STRING *email) 514{ 515 char *emtmp; 516 /* First some sanity checks */ 517 if(email->type != V_ASN1_IA5STRING) return 1; 518 if(!email->data || !email->length) return 1; 519 if(!*sk) *sk = sk_new(sk_strcmp); 520 if(!*sk) return 0; 521 /* Don't add duplicates */ 522 if(sk_find(*sk, (char *)email->data) != -1) return 1; 523 emtmp = BUF_strdup((char *)email->data); 524 if(!emtmp || !sk_push(*sk, emtmp)) { 525 X509_email_free(*sk); 526 *sk = NULL; 527 return 0; 528 } 529 return 1; 530} 531 532void X509_email_free(STACK *sk) 533{ 534 sk_pop_free(sk, str_free); 535} 536