v3_utl.c revision 55714
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); 68 69/* Add a CONF_VALUE name value pair to stack */ 70 71int X509V3_add_value(const char *name, const char *value, 72 STACK_OF(CONF_VALUE) **extlist) 73{ 74 CONF_VALUE *vtmp = NULL; 75 char *tname = NULL, *tvalue = NULL; 76 if(name && !(tname = BUF_strdup(name))) goto err; 77 if(value && !(tvalue = BUF_strdup(value))) goto err;; 78 if(!(vtmp = (CONF_VALUE *)Malloc(sizeof(CONF_VALUE)))) goto err; 79 if(!*extlist && !(*extlist = sk_CONF_VALUE_new(NULL))) goto err; 80 vtmp->section = NULL; 81 vtmp->name = tname; 82 vtmp->value = tvalue; 83 if(!sk_CONF_VALUE_push(*extlist, vtmp)) goto err; 84 return 1; 85 err: 86 X509V3err(X509V3_F_X509V3_ADD_VALUE,ERR_R_MALLOC_FAILURE); 87 if(vtmp) Free(vtmp); 88 if(tname) Free(tname); 89 if(tvalue) Free(tvalue); 90 return 0; 91} 92 93int X509V3_add_value_uchar(const char *name, const unsigned char *value, 94 STACK_OF(CONF_VALUE) **extlist) 95 { 96 return X509V3_add_value(name,(const char *)value,extlist); 97 } 98 99/* Free function for STACK_OF(CONF_VALUE) */ 100 101void X509V3_conf_free(CONF_VALUE *conf) 102{ 103 if(!conf) return; 104 if(conf->name) Free(conf->name); 105 if(conf->value) Free(conf->value); 106 if(conf->section) Free(conf->section); 107 Free((char *)conf); 108} 109 110int X509V3_add_value_bool(const char *name, int asn1_bool, 111 STACK_OF(CONF_VALUE) **extlist) 112{ 113 if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist); 114 return X509V3_add_value(name, "FALSE", extlist); 115} 116 117int X509V3_add_value_bool_nf(char *name, int asn1_bool, 118 STACK_OF(CONF_VALUE) **extlist) 119{ 120 if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist); 121 return 1; 122} 123 124 125char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a) 126{ 127 BIGNUM *bntmp = NULL; 128 char *strtmp = NULL; 129 if(!a) return NULL; 130 if(!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || 131 !(strtmp = BN_bn2dec(bntmp)) ) 132 X509V3err(X509V3_F_I2S_ASN1_ENUMERATED,ERR_R_MALLOC_FAILURE); 133 BN_free(bntmp); 134 return strtmp; 135} 136 137char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a) 138{ 139 BIGNUM *bntmp = NULL; 140 char *strtmp = NULL; 141 if(!a) return NULL; 142 if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || 143 !(strtmp = BN_bn2dec(bntmp)) ) 144 X509V3err(X509V3_F_I2S_ASN1_INTEGER,ERR_R_MALLOC_FAILURE); 145 BN_free(bntmp); 146 return strtmp; 147} 148 149ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) 150{ 151 BIGNUM *bn = NULL; 152 ASN1_INTEGER *aint; 153 bn = BN_new(); 154 if(!value) { 155 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE); 156 return 0; 157 } 158 if(!BN_dec2bn(&bn, value)) { 159 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR); 160 return 0; 161 } 162 163 if(!(aint = BN_to_ASN1_INTEGER(bn, NULL))) { 164 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_TO_ASN1_INTEGER_ERROR); 165 return 0; 166 } 167 BN_free(bn); 168 return aint; 169} 170 171int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, 172 STACK_OF(CONF_VALUE) **extlist) 173{ 174 char *strtmp; 175 int ret; 176 if(!aint) return 1; 177 if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0; 178 ret = X509V3_add_value(name, strtmp, extlist); 179 Free(strtmp); 180 return ret; 181} 182 183int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool) 184{ 185 char *btmp; 186 if(!(btmp = value->value)) goto err; 187 if(!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") 188 || !strcmp(btmp, "Y") || !strcmp(btmp, "y") 189 || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { 190 *asn1_bool = 0xff; 191 return 1; 192 } else if(!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") 193 || !strcmp(btmp, "N") || !strcmp(btmp, "n") 194 || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { 195 *asn1_bool = 0; 196 return 1; 197 } 198 err: 199 X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,X509V3_R_INVALID_BOOLEAN_STRING); 200 X509V3_conf_err(value); 201 return 0; 202} 203 204int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint) 205{ 206 ASN1_INTEGER *itmp; 207 if(!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { 208 X509V3_conf_err(value); 209 return 0; 210 } 211 *aint = itmp; 212 return 1; 213} 214 215#define HDR_NAME 1 216#define HDR_VALUE 2 217 218/*#define DEBUG*/ 219 220STACK_OF(CONF_VALUE) *X509V3_parse_list(char *line) 221{ 222 char *p, *q, c; 223 char *ntmp, *vtmp; 224 STACK_OF(CONF_VALUE) *values = NULL; 225 char *linebuf; 226 int state; 227 /* We are going to modify the line so copy it first */ 228 linebuf = BUF_strdup(line); 229 state = HDR_NAME; 230 ntmp = NULL; 231 /* Go through all characters */ 232 for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) { 233 234 switch(state) { 235 case HDR_NAME: 236 if(c == ':') { 237 state = HDR_VALUE; 238 *p = 0; 239 ntmp = strip_spaces(q); 240 if(!ntmp) { 241 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); 242 goto err; 243 } 244 q = p + 1; 245 } else if(c == ',') { 246 *p = 0; 247 ntmp = strip_spaces(q); 248 q = p + 1; 249#ifdef DEBUG 250 printf("%s\n", ntmp); 251#endif 252 if(!ntmp) { 253 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); 254 goto err; 255 } 256 X509V3_add_value(ntmp, NULL, &values); 257 } 258 break ; 259 260 case HDR_VALUE: 261 if(c == ',') { 262 state = HDR_NAME; 263 *p = 0; 264 vtmp = strip_spaces(q); 265#ifdef DEBUG 266 printf("%s\n", ntmp); 267#endif 268 if(!vtmp) { 269 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE); 270 goto err; 271 } 272 X509V3_add_value(ntmp, vtmp, &values); 273 ntmp = NULL; 274 q = p + 1; 275 } 276 277 } 278 } 279 280 if(state == HDR_VALUE) { 281 vtmp = strip_spaces(q); 282#ifdef DEBUG 283 printf("%s=%s\n", ntmp, vtmp); 284#endif 285 if(!vtmp) { 286 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE); 287 goto err; 288 } 289 X509V3_add_value(ntmp, vtmp, &values); 290 } else { 291 ntmp = strip_spaces(q); 292#ifdef DEBUG 293 printf("%s\n", ntmp); 294#endif 295 if(!ntmp) { 296 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); 297 goto err; 298 } 299 X509V3_add_value(ntmp, NULL, &values); 300 } 301Free(linebuf); 302return values; 303 304err: 305Free(linebuf); 306sk_CONF_VALUE_pop_free(values, X509V3_conf_free); 307return NULL; 308 309} 310 311/* Delete leading and trailing spaces from a string */ 312static char *strip_spaces(char *name) 313{ 314 char *p, *q; 315 /* Skip over leading spaces */ 316 p = name; 317 while(*p && isspace((unsigned char)*p)) p++; 318 if(!*p) return NULL; 319 q = p + strlen(p) - 1; 320 while((q != p) && isspace((unsigned char)*q)) q--; 321 if(p != q) q[1] = 0; 322 if(!*p) return NULL; 323 return p; 324} 325 326/* hex string utilities */ 327 328/* Given a buffer of length 'len' return a Malloc'ed string with its 329 * hex representation 330 */ 331 332char *hex_to_string(unsigned char *buffer, long len) 333{ 334 char *tmp, *q; 335 unsigned char *p; 336 int i; 337 static char hexdig[] = "0123456789ABCDEF"; 338 if(!buffer || !len) return NULL; 339 if(!(tmp = Malloc(len * 3 + 1))) { 340 X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE); 341 return NULL; 342 } 343 q = tmp; 344 for(i = 0, p = buffer; i < len; i++,p++) { 345 *q++ = hexdig[(*p >> 4) & 0xf]; 346 *q++ = hexdig[*p & 0xf]; 347 *q++ = ':'; 348 } 349 q[-1] = 0; 350 return tmp; 351} 352 353/* Give a string of hex digits convert to 354 * a buffer 355 */ 356 357unsigned char *string_to_hex(char *str, long *len) 358{ 359 unsigned char *hexbuf, *q; 360 unsigned char ch, cl, *p; 361 if(!str) { 362 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_INVALID_NULL_ARGUMENT); 363 return NULL; 364 } 365 if(!(hexbuf = Malloc(strlen(str) >> 1))) goto err; 366 for(p = (unsigned char *)str, q = hexbuf; *p;) { 367 ch = *p++; 368 if(ch == ':') continue; 369 cl = *p++; 370 if(!cl) { 371 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS); 372 Free(hexbuf); 373 return NULL; 374 } 375 if(isupper(ch)) ch = tolower(ch); 376 if(isupper(cl)) cl = tolower(cl); 377 378 if((ch >= '0') && (ch <= '9')) ch -= '0'; 379 else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10; 380 else goto badhex; 381 382 if((cl >= '0') && (cl <= '9')) cl -= '0'; 383 else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10; 384 else goto badhex; 385 386 *q++ = (ch << 4) | cl; 387 } 388 389 if(len) *len = q - hexbuf; 390 391 return hexbuf; 392 393 err: 394 if(hexbuf) Free(hexbuf); 395 X509V3err(X509V3_F_STRING_TO_HEX,ERR_R_MALLOC_FAILURE); 396 return NULL; 397 398 badhex: 399 Free(hexbuf); 400 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ILLEGAL_HEX_DIGIT); 401 return NULL; 402 403} 404 405/* V2I name comparison function: returns zero if 'name' matches 406 * cmp or cmp.* 407 */ 408 409int name_cmp(const char *name, const char *cmp) 410{ 411 int len, ret; 412 char c; 413 len = strlen(cmp); 414 if((ret = strncmp(name, cmp, len))) return ret; 415 c = name[len]; 416 if(!c || (c=='.')) return 0; 417 return 1; 418} 419