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