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