1 /* $OpenBSD: x509_genn.c,v 1.7 2024/07/08 14:47:44 beck Exp $ */ 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project 1999. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 1999-2008 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 59 60 #include <stdio.h> 61 62 #include <openssl/asn1t.h> 63 #include <openssl/conf.h> 64 #include <openssl/x509v3.h> 65 66 static const ASN1_TEMPLATE OTHERNAME_seq_tt[] = { 67 { 68 .flags = 0, 69 .tag = 0, 70 .offset = offsetof(OTHERNAME, type_id), 71 .field_name = "type_id", 72 .item = &ASN1_OBJECT_it, 73 }, 74 /* Maybe have a true ANY DEFINED BY later */ 75 { 76 .flags = ASN1_TFLG_EXPLICIT, 77 .tag = 0, 78 .offset = offsetof(OTHERNAME, value), 79 .field_name = "value", 80 .item = &ASN1_ANY_it, 81 }, 82 }; 83 84 const ASN1_ITEM OTHERNAME_it = { 85 .itype = ASN1_ITYPE_SEQUENCE, 86 .utype = V_ASN1_SEQUENCE, 87 .templates = OTHERNAME_seq_tt, 88 .tcount = sizeof(OTHERNAME_seq_tt) / sizeof(ASN1_TEMPLATE), 89 .funcs = NULL, 90 .size = sizeof(OTHERNAME), 91 .sname = "OTHERNAME", 92 }; 93 LCRYPTO_ALIAS(OTHERNAME_it); 94 95 96 OTHERNAME * 97 d2i_OTHERNAME(OTHERNAME **a, const unsigned char **in, long len) 98 { 99 return (OTHERNAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 100 &OTHERNAME_it); 101 } 102 LCRYPTO_ALIAS(d2i_OTHERNAME); 103 104 int 105 i2d_OTHERNAME(OTHERNAME *a, unsigned char **out) 106 { 107 return ASN1_item_i2d((ASN1_VALUE *)a, out, &OTHERNAME_it); 108 } 109 LCRYPTO_ALIAS(i2d_OTHERNAME); 110 111 OTHERNAME * 112 OTHERNAME_new(void) 113 { 114 return (OTHERNAME *)ASN1_item_new(&OTHERNAME_it); 115 } 116 LCRYPTO_ALIAS(OTHERNAME_new); 117 118 void 119 OTHERNAME_free(OTHERNAME *a) 120 { 121 ASN1_item_free((ASN1_VALUE *)a, &OTHERNAME_it); 122 } 123 LCRYPTO_ALIAS(OTHERNAME_free); 124 125 /* Uses explicit tagging since DIRECTORYSTRING is a CHOICE type */ 126 static const ASN1_TEMPLATE EDIPARTYNAME_seq_tt[] = { 127 { 128 .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, 129 .tag = 0, 130 .offset = offsetof(EDIPARTYNAME, nameAssigner), 131 .field_name = "nameAssigner", 132 .item = &DIRECTORYSTRING_it, 133 }, 134 { 135 .flags = ASN1_TFLG_EXPLICIT, 136 .tag = 1, 137 .offset = offsetof(EDIPARTYNAME, partyName), 138 .field_name = "partyName", 139 .item = &DIRECTORYSTRING_it, 140 }, 141 }; 142 143 const ASN1_ITEM EDIPARTYNAME_it = { 144 .itype = ASN1_ITYPE_SEQUENCE, 145 .utype = V_ASN1_SEQUENCE, 146 .templates = EDIPARTYNAME_seq_tt, 147 .tcount = sizeof(EDIPARTYNAME_seq_tt) / sizeof(ASN1_TEMPLATE), 148 .funcs = NULL, 149 .size = sizeof(EDIPARTYNAME), 150 .sname = "EDIPARTYNAME", 151 }; 152 LCRYPTO_ALIAS(EDIPARTYNAME_it); 153 154 155 EDIPARTYNAME * 156 d2i_EDIPARTYNAME(EDIPARTYNAME **a, const unsigned char **in, long len) 157 { 158 return (EDIPARTYNAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 159 &EDIPARTYNAME_it); 160 } 161 LCRYPTO_ALIAS(d2i_EDIPARTYNAME); 162 163 int 164 i2d_EDIPARTYNAME(EDIPARTYNAME *a, unsigned char **out) 165 { 166 return ASN1_item_i2d((ASN1_VALUE *)a, out, &EDIPARTYNAME_it); 167 } 168 LCRYPTO_ALIAS(i2d_EDIPARTYNAME); 169 170 EDIPARTYNAME * 171 EDIPARTYNAME_new(void) 172 { 173 return (EDIPARTYNAME *)ASN1_item_new(&EDIPARTYNAME_it); 174 } 175 LCRYPTO_ALIAS(EDIPARTYNAME_new); 176 177 void 178 EDIPARTYNAME_free(EDIPARTYNAME *a) 179 { 180 ASN1_item_free((ASN1_VALUE *)a, &EDIPARTYNAME_it); 181 } 182 LCRYPTO_ALIAS(EDIPARTYNAME_free); 183 184 static const ASN1_TEMPLATE GENERAL_NAME_ch_tt[] = { 185 { 186 .flags = ASN1_TFLG_IMPLICIT, 187 .tag = GEN_OTHERNAME, 188 .offset = offsetof(GENERAL_NAME, d.otherName), 189 .field_name = "d.otherName", 190 .item = &OTHERNAME_it, 191 }, 192 { 193 .flags = ASN1_TFLG_IMPLICIT, 194 .tag = GEN_EMAIL, 195 .offset = offsetof(GENERAL_NAME, d.rfc822Name), 196 .field_name = "d.rfc822Name", 197 .item = &ASN1_IA5STRING_it, 198 }, 199 { 200 .flags = ASN1_TFLG_IMPLICIT, 201 .tag = GEN_DNS, 202 .offset = offsetof(GENERAL_NAME, d.dNSName), 203 .field_name = "d.dNSName", 204 .item = &ASN1_IA5STRING_it, 205 }, 206 /* Don't decode this */ 207 { 208 .flags = ASN1_TFLG_IMPLICIT, 209 .tag = GEN_X400, 210 .offset = offsetof(GENERAL_NAME, d.x400Address), 211 .field_name = "d.x400Address", 212 .item = &ASN1_SEQUENCE_it, 213 }, 214 /* X509_NAME is a CHOICE type so use EXPLICIT */ 215 { 216 .flags = ASN1_TFLG_EXPLICIT, 217 .tag = GEN_DIRNAME, 218 .offset = offsetof(GENERAL_NAME, d.directoryName), 219 .field_name = "d.directoryName", 220 .item = &X509_NAME_it, 221 }, 222 { 223 .flags = ASN1_TFLG_IMPLICIT, 224 .tag = GEN_EDIPARTY, 225 .offset = offsetof(GENERAL_NAME, d.ediPartyName), 226 .field_name = "d.ediPartyName", 227 .item = &EDIPARTYNAME_it, 228 }, 229 { 230 .flags = ASN1_TFLG_IMPLICIT, 231 .tag = GEN_URI, 232 .offset = offsetof(GENERAL_NAME, d.uniformResourceIdentifier), 233 .field_name = "d.uniformResourceIdentifier", 234 .item = &ASN1_IA5STRING_it, 235 }, 236 { 237 .flags = ASN1_TFLG_IMPLICIT, 238 .tag = GEN_IPADD, 239 .offset = offsetof(GENERAL_NAME, d.iPAddress), 240 .field_name = "d.iPAddress", 241 .item = &ASN1_OCTET_STRING_it, 242 }, 243 { 244 .flags = ASN1_TFLG_IMPLICIT, 245 .tag = GEN_RID, 246 .offset = offsetof(GENERAL_NAME, d.registeredID), 247 .field_name = "d.registeredID", 248 .item = &ASN1_OBJECT_it, 249 }, 250 }; 251 252 const ASN1_ITEM GENERAL_NAME_it = { 253 .itype = ASN1_ITYPE_CHOICE, 254 .utype = offsetof(GENERAL_NAME, type), 255 .templates = GENERAL_NAME_ch_tt, 256 .tcount = sizeof(GENERAL_NAME_ch_tt) / sizeof(ASN1_TEMPLATE), 257 .funcs = NULL, 258 .size = sizeof(GENERAL_NAME), 259 .sname = "GENERAL_NAME", 260 }; 261 LCRYPTO_ALIAS(GENERAL_NAME_it); 262 263 264 GENERAL_NAME * 265 d2i_GENERAL_NAME(GENERAL_NAME **a, const unsigned char **in, long len) 266 { 267 return (GENERAL_NAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 268 &GENERAL_NAME_it); 269 } 270 LCRYPTO_ALIAS(d2i_GENERAL_NAME); 271 272 int 273 i2d_GENERAL_NAME(GENERAL_NAME *a, unsigned char **out) 274 { 275 return ASN1_item_i2d((ASN1_VALUE *)a, out, &GENERAL_NAME_it); 276 } 277 LCRYPTO_ALIAS(i2d_GENERAL_NAME); 278 279 GENERAL_NAME * 280 GENERAL_NAME_new(void) 281 { 282 return (GENERAL_NAME *)ASN1_item_new(&GENERAL_NAME_it); 283 } 284 LCRYPTO_ALIAS(GENERAL_NAME_new); 285 286 void 287 GENERAL_NAME_free(GENERAL_NAME *a) 288 { 289 ASN1_item_free((ASN1_VALUE *)a, &GENERAL_NAME_it); 290 } 291 LCRYPTO_ALIAS(GENERAL_NAME_free); 292 293 static const ASN1_TEMPLATE GENERAL_NAMES_item_tt = { 294 .flags = ASN1_TFLG_SEQUENCE_OF, 295 .tag = 0, 296 .offset = 0, 297 .field_name = "GeneralNames", 298 .item = &GENERAL_NAME_it, 299 }; 300 301 const ASN1_ITEM GENERAL_NAMES_it = { 302 .itype = ASN1_ITYPE_PRIMITIVE, 303 .utype = -1, 304 .templates = &GENERAL_NAMES_item_tt, 305 .tcount = 0, 306 .funcs = NULL, 307 .size = 0, 308 .sname = "GENERAL_NAMES", 309 }; 310 LCRYPTO_ALIAS(GENERAL_NAMES_it); 311 312 313 GENERAL_NAMES * 314 d2i_GENERAL_NAMES(GENERAL_NAMES **a, const unsigned char **in, long len) 315 { 316 return (GENERAL_NAMES *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, 317 &GENERAL_NAMES_it); 318 } 319 LCRYPTO_ALIAS(d2i_GENERAL_NAMES); 320 321 int 322 i2d_GENERAL_NAMES(GENERAL_NAMES *a, unsigned char **out) 323 { 324 return ASN1_item_i2d((ASN1_VALUE *)a, out, &GENERAL_NAMES_it); 325 } 326 LCRYPTO_ALIAS(i2d_GENERAL_NAMES); 327 328 GENERAL_NAMES * 329 GENERAL_NAMES_new(void) 330 { 331 return (GENERAL_NAMES *)ASN1_item_new(&GENERAL_NAMES_it); 332 } 333 LCRYPTO_ALIAS(GENERAL_NAMES_new); 334 335 void 336 GENERAL_NAMES_free(GENERAL_NAMES *a) 337 { 338 ASN1_item_free((ASN1_VALUE *)a, &GENERAL_NAMES_it); 339 } 340 LCRYPTO_ALIAS(GENERAL_NAMES_free); 341 342 GENERAL_NAME * 343 GENERAL_NAME_dup(GENERAL_NAME *a) 344 { 345 return ASN1_item_dup(&GENERAL_NAME_it, a); 346 } 347 LCRYPTO_ALIAS(GENERAL_NAME_dup); 348 349 static int 350 EDIPARTYNAME_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b) 351 { 352 int res; 353 354 /* 355 * Shouldn't be possible in a valid GENERAL_NAME, but we handle it 356 * anyway. OTHERNAME_cmp treats NULL != NULL, so we do the same here. 357 */ 358 if (a == NULL || b == NULL) 359 return -1; 360 if (a->nameAssigner == NULL && b->nameAssigner != NULL) 361 return -1; 362 if (a->nameAssigner != NULL && b->nameAssigner == NULL) 363 return 1; 364 /* If we get here, both have nameAssigner set or both unset. */ 365 if (a->nameAssigner != NULL) { 366 res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner); 367 if (res != 0) 368 return res; 369 } 370 /* 371 * partyName is required, so these should never be NULL. We treat it in 372 * the same way as the a == NULL || b == NULL case above. 373 */ 374 if (a->partyName == NULL || b->partyName == NULL) 375 return -1; 376 377 return ASN1_STRING_cmp(a->partyName, b->partyName); 378 } 379 380 /* Returns 0 if they are equal, != 0 otherwise. */ 381 int 382 GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b) 383 { 384 int result = -1; 385 386 if (!a || !b || a->type != b->type) 387 return -1; 388 switch (a->type) { 389 case GEN_X400: 390 result = ASN1_STRING_cmp(a->d.x400Address, b->d.x400Address); 391 break; 392 393 case GEN_EDIPARTY: 394 result = EDIPARTYNAME_cmp(a->d.ediPartyName, b->d.ediPartyName); 395 break; 396 397 case GEN_OTHERNAME: 398 result = OTHERNAME_cmp(a->d.otherName, b->d.otherName); 399 break; 400 401 case GEN_EMAIL: 402 case GEN_DNS: 403 case GEN_URI: 404 result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5); 405 break; 406 407 case GEN_DIRNAME: 408 result = X509_NAME_cmp(a->d.dirn, b->d.dirn); 409 break; 410 411 case GEN_IPADD: 412 result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip); 413 break; 414 415 case GEN_RID: 416 result = OBJ_cmp(a->d.rid, b->d.rid); 417 break; 418 } 419 return result; 420 } 421 LCRYPTO_ALIAS(GENERAL_NAME_cmp); 422 423 /* Returns 0 if they are equal, != 0 otherwise. */ 424 int 425 OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b) 426 { 427 int result = -1; 428 429 if (!a || !b) 430 return -1; 431 /* Check their type first. */ 432 if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0) 433 return result; 434 /* Check the value. */ 435 result = ASN1_TYPE_cmp(a->value, b->value); 436 return result; 437 } 438 LCRYPTO_ALIAS(OTHERNAME_cmp); 439 440 void 441 GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value) 442 { 443 switch (type) { 444 case GEN_X400: 445 a->d.x400Address = value; 446 break; 447 448 case GEN_EDIPARTY: 449 a->d.ediPartyName = value; 450 break; 451 452 case GEN_OTHERNAME: 453 a->d.otherName = value; 454 break; 455 456 case GEN_EMAIL: 457 case GEN_DNS: 458 case GEN_URI: 459 a->d.ia5 = value; 460 break; 461 462 case GEN_DIRNAME: 463 a->d.dirn = value; 464 break; 465 466 case GEN_IPADD: 467 a->d.ip = value; 468 break; 469 470 case GEN_RID: 471 a->d.rid = value; 472 break; 473 } 474 a->type = type; 475 } 476 LCRYPTO_ALIAS(GENERAL_NAME_set0_value); 477 478 void * 479 GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype) 480 { 481 if (ptype) 482 *ptype = a->type; 483 switch (a->type) { 484 case GEN_X400: 485 return a->d.x400Address; 486 487 case GEN_EDIPARTY: 488 return a->d.ediPartyName; 489 490 case GEN_OTHERNAME: 491 return a->d.otherName; 492 493 case GEN_EMAIL: 494 case GEN_DNS: 495 case GEN_URI: 496 return a->d.ia5; 497 498 case GEN_DIRNAME: 499 return a->d.dirn; 500 501 case GEN_IPADD: 502 return a->d.ip; 503 504 case GEN_RID: 505 return a->d.rid; 506 507 default: 508 return NULL; 509 } 510 } 511 LCRYPTO_ALIAS(GENERAL_NAME_get0_value); 512 513 int 514 GENERAL_NAME_set0_othername(GENERAL_NAME *gen, ASN1_OBJECT *oid, 515 ASN1_TYPE *value) 516 { 517 OTHERNAME *oth; 518 519 oth = OTHERNAME_new(); 520 if (!oth) 521 return 0; 522 oth->type_id = oid; 523 oth->value = value; 524 GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth); 525 return 1; 526 } 527 LCRYPTO_ALIAS(GENERAL_NAME_set0_othername); 528 529 int 530 GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, ASN1_OBJECT **poid, 531 ASN1_TYPE **pvalue) 532 { 533 if (gen->type != GEN_OTHERNAME) 534 return 0; 535 if (poid) 536 *poid = gen->d.otherName->type_id; 537 if (pvalue) 538 *pvalue = gen->d.otherName->value; 539 return 1; 540 } 541 LCRYPTO_ALIAS(GENERAL_NAME_get0_otherName); 542