1 /* $OpenBSD: x509name.c,v 1.30 2022/12/26 07:18:53 jmc 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 "x509_local.h" 70 71 int 72 X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len) 73 { 74 ASN1_OBJECT *obj; 75 76 obj = OBJ_nid2obj(nid); 77 if (obj == NULL) 78 return (-1); 79 return (X509_NAME_get_text_by_OBJ(name, obj, buf, len)); 80 } 81 LCRYPTO_ALIAS(X509_NAME_get_text_by_NID) 82 83 int 84 X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, char *buf, 85 int len) 86 { 87 int i; 88 ASN1_STRING *data; 89 90 i = X509_NAME_get_index_by_OBJ(name, obj, -1); 91 if (i < 0) 92 return (-1); 93 data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); 94 i = (data->length > (len - 1)) ? (len - 1) : data->length; 95 if (buf == NULL) 96 return (data->length); 97 if (i >= 0) { 98 memcpy(buf, data->data, i); 99 buf[i] = '\0'; 100 } 101 return (i); 102 } 103 LCRYPTO_ALIAS(X509_NAME_get_text_by_OBJ) 104 105 int 106 X509_NAME_entry_count(const X509_NAME *name) 107 { 108 if (name == NULL) 109 return (0); 110 return (sk_X509_NAME_ENTRY_num(name->entries)); 111 } 112 LCRYPTO_ALIAS(X509_NAME_entry_count) 113 114 int 115 X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos) 116 { 117 ASN1_OBJECT *obj; 118 119 obj = OBJ_nid2obj(nid); 120 if (obj == NULL) 121 return (-2); 122 return (X509_NAME_get_index_by_OBJ(name, obj, lastpos)); 123 } 124 LCRYPTO_ALIAS(X509_NAME_get_index_by_NID) 125 126 /* NOTE: you should be passing -1, not 0 as lastpos */ 127 int 128 X509_NAME_get_index_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj, 129 int lastpos) 130 { 131 int n; 132 X509_NAME_ENTRY *ne; 133 STACK_OF(X509_NAME_ENTRY) *sk; 134 135 if (name == NULL) 136 return (-1); 137 if (lastpos < 0) 138 lastpos = -1; 139 sk = name->entries; 140 n = sk_X509_NAME_ENTRY_num(sk); 141 for (lastpos++; lastpos < n; lastpos++) { 142 ne = sk_X509_NAME_ENTRY_value(sk, lastpos); 143 if (OBJ_cmp(ne->object, obj) == 0) 144 return (lastpos); 145 } 146 return (-1); 147 } 148 LCRYPTO_ALIAS(X509_NAME_get_index_by_OBJ) 149 150 X509_NAME_ENTRY * 151 X509_NAME_get_entry(const X509_NAME *name, int loc) 152 { 153 if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc || 154 loc < 0) 155 return (NULL); 156 else 157 return (sk_X509_NAME_ENTRY_value(name->entries, loc)); 158 } 159 LCRYPTO_ALIAS(X509_NAME_get_entry) 160 161 X509_NAME_ENTRY * 162 X509_NAME_delete_entry(X509_NAME *name, int loc) 163 { 164 X509_NAME_ENTRY *ret; 165 int i, n, set_prev, set_next; 166 STACK_OF(X509_NAME_ENTRY) *sk; 167 168 if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc || 169 loc < 0) 170 return (NULL); 171 sk = name->entries; 172 ret = sk_X509_NAME_ENTRY_delete(sk, loc); 173 n = sk_X509_NAME_ENTRY_num(sk); 174 name->modified = 1; 175 if (loc == n) 176 return (ret); 177 178 /* else we need to fixup the set field */ 179 if (loc != 0) 180 set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set; 181 else 182 set_prev = ret->set - 1; 183 set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set; 184 185 /* set_prev is the previous set 186 * set is the current set 187 * set_next is the following 188 * prev 1 1 1 1 1 1 1 1 189 * set 1 1 2 2 190 * next 1 1 2 2 2 2 3 2 191 * so basically only if prev and next differ by 2, then 192 * re-number down by 1 */ 193 if (set_prev + 1 < set_next) 194 for (i = loc; i < n; i++) 195 sk_X509_NAME_ENTRY_value(sk, i)->set--; 196 return (ret); 197 } 198 LCRYPTO_ALIAS(X509_NAME_delete_entry) 199 200 int 201 X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type, 202 const unsigned char *bytes, int len, int loc, int set) 203 { 204 X509_NAME_ENTRY *ne; 205 int ret; 206 207 ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len); 208 if (!ne) 209 return 0; 210 ret = X509_NAME_add_entry(name, ne, loc, set); 211 X509_NAME_ENTRY_free(ne); 212 return ret; 213 } 214 LCRYPTO_ALIAS(X509_NAME_add_entry_by_OBJ) 215 216 int 217 X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, 218 const unsigned char *bytes, int len, int loc, int set) 219 { 220 X509_NAME_ENTRY *ne; 221 int ret; 222 223 ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len); 224 if (!ne) 225 return 0; 226 ret = X509_NAME_add_entry(name, ne, loc, set); 227 X509_NAME_ENTRY_free(ne); 228 return ret; 229 } 230 LCRYPTO_ALIAS(X509_NAME_add_entry_by_NID) 231 232 int 233 X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, 234 const unsigned char *bytes, int len, int loc, int set) 235 { 236 X509_NAME_ENTRY *ne; 237 int ret; 238 239 ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len); 240 if (!ne) 241 return 0; 242 ret = X509_NAME_add_entry(name, ne, loc, set); 243 X509_NAME_ENTRY_free(ne); 244 return ret; 245 } 246 LCRYPTO_ALIAS(X509_NAME_add_entry_by_txt) 247 248 /* if set is -1, append to previous set, 0 'a new one', and 1, 249 * prepend to the guy we are about to stomp on. */ 250 int 251 X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc, 252 int set) 253 { 254 X509_NAME_ENTRY *new_name = NULL; 255 int n, i, inc; 256 STACK_OF(X509_NAME_ENTRY) *sk; 257 258 if (name == NULL) 259 return (0); 260 sk = name->entries; 261 n = sk_X509_NAME_ENTRY_num(sk); 262 if (loc > n) 263 loc = n; 264 else if (loc < 0) 265 loc = n; 266 inc = (set == 0); 267 name->modified = 1; 268 269 if (set == -1) { 270 if (loc == 0) { 271 set = 0; 272 inc = 1; 273 } else 274 set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set; 275 } else /* if (set >= 0) */ { 276 if (loc >= n) { 277 if (loc != 0) 278 set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1; 279 else 280 set = 0; 281 } else 282 set = sk_X509_NAME_ENTRY_value(sk, loc)->set; 283 } 284 285 /* OpenSSL has ASN1-generated X509_NAME_ENTRY_dup() without const. */ 286 if ((new_name = X509_NAME_ENTRY_dup((X509_NAME_ENTRY *)ne)) == NULL) 287 goto err; 288 new_name->set = set; 289 if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) { 290 X509error(ERR_R_MALLOC_FAILURE); 291 goto err; 292 } 293 if (inc) { 294 n = sk_X509_NAME_ENTRY_num(sk); 295 for (i = loc + 1; i < n; i++) 296 sk_X509_NAME_ENTRY_value(sk, i)->set += 1; 297 } 298 return (1); 299 300 err: 301 if (new_name != NULL) 302 X509_NAME_ENTRY_free(new_name); 303 return (0); 304 } 305 LCRYPTO_ALIAS(X509_NAME_add_entry) 306 307 X509_NAME_ENTRY * 308 X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, 309 const char *field, int type, const unsigned char *bytes, int len) 310 { 311 ASN1_OBJECT *obj; 312 X509_NAME_ENTRY *nentry; 313 314 obj = OBJ_txt2obj(field, 0); 315 if (obj == NULL) { 316 X509error(X509_R_INVALID_FIELD_NAME); 317 ERR_asprintf_error_data("name=%s", field); 318 return (NULL); 319 } 320 nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); 321 ASN1_OBJECT_free(obj); 322 return nentry; 323 } 324 LCRYPTO_ALIAS(X509_NAME_ENTRY_create_by_txt) 325 326 X509_NAME_ENTRY * 327 X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, int type, 328 const unsigned char *bytes, int len) 329 { 330 ASN1_OBJECT *obj; 331 X509_NAME_ENTRY *nentry; 332 333 obj = OBJ_nid2obj(nid); 334 if (obj == NULL) { 335 X509error(X509_R_UNKNOWN_NID); 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_NID) 343 344 X509_NAME_ENTRY * 345 X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, const ASN1_OBJECT *obj, 346 int type, const unsigned char *bytes, int len) 347 { 348 X509_NAME_ENTRY *ret; 349 350 if ((ne == NULL) || (*ne == NULL)) { 351 if ((ret = X509_NAME_ENTRY_new()) == NULL) 352 return (NULL); 353 } else 354 ret= *ne; 355 356 if (!X509_NAME_ENTRY_set_object(ret, obj)) 357 goto err; 358 if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len)) 359 goto err; 360 361 if ((ne != NULL) && (*ne == NULL)) 362 *ne = ret; 363 return (ret); 364 365 err: 366 if ((ne == NULL) || (ret != *ne)) 367 X509_NAME_ENTRY_free(ret); 368 return (NULL); 369 } 370 LCRYPTO_ALIAS(X509_NAME_ENTRY_create_by_OBJ) 371 372 int 373 X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj) 374 { 375 if ((ne == NULL) || (obj == NULL)) { 376 X509error(ERR_R_PASSED_NULL_PARAMETER); 377 return (0); 378 } 379 ASN1_OBJECT_free(ne->object); 380 ne->object = OBJ_dup(obj); 381 return ((ne->object == NULL) ? 0 : 1); 382 } 383 LCRYPTO_ALIAS(X509_NAME_ENTRY_set_object) 384 385 int 386 X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, 387 const unsigned char *bytes, int len) 388 { 389 int i; 390 391 if ((ne == NULL) || ((bytes == NULL) && (len != 0))) 392 return (0); 393 if ((type > 0) && (type & MBSTRING_FLAG)) 394 return ASN1_STRING_set_by_NID(&ne->value, bytes, len, type, 395 OBJ_obj2nid(ne->object)) ? 1 : 0; 396 if (len < 0) 397 len = strlen((const char *)bytes); 398 i = ASN1_STRING_set(ne->value, bytes, len); 399 if (!i) 400 return (0); 401 if (type != V_ASN1_UNDEF) { 402 if (type == V_ASN1_APP_CHOOSE) 403 ne->value->type = ASN1_PRINTABLE_type(bytes, len); 404 else 405 ne->value->type = type; 406 } 407 return (1); 408 } 409 LCRYPTO_ALIAS(X509_NAME_ENTRY_set_data) 410 411 ASN1_OBJECT * 412 X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne) 413 { 414 if (ne == NULL) 415 return (NULL); 416 return (ne->object); 417 } 418 LCRYPTO_ALIAS(X509_NAME_ENTRY_get_object) 419 420 ASN1_STRING * 421 X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne) 422 { 423 if (ne == NULL) 424 return (NULL); 425 return (ne->value); 426 } 427 LCRYPTO_ALIAS(X509_NAME_ENTRY_get_data) 428 429 int 430 X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) 431 { 432 return (ne->set); 433 } 434 LCRYPTO_ALIAS(X509_NAME_ENTRY_set) 435