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