Annotation of embedaddon/strongswan/src/libstrongswan/plugins/x509/x509_pkcs10.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2005 Jan Hutter, Martin Willi
! 3: * Copyright (C) 2009-2017 Andreas Steffen
! 4: * HSR Hochschule fuer Technik Rapperswil
! 5: *
! 6: * This program is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2 of the License, or (at your
! 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 10: *
! 11: * This program is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 14: * for more details.
! 15: */
! 16:
! 17: #include "x509_pkcs10.h"
! 18:
! 19: #include <library.h>
! 20: #include <utils/debug.h>
! 21: #include <asn1/oid.h>
! 22: #include <asn1/asn1.h>
! 23: #include <asn1/asn1_parser.h>
! 24: #include <credentials/keys/private_key.h>
! 25: #include <collections/linked_list.h>
! 26: #include <utils/identification.h>
! 27:
! 28: typedef struct private_x509_pkcs10_t private_x509_pkcs10_t;
! 29:
! 30: /**
! 31: * Private data of a x509_pkcs10_t object.
! 32: */
! 33: struct private_x509_pkcs10_t {
! 34: /**
! 35: * Public interface for this certificate.
! 36: */
! 37: x509_pkcs10_t public;
! 38:
! 39: /**
! 40: * PKCS#10 certificate request encoding in ASN.1 DER format
! 41: */
! 42: chunk_t encoding;
! 43:
! 44: /**
! 45: * PKCS#10 request body over which signature is computed
! 46: */
! 47: chunk_t certificationRequestInfo;
! 48:
! 49: /**
! 50: * Version of the PKCS#10 certificate request
! 51: */
! 52: u_int version;
! 53:
! 54: /**
! 55: * ID representing the certificate subject
! 56: */
! 57: identification_t *subject;
! 58:
! 59: /**
! 60: * List of subjectAltNames as identification_t
! 61: */
! 62: linked_list_t *subjectAltNames;
! 63:
! 64: /**
! 65: * certificate's embedded public key
! 66: */
! 67: public_key_t *public_key;
! 68:
! 69: /**
! 70: * challenge password
! 71: */
! 72: chunk_t challengePassword;
! 73:
! 74: /**
! 75: * Signature scheme
! 76: */
! 77: signature_params_t *scheme;
! 78:
! 79: /**
! 80: * Signature
! 81: */
! 82: chunk_t signature;
! 83:
! 84: /**
! 85: * Is the certificate request self-signed?
! 86: */
! 87: bool self_signed;
! 88:
! 89: /**
! 90: * Certificate request parsed from blob/file?
! 91: */
! 92: bool parsed;
! 93:
! 94: /**
! 95: * reference count
! 96: */
! 97: refcount_t ref;
! 98: };
! 99:
! 100: /**
! 101: * Imported from x509_cert.c
! 102: */
! 103: extern bool x509_parse_generalNames(chunk_t blob, int level0, bool implicit,
! 104: linked_list_t *list);
! 105: extern chunk_t x509_build_subjectAltNames(linked_list_t *list);
! 106:
! 107: METHOD(certificate_t, get_type, certificate_type_t,
! 108: private_x509_pkcs10_t *this)
! 109: {
! 110: return CERT_PKCS10_REQUEST;
! 111: }
! 112:
! 113: METHOD(certificate_t, get_subject, identification_t*,
! 114: private_x509_pkcs10_t *this)
! 115: {
! 116: return this->subject;
! 117: }
! 118:
! 119: METHOD(certificate_t, has_subject, id_match_t,
! 120: private_x509_pkcs10_t *this, identification_t *subject)
! 121: {
! 122: return this->subject->matches(this->subject, subject);
! 123: }
! 124:
! 125: METHOD(certificate_t, issued_by, bool,
! 126: private_x509_pkcs10_t *this, certificate_t *issuer,
! 127: signature_params_t **scheme)
! 128: {
! 129: public_key_t *key;
! 130: bool valid;
! 131:
! 132: if (&this->public.interface.interface != issuer)
! 133: {
! 134: return FALSE;
! 135: }
! 136: if (this->self_signed)
! 137: {
! 138: valid = TRUE;
! 139: }
! 140: else
! 141: {
! 142: /* get the public key contained in the certificate request */
! 143: key = this->public_key;
! 144: if (!key)
! 145: {
! 146: return FALSE;
! 147: }
! 148: valid = key->verify(key, this->scheme->scheme, this->scheme->params,
! 149: this->certificationRequestInfo, this->signature);
! 150: }
! 151: if (valid && scheme)
! 152: {
! 153: *scheme = signature_params_clone(this->scheme);
! 154: }
! 155: return valid;
! 156: }
! 157:
! 158: METHOD(certificate_t, get_public_key, public_key_t*,
! 159: private_x509_pkcs10_t *this)
! 160: {
! 161: this->public_key->get_ref(this->public_key);
! 162: return this->public_key;
! 163: }
! 164:
! 165: METHOD(certificate_t, get_validity, bool,
! 166: private_x509_pkcs10_t *this, time_t *when, time_t *not_before,
! 167: time_t *not_after)
! 168: {
! 169: if (not_before)
! 170: {
! 171: *not_before = 0;
! 172: }
! 173: if (not_after)
! 174: {
! 175: *not_after = ~0;
! 176: }
! 177: return TRUE;
! 178: }
! 179:
! 180: METHOD(certificate_t, get_encoding, bool,
! 181: private_x509_pkcs10_t *this, cred_encoding_type_t type, chunk_t *encoding)
! 182: {
! 183: if (type == CERT_ASN1_DER)
! 184: {
! 185: *encoding = chunk_clone(this->encoding);
! 186: return TRUE;
! 187: }
! 188: return lib->encoding->encode(lib->encoding, type, NULL, encoding,
! 189: CRED_PART_PKCS10_ASN1_DER, this->encoding, CRED_PART_END);
! 190: }
! 191:
! 192: METHOD(certificate_t, equals, bool,
! 193: private_x509_pkcs10_t *this, certificate_t *other)
! 194: {
! 195: chunk_t encoding;
! 196: bool equal;
! 197:
! 198: if (this == (private_x509_pkcs10_t*)other)
! 199: {
! 200: return TRUE;
! 201: }
! 202: if (other->get_type(other) != CERT_PKCS10_REQUEST)
! 203: {
! 204: return FALSE;
! 205: }
! 206: if (other->equals == (void*)equals)
! 207: { /* skip allocation if we have the same implementation */
! 208: return chunk_equals(this->encoding, ((private_x509_pkcs10_t*)other)->encoding);
! 209: }
! 210: if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
! 211: {
! 212: return FALSE;
! 213: }
! 214: equal = chunk_equals(this->encoding, encoding);
! 215: free(encoding.ptr);
! 216: return equal;
! 217: }
! 218:
! 219: METHOD(certificate_t, get_ref, certificate_t*,
! 220: private_x509_pkcs10_t *this)
! 221: {
! 222: ref_get(&this->ref);
! 223: return &this->public.interface.interface;
! 224: }
! 225:
! 226: METHOD(pkcs10_t, get_challengePassword, chunk_t,
! 227: private_x509_pkcs10_t *this)
! 228: {
! 229: return this->challengePassword;
! 230: }
! 231:
! 232: METHOD(pkcs10_t, create_subjectAltName_enumerator, enumerator_t*,
! 233: private_x509_pkcs10_t *this)
! 234: {
! 235: return this->subjectAltNames->create_enumerator(this->subjectAltNames);
! 236: }
! 237:
! 238: /**
! 239: * ASN.1 definition of a PKCS#10 extension request
! 240: */
! 241: static const asn1Object_t extensionRequestObjects[] = {
! 242: { 0, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
! 243: { 1, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
! 244: { 2, "extnID", ASN1_OID, ASN1_BODY }, /* 2 */
! 245: { 2, "critical", ASN1_BOOLEAN, ASN1_DEF|ASN1_BODY }, /* 3 */
! 246: { 2, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */
! 247: { 1, "end loop", ASN1_EOC, ASN1_END }, /* 5 */
! 248: { 0, "exit", ASN1_EOC, ASN1_EXIT }
! 249: };
! 250: #define PKCS10_EXTN_ID 2
! 251: #define PKCS10_EXTN_CRITICAL 3
! 252: #define PKCS10_EXTN_VALUE 4
! 253:
! 254: /**
! 255: * Parses a PKCS#10 extension request
! 256: */
! 257: static bool parse_extension_request(private_x509_pkcs10_t *this, chunk_t blob, int level0)
! 258: {
! 259: asn1_parser_t *parser;
! 260: chunk_t object;
! 261: int objectID;
! 262: int extn_oid = OID_UNKNOWN;
! 263: bool success = FALSE;
! 264: bool critical;
! 265:
! 266: parser = asn1_parser_create(extensionRequestObjects, blob);
! 267: parser->set_top_level(parser, level0);
! 268:
! 269: while (parser->iterate(parser, &objectID, &object))
! 270: {
! 271: u_int level = parser->get_level(parser)+1;
! 272:
! 273: switch (objectID)
! 274: {
! 275: case PKCS10_EXTN_ID:
! 276: extn_oid = asn1_known_oid(object);
! 277: break;
! 278: case PKCS10_EXTN_CRITICAL:
! 279: critical = object.len && *object.ptr;
! 280: DBG2(DBG_ASN, " %s", critical ? "TRUE" : "FALSE");
! 281: break;
! 282: case PKCS10_EXTN_VALUE:
! 283: {
! 284: switch (extn_oid)
! 285: {
! 286: case OID_SUBJECT_ALT_NAME:
! 287: if (!x509_parse_generalNames(object, level, FALSE,
! 288: this->subjectAltNames))
! 289: {
! 290: goto end;
! 291: }
! 292: break;
! 293: default:
! 294: break;
! 295: }
! 296: break;
! 297: }
! 298: default:
! 299: break;
! 300: }
! 301: }
! 302: success = parser->success(parser);
! 303:
! 304: end:
! 305: parser->destroy(parser);
! 306:
! 307: return success;
! 308: }
! 309:
! 310: /**
! 311: * Parses a PKCS#10 challenge password
! 312: */
! 313: static bool parse_challengePassword(private_x509_pkcs10_t *this, chunk_t blob, int level)
! 314: {
! 315: char tag;
! 316:
! 317: if (blob.len < 2)
! 318: {
! 319: DBG1(DBG_ASN, "L%d - challengePassword: ASN.1 object smaller "
! 320: "than 2 octets", level);
! 321: return FALSE;
! 322: }
! 323: tag = *blob.ptr;
! 324: if (tag < ASN1_UTF8STRING || tag > ASN1_IA5STRING)
! 325: {
! 326: DBG1(DBG_ASN, "L%d - challengePassword: ASN.1 object is not "
! 327: "a character string", level);
! 328: return FALSE;
! 329: }
! 330: if (asn1_length(&blob) == ASN1_INVALID_LENGTH)
! 331: {
! 332: DBG1(DBG_ASN, "L%d - challengePassword: ASN.1 object has an "
! 333: "invalid length", level);
! 334: return FALSE;
! 335: }
! 336: DBG2(DBG_ASN, "L%d - challengePassword:", level);
! 337: DBG4(DBG_ASN, " '%.*s'", (int)blob.len, blob.ptr);
! 338: return TRUE;
! 339: }
! 340:
! 341: /**
! 342: * ASN.1 definition of a PKCS#10 certificate request
! 343: */
! 344: static const asn1Object_t certificationRequestObjects[] = {
! 345: { 0, "certificationRequest", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
! 346: { 1, "certificationRequestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
! 347: { 2, "version", ASN1_INTEGER, ASN1_BODY }, /* 2 */
! 348: { 2, "subject", ASN1_SEQUENCE, ASN1_OBJ }, /* 3 */
! 349: { 2, "subjectPublicKeyInfo", ASN1_SEQUENCE, ASN1_RAW }, /* 4 */
! 350: { 2, "attributes", ASN1_CONTEXT_C_0, ASN1_LOOP }, /* 5 */
! 351: { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 6 */
! 352: { 4, "type", ASN1_OID, ASN1_BODY }, /* 7 */
! 353: { 4, "values", ASN1_SET, ASN1_LOOP }, /* 8 */
! 354: { 5, "value", ASN1_EOC, ASN1_RAW }, /* 9 */
! 355: { 4, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
! 356: { 2, "end loop", ASN1_EOC, ASN1_END }, /* 11 */
! 357: { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 12 */
! 358: { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 13 */
! 359: { 0, "exit", ASN1_EOC, ASN1_EXIT }
! 360: };
! 361: #define PKCS10_CERT_REQUEST_INFO 1
! 362: #define PKCS10_VERSION 2
! 363: #define PKCS10_SUBJECT 3
! 364: #define PKCS10_SUBJECT_PUBLIC_KEY_INFO 4
! 365: #define PKCS10_ATTR_TYPE 7
! 366: #define PKCS10_ATTR_VALUE 9
! 367: #define PKCS10_ALGORITHM 12
! 368: #define PKCS10_SIGNATURE 13
! 369:
! 370: /**
! 371: * Parses a PKCS#10 certificate request
! 372: */
! 373: static bool parse_certificate_request(private_x509_pkcs10_t *this)
! 374: {
! 375: asn1_parser_t *parser;
! 376: chunk_t object;
! 377: int objectID;
! 378: int attr_oid = OID_UNKNOWN;
! 379: bool success = FALSE;
! 380:
! 381: parser = asn1_parser_create(certificationRequestObjects, this->encoding);
! 382:
! 383: while (parser->iterate(parser, &objectID, &object))
! 384: {
! 385: u_int level = parser->get_level(parser)+1;
! 386:
! 387: switch (objectID)
! 388: {
! 389: case PKCS10_CERT_REQUEST_INFO:
! 390: this->certificationRequestInfo = object;
! 391: break;
! 392: case PKCS10_VERSION:
! 393: if (object.len > 0 && *object.ptr != 0)
! 394: {
! 395: DBG1(DBG_ASN, "PKCS#10 certificate request format is "
! 396: "not version 1");
! 397: goto end;
! 398: }
! 399: break;
! 400: case PKCS10_SUBJECT:
! 401: this->subject = identification_create_from_encoding(ID_DER_ASN1_DN, object);
! 402: DBG2(DBG_ASN, " '%Y'", this->subject);
! 403: break;
! 404: case PKCS10_SUBJECT_PUBLIC_KEY_INFO:
! 405: this->public_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
! 406: KEY_ANY, BUILD_BLOB_ASN1_DER, object, BUILD_END);
! 407: if (!this->public_key)
! 408: {
! 409: goto end;
! 410: }
! 411: break;
! 412: case PKCS10_ATTR_TYPE:
! 413: attr_oid = asn1_known_oid(object);
! 414: break;
! 415: case PKCS10_ATTR_VALUE:
! 416: switch (attr_oid)
! 417: {
! 418: case OID_EXTENSION_REQUEST:
! 419: if (!parse_extension_request(this, object, level))
! 420: {
! 421: goto end;
! 422: }
! 423: break;
! 424: case OID_CHALLENGE_PASSWORD:
! 425: if (!parse_challengePassword(this, object, level))
! 426: {
! 427: goto end;
! 428: }
! 429: break;
! 430: default:
! 431: break;
! 432: }
! 433: break;
! 434: case PKCS10_ALGORITHM:
! 435: INIT(this->scheme);
! 436: if (!signature_params_parse(object, level, this->scheme))
! 437: {
! 438: DBG1(DBG_ASN, " unable to parse signature algorithm");
! 439: goto end;
! 440: }
! 441: break;
! 442: case PKCS10_SIGNATURE:
! 443: this->signature = chunk_skip(object, 1);
! 444: break;
! 445: default:
! 446: break;
! 447: }
! 448: }
! 449: success = parser->success(parser);
! 450:
! 451: end:
! 452: parser->destroy(parser);
! 453: if (success)
! 454: {
! 455: /* check if the certificate request is self-signed */
! 456: if (issued_by(this, &this->public.interface.interface, NULL))
! 457: {
! 458: this->self_signed = TRUE;
! 459: }
! 460: else
! 461: {
! 462: DBG1(DBG_LIB, "certificate request is not self-signed");
! 463: success = FALSE;
! 464: }
! 465: }
! 466: return success;
! 467: }
! 468:
! 469: METHOD(certificate_t, destroy, void,
! 470: private_x509_pkcs10_t *this)
! 471: {
! 472: if (ref_put(&this->ref))
! 473: {
! 474: this->subjectAltNames->destroy_offset(this->subjectAltNames,
! 475: offsetof(identification_t, destroy));
! 476: signature_params_destroy(this->scheme);
! 477: DESTROY_IF(this->subject);
! 478: DESTROY_IF(this->public_key);
! 479: chunk_free(&this->encoding);
! 480: if (!this->parsed)
! 481: { /* only parsed certificate requests point these fields to "encoded" */
! 482: chunk_free(&this->certificationRequestInfo);
! 483: chunk_free(&this->challengePassword);
! 484: chunk_free(&this->signature);
! 485: }
! 486: free(this);
! 487: }
! 488: }
! 489:
! 490: /**
! 491: * create an empty but initialized PKCS#10 certificate request
! 492: */
! 493: static private_x509_pkcs10_t* create_empty(void)
! 494: {
! 495: private_x509_pkcs10_t *this;
! 496:
! 497: INIT(this,
! 498: .public = {
! 499: .interface = {
! 500: .interface = {
! 501: .get_type = _get_type,
! 502: .get_subject = _get_subject,
! 503: .get_issuer = _get_subject,
! 504: .has_subject = _has_subject,
! 505: .has_issuer = _has_subject,
! 506: .issued_by = _issued_by,
! 507: .get_public_key = _get_public_key,
! 508: .get_validity = _get_validity,
! 509: .get_encoding = _get_encoding,
! 510: .equals = _equals,
! 511: .get_ref = _get_ref,
! 512: .destroy = _destroy,
! 513: },
! 514: .get_challengePassword = _get_challengePassword,
! 515: .create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
! 516: },
! 517: },
! 518: .subjectAltNames = linked_list_create(),
! 519: .ref = 1,
! 520: );
! 521:
! 522: return this;
! 523: }
! 524:
! 525: /**
! 526: * Generate and sign a new certificate request
! 527: */
! 528: static bool generate(private_x509_pkcs10_t *cert, private_key_t *sign_key,
! 529: int digest_alg)
! 530: {
! 531: chunk_t key_info, subjectAltNames, attributes;
! 532: chunk_t extensionRequest = chunk_empty;
! 533: chunk_t challengePassword = chunk_empty, sig_scheme = chunk_empty;
! 534: identification_t *subject;
! 535:
! 536: subject = cert->subject;
! 537: cert->public_key = sign_key->get_public_key(sign_key);
! 538:
! 539: /* select signature scheme, if not already specified */
! 540: if (!cert->scheme)
! 541: {
! 542: INIT(cert->scheme,
! 543: .scheme = signature_scheme_from_oid(
! 544: hasher_signature_algorithm_to_oid(digest_alg,
! 545: sign_key->get_type(sign_key))),
! 546: );
! 547: }
! 548: if (cert->scheme->scheme == SIGN_UNKNOWN)
! 549: {
! 550: return FALSE;
! 551: }
! 552: if (!signature_params_build(cert->scheme, &sig_scheme))
! 553: {
! 554: return FALSE;
! 555: }
! 556:
! 557: if (!cert->public_key->get_encoding(cert->public_key,
! 558: PUBKEY_SPKI_ASN1_DER, &key_info))
! 559: {
! 560: chunk_free(&sig_scheme);
! 561: return FALSE;
! 562: }
! 563:
! 564: /* encode subjectAltNames */
! 565: subjectAltNames = x509_build_subjectAltNames(cert->subjectAltNames);
! 566:
! 567: if (subjectAltNames.ptr)
! 568: {
! 569: extensionRequest = asn1_wrap(ASN1_SEQUENCE, "mm",
! 570: asn1_build_known_oid(OID_EXTENSION_REQUEST),
! 571: asn1_wrap(ASN1_SET, "m",
! 572: asn1_wrap(ASN1_SEQUENCE, "m", subjectAltNames)
! 573: ));
! 574: }
! 575: if (cert->challengePassword.len > 0)
! 576: {
! 577: asn1_t type = asn1_is_printablestring(cert->challengePassword) ?
! 578: ASN1_PRINTABLESTRING : ASN1_T61STRING;
! 579:
! 580: challengePassword = asn1_wrap(ASN1_SEQUENCE, "mm",
! 581: asn1_build_known_oid(OID_CHALLENGE_PASSWORD),
! 582: asn1_wrap(ASN1_SET, "m",
! 583: asn1_simple_object(type, cert->challengePassword)
! 584: )
! 585: );
! 586: }
! 587: attributes = asn1_wrap(ASN1_CONTEXT_C_0, "mm", extensionRequest,
! 588: challengePassword);
! 589:
! 590: cert->certificationRequestInfo = asn1_wrap(ASN1_SEQUENCE, "ccmm",
! 591: ASN1_INTEGER_0,
! 592: subject->get_encoding(subject),
! 593: key_info,
! 594: attributes);
! 595:
! 596: if (!sign_key->sign(sign_key, cert->scheme->scheme, cert->scheme->params,
! 597: cert->certificationRequestInfo, &cert->signature))
! 598: {
! 599: chunk_free(&sig_scheme);
! 600: return FALSE;
! 601: }
! 602:
! 603: cert->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm",
! 604: cert->certificationRequestInfo,
! 605: sig_scheme,
! 606: asn1_bitstring("c", cert->signature));
! 607: return TRUE;
! 608: }
! 609:
! 610: /**
! 611: * See header.
! 612: */
! 613: x509_pkcs10_t *x509_pkcs10_load(certificate_type_t type, va_list args)
! 614: {
! 615: chunk_t blob = chunk_empty;
! 616:
! 617: while (TRUE)
! 618: {
! 619: switch (va_arg(args, builder_part_t))
! 620: {
! 621: case BUILD_BLOB_ASN1_DER:
! 622: blob = va_arg(args, chunk_t);
! 623: continue;
! 624: case BUILD_END:
! 625: break;
! 626: default:
! 627: return NULL;
! 628: }
! 629: break;
! 630: }
! 631:
! 632: if (blob.ptr)
! 633: {
! 634: private_x509_pkcs10_t *cert = create_empty();
! 635:
! 636: cert->encoding = chunk_clone(blob);
! 637: cert->parsed = TRUE;
! 638: if (parse_certificate_request(cert))
! 639: {
! 640: return &cert->public;
! 641: }
! 642: destroy(cert);
! 643: }
! 644: return NULL;
! 645: }
! 646:
! 647: /**
! 648: * See header.
! 649: */
! 650: x509_pkcs10_t *x509_pkcs10_gen(certificate_type_t type, va_list args)
! 651: {
! 652: private_x509_pkcs10_t *cert;
! 653: private_key_t *sign_key = NULL;
! 654: hash_algorithm_t digest_alg = HASH_SHA1;
! 655:
! 656: cert = create_empty();
! 657: while (TRUE)
! 658: {
! 659: switch (va_arg(args, builder_part_t))
! 660: {
! 661: case BUILD_SIGNING_KEY:
! 662: sign_key = va_arg(args, private_key_t*);
! 663: continue;
! 664: case BUILD_SUBJECT:
! 665: cert->subject = va_arg(args, identification_t*);
! 666: cert->subject = cert->subject->clone(cert->subject);
! 667: continue;
! 668: case BUILD_SUBJECT_ALTNAMES:
! 669: {
! 670: enumerator_t *enumerator;
! 671: identification_t *id;
! 672: linked_list_t *list;
! 673:
! 674: list = va_arg(args, linked_list_t*);
! 675: enumerator = list->create_enumerator(list);
! 676: while (enumerator->enumerate(enumerator, &id))
! 677: {
! 678: cert->subjectAltNames->insert_last(cert->subjectAltNames,
! 679: id->clone(id));
! 680: }
! 681: enumerator->destroy(enumerator);
! 682: continue;
! 683: }
! 684: case BUILD_CHALLENGE_PWD:
! 685: cert->challengePassword = chunk_clone(va_arg(args, chunk_t));
! 686: continue;
! 687: case BUILD_SIGNATURE_SCHEME:
! 688: cert->scheme = va_arg(args, signature_params_t*);
! 689: cert->scheme = signature_params_clone(cert->scheme);
! 690: continue;
! 691: case BUILD_DIGEST_ALG:
! 692: digest_alg = va_arg(args, int);
! 693: continue;
! 694: case BUILD_END:
! 695: break;
! 696: default:
! 697: destroy(cert);
! 698: return NULL;
! 699: }
! 700: break;
! 701: }
! 702:
! 703: if (sign_key && generate(cert, sign_key, digest_alg))
! 704: {
! 705: return &cert->public;
! 706: }
! 707: destroy(cert);
! 708: return NULL;
! 709: }
! 710:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>