155714Skris/* v3_utl.c */ 2296341Sdelphij/* 3296341Sdelphij * 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 14296341Sdelphij * 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); 69296341Sdelphijstatic int sk_strcmp(const char *const *a, const char *const *b); 70296341Sdelphijstatic STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, 71296341Sdelphij 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, 83296341Sdelphij STACK_OF(CONF_VALUE) **extlist) 8455714Skris{ 85296341Sdelphij CONF_VALUE *vtmp = NULL; 86296341Sdelphij char *tname = NULL, *tvalue = NULL; 87296341Sdelphij if (name && !(tname = BUF_strdup(name))) 88296341Sdelphij goto err; 89296341Sdelphij if (value && !(tvalue = BUF_strdup(value))) 90296341Sdelphij goto err; 91296341Sdelphij if (!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) 92296341Sdelphij goto err; 93296341Sdelphij if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) 94296341Sdelphij goto err; 95296341Sdelphij vtmp->section = NULL; 96296341Sdelphij vtmp->name = tname; 97296341Sdelphij vtmp->value = tvalue; 98296341Sdelphij if (!sk_CONF_VALUE_push(*extlist, vtmp)) 99296341Sdelphij goto err; 100296341Sdelphij return 1; 101296341Sdelphij err: 102296341Sdelphij X509V3err(X509V3_F_X509V3_ADD_VALUE, ERR_R_MALLOC_FAILURE); 103296341Sdelphij if (vtmp) 104296341Sdelphij OPENSSL_free(vtmp); 105296341Sdelphij if (tname) 106296341Sdelphij OPENSSL_free(tname); 107296341Sdelphij if (tvalue) 108296341Sdelphij OPENSSL_free(tvalue); 109296341Sdelphij return 0; 11055714Skris} 11155714Skris 11255714Skrisint X509V3_add_value_uchar(const char *name, const unsigned char *value, 113296341Sdelphij STACK_OF(CONF_VALUE) **extlist) 114296341Sdelphij{ 115296341Sdelphij return X509V3_add_value(name, (const char *)value, extlist); 116296341Sdelphij} 11755714Skris 11855714Skris/* Free function for STACK_OF(CONF_VALUE) */ 11955714Skris 12055714Skrisvoid X509V3_conf_free(CONF_VALUE *conf) 12155714Skris{ 122296341Sdelphij if (!conf) 123296341Sdelphij return; 124296341Sdelphij if (conf->name) 125296341Sdelphij OPENSSL_free(conf->name); 126296341Sdelphij if (conf->value) 127296341Sdelphij OPENSSL_free(conf->value); 128296341Sdelphij if (conf->section) 129296341Sdelphij OPENSSL_free(conf->section); 130296341Sdelphij OPENSSL_free(conf); 13155714Skris} 13255714Skris 13355714Skrisint X509V3_add_value_bool(const char *name, int asn1_bool, 134296341Sdelphij STACK_OF(CONF_VALUE) **extlist) 13555714Skris{ 136296341Sdelphij if (asn1_bool) 137296341Sdelphij return X509V3_add_value(name, "TRUE", extlist); 138296341Sdelphij return X509V3_add_value(name, "FALSE", extlist); 13955714Skris} 14055714Skris 14155714Skrisint X509V3_add_value_bool_nf(char *name, int asn1_bool, 142296341Sdelphij STACK_OF(CONF_VALUE) **extlist) 14355714Skris{ 144296341Sdelphij if (asn1_bool) 145296341Sdelphij return X509V3_add_value(name, "TRUE", extlist); 146296341Sdelphij return 1; 14755714Skris} 14855714Skris 14955714Skrischar *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a) 15055714Skris{ 151296341Sdelphij BIGNUM *bntmp = NULL; 152296341Sdelphij char *strtmp = NULL; 153296341Sdelphij if (!a) 154296341Sdelphij return NULL; 155296341Sdelphij if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || 156296341Sdelphij !(strtmp = BN_bn2dec(bntmp))) 157296341Sdelphij X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE); 158296341Sdelphij BN_free(bntmp); 159296341Sdelphij return strtmp; 16055714Skris} 16155714Skris 16255714Skrischar *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a) 16355714Skris{ 164296341Sdelphij BIGNUM *bntmp = NULL; 165296341Sdelphij char *strtmp = NULL; 166296341Sdelphij if (!a) 167296341Sdelphij return NULL; 168296341Sdelphij if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || 169296341Sdelphij !(strtmp = BN_bn2dec(bntmp))) 170296341Sdelphij X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); 171296341Sdelphij BN_free(bntmp); 172296341Sdelphij return strtmp; 17355714Skris} 17455714Skris 17555714SkrisASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) 17655714Skris{ 177296341Sdelphij BIGNUM *bn = NULL; 178296341Sdelphij ASN1_INTEGER *aint; 179296341Sdelphij int isneg, ishex; 180296341Sdelphij int ret; 181296341Sdelphij if (!value) { 182296341Sdelphij X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE); 183296341Sdelphij return 0; 184296341Sdelphij } 185296341Sdelphij bn = BN_new(); 186296341Sdelphij if (value[0] == '-') { 187296341Sdelphij value++; 188296341Sdelphij isneg = 1; 189296341Sdelphij } else 190296341Sdelphij isneg = 0; 191109998Smarkm 192296341Sdelphij if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) { 193296341Sdelphij value += 2; 194296341Sdelphij ishex = 1; 195296341Sdelphij } else 196296341Sdelphij ishex = 0; 197109998Smarkm 198296341Sdelphij if (ishex) 199296341Sdelphij ret = BN_hex2bn(&bn, value); 200296341Sdelphij else 201296341Sdelphij ret = BN_dec2bn(&bn, value); 202109998Smarkm 203296341Sdelphij if (!ret || value[ret]) { 204296341Sdelphij BN_free(bn); 205296341Sdelphij X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR); 206296341Sdelphij return 0; 207296341Sdelphij } 20855714Skris 209296341Sdelphij if (isneg && BN_is_zero(bn)) 210296341Sdelphij isneg = 0; 211109998Smarkm 212296341Sdelphij aint = BN_to_ASN1_INTEGER(bn, NULL); 213296341Sdelphij BN_free(bn); 214296341Sdelphij if (!aint) { 215296341Sdelphij X509V3err(X509V3_F_S2I_ASN1_INTEGER, 216296341Sdelphij X509V3_R_BN_TO_ASN1_INTEGER_ERROR); 217296341Sdelphij return 0; 218296341Sdelphij } 219296341Sdelphij if (isneg) 220296341Sdelphij aint->type |= V_ASN1_NEG; 221296341Sdelphij return aint; 22255714Skris} 22355714Skris 22455714Skrisint X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, 225296341Sdelphij STACK_OF(CONF_VALUE) **extlist) 22655714Skris{ 227296341Sdelphij char *strtmp; 228296341Sdelphij int ret; 229296341Sdelphij if (!aint) 230296341Sdelphij return 1; 231296341Sdelphij if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) 232296341Sdelphij return 0; 233296341Sdelphij ret = X509V3_add_value(name, strtmp, extlist); 234296341Sdelphij OPENSSL_free(strtmp); 235296341Sdelphij return ret; 23655714Skris} 23755714Skris 23855714Skrisint X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool) 23955714Skris{ 240296341Sdelphij char *btmp; 241296341Sdelphij if (!(btmp = value->value)) 242296341Sdelphij goto err; 243296341Sdelphij if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") 244296341Sdelphij || !strcmp(btmp, "Y") || !strcmp(btmp, "y") 245296341Sdelphij || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { 246296341Sdelphij *asn1_bool = 0xff; 247296341Sdelphij return 1; 248296341Sdelphij } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") 249296341Sdelphij || !strcmp(btmp, "N") || !strcmp(btmp, "n") 250296341Sdelphij || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { 251296341Sdelphij *asn1_bool = 0; 252296341Sdelphij return 1; 253296341Sdelphij } 254296341Sdelphij err: 255296341Sdelphij X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL, 256296341Sdelphij X509V3_R_INVALID_BOOLEAN_STRING); 257296341Sdelphij X509V3_conf_err(value); 258296341Sdelphij return 0; 25955714Skris} 26055714Skris 26155714Skrisint X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint) 26255714Skris{ 263296341Sdelphij ASN1_INTEGER *itmp; 264296341Sdelphij if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { 265296341Sdelphij X509V3_conf_err(value); 266296341Sdelphij return 0; 267296341Sdelphij } 268296341Sdelphij *aint = itmp; 269296341Sdelphij return 1; 27055714Skris} 27155714Skris 272296341Sdelphij#define HDR_NAME 1 273296341Sdelphij#define HDR_VALUE 2 27455714Skris 275296341Sdelphij/* 276296341Sdelphij * #define DEBUG 277296341Sdelphij */ 27855714Skris 279109998SmarkmSTACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) 28055714Skris{ 281296341Sdelphij char *p, *q, c; 282296341Sdelphij char *ntmp, *vtmp; 283296341Sdelphij STACK_OF(CONF_VALUE) *values = NULL; 284296341Sdelphij char *linebuf; 285296341Sdelphij int state; 286296341Sdelphij /* We are going to modify the line so copy it first */ 287296341Sdelphij linebuf = BUF_strdup(line); 288296341Sdelphij if (linebuf == NULL) { 289296341Sdelphij X509V3err(X509V3_F_X509V3_PARSE_LIST, ERR_R_MALLOC_FAILURE); 290296341Sdelphij goto err; 291296341Sdelphij } 292296341Sdelphij state = HDR_NAME; 293296341Sdelphij ntmp = NULL; 294296341Sdelphij /* Go through all characters */ 295296341Sdelphij for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); 296296341Sdelphij p++) { 29755714Skris 298296341Sdelphij switch (state) { 299296341Sdelphij case HDR_NAME: 300296341Sdelphij if (c == ':') { 301296341Sdelphij state = HDR_VALUE; 302296341Sdelphij *p = 0; 303296341Sdelphij ntmp = strip_spaces(q); 304296341Sdelphij if (!ntmp) { 305296341Sdelphij X509V3err(X509V3_F_X509V3_PARSE_LIST, 306296341Sdelphij X509V3_R_INVALID_NULL_NAME); 307296341Sdelphij goto err; 308296341Sdelphij } 309296341Sdelphij q = p + 1; 310296341Sdelphij } else if (c == ',') { 311296341Sdelphij *p = 0; 312296341Sdelphij ntmp = strip_spaces(q); 313296341Sdelphij q = p + 1; 314100928Snectar#if 0 315296341Sdelphij printf("%s\n", ntmp); 31655714Skris#endif 317296341Sdelphij if (!ntmp) { 318296341Sdelphij X509V3err(X509V3_F_X509V3_PARSE_LIST, 319296341Sdelphij X509V3_R_INVALID_NULL_NAME); 320296341Sdelphij goto err; 321296341Sdelphij } 322296341Sdelphij X509V3_add_value(ntmp, NULL, &values); 323296341Sdelphij } 324296341Sdelphij break; 32555714Skris 326296341Sdelphij case HDR_VALUE: 327296341Sdelphij if (c == ',') { 328296341Sdelphij state = HDR_NAME; 329296341Sdelphij *p = 0; 330296341Sdelphij vtmp = strip_spaces(q); 331100928Snectar#if 0 332296341Sdelphij printf("%s\n", ntmp); 33355714Skris#endif 334296341Sdelphij if (!vtmp) { 335296341Sdelphij X509V3err(X509V3_F_X509V3_PARSE_LIST, 336296341Sdelphij X509V3_R_INVALID_NULL_VALUE); 337296341Sdelphij goto err; 338296341Sdelphij } 339296341Sdelphij X509V3_add_value(ntmp, vtmp, &values); 340296341Sdelphij ntmp = NULL; 341296341Sdelphij q = p + 1; 342296341Sdelphij } 34355714Skris 344296341Sdelphij } 345296341Sdelphij } 34655714Skris 347296341Sdelphij if (state == HDR_VALUE) { 348296341Sdelphij vtmp = strip_spaces(q); 349100928Snectar#if 0 350296341Sdelphij printf("%s=%s\n", ntmp, vtmp); 35155714Skris#endif 352296341Sdelphij if (!vtmp) { 353296341Sdelphij X509V3err(X509V3_F_X509V3_PARSE_LIST, 354296341Sdelphij X509V3_R_INVALID_NULL_VALUE); 355296341Sdelphij goto err; 356296341Sdelphij } 357296341Sdelphij X509V3_add_value(ntmp, vtmp, &values); 358296341Sdelphij } else { 359296341Sdelphij ntmp = strip_spaces(q); 360100928Snectar#if 0 361296341Sdelphij printf("%s\n", ntmp); 36255714Skris#endif 363296341Sdelphij if (!ntmp) { 364296341Sdelphij X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); 365296341Sdelphij goto err; 366296341Sdelphij } 367296341Sdelphij X509V3_add_value(ntmp, NULL, &values); 368296341Sdelphij } 369296341Sdelphij OPENSSL_free(linebuf); 370296341Sdelphij return values; 37155714Skris 372296341Sdelphij err: 373296341Sdelphij OPENSSL_free(linebuf); 374296341Sdelphij sk_CONF_VALUE_pop_free(values, X509V3_conf_free); 375296341Sdelphij return NULL; 37655714Skris 37755714Skris} 37855714Skris 37955714Skris/* Delete leading and trailing spaces from a string */ 38055714Skrisstatic char *strip_spaces(char *name) 38155714Skris{ 382296341Sdelphij char *p, *q; 383296341Sdelphij /* Skip over leading spaces */ 384296341Sdelphij p = name; 385296341Sdelphij while (*p && isspace((unsigned char)*p)) 386296341Sdelphij p++; 387296341Sdelphij if (!*p) 388296341Sdelphij return NULL; 389296341Sdelphij q = p + strlen(p) - 1; 390296341Sdelphij while ((q != p) && isspace((unsigned char)*q)) 391296341Sdelphij q--; 392296341Sdelphij if (p != q) 393296341Sdelphij q[1] = 0; 394296341Sdelphij if (!*p) 395296341Sdelphij return NULL; 396296341Sdelphij return p; 39755714Skris} 39855714Skris 39955714Skris/* hex string utilities */ 40055714Skris 401296341Sdelphij/* 402296341Sdelphij * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its 403296341Sdelphij * hex representation @@@ (Contents of buffer are always kept in ASCII, also 404296341Sdelphij * on EBCDIC machines) 40555714Skris */ 40655714Skris 407238405Sjkimchar *hex_to_string(const unsigned char *buffer, long len) 40855714Skris{ 409296341Sdelphij char *tmp, *q; 410296341Sdelphij const unsigned char *p; 411296341Sdelphij int i; 412296341Sdelphij const static char hexdig[] = "0123456789ABCDEF"; 413296341Sdelphij if (!buffer || !len) 414296341Sdelphij return NULL; 415296341Sdelphij if (!(tmp = OPENSSL_malloc(len * 3 + 1))) { 416296341Sdelphij X509V3err(X509V3_F_HEX_TO_STRING, ERR_R_MALLOC_FAILURE); 417296341Sdelphij return NULL; 418296341Sdelphij } 419296341Sdelphij q = tmp; 420296341Sdelphij for (i = 0, p = buffer; i < len; i++, p++) { 421296341Sdelphij *q++ = hexdig[(*p >> 4) & 0xf]; 422296341Sdelphij *q++ = hexdig[*p & 0xf]; 423296341Sdelphij *q++ = ':'; 424296341Sdelphij } 425296341Sdelphij q[-1] = 0; 42668651Skris#ifdef CHARSET_EBCDIC 427296341Sdelphij ebcdic2ascii(tmp, tmp, q - tmp - 1); 42868651Skris#endif 42968651Skris 430296341Sdelphij return tmp; 43155714Skris} 43255714Skris 433296341Sdelphij/* 434296341Sdelphij * Give a string of hex digits convert to a buffer 43555714Skris */ 43655714Skris 437238405Sjkimunsigned char *string_to_hex(const char *str, long *len) 43855714Skris{ 439296341Sdelphij unsigned char *hexbuf, *q; 440296341Sdelphij unsigned char ch, cl, *p; 441296341Sdelphij if (!str) { 442296341Sdelphij X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_INVALID_NULL_ARGUMENT); 443296341Sdelphij return NULL; 444296341Sdelphij } 445296341Sdelphij if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) 446296341Sdelphij goto err; 447296341Sdelphij for (p = (unsigned char *)str, q = hexbuf; *p;) { 448296341Sdelphij ch = *p++; 44968651Skris#ifdef CHARSET_EBCDIC 450296341Sdelphij ch = os_toebcdic[ch]; 45168651Skris#endif 452296341Sdelphij if (ch == ':') 453296341Sdelphij continue; 454296341Sdelphij cl = *p++; 45568651Skris#ifdef CHARSET_EBCDIC 456296341Sdelphij cl = os_toebcdic[cl]; 45768651Skris#endif 458296341Sdelphij if (!cl) { 459296341Sdelphij X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ODD_NUMBER_OF_DIGITS); 460296341Sdelphij OPENSSL_free(hexbuf); 461296341Sdelphij return NULL; 462296341Sdelphij } 463296341Sdelphij if (isupper(ch)) 464296341Sdelphij ch = tolower(ch); 465296341Sdelphij if (isupper(cl)) 466296341Sdelphij cl = tolower(cl); 46755714Skris 468296341Sdelphij if ((ch >= '0') && (ch <= '9')) 469296341Sdelphij ch -= '0'; 470296341Sdelphij else if ((ch >= 'a') && (ch <= 'f')) 471296341Sdelphij ch -= 'a' - 10; 472296341Sdelphij else 473296341Sdelphij goto badhex; 47455714Skris 475296341Sdelphij if ((cl >= '0') && (cl <= '9')) 476296341Sdelphij cl -= '0'; 477296341Sdelphij else if ((cl >= 'a') && (cl <= 'f')) 478296341Sdelphij cl -= 'a' - 10; 479296341Sdelphij else 480296341Sdelphij goto badhex; 48155714Skris 482296341Sdelphij *q++ = (ch << 4) | cl; 483296341Sdelphij } 48455714Skris 485296341Sdelphij if (len) 486296341Sdelphij *len = q - hexbuf; 48755714Skris 488296341Sdelphij return hexbuf; 48955714Skris 490296341Sdelphij err: 491296341Sdelphij if (hexbuf) 492296341Sdelphij OPENSSL_free(hexbuf); 493296341Sdelphij X509V3err(X509V3_F_STRING_TO_HEX, ERR_R_MALLOC_FAILURE); 494296341Sdelphij return NULL; 49555714Skris 496296341Sdelphij badhex: 497296341Sdelphij OPENSSL_free(hexbuf); 498296341Sdelphij X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ILLEGAL_HEX_DIGIT); 499296341Sdelphij return NULL; 50055714Skris 50155714Skris} 50255714Skris 503296341Sdelphij/* 504296341Sdelphij * V2I name comparison function: returns zero if 'name' matches cmp or cmp.* 50555714Skris */ 50655714Skris 50755714Skrisint name_cmp(const char *name, const char *cmp) 50855714Skris{ 509296341Sdelphij int len, ret; 510296341Sdelphij char c; 511296341Sdelphij len = strlen(cmp); 512296341Sdelphij if ((ret = strncmp(name, cmp, len))) 513296341Sdelphij return ret; 514296341Sdelphij c = name[len]; 515296341Sdelphij if (!c || (c == '.')) 516296341Sdelphij return 0; 517296341Sdelphij return 1; 51855714Skris} 51968651Skris 520296341Sdelphijstatic int sk_strcmp(const char *const *a, const char *const *b) 52168651Skris{ 522296341Sdelphij return strcmp(*a, *b); 52368651Skris} 52468651Skris 525238405SjkimSTACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x) 52668651Skris{ 527296341Sdelphij GENERAL_NAMES *gens; 528296341Sdelphij STACK_OF(OPENSSL_STRING) *ret; 529238405Sjkim 530296341Sdelphij gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 531296341Sdelphij ret = get_email(X509_get_subject_name(x), gens); 532296341Sdelphij sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 533296341Sdelphij return ret; 53468651Skris} 53568651Skris 536238405SjkimSTACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x) 537194206Ssimon{ 538296341Sdelphij AUTHORITY_INFO_ACCESS *info; 539296341Sdelphij STACK_OF(OPENSSL_STRING) *ret = NULL; 540296341Sdelphij int i; 541238405Sjkim 542296341Sdelphij info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); 543296341Sdelphij if (!info) 544296341Sdelphij return NULL; 545296341Sdelphij for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { 546296341Sdelphij ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); 547296341Sdelphij if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { 548296341Sdelphij if (ad->location->type == GEN_URI) { 549296341Sdelphij if (!append_ia5 550296341Sdelphij (&ret, ad->location->d.uniformResourceIdentifier)) 551296341Sdelphij break; 552296341Sdelphij } 553296341Sdelphij } 554296341Sdelphij } 555296341Sdelphij AUTHORITY_INFO_ACCESS_free(info); 556296341Sdelphij return ret; 557194206Ssimon} 558194206Ssimon 559238405SjkimSTACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x) 56068651Skris{ 561296341Sdelphij GENERAL_NAMES *gens; 562296341Sdelphij STACK_OF(X509_EXTENSION) *exts; 563296341Sdelphij STACK_OF(OPENSSL_STRING) *ret; 564238405Sjkim 565296341Sdelphij exts = X509_REQ_get_extensions(x); 566296341Sdelphij gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); 567296341Sdelphij ret = get_email(X509_REQ_get_subject_name(x), gens); 568296341Sdelphij sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 569296341Sdelphij sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 570296341Sdelphij return ret; 57168651Skris} 57268651Skris 573296341Sdelphijstatic STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, 574296341Sdelphij GENERAL_NAMES *gens) 57568651Skris{ 576296341Sdelphij STACK_OF(OPENSSL_STRING) *ret = NULL; 577296341Sdelphij X509_NAME_ENTRY *ne; 578296341Sdelphij ASN1_IA5STRING *email; 579296341Sdelphij GENERAL_NAME *gen; 580296341Sdelphij int i; 581296341Sdelphij /* Now add any email address(es) to STACK */ 582296341Sdelphij i = -1; 583296341Sdelphij /* First supplied X509_NAME */ 584296341Sdelphij while ((i = X509_NAME_get_index_by_NID(name, 585296341Sdelphij NID_pkcs9_emailAddress, i)) >= 0) { 586296341Sdelphij ne = X509_NAME_get_entry(name, i); 587296341Sdelphij email = X509_NAME_ENTRY_get_data(ne); 588296341Sdelphij if (!append_ia5(&ret, email)) 589296341Sdelphij return NULL; 590296341Sdelphij } 591296341Sdelphij for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 592296341Sdelphij gen = sk_GENERAL_NAME_value(gens, i); 593296341Sdelphij if (gen->type != GEN_EMAIL) 594296341Sdelphij continue; 595296341Sdelphij if (!append_ia5(&ret, gen->d.ia5)) 596296341Sdelphij return NULL; 597296341Sdelphij } 598296341Sdelphij return ret; 59968651Skris} 60068651Skris 601238405Sjkimstatic void str_free(OPENSSL_STRING str) 60268651Skris{ 603296341Sdelphij OPENSSL_free(str); 60468651Skris} 60568651Skris 606238405Sjkimstatic int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) 60768651Skris{ 608296341Sdelphij char *emtmp; 609296341Sdelphij /* First some sanity checks */ 610296341Sdelphij if (email->type != V_ASN1_IA5STRING) 611296341Sdelphij return 1; 612296341Sdelphij if (!email->data || !email->length) 613296341Sdelphij return 1; 614296341Sdelphij if (!*sk) 615296341Sdelphij *sk = sk_OPENSSL_STRING_new(sk_strcmp); 616296341Sdelphij if (!*sk) 617296341Sdelphij return 0; 618296341Sdelphij /* Don't add duplicates */ 619296341Sdelphij if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1) 620296341Sdelphij return 1; 621296341Sdelphij emtmp = BUF_strdup((char *)email->data); 622296341Sdelphij if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) { 623296341Sdelphij X509_email_free(*sk); 624296341Sdelphij *sk = NULL; 625296341Sdelphij return 0; 626296341Sdelphij } 627296341Sdelphij return 1; 62868651Skris} 62968651Skris 630238405Sjkimvoid X509_email_free(STACK_OF(OPENSSL_STRING) *sk) 63168651Skris{ 632296341Sdelphij sk_OPENSSL_STRING_pop_free(sk, str_free); 63368651Skris} 634160814Ssimon 635296341Sdelphij/* 636296341Sdelphij * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible 637296341Sdelphij * with RFC3280. 638160814Ssimon */ 639160814Ssimon 640160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) 641296341Sdelphij{ 642296341Sdelphij unsigned char ipout[16]; 643296341Sdelphij ASN1_OCTET_STRING *ret; 644296341Sdelphij int iplen; 645160814Ssimon 646296341Sdelphij /* If string contains a ':' assume IPv6 */ 647160814Ssimon 648296341Sdelphij iplen = a2i_ipadd(ipout, ipasc); 649160814Ssimon 650296341Sdelphij if (!iplen) 651296341Sdelphij return NULL; 652160814Ssimon 653296341Sdelphij ret = ASN1_OCTET_STRING_new(); 654296341Sdelphij if (!ret) 655296341Sdelphij return NULL; 656296341Sdelphij if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { 657296341Sdelphij ASN1_OCTET_STRING_free(ret); 658296341Sdelphij return NULL; 659296341Sdelphij } 660296341Sdelphij return ret; 661296341Sdelphij} 662160814Ssimon 663160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc) 664296341Sdelphij{ 665296341Sdelphij ASN1_OCTET_STRING *ret = NULL; 666296341Sdelphij unsigned char ipout[32]; 667296341Sdelphij char *iptmp = NULL, *p; 668296341Sdelphij int iplen1, iplen2; 669296341Sdelphij p = strchr(ipasc, '/'); 670296341Sdelphij if (!p) 671296341Sdelphij return NULL; 672296341Sdelphij iptmp = BUF_strdup(ipasc); 673296341Sdelphij if (!iptmp) 674296341Sdelphij return NULL; 675296341Sdelphij p = iptmp + (p - ipasc); 676296341Sdelphij *p++ = 0; 677160814Ssimon 678296341Sdelphij iplen1 = a2i_ipadd(ipout, iptmp); 679160814Ssimon 680296341Sdelphij if (!iplen1) 681296341Sdelphij goto err; 682160814Ssimon 683296341Sdelphij iplen2 = a2i_ipadd(ipout + iplen1, p); 684160814Ssimon 685296341Sdelphij OPENSSL_free(iptmp); 686296341Sdelphij iptmp = NULL; 687160814Ssimon 688296341Sdelphij if (!iplen2 || (iplen1 != iplen2)) 689296341Sdelphij goto err; 690160814Ssimon 691296341Sdelphij ret = ASN1_OCTET_STRING_new(); 692296341Sdelphij if (!ret) 693296341Sdelphij goto err; 694296341Sdelphij if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) 695296341Sdelphij goto err; 696160814Ssimon 697296341Sdelphij return ret; 698160814Ssimon 699296341Sdelphij err: 700296341Sdelphij if (iptmp) 701296341Sdelphij OPENSSL_free(iptmp); 702296341Sdelphij if (ret) 703296341Sdelphij ASN1_OCTET_STRING_free(ret); 704296341Sdelphij return NULL; 705296341Sdelphij} 706160814Ssimon 707167612Ssimonint a2i_ipadd(unsigned char *ipout, const char *ipasc) 708296341Sdelphij{ 709296341Sdelphij /* If string contains a ':' assume IPv6 */ 710160814Ssimon 711296341Sdelphij if (strchr(ipasc, ':')) { 712296341Sdelphij if (!ipv6_from_asc(ipout, ipasc)) 713296341Sdelphij return 0; 714296341Sdelphij return 16; 715296341Sdelphij } else { 716296341Sdelphij if (!ipv4_from_asc(ipout, ipasc)) 717296341Sdelphij return 0; 718296341Sdelphij return 4; 719296341Sdelphij } 720296341Sdelphij} 721160814Ssimon 722160814Ssimonstatic int ipv4_from_asc(unsigned char *v4, const char *in) 723296341Sdelphij{ 724296341Sdelphij int a0, a1, a2, a3; 725296341Sdelphij if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) 726296341Sdelphij return 0; 727296341Sdelphij if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) 728296341Sdelphij || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) 729296341Sdelphij return 0; 730296341Sdelphij v4[0] = a0; 731296341Sdelphij v4[1] = a1; 732296341Sdelphij v4[2] = a2; 733296341Sdelphij v4[3] = a3; 734296341Sdelphij return 1; 735296341Sdelphij} 736160814Ssimon 737160814Ssimontypedef struct { 738296341Sdelphij /* Temporary store for IPV6 output */ 739296341Sdelphij unsigned char tmp[16]; 740296341Sdelphij /* Total number of bytes in tmp */ 741296341Sdelphij int total; 742296341Sdelphij /* The position of a zero (corresponding to '::') */ 743296341Sdelphij int zero_pos; 744296341Sdelphij /* Number of zeroes */ 745296341Sdelphij int zero_cnt; 746296341Sdelphij} IPV6_STAT; 747160814Ssimon 748160814Ssimonstatic int ipv6_from_asc(unsigned char *v6, const char *in) 749296341Sdelphij{ 750296341Sdelphij IPV6_STAT v6stat; 751296341Sdelphij v6stat.total = 0; 752296341Sdelphij v6stat.zero_pos = -1; 753296341Sdelphij v6stat.zero_cnt = 0; 754296341Sdelphij /* 755296341Sdelphij * Treat the IPv6 representation as a list of values separated by ':'. 756296341Sdelphij * The presence of a '::' will parse as one, two or three zero length 757296341Sdelphij * elements. 758296341Sdelphij */ 759296341Sdelphij if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) 760296341Sdelphij return 0; 761160814Ssimon 762296341Sdelphij /* Now for some sanity checks */ 763160814Ssimon 764296341Sdelphij if (v6stat.zero_pos == -1) { 765296341Sdelphij /* If no '::' must have exactly 16 bytes */ 766296341Sdelphij if (v6stat.total != 16) 767296341Sdelphij return 0; 768296341Sdelphij } else { 769296341Sdelphij /* If '::' must have less than 16 bytes */ 770296341Sdelphij if (v6stat.total == 16) 771296341Sdelphij return 0; 772296341Sdelphij /* More than three zeroes is an error */ 773296341Sdelphij if (v6stat.zero_cnt > 3) 774296341Sdelphij return 0; 775296341Sdelphij /* Can only have three zeroes if nothing else present */ 776296341Sdelphij else if (v6stat.zero_cnt == 3) { 777296341Sdelphij if (v6stat.total > 0) 778296341Sdelphij return 0; 779296341Sdelphij } 780296341Sdelphij /* Can only have two zeroes if at start or end */ 781296341Sdelphij else if (v6stat.zero_cnt == 2) { 782296341Sdelphij if ((v6stat.zero_pos != 0) 783296341Sdelphij && (v6stat.zero_pos != v6stat.total)) 784296341Sdelphij return 0; 785296341Sdelphij } else 786296341Sdelphij /* Can only have one zero if *not* start or end */ 787296341Sdelphij { 788296341Sdelphij if ((v6stat.zero_pos == 0) 789296341Sdelphij || (v6stat.zero_pos == v6stat.total)) 790296341Sdelphij return 0; 791296341Sdelphij } 792296341Sdelphij } 793160814Ssimon 794296341Sdelphij /* Format result */ 795160814Ssimon 796296341Sdelphij if (v6stat.zero_pos >= 0) { 797296341Sdelphij /* Copy initial part */ 798296341Sdelphij memcpy(v6, v6stat.tmp, v6stat.zero_pos); 799296341Sdelphij /* Zero middle */ 800296341Sdelphij memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); 801296341Sdelphij /* Copy final part */ 802296341Sdelphij if (v6stat.total != v6stat.zero_pos) 803296341Sdelphij memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, 804296341Sdelphij v6stat.tmp + v6stat.zero_pos, 805296341Sdelphij v6stat.total - v6stat.zero_pos); 806296341Sdelphij } else 807296341Sdelphij memcpy(v6, v6stat.tmp, 16); 808160814Ssimon 809296341Sdelphij return 1; 810296341Sdelphij} 811160814Ssimon 812160814Ssimonstatic int ipv6_cb(const char *elem, int len, void *usr) 813296341Sdelphij{ 814296341Sdelphij IPV6_STAT *s = usr; 815296341Sdelphij /* Error if 16 bytes written */ 816296341Sdelphij if (s->total == 16) 817296341Sdelphij return 0; 818296341Sdelphij if (len == 0) { 819296341Sdelphij /* Zero length element, corresponds to '::' */ 820296341Sdelphij if (s->zero_pos == -1) 821296341Sdelphij s->zero_pos = s->total; 822296341Sdelphij /* If we've already got a :: its an error */ 823296341Sdelphij else if (s->zero_pos != s->total) 824296341Sdelphij return 0; 825296341Sdelphij s->zero_cnt++; 826296341Sdelphij } else { 827296341Sdelphij /* If more than 4 characters could be final a.b.c.d form */ 828296341Sdelphij if (len > 4) { 829296341Sdelphij /* Need at least 4 bytes left */ 830296341Sdelphij if (s->total > 12) 831296341Sdelphij return 0; 832296341Sdelphij /* Must be end of string */ 833296341Sdelphij if (elem[len]) 834296341Sdelphij return 0; 835296341Sdelphij if (!ipv4_from_asc(s->tmp + s->total, elem)) 836296341Sdelphij return 0; 837296341Sdelphij s->total += 4; 838296341Sdelphij } else { 839296341Sdelphij if (!ipv6_hex(s->tmp + s->total, elem, len)) 840296341Sdelphij return 0; 841296341Sdelphij s->total += 2; 842296341Sdelphij } 843296341Sdelphij } 844296341Sdelphij return 1; 845296341Sdelphij} 846160814Ssimon 847296341Sdelphij/* 848296341Sdelphij * 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) 852296341Sdelphij{ 853296341Sdelphij unsigned char c; 854296341Sdelphij unsigned int num = 0; 855296341Sdelphij if (inlen > 4) 856296341Sdelphij return 0; 857296341Sdelphij while (inlen--) { 858296341Sdelphij c = *in++; 859296341Sdelphij num <<= 4; 860296341Sdelphij if ((c >= '0') && (c <= '9')) 861296341Sdelphij num |= c - '0'; 862296341Sdelphij else if ((c >= 'A') && (c <= 'F')) 863296341Sdelphij num |= c - 'A' + 10; 864296341Sdelphij else if ((c >= 'a') && (c <= 'f')) 865296341Sdelphij num |= c - 'a' + 10; 866296341Sdelphij else 867296341Sdelphij return 0; 868296341Sdelphij } 869296341Sdelphij out[0] = num >> 8; 870296341Sdelphij out[1] = num & 0xff; 871296341Sdelphij return 1; 872296341Sdelphij} 873160814Ssimon 874296341Sdelphijint X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk, 875296341Sdelphij unsigned long chtype) 876296341Sdelphij{ 877296341Sdelphij CONF_VALUE *v; 878296341Sdelphij int i, mval; 879296341Sdelphij char *p, *type; 880296341Sdelphij if (!nm) 881296341Sdelphij return 0; 882160814Ssimon 883296341Sdelphij for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { 884296341Sdelphij v = sk_CONF_VALUE_value(dn_sk, i); 885296341Sdelphij type = v->name; 886296341Sdelphij /* 887296341Sdelphij * Skip past any leading X. X: X, etc to allow for multiple instances 888296341Sdelphij */ 889296341Sdelphij for (p = type; *p; p++) 890160814Ssimon#ifndef CHARSET_EBCDIC 891296341Sdelphij if ((*p == ':') || (*p == ',') || (*p == '.')) 892160814Ssimon#else 893296341Sdelphij if ((*p == os_toascii[':']) || (*p == os_toascii[',']) 894296341Sdelphij || (*p == os_toascii['.'])) 895160814Ssimon#endif 896296341Sdelphij { 897296341Sdelphij p++; 898296341Sdelphij if (*p) 899296341Sdelphij type = p; 900296341Sdelphij break; 901296341Sdelphij } 902160814Ssimon#ifndef CHARSET_EBCDIC 903296341Sdelphij if (*type == '+') 904160814Ssimon#else 905296341Sdelphij if (*type == os_toascii['+']) 906160814Ssimon#endif 907296341Sdelphij { 908296341Sdelphij mval = -1; 909296341Sdelphij type++; 910296341Sdelphij } else 911296341Sdelphij mval = 0; 912296341Sdelphij if (!X509_NAME_add_entry_by_txt(nm, type, chtype, 913296341Sdelphij (unsigned char *)v->value, -1, -1, 914296341Sdelphij mval)) 915296341Sdelphij return 0; 916160814Ssimon 917296341Sdelphij } 918296341Sdelphij return 1; 919296341Sdelphij} 920