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