1 /* $OpenBSD: x509name.c,v 1.35 2023/05/29 11:54:50 beck Exp $ */ 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59 #include <stdio.h> 60 #include <string.h> 61 62 #include <openssl/asn1.h> 63 #include <openssl/err.h> 64 #include <openssl/evp.h> 65 #include <openssl/objects.h> 66 #include <openssl/stack.h> 67 #include <openssl/x509.h> 68 69 #include "bytestring.h" 70 #include "x509_local.h" 71 72 int 73 X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len) 74 { 75 ASN1_OBJECT *obj; 76 77 obj = OBJ_nid2obj(nid); 78 if (obj == NULL) 79 return (-1); 80 return (X509_NAME_get_text_by_OBJ(name, obj, buf, len)); 81 } 82 LCRYPTO_ALIAS(X509_NAME_get_text_by_NID); 83 84 int 85 X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, char *buf, 86 int len) 87 { 88 unsigned char *text = NULL; 89 ASN1_STRING *data; 90 int i, text_len; 91 int ret = -1; 92 CBS cbs; 93 94 i = X509_NAME_get_index_by_OBJ(name, obj, -1); 95 if (i < 0) 96 goto err; 97 data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); 98 /* 99 * Fail if we cannot encode as UTF-8, or if the UTF-8 encoding of the 100 * string contains a 0 byte, because mortal callers seldom handle the 101 * length difference correctly. 102 */ 103 if ((text_len = ASN1_STRING_to_UTF8(&text, data)) < 0) 104 goto err; 105 CBS_init(&cbs, text, text_len); 106 if (CBS_contains_zero_byte(&cbs)) 107 goto err; 108 /* We still support the "pass NULL to find out how much" API */ 109 if (buf != NULL) { 110 if (len <= 0 || !CBS_write_bytes(&cbs, buf, len - 1, NULL)) 111 goto err; 112 /* It must be a C string */ 113 buf[text_len] = '\0'; 114 } 115 ret = text_len; 116 117 err: 118 free(text); 119 return (ret); 120 } 121 LCRYPTO_ALIAS(X509_NAME_get_text_by_OBJ); 122 123 int 124 X509_NAME_entry_count(const X509_NAME *name) 125 { 126 if (name == NULL) 127 return (0); 128 return (sk_X509_NAME_ENTRY_num(name->entries)); 129 } 130 LCRYPTO_ALIAS(X509_NAME_entry_count); 131 132 int 133 X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos) 134 { 135 ASN1_OBJECT *obj; 136 137 obj = OBJ_nid2obj(nid); 138 if (obj == NULL) 139 return (-2); 140 return (X509_NAME_get_index_by_OBJ(name, obj, lastpos)); 141 } 142 LCRYPTO_ALIAS(X509_NAME_get_index_by_NID); 143 144 /* NOTE: you should be passing -1, not 0 as lastpos */ 145 int 146 X509_NAME_get_index_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj, 147 int lastpos) 148 { 149 int n; 150 X509_NAME_ENTRY *ne; 151 STACK_OF(X509_NAME_ENTRY) *sk; 152 153 if (name == NULL) 154 return (-1); 155 if (lastpos < 0) 156 lastpos = -1; 157 sk = name->entries; 158 n = sk_X509_NAME_ENTRY_num(sk); 159 for (lastpos++; lastpos < n; lastpos++) { 160 ne = sk_X509_NAME_ENTRY_value(sk, lastpos); 161 if (OBJ_cmp(ne->object, obj) == 0) 162 return (lastpos); 163 } 164 return (-1); 165 } 166 LCRYPTO_ALIAS(X509_NAME_get_index_by_OBJ); 167 168 X509_NAME_ENTRY * 169 X509_NAME_get_entry(const X509_NAME *name, int loc) 170 { 171 if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc || 172 loc < 0) 173 return (NULL); 174 else 175 return (sk_X509_NAME_ENTRY_value(name->entries, loc)); 176 } 177 LCRYPTO_ALIAS(X509_NAME_get_entry); 178 179 X509_NAME_ENTRY * 180 X509_NAME_delete_entry(X509_NAME *name, int loc) 181 { 182 X509_NAME_ENTRY *ret; 183 int i, n, set_prev, set_next; 184 STACK_OF(X509_NAME_ENTRY) *sk; 185 186 if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc || 187 loc < 0) 188 return (NULL); 189 sk = name->entries; 190 ret = sk_X509_NAME_ENTRY_delete(sk, loc); 191 n = sk_X509_NAME_ENTRY_num(sk); 192 name->modified = 1; 193 if (loc == n) 194 return (ret); 195 196 /* else we need to fixup the set field */ 197 if (loc != 0) 198 set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set; 199 else 200 set_prev = ret->set - 1; 201 set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set; 202 203 /* set_prev is the previous set 204 * set is the current set 205 * set_next is the following 206 * prev 1 1 1 1 1 1 1 1 207 * set 1 1 2 2 208 * next 1 1 2 2 2 2 3 2 209 * so basically only if prev and next differ by 2, then 210 * re-number down by 1 */ 211 if (set_prev + 1 < set_next) 212 for (i = loc; i < n; i++) 213 sk_X509_NAME_ENTRY_value(sk, i)->set--; 214 return (ret); 215 } 216 LCRYPTO_ALIAS(X509_NAME_delete_entry); 217 218 int 219 X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type, 220 const unsigned char *bytes, int len, int loc, int set) 221 { 222 X509_NAME_ENTRY *ne; 223 int ret; 224 225 ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len); 226 if (!ne) 227 return 0; 228 ret = X509_NAME_add_entry(name, ne, loc, set); 229 X509_NAME_ENTRY_free(ne); 230 return ret; 231 } 232 LCRYPTO_ALIAS(X509_NAME_add_entry_by_OBJ); 233 234 int 235 X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, 236 const unsigned char *bytes, int len, int loc, int set) 237 { 238 X509_NAME_ENTRY *ne; 239 int ret; 240 241 ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len); 242 if (!ne) 243 return 0; 244 ret = X509_NAME_add_entry(name, ne, loc, set); 245 X509_NAME_ENTRY_free(ne); 246 return ret; 247 } 248 LCRYPTO_ALIAS(X509_NAME_add_entry_by_NID); 249 250 int 251 X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, 252 const unsigned char *bytes, int len, int loc, int set) 253 { 254 X509_NAME_ENTRY *ne; 255 int ret; 256 257 ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len); 258 if (!ne) 259 return 0; 260 ret = X509_NAME_add_entry(name, ne, loc, set); 261 X509_NAME_ENTRY_free(ne); 262 return ret; 263 } 264 LCRYPTO_ALIAS(X509_NAME_add_entry_by_txt); 265 266 /* if set is -1, append to previous set, 0 'a new one', and 1, 267 * prepend to the guy we are about to stomp on. */ 268 int 269 X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc, 270 int set) 271 { 272 X509_NAME_ENTRY *new_name = NULL; 273 int n, i, inc; 274 STACK_OF(X509_NAME_ENTRY) *sk; 275 276 if (name == NULL) 277 return (0); 278 sk = name->entries; 279 n = sk_X509_NAME_ENTRY_num(sk); 280 if (loc > n) 281 loc = n; 282 else if (loc < 0) 283 loc = n; 284 inc = (set == 0); 285 name->modified = 1; 286 287 if (set == -1) { 288 if (loc == 0) { 289 set = 0; 290 inc = 1; 291 } else 292 set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set; 293 } else /* if (set >= 0) */ { 294 if (loc >= n) { 295 if (loc != 0) 296 set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1; 297 else 298 set = 0; 299 } else 300 set = sk_X509_NAME_ENTRY_value(sk, loc)->set; 301 } 302 303 /* OpenSSL has ASN1-generated X509_NAME_ENTRY_dup() without const. */ 304 if ((new_name = X509_NAME_ENTRY_dup((X509_NAME_ENTRY *)ne)) == NULL) 305 goto err; 306 new_name->set = set; 307 if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) { 308 X509error(ERR_R_MALLOC_FAILURE); 309 goto err; 310 } 311 if (inc) { 312 n = sk_X509_NAME_ENTRY_num(sk); 313 for (i = loc + 1; i < n; i++) 314 sk_X509_NAME_ENTRY_value(sk, i)->set += 1; 315 } 316 return (1); 317 318 err: 319 if (new_name != NULL) 320 X509_NAME_ENTRY_free(new_name); 321 return (0); 322 } 323 LCRYPTO_ALIAS(X509_NAME_add_entry); 324 325 X509_NAME_ENTRY * 326 X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, 327 const char *field, int type, const unsigned char *bytes, int len) 328 { 329 ASN1_OBJECT *obj; 330 X509_NAME_ENTRY *nentry; 331 332 obj = OBJ_txt2obj(field, 0); 333 if (obj == NULL) { 334 X509error(X509_R_INVALID_FIELD_NAME); 335 ERR_asprintf_error_data("name=%s", field); 336 return (NULL); 337 } 338 nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); 339 ASN1_OBJECT_free(obj); 340 return nentry; 341 } 342 LCRYPTO_ALIAS(X509_NAME_ENTRY_create_by_txt); 343 344 X509_NAME_ENTRY * 345 X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, int type, 346 const unsigned char *bytes, int len) 347 { 348 ASN1_OBJECT *obj; 349 X509_NAME_ENTRY *nentry; 350 351 obj = OBJ_nid2obj(nid); 352 if (obj == NULL) { 353 X509error(X509_R_UNKNOWN_NID); 354 return (NULL); 355 } 356 nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); 357 ASN1_OBJECT_free(obj); 358 return nentry; 359 } 360 LCRYPTO_ALIAS(X509_NAME_ENTRY_create_by_NID); 361 362 X509_NAME_ENTRY * 363 X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, const ASN1_OBJECT *obj, 364 int type, const unsigned char *bytes, int len) 365 { 366 X509_NAME_ENTRY *ret; 367 368 if ((ne == NULL) || (*ne == NULL)) { 369 if ((ret = X509_NAME_ENTRY_new()) == NULL) 370 return (NULL); 371 } else 372 ret= *ne; 373 374 if (!X509_NAME_ENTRY_set_object(ret, obj)) 375 goto err; 376 if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len)) 377 goto err; 378 379 if ((ne != NULL) && (*ne == NULL)) 380 *ne = ret; 381 return (ret); 382 383 err: 384 if ((ne == NULL) || (ret != *ne)) 385 X509_NAME_ENTRY_free(ret); 386 return (NULL); 387 } 388 LCRYPTO_ALIAS(X509_NAME_ENTRY_create_by_OBJ); 389 390 int 391 X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj) 392 { 393 if ((ne == NULL) || (obj == NULL)) { 394 X509error(ERR_R_PASSED_NULL_PARAMETER); 395 return (0); 396 } 397 ASN1_OBJECT_free(ne->object); 398 ne->object = OBJ_dup(obj); 399 return ((ne->object == NULL) ? 0 : 1); 400 } 401 LCRYPTO_ALIAS(X509_NAME_ENTRY_set_object); 402 403 int 404 X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, 405 const unsigned char *bytes, int len) 406 { 407 int i; 408 409 if ((ne == NULL) || ((bytes == NULL) && (len != 0))) 410 return (0); 411 if ((type > 0) && (type & MBSTRING_FLAG)) 412 return ASN1_STRING_set_by_NID(&ne->value, bytes, len, type, 413 OBJ_obj2nid(ne->object)) ? 1 : 0; 414 if (len < 0) 415 len = strlen((const char *)bytes); 416 i = ASN1_STRING_set(ne->value, bytes, len); 417 if (!i) 418 return (0); 419 if (type != V_ASN1_UNDEF) { 420 if (type == V_ASN1_APP_CHOOSE) 421 ne->value->type = ASN1_PRINTABLE_type(bytes, len); 422 else 423 ne->value->type = type; 424 } 425 return (1); 426 } 427 LCRYPTO_ALIAS(X509_NAME_ENTRY_set_data); 428 429 ASN1_OBJECT * 430 X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne) 431 { 432 if (ne == NULL) 433 return (NULL); 434 return (ne->object); 435 } 436 LCRYPTO_ALIAS(X509_NAME_ENTRY_get_object); 437 438 ASN1_STRING * 439 X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne) 440 { 441 if (ne == NULL) 442 return (NULL); 443 return (ne->value); 444 } 445 LCRYPTO_ALIAS(X509_NAME_ENTRY_get_data); 446 447 int 448 X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) 449 { 450 return (ne->set); 451 } 452 LCRYPTO_ALIAS(X509_NAME_ENTRY_set); 453