155714Skris/* v3_utl.c */ 2280304Sjkim/* 3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4160814Ssimon * project. 555714Skris */ 655714Skris/* ==================================================================== 7160814Ssimon * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. 855714Skris * 955714Skris * Redistribution and use in source and binary forms, with or without 1055714Skris * modification, are permitted provided that the following conditions 1155714Skris * are met: 1255714Skris * 1355714Skris * 1. Redistributions of source code must retain the above copyright 14280304Sjkim * notice, this list of conditions and the following disclaimer. 1555714Skris * 1655714Skris * 2. Redistributions in binary form must reproduce the above copyright 1755714Skris * notice, this list of conditions and the following disclaimer in 1855714Skris * the documentation and/or other materials provided with the 1955714Skris * distribution. 2055714Skris * 2155714Skris * 3. All advertising materials mentioning features or use of this 2255714Skris * software must display the following acknowledgment: 2355714Skris * "This product includes software developed by the OpenSSL Project 2455714Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2555714Skris * 2655714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2755714Skris * endorse or promote products derived from this software without 2855714Skris * prior written permission. For written permission, please contact 2955714Skris * licensing@OpenSSL.org. 3055714Skris * 3155714Skris * 5. Products derived from this software may not be called "OpenSSL" 3255714Skris * nor may "OpenSSL" appear in their names without prior written 3355714Skris * permission of the OpenSSL Project. 3455714Skris * 3555714Skris * 6. Redistributions of any form whatsoever must retain the following 3655714Skris * acknowledgment: 3755714Skris * "This product includes software developed by the OpenSSL Project 3855714Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3955714Skris * 4055714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4155714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4255714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4355714Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4455714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4555714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4655714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4755714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5055714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5155714Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5255714Skris * ==================================================================== 5355714Skris * 5455714Skris * This product includes cryptographic software written by Eric Young 5555714Skris * (eay@cryptsoft.com). This product includes software written by Tim 5655714Skris * Hudson (tjh@cryptsoft.com). 5755714Skris * 5855714Skris */ 5955714Skris/* X509 v3 extension utilities */ 6055714Skris 6155714Skris#include <stdio.h> 6255714Skris#include <ctype.h> 6355714Skris#include "cryptlib.h" 6455714Skris#include <openssl/conf.h> 6555714Skris#include <openssl/x509v3.h> 66160814Ssimon#include <openssl/bn.h> 6755714Skris 6855714Skrisstatic char *strip_spaces(char *name); 69280304Sjkimstatic int sk_strcmp(const char *const *a, const char *const *b); 70280304Sjkimstatic STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, 71280304Sjkim GENERAL_NAMES *gens); 72238405Sjkimstatic void str_free(OPENSSL_STRING str); 73238405Sjkimstatic int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email); 7455714Skris 75160814Ssimonstatic int ipv4_from_asc(unsigned char *v4, const char *in); 76160814Ssimonstatic int ipv6_from_asc(unsigned char *v6, const char *in); 77160814Ssimonstatic int ipv6_cb(const char *elem, int len, void *usr); 78160814Ssimonstatic int ipv6_hex(unsigned char *out, const char *in, int inlen); 79160814Ssimon 8055714Skris/* Add a CONF_VALUE name value pair to stack */ 8155714Skris 8255714Skrisint X509V3_add_value(const char *name, const char *value, 83280304Sjkim STACK_OF(CONF_VALUE) **extlist) 8455714Skris{ 85280304Sjkim CONF_VALUE *vtmp = NULL; 86280304Sjkim char *tname = NULL, *tvalue = NULL; 87280304Sjkim if (name && !(tname = BUF_strdup(name))) 88280304Sjkim goto err; 89280304Sjkim if (value && !(tvalue = BUF_strdup(value))) 90280304Sjkim goto err; 91280304Sjkim if (!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) 92280304Sjkim goto err; 93280304Sjkim if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) 94280304Sjkim goto err; 95280304Sjkim vtmp->section = NULL; 96280304Sjkim vtmp->name = tname; 97280304Sjkim vtmp->value = tvalue; 98280304Sjkim if (!sk_CONF_VALUE_push(*extlist, vtmp)) 99280304Sjkim goto err; 100280304Sjkim return 1; 101280304Sjkim err: 102280304Sjkim X509V3err(X509V3_F_X509V3_ADD_VALUE, ERR_R_MALLOC_FAILURE); 103280304Sjkim if (vtmp) 104280304Sjkim OPENSSL_free(vtmp); 105280304Sjkim if (tname) 106280304Sjkim OPENSSL_free(tname); 107280304Sjkim if (tvalue) 108280304Sjkim OPENSSL_free(tvalue); 109280304Sjkim return 0; 11055714Skris} 11155714Skris 11255714Skrisint X509V3_add_value_uchar(const char *name, const unsigned char *value, 113280304Sjkim STACK_OF(CONF_VALUE) **extlist) 114280304Sjkim{ 115280304Sjkim return X509V3_add_value(name, (const char *)value, extlist); 116280304Sjkim} 11755714Skris 11855714Skris/* Free function for STACK_OF(CONF_VALUE) */ 11955714Skris 12055714Skrisvoid X509V3_conf_free(CONF_VALUE *conf) 12155714Skris{ 122280304Sjkim if (!conf) 123280304Sjkim return; 124280304Sjkim if (conf->name) 125280304Sjkim OPENSSL_free(conf->name); 126280304Sjkim if (conf->value) 127280304Sjkim OPENSSL_free(conf->value); 128280304Sjkim if (conf->section) 129280304Sjkim OPENSSL_free(conf->section); 130280304Sjkim OPENSSL_free(conf); 13155714Skris} 13255714Skris 13355714Skrisint X509V3_add_value_bool(const char *name, int asn1_bool, 134280304Sjkim STACK_OF(CONF_VALUE) **extlist) 13555714Skris{ 136280304Sjkim if (asn1_bool) 137280304Sjkim return X509V3_add_value(name, "TRUE", extlist); 138280304Sjkim return X509V3_add_value(name, "FALSE", extlist); 13955714Skris} 14055714Skris 14155714Skrisint X509V3_add_value_bool_nf(char *name, int asn1_bool, 142280304Sjkim STACK_OF(CONF_VALUE) **extlist) 14355714Skris{ 144280304Sjkim if (asn1_bool) 145280304Sjkim return X509V3_add_value(name, "TRUE", extlist); 146280304Sjkim return 1; 14755714Skris} 14855714Skris 14955714Skrischar *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a) 15055714Skris{ 151280304Sjkim BIGNUM *bntmp = NULL; 152280304Sjkim char *strtmp = NULL; 153280304Sjkim if (!a) 154280304Sjkim return NULL; 155280304Sjkim if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || 156280304Sjkim !(strtmp = BN_bn2dec(bntmp))) 157280304Sjkim X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE); 158280304Sjkim BN_free(bntmp); 159280304Sjkim return strtmp; 16055714Skris} 16155714Skris 16255714Skrischar *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a) 16355714Skris{ 164280304Sjkim BIGNUM *bntmp = NULL; 165280304Sjkim char *strtmp = NULL; 166280304Sjkim if (!a) 167280304Sjkim return NULL; 168280304Sjkim if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || 169280304Sjkim !(strtmp = BN_bn2dec(bntmp))) 170280304Sjkim X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); 171280304Sjkim BN_free(bntmp); 172280304Sjkim return strtmp; 17355714Skris} 17455714Skris 17555714SkrisASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) 17655714Skris{ 177280304Sjkim BIGNUM *bn = NULL; 178280304Sjkim ASN1_INTEGER *aint; 179280304Sjkim int isneg, ishex; 180280304Sjkim int ret; 181280304Sjkim if (!value) { 182280304Sjkim X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE); 183280304Sjkim return 0; 184280304Sjkim } 185280304Sjkim bn = BN_new(); 186280304Sjkim if (value[0] == '-') { 187280304Sjkim value++; 188280304Sjkim isneg = 1; 189280304Sjkim } else 190280304Sjkim isneg = 0; 191109998Smarkm 192280304Sjkim if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) { 193280304Sjkim value += 2; 194280304Sjkim ishex = 1; 195280304Sjkim } else 196280304Sjkim ishex = 0; 197109998Smarkm 198280304Sjkim if (ishex) 199280304Sjkim ret = BN_hex2bn(&bn, value); 200280304Sjkim else 201280304Sjkim ret = BN_dec2bn(&bn, value); 202109998Smarkm 203280304Sjkim if (!ret || value[ret]) { 204280304Sjkim BN_free(bn); 205280304Sjkim X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR); 206280304Sjkim return 0; 207280304Sjkim } 20855714Skris 209280304Sjkim if (isneg && BN_is_zero(bn)) 210280304Sjkim isneg = 0; 211109998Smarkm 212280304Sjkim aint = BN_to_ASN1_INTEGER(bn, NULL); 213280304Sjkim BN_free(bn); 214280304Sjkim if (!aint) { 215280304Sjkim X509V3err(X509V3_F_S2I_ASN1_INTEGER, 216280304Sjkim X509V3_R_BN_TO_ASN1_INTEGER_ERROR); 217280304Sjkim return 0; 218280304Sjkim } 219280304Sjkim if (isneg) 220280304Sjkim aint->type |= V_ASN1_NEG; 221280304Sjkim return aint; 22255714Skris} 22355714Skris 22455714Skrisint X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, 225280304Sjkim STACK_OF(CONF_VALUE) **extlist) 22655714Skris{ 227280304Sjkim char *strtmp; 228280304Sjkim int ret; 229280304Sjkim if (!aint) 230280304Sjkim return 1; 231280304Sjkim if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) 232280304Sjkim return 0; 233280304Sjkim ret = X509V3_add_value(name, strtmp, extlist); 234280304Sjkim OPENSSL_free(strtmp); 235280304Sjkim return ret; 23655714Skris} 23755714Skris 23855714Skrisint X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool) 23955714Skris{ 240280304Sjkim char *btmp; 241280304Sjkim if (!(btmp = value->value)) 242280304Sjkim goto err; 243280304Sjkim if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") 244280304Sjkim || !strcmp(btmp, "Y") || !strcmp(btmp, "y") 245280304Sjkim || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { 246280304Sjkim *asn1_bool = 0xff; 247280304Sjkim return 1; 248280304Sjkim } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") 249280304Sjkim || !strcmp(btmp, "N") || !strcmp(btmp, "n") 250280304Sjkim || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { 251280304Sjkim *asn1_bool = 0; 252280304Sjkim return 1; 253280304Sjkim } 254280304Sjkim err: 255280304Sjkim X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL, 256280304Sjkim X509V3_R_INVALID_BOOLEAN_STRING); 257280304Sjkim X509V3_conf_err(value); 258280304Sjkim return 0; 25955714Skris} 26055714Skris 26155714Skrisint X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint) 26255714Skris{ 263280304Sjkim ASN1_INTEGER *itmp; 264280304Sjkim if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { 265280304Sjkim X509V3_conf_err(value); 266280304Sjkim return 0; 267280304Sjkim } 268280304Sjkim *aint = itmp; 269280304Sjkim return 1; 27055714Skris} 27155714Skris 272280304Sjkim#define HDR_NAME 1 273280304Sjkim#define HDR_VALUE 2 27455714Skris 275280304Sjkim/* 276280304Sjkim * #define DEBUG 277280304Sjkim */ 27855714Skris 279109998SmarkmSTACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) 28055714Skris{ 281280304Sjkim char *p, *q, c; 282280304Sjkim char *ntmp, *vtmp; 283280304Sjkim STACK_OF(CONF_VALUE) *values = NULL; 284280304Sjkim char *linebuf; 285280304Sjkim int state; 286280304Sjkim /* We are going to modify the line so copy it first */ 287280304Sjkim linebuf = BUF_strdup(line); 288284285Sjkim if (linebuf == NULL) { 289284285Sjkim X509V3err(X509V3_F_X509V3_PARSE_LIST, ERR_R_MALLOC_FAILURE); 290284285Sjkim goto err; 291284285Sjkim } 292280304Sjkim state = HDR_NAME; 293280304Sjkim ntmp = NULL; 294280304Sjkim /* Go through all characters */ 295280304Sjkim for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); 296280304Sjkim p++) { 29755714Skris 298280304Sjkim switch (state) { 299280304Sjkim case HDR_NAME: 300280304Sjkim if (c == ':') { 301280304Sjkim state = HDR_VALUE; 302280304Sjkim *p = 0; 303280304Sjkim ntmp = strip_spaces(q); 304280304Sjkim if (!ntmp) { 305280304Sjkim X509V3err(X509V3_F_X509V3_PARSE_LIST, 306280304Sjkim X509V3_R_INVALID_NULL_NAME); 307280304Sjkim goto err; 308280304Sjkim } 309280304Sjkim q = p + 1; 310280304Sjkim } else if (c == ',') { 311280304Sjkim *p = 0; 312280304Sjkim ntmp = strip_spaces(q); 313280304Sjkim q = p + 1; 314100928Snectar#if 0 315280304Sjkim printf("%s\n", ntmp); 31655714Skris#endif 317280304Sjkim if (!ntmp) { 318280304Sjkim X509V3err(X509V3_F_X509V3_PARSE_LIST, 319280304Sjkim X509V3_R_INVALID_NULL_NAME); 320280304Sjkim goto err; 321280304Sjkim } 322280304Sjkim X509V3_add_value(ntmp, NULL, &values); 323280304Sjkim } 324280304Sjkim break; 32555714Skris 326280304Sjkim case HDR_VALUE: 327280304Sjkim if (c == ',') { 328280304Sjkim state = HDR_NAME; 329280304Sjkim *p = 0; 330280304Sjkim vtmp = strip_spaces(q); 331100928Snectar#if 0 332280304Sjkim printf("%s\n", ntmp); 33355714Skris#endif 334280304Sjkim if (!vtmp) { 335280304Sjkim X509V3err(X509V3_F_X509V3_PARSE_LIST, 336280304Sjkim X509V3_R_INVALID_NULL_VALUE); 337280304Sjkim goto err; 338280304Sjkim } 339280304Sjkim X509V3_add_value(ntmp, vtmp, &values); 340280304Sjkim ntmp = NULL; 341280304Sjkim q = p + 1; 342280304Sjkim } 34355714Skris 344280304Sjkim } 345280304Sjkim } 34655714Skris 347280304Sjkim if (state == HDR_VALUE) { 348280304Sjkim vtmp = strip_spaces(q); 349100928Snectar#if 0 350280304Sjkim printf("%s=%s\n", ntmp, vtmp); 35155714Skris#endif 352280304Sjkim if (!vtmp) { 353280304Sjkim X509V3err(X509V3_F_X509V3_PARSE_LIST, 354280304Sjkim X509V3_R_INVALID_NULL_VALUE); 355280304Sjkim goto err; 356280304Sjkim } 357280304Sjkim X509V3_add_value(ntmp, vtmp, &values); 358280304Sjkim } else { 359280304Sjkim ntmp = strip_spaces(q); 360100928Snectar#if 0 361280304Sjkim printf("%s\n", ntmp); 36255714Skris#endif 363280304Sjkim if (!ntmp) { 364280304Sjkim X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); 365280304Sjkim goto err; 366280304Sjkim } 367280304Sjkim X509V3_add_value(ntmp, NULL, &values); 368280304Sjkim } 369280304Sjkim OPENSSL_free(linebuf); 370280304Sjkim return values; 37155714Skris 372280304Sjkim err: 373280304Sjkim OPENSSL_free(linebuf); 374280304Sjkim sk_CONF_VALUE_pop_free(values, X509V3_conf_free); 375280304Sjkim return NULL; 37655714Skris 37755714Skris} 37855714Skris 37955714Skris/* Delete leading and trailing spaces from a string */ 38055714Skrisstatic char *strip_spaces(char *name) 38155714Skris{ 382280304Sjkim char *p, *q; 383280304Sjkim /* Skip over leading spaces */ 384280304Sjkim p = name; 385280304Sjkim while (*p && isspace((unsigned char)*p)) 386280304Sjkim p++; 387280304Sjkim if (!*p) 388280304Sjkim return NULL; 389280304Sjkim q = p + strlen(p) - 1; 390280304Sjkim while ((q != p) && isspace((unsigned char)*q)) 391280304Sjkim q--; 392280304Sjkim if (p != q) 393280304Sjkim q[1] = 0; 394280304Sjkim if (!*p) 395280304Sjkim return NULL; 396280304Sjkim return p; 39755714Skris} 39855714Skris 39955714Skris/* hex string utilities */ 40055714Skris 401280304Sjkim/* 402280304Sjkim * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its 403280304Sjkim * hex representation @@@ (Contents of buffer are always kept in ASCII, also 404280304Sjkim * on EBCDIC machines) 40555714Skris */ 40655714Skris 407238405Sjkimchar *hex_to_string(const unsigned char *buffer, long len) 40855714Skris{ 409280304Sjkim char *tmp, *q; 410280304Sjkim const unsigned char *p; 411280304Sjkim int i; 412280304Sjkim const static char hexdig[] = "0123456789ABCDEF"; 413280304Sjkim if (!buffer || !len) 414280304Sjkim return NULL; 415280304Sjkim if (!(tmp = OPENSSL_malloc(len * 3 + 1))) { 416280304Sjkim X509V3err(X509V3_F_HEX_TO_STRING, ERR_R_MALLOC_FAILURE); 417280304Sjkim return NULL; 418280304Sjkim } 419280304Sjkim q = tmp; 420280304Sjkim for (i = 0, p = buffer; i < len; i++, p++) { 421280304Sjkim *q++ = hexdig[(*p >> 4) & 0xf]; 422280304Sjkim *q++ = hexdig[*p & 0xf]; 423280304Sjkim *q++ = ':'; 424280304Sjkim } 425280304Sjkim q[-1] = 0; 42668651Skris#ifdef CHARSET_EBCDIC 427280304Sjkim ebcdic2ascii(tmp, tmp, q - tmp - 1); 42868651Skris#endif 42968651Skris 430280304Sjkim return tmp; 43155714Skris} 43255714Skris 433280304Sjkim/* 434280304Sjkim * Give a string of hex digits convert to a buffer 43555714Skris */ 43655714Skris 437238405Sjkimunsigned char *string_to_hex(const char *str, long *len) 43855714Skris{ 439280304Sjkim unsigned char *hexbuf, *q; 440280304Sjkim unsigned char ch, cl, *p; 441280304Sjkim if (!str) { 442280304Sjkim X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_INVALID_NULL_ARGUMENT); 443280304Sjkim return NULL; 444280304Sjkim } 445280304Sjkim if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) 446280304Sjkim goto err; 447280304Sjkim for (p = (unsigned char *)str, q = hexbuf; *p;) { 448280304Sjkim ch = *p++; 44968651Skris#ifdef CHARSET_EBCDIC 450280304Sjkim ch = os_toebcdic[ch]; 45168651Skris#endif 452280304Sjkim if (ch == ':') 453280304Sjkim continue; 454280304Sjkim cl = *p++; 45568651Skris#ifdef CHARSET_EBCDIC 456280304Sjkim cl = os_toebcdic[cl]; 45768651Skris#endif 458280304Sjkim if (!cl) { 459280304Sjkim X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ODD_NUMBER_OF_DIGITS); 460280304Sjkim OPENSSL_free(hexbuf); 461280304Sjkim return NULL; 462280304Sjkim } 463280304Sjkim if (isupper(ch)) 464280304Sjkim ch = tolower(ch); 465280304Sjkim if (isupper(cl)) 466280304Sjkim cl = tolower(cl); 46755714Skris 468280304Sjkim if ((ch >= '0') && (ch <= '9')) 469280304Sjkim ch -= '0'; 470280304Sjkim else if ((ch >= 'a') && (ch <= 'f')) 471280304Sjkim ch -= 'a' - 10; 472280304Sjkim else 473280304Sjkim goto badhex; 47455714Skris 475280304Sjkim if ((cl >= '0') && (cl <= '9')) 476280304Sjkim cl -= '0'; 477280304Sjkim else if ((cl >= 'a') && (cl <= 'f')) 478280304Sjkim cl -= 'a' - 10; 479280304Sjkim else 480280304Sjkim goto badhex; 48155714Skris 482280304Sjkim *q++ = (ch << 4) | cl; 483280304Sjkim } 48455714Skris 485280304Sjkim if (len) 486280304Sjkim *len = q - hexbuf; 48755714Skris 488280304Sjkim return hexbuf; 48955714Skris 490280304Sjkim err: 491280304Sjkim if (hexbuf) 492280304Sjkim OPENSSL_free(hexbuf); 493280304Sjkim X509V3err(X509V3_F_STRING_TO_HEX, ERR_R_MALLOC_FAILURE); 494280304Sjkim return NULL; 49555714Skris 496280304Sjkim badhex: 497280304Sjkim OPENSSL_free(hexbuf); 498280304Sjkim X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ILLEGAL_HEX_DIGIT); 499280304Sjkim return NULL; 50055714Skris 50155714Skris} 50255714Skris 503280304Sjkim/* 504280304Sjkim * V2I name comparison function: returns zero if 'name' matches cmp or cmp.* 50555714Skris */ 50655714Skris 50755714Skrisint name_cmp(const char *name, const char *cmp) 50855714Skris{ 509280304Sjkim int len, ret; 510280304Sjkim char c; 511280304Sjkim len = strlen(cmp); 512280304Sjkim if ((ret = strncmp(name, cmp, len))) 513280304Sjkim return ret; 514280304Sjkim c = name[len]; 515280304Sjkim if (!c || (c == '.')) 516280304Sjkim return 0; 517280304Sjkim return 1; 51855714Skris} 51968651Skris 520280304Sjkimstatic int sk_strcmp(const char *const *a, const char *const *b) 52168651Skris{ 522280304Sjkim return strcmp(*a, *b); 52368651Skris} 52468651Skris 525238405SjkimSTACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x) 52668651Skris{ 527280304Sjkim GENERAL_NAMES *gens; 528280304Sjkim STACK_OF(OPENSSL_STRING) *ret; 529238405Sjkim 530280304Sjkim gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 531280304Sjkim ret = get_email(X509_get_subject_name(x), gens); 532280304Sjkim sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 533280304Sjkim return ret; 53468651Skris} 53568651Skris 536238405SjkimSTACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x) 537194206Ssimon{ 538280304Sjkim AUTHORITY_INFO_ACCESS *info; 539280304Sjkim STACK_OF(OPENSSL_STRING) *ret = NULL; 540280304Sjkim int i; 541238405Sjkim 542280304Sjkim info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); 543280304Sjkim if (!info) 544280304Sjkim return NULL; 545280304Sjkim for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { 546280304Sjkim ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); 547280304Sjkim if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { 548280304Sjkim if (ad->location->type == GEN_URI) { 549280304Sjkim if (!append_ia5 550280304Sjkim (&ret, ad->location->d.uniformResourceIdentifier)) 551280304Sjkim break; 552280304Sjkim } 553280304Sjkim } 554280304Sjkim } 555280304Sjkim AUTHORITY_INFO_ACCESS_free(info); 556280304Sjkim return ret; 557194206Ssimon} 558194206Ssimon 559238405SjkimSTACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x) 56068651Skris{ 561280304Sjkim GENERAL_NAMES *gens; 562280304Sjkim STACK_OF(X509_EXTENSION) *exts; 563280304Sjkim STACK_OF(OPENSSL_STRING) *ret; 564238405Sjkim 565280304Sjkim exts = X509_REQ_get_extensions(x); 566280304Sjkim gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); 567280304Sjkim ret = get_email(X509_REQ_get_subject_name(x), gens); 568280304Sjkim sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 569280304Sjkim sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 570280304Sjkim return ret; 57168651Skris} 57268651Skris 573280304Sjkimstatic STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, 574280304Sjkim GENERAL_NAMES *gens) 57568651Skris{ 576280304Sjkim STACK_OF(OPENSSL_STRING) *ret = NULL; 577280304Sjkim X509_NAME_ENTRY *ne; 578280304Sjkim ASN1_IA5STRING *email; 579280304Sjkim GENERAL_NAME *gen; 580280304Sjkim int i; 581280304Sjkim /* Now add any email address(es) to STACK */ 582280304Sjkim i = -1; 583280304Sjkim /* First supplied X509_NAME */ 584280304Sjkim while ((i = X509_NAME_get_index_by_NID(name, 585280304Sjkim NID_pkcs9_emailAddress, i)) >= 0) { 586280304Sjkim ne = X509_NAME_get_entry(name, i); 587280304Sjkim email = X509_NAME_ENTRY_get_data(ne); 588280304Sjkim if (!append_ia5(&ret, email)) 589280304Sjkim return NULL; 590280304Sjkim } 591280304Sjkim for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 592280304Sjkim gen = sk_GENERAL_NAME_value(gens, i); 593280304Sjkim if (gen->type != GEN_EMAIL) 594280304Sjkim continue; 595280304Sjkim if (!append_ia5(&ret, gen->d.ia5)) 596280304Sjkim return NULL; 597280304Sjkim } 598280304Sjkim return ret; 59968651Skris} 60068651Skris 601238405Sjkimstatic void str_free(OPENSSL_STRING str) 60268651Skris{ 603280304Sjkim OPENSSL_free(str); 60468651Skris} 60568651Skris 606238405Sjkimstatic int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) 60768651Skris{ 608280304Sjkim char *emtmp; 609280304Sjkim /* First some sanity checks */ 610280304Sjkim if (email->type != V_ASN1_IA5STRING) 611280304Sjkim return 1; 612280304Sjkim if (!email->data || !email->length) 613280304Sjkim return 1; 614280304Sjkim if (!*sk) 615280304Sjkim *sk = sk_OPENSSL_STRING_new(sk_strcmp); 616280304Sjkim if (!*sk) 617280304Sjkim return 0; 618280304Sjkim /* Don't add duplicates */ 619280304Sjkim if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1) 620280304Sjkim return 1; 621280304Sjkim emtmp = BUF_strdup((char *)email->data); 622280304Sjkim if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) { 623280304Sjkim X509_email_free(*sk); 624280304Sjkim *sk = NULL; 625280304Sjkim return 0; 626280304Sjkim } 627280304Sjkim return 1; 62868651Skris} 62968651Skris 630238405Sjkimvoid X509_email_free(STACK_OF(OPENSSL_STRING) *sk) 63168651Skris{ 632280304Sjkim sk_OPENSSL_STRING_pop_free(sk, str_free); 63368651Skris} 634160814Ssimon 635280304Sjkim/* 636280304Sjkim * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible 637280304Sjkim * with RFC3280. 638160814Ssimon */ 639160814Ssimon 640160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) 641280304Sjkim{ 642280304Sjkim unsigned char ipout[16]; 643280304Sjkim ASN1_OCTET_STRING *ret; 644280304Sjkim int iplen; 645160814Ssimon 646280304Sjkim /* If string contains a ':' assume IPv6 */ 647160814Ssimon 648280304Sjkim iplen = a2i_ipadd(ipout, ipasc); 649160814Ssimon 650280304Sjkim if (!iplen) 651280304Sjkim return NULL; 652160814Ssimon 653280304Sjkim ret = ASN1_OCTET_STRING_new(); 654280304Sjkim if (!ret) 655280304Sjkim return NULL; 656280304Sjkim if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { 657280304Sjkim ASN1_OCTET_STRING_free(ret); 658280304Sjkim return NULL; 659280304Sjkim } 660280304Sjkim return ret; 661280304Sjkim} 662160814Ssimon 663160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc) 664280304Sjkim{ 665280304Sjkim ASN1_OCTET_STRING *ret = NULL; 666280304Sjkim unsigned char ipout[32]; 667280304Sjkim char *iptmp = NULL, *p; 668280304Sjkim int iplen1, iplen2; 669280304Sjkim p = strchr(ipasc, '/'); 670280304Sjkim if (!p) 671280304Sjkim return NULL; 672280304Sjkim iptmp = BUF_strdup(ipasc); 673280304Sjkim if (!iptmp) 674280304Sjkim return NULL; 675280304Sjkim p = iptmp + (p - ipasc); 676280304Sjkim *p++ = 0; 677160814Ssimon 678280304Sjkim iplen1 = a2i_ipadd(ipout, iptmp); 679160814Ssimon 680280304Sjkim if (!iplen1) 681280304Sjkim goto err; 682160814Ssimon 683280304Sjkim iplen2 = a2i_ipadd(ipout + iplen1, p); 684160814Ssimon 685280304Sjkim OPENSSL_free(iptmp); 686280304Sjkim iptmp = NULL; 687160814Ssimon 688280304Sjkim if (!iplen2 || (iplen1 != iplen2)) 689280304Sjkim goto err; 690160814Ssimon 691280304Sjkim ret = ASN1_OCTET_STRING_new(); 692280304Sjkim if (!ret) 693280304Sjkim goto err; 694280304Sjkim if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) 695280304Sjkim goto err; 696160814Ssimon 697280304Sjkim return ret; 698160814Ssimon 699280304Sjkim err: 700280304Sjkim if (iptmp) 701280304Sjkim OPENSSL_free(iptmp); 702280304Sjkim if (ret) 703280304Sjkim ASN1_OCTET_STRING_free(ret); 704280304Sjkim return NULL; 705280304Sjkim} 706160814Ssimon 707167612Ssimonint a2i_ipadd(unsigned char *ipout, const char *ipasc) 708280304Sjkim{ 709280304Sjkim /* If string contains a ':' assume IPv6 */ 710160814Ssimon 711280304Sjkim if (strchr(ipasc, ':')) { 712280304Sjkim if (!ipv6_from_asc(ipout, ipasc)) 713280304Sjkim return 0; 714280304Sjkim return 16; 715280304Sjkim } else { 716280304Sjkim if (!ipv4_from_asc(ipout, ipasc)) 717280304Sjkim return 0; 718280304Sjkim return 4; 719280304Sjkim } 720280304Sjkim} 721160814Ssimon 722160814Ssimonstatic int ipv4_from_asc(unsigned char *v4, const char *in) 723280304Sjkim{ 724280304Sjkim int a0, a1, a2, a3; 725280304Sjkim if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) 726280304Sjkim return 0; 727280304Sjkim if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) 728280304Sjkim || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) 729280304Sjkim return 0; 730280304Sjkim v4[0] = a0; 731280304Sjkim v4[1] = a1; 732280304Sjkim v4[2] = a2; 733280304Sjkim v4[3] = a3; 734280304Sjkim return 1; 735280304Sjkim} 736160814Ssimon 737160814Ssimontypedef struct { 738280304Sjkim /* Temporary store for IPV6 output */ 739280304Sjkim unsigned char tmp[16]; 740280304Sjkim /* Total number of bytes in tmp */ 741280304Sjkim int total; 742280304Sjkim /* The position of a zero (corresponding to '::') */ 743280304Sjkim int zero_pos; 744280304Sjkim /* Number of zeroes */ 745280304Sjkim int zero_cnt; 746280304Sjkim} IPV6_STAT; 747160814Ssimon 748160814Ssimonstatic int ipv6_from_asc(unsigned char *v6, const char *in) 749280304Sjkim{ 750280304Sjkim IPV6_STAT v6stat; 751280304Sjkim v6stat.total = 0; 752280304Sjkim v6stat.zero_pos = -1; 753280304Sjkim v6stat.zero_cnt = 0; 754280304Sjkim /* 755280304Sjkim * Treat the IPv6 representation as a list of values separated by ':'. 756280304Sjkim * The presence of a '::' will parse as one, two or three zero length 757280304Sjkim * elements. 758280304Sjkim */ 759280304Sjkim if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) 760280304Sjkim return 0; 761160814Ssimon 762280304Sjkim /* Now for some sanity checks */ 763160814Ssimon 764280304Sjkim if (v6stat.zero_pos == -1) { 765280304Sjkim /* If no '::' must have exactly 16 bytes */ 766280304Sjkim if (v6stat.total != 16) 767280304Sjkim return 0; 768280304Sjkim } else { 769280304Sjkim /* If '::' must have less than 16 bytes */ 770280304Sjkim if (v6stat.total == 16) 771280304Sjkim return 0; 772280304Sjkim /* More than three zeroes is an error */ 773280304Sjkim if (v6stat.zero_cnt > 3) 774280304Sjkim return 0; 775280304Sjkim /* Can only have three zeroes if nothing else present */ 776280304Sjkim else if (v6stat.zero_cnt == 3) { 777280304Sjkim if (v6stat.total > 0) 778280304Sjkim return 0; 779280304Sjkim } 780280304Sjkim /* Can only have two zeroes if at start or end */ 781280304Sjkim else if (v6stat.zero_cnt == 2) { 782280304Sjkim if ((v6stat.zero_pos != 0) 783280304Sjkim && (v6stat.zero_pos != v6stat.total)) 784280304Sjkim return 0; 785280304Sjkim } else 786280304Sjkim /* Can only have one zero if *not* start or end */ 787280304Sjkim { 788280304Sjkim if ((v6stat.zero_pos == 0) 789280304Sjkim || (v6stat.zero_pos == v6stat.total)) 790280304Sjkim return 0; 791280304Sjkim } 792280304Sjkim } 793160814Ssimon 794280304Sjkim /* Format result */ 795160814Ssimon 796280304Sjkim if (v6stat.zero_pos >= 0) { 797280304Sjkim /* Copy initial part */ 798280304Sjkim memcpy(v6, v6stat.tmp, v6stat.zero_pos); 799280304Sjkim /* Zero middle */ 800280304Sjkim memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); 801280304Sjkim /* Copy final part */ 802280304Sjkim if (v6stat.total != v6stat.zero_pos) 803280304Sjkim memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, 804280304Sjkim v6stat.tmp + v6stat.zero_pos, 805280304Sjkim v6stat.total - v6stat.zero_pos); 806280304Sjkim } else 807280304Sjkim memcpy(v6, v6stat.tmp, 16); 808160814Ssimon 809280304Sjkim return 1; 810280304Sjkim} 811160814Ssimon 812160814Ssimonstatic int ipv6_cb(const char *elem, int len, void *usr) 813280304Sjkim{ 814280304Sjkim IPV6_STAT *s = usr; 815280304Sjkim /* Error if 16 bytes written */ 816280304Sjkim if (s->total == 16) 817280304Sjkim return 0; 818280304Sjkim if (len == 0) { 819280304Sjkim /* Zero length element, corresponds to '::' */ 820280304Sjkim if (s->zero_pos == -1) 821280304Sjkim s->zero_pos = s->total; 822280304Sjkim /* If we've already got a :: its an error */ 823280304Sjkim else if (s->zero_pos != s->total) 824280304Sjkim return 0; 825280304Sjkim s->zero_cnt++; 826280304Sjkim } else { 827280304Sjkim /* If more than 4 characters could be final a.b.c.d form */ 828280304Sjkim if (len > 4) { 829280304Sjkim /* Need at least 4 bytes left */ 830280304Sjkim if (s->total > 12) 831280304Sjkim return 0; 832280304Sjkim /* Must be end of string */ 833280304Sjkim if (elem[len]) 834280304Sjkim return 0; 835280304Sjkim if (!ipv4_from_asc(s->tmp + s->total, elem)) 836280304Sjkim return 0; 837280304Sjkim s->total += 4; 838280304Sjkim } else { 839280304Sjkim if (!ipv6_hex(s->tmp + s->total, elem, len)) 840280304Sjkim return 0; 841280304Sjkim s->total += 2; 842280304Sjkim } 843280304Sjkim } 844280304Sjkim return 1; 845280304Sjkim} 846160814Ssimon 847280304Sjkim/* 848280304Sjkim * Convert a string of up to 4 hex digits into the corresponding IPv6 form. 849160814Ssimon */ 850160814Ssimon 851160814Ssimonstatic int ipv6_hex(unsigned char *out, const char *in, int inlen) 852280304Sjkim{ 853280304Sjkim unsigned char c; 854280304Sjkim unsigned int num = 0; 855280304Sjkim if (inlen > 4) 856280304Sjkim return 0; 857280304Sjkim while (inlen--) { 858280304Sjkim c = *in++; 859280304Sjkim num <<= 4; 860280304Sjkim if ((c >= '0') && (c <= '9')) 861280304Sjkim num |= c - '0'; 862280304Sjkim else if ((c >= 'A') && (c <= 'F')) 863280304Sjkim num |= c - 'A' + 10; 864280304Sjkim else if ((c >= 'a') && (c <= 'f')) 865280304Sjkim num |= c - 'a' + 10; 866280304Sjkim else 867280304Sjkim return 0; 868280304Sjkim } 869280304Sjkim out[0] = num >> 8; 870280304Sjkim out[1] = num & 0xff; 871280304Sjkim return 1; 872280304Sjkim} 873160814Ssimon 874280304Sjkimint X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk, 875280304Sjkim unsigned long chtype) 876280304Sjkim{ 877280304Sjkim CONF_VALUE *v; 878280304Sjkim int i, mval; 879280304Sjkim char *p, *type; 880280304Sjkim if (!nm) 881280304Sjkim return 0; 882160814Ssimon 883280304Sjkim for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { 884280304Sjkim v = sk_CONF_VALUE_value(dn_sk, i); 885280304Sjkim type = v->name; 886280304Sjkim /* 887280304Sjkim * Skip past any leading X. X: X, etc to allow for multiple instances 888280304Sjkim */ 889280304Sjkim for (p = type; *p; p++) 890160814Ssimon#ifndef CHARSET_EBCDIC 891280304Sjkim if ((*p == ':') || (*p == ',') || (*p == '.')) 892160814Ssimon#else 893280304Sjkim if ((*p == os_toascii[':']) || (*p == os_toascii[',']) 894280304Sjkim || (*p == os_toascii['.'])) 895160814Ssimon#endif 896280304Sjkim { 897280304Sjkim p++; 898280304Sjkim if (*p) 899280304Sjkim type = p; 900280304Sjkim break; 901280304Sjkim } 902160814Ssimon#ifndef CHARSET_EBCDIC 903280304Sjkim if (*type == '+') 904160814Ssimon#else 905280304Sjkim if (*type == os_toascii['+']) 906160814Ssimon#endif 907280304Sjkim { 908280304Sjkim mval = -1; 909280304Sjkim type++; 910280304Sjkim } else 911280304Sjkim mval = 0; 912280304Sjkim if (!X509_NAME_add_entry_by_txt(nm, type, chtype, 913280304Sjkim (unsigned char *)v->value, -1, -1, 914280304Sjkim mval)) 915280304Sjkim return 0; 916160814Ssimon 917280304Sjkim } 918280304Sjkim return 1; 919280304Sjkim} 920