2 * Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
3 * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
4 * Copyright (C) 2002 Mario Strasser
5 * Copyright (C) 2000-2006 Andreas Steffen
6 * Copyright (C) 2006-2009 Martin Willi
7 * Copyright (C) 2008 Tobias Brunner
8 * Hochschule fuer Technik Rapperswil
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 #include "x509_cert.h"
34 #include <asn1/asn1.h>
35 #include <asn1/asn1_parser.h>
36 #include <crypto/hashers/hasher.h>
37 #include <credentials/keys/private_key.h>
38 #include <utils/linked_list.h>
39 #include <utils/identification.h>
42 * Different kinds of generalNames
49 GN_DIRECTORY_NAME
= 4,
50 GN_EDI_PARTY_NAME
= 5,
57 typedef struct private_x509_cert_t private_x509_cert_t
;
60 * Private data of a x509_cert_t object.
62 struct private_x509_cert_t
{
64 * Public interface for this certificate.
69 * X.509 certificate encoding in ASN.1 DER format
74 * SHA1 hash of the DER encoding of this X.509 certificate
76 chunk_t encoding_hash
;
79 * X.509 certificate body over which signature is computed
81 chunk_t tbsCertificate
;
84 * Version of the X.509 certificate
89 * Serial number of the X.509 certificate
94 * ID representing the certificate issuer
96 identification_t
*issuer
;
99 * Start time of certificate validity
104 * End time of certificate validity
109 * ID representing the certificate subject
111 identification_t
*subject
;
114 * List of subjectAltNames as identification_t
116 linked_list_t
*subjectAltNames
;
119 * List of crlDistributionPoints as allocated char*
121 linked_list_t
*crl_uris
;
124 * List ocspAccessLocations as allocated char*
126 linked_list_t
*ocsp_uris
;
129 * certificate's embedded public key
131 public_key_t
*public_key
;
134 * Subject Key Identifier
136 chunk_t subjectKeyID
;
139 * Authority Key Identifier
141 chunk_t authKeyIdentifier
;
144 * Authority Key Serial Number
146 chunk_t authKeySerialNumber
;
149 * x509 constraints and other flags
154 * Signature algorithm
164 * Certificate parsed from blob/file?
174 static const chunk_t ASN1_subjectAltName_oid
= chunk_from_chars(
175 0x06, 0x03, 0x55, 0x1D, 0x11
179 * ASN.1 definition of a basicConstraints extension
181 static const asn1Object_t basicConstraintsObjects
[] = {
182 { 0, "basicConstraints", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
183 { 1, "CA", ASN1_BOOLEAN
, ASN1_DEF
|ASN1_BODY
}, /* 1 */
184 { 1, "pathLenConstraint", ASN1_INTEGER
, ASN1_OPT
|ASN1_BODY
}, /* 2 */
185 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 3 */
186 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
188 #define BASIC_CONSTRAINTS_CA 1
191 * Extracts the basicConstraints extension
193 static bool parse_basicConstraints(chunk_t blob
, int level0
)
195 asn1_parser_t
*parser
;
200 parser
= asn1_parser_create(basicConstraintsObjects
, blob
);
201 parser
->set_top_level(parser
, level0
);
203 while (parser
->iterate(parser
, &objectID
, &object
))
205 if (objectID
== BASIC_CONSTRAINTS_CA
)
207 isCA
= object
.len
&& *object
.ptr
;
208 DBG2(" %s", isCA ?
"TRUE" : "FALSE");
211 parser
->destroy(parser
);
217 * ASN.1 definition of otherName
219 static const asn1Object_t otherNameObjects
[] = {
220 {0, "type-id", ASN1_OID
, ASN1_BODY
}, /* 0 */
221 {0, "value", ASN1_CONTEXT_C_0
, ASN1_BODY
}, /* 1 */
222 {0, "exit", ASN1_EOC
, ASN1_EXIT
}
224 #define ON_OBJ_ID_TYPE 0
225 #define ON_OBJ_VALUE 1
228 * Extracts an otherName
230 static bool parse_otherName(chunk_t blob
, int level0
)
232 asn1_parser_t
*parser
;
235 int oid
= OID_UNKNOWN
;
236 bool success
= FALSE
;
238 parser
= asn1_parser_create(otherNameObjects
, blob
);
239 parser
->set_top_level(parser
, level0
);
241 while (parser
->iterate(parser
, &objectID
, &object
))
246 oid
= asn1_known_oid(object
);
249 if (oid
== OID_XMPP_ADDR
)
251 if (!asn1_parse_simple_object(&object
, ASN1_UTF8STRING
,
252 parser
->get_level(parser
)+1, "xmppAddr"))
262 success
= parser
->success(parser
);
265 parser
->destroy(parser
);
270 * ASN.1 definition of generalName
272 static const asn1Object_t generalNameObjects
[] = {
273 { 0, "otherName", ASN1_CONTEXT_C_0
, ASN1_OPT
|ASN1_BODY
}, /* 0 */
274 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 1 */
275 { 0, "rfc822Name", ASN1_CONTEXT_S_1
, ASN1_OPT
|ASN1_BODY
}, /* 2 */
276 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 3 */
277 { 0, "dnsName", ASN1_CONTEXT_S_2
, ASN1_OPT
|ASN1_BODY
}, /* 4 */
278 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 5 */
279 { 0, "x400Address", ASN1_CONTEXT_S_3
, ASN1_OPT
|ASN1_BODY
}, /* 6 */
280 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 7 */
281 { 0, "directoryName", ASN1_CONTEXT_C_4
, ASN1_OPT
|ASN1_BODY
}, /* 8 */
282 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 9 */
283 { 0, "ediPartyName", ASN1_CONTEXT_C_5
, ASN1_OPT
|ASN1_BODY
}, /* 10 */
284 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 11 */
285 { 0, "URI", ASN1_CONTEXT_S_6
, ASN1_OPT
|ASN1_BODY
}, /* 12 */
286 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 13 */
287 { 0, "ipAddress", ASN1_CONTEXT_S_7
, ASN1_OPT
|ASN1_BODY
}, /* 14 */
288 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 15 */
289 { 0, "registeredID", ASN1_CONTEXT_S_8
, ASN1_OPT
|ASN1_BODY
}, /* 16 */
290 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 17 */
291 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
293 #define GN_OBJ_OTHER_NAME 0
294 #define GN_OBJ_RFC822_NAME 2
295 #define GN_OBJ_DNS_NAME 4
296 #define GN_OBJ_X400_ADDRESS 6
297 #define GN_OBJ_DIRECTORY_NAME 8
298 #define GN_OBJ_EDI_PARTY_NAME 10
299 #define GN_OBJ_URI 12
300 #define GN_OBJ_IP_ADDRESS 14
301 #define GN_OBJ_REGISTERED_ID 16
304 * Extracts a generalName
306 static identification_t
*parse_generalName(chunk_t blob
, int level0
)
308 asn1_parser_t
*parser
;
312 identification_t
*gn
= NULL
;
314 parser
= asn1_parser_create(generalNameObjects
, blob
);
315 parser
->set_top_level(parser
, level0
);
317 while (parser
->iterate(parser
, &objectID
, &object
))
319 id_type_t id_type
= ID_ANY
;
323 case GN_OBJ_RFC822_NAME
:
324 id_type
= ID_RFC822_ADDR
;
326 case GN_OBJ_DNS_NAME
:
330 id_type
= ID_DER_ASN1_GN_URI
;
332 case GN_OBJ_DIRECTORY_NAME
:
333 id_type
= ID_DER_ASN1_DN
;
335 case GN_OBJ_IP_ADDRESS
:
336 id_type
= ID_IPV4_ADDR
;
338 case GN_OBJ_OTHER_NAME
:
339 if (!parse_otherName(object
, parser
->get_level(parser
)+1))
344 case GN_OBJ_X400_ADDRESS
:
345 case GN_OBJ_EDI_PARTY_NAME
:
346 case GN_OBJ_REGISTERED_ID
:
350 if (id_type
!= ID_ANY
)
352 gn
= identification_create_from_encoding(id_type
, object
);
359 parser
->destroy(parser
);
364 * ASN.1 definition of generalNames
366 static const asn1Object_t generalNamesObjects
[] = {
367 { 0, "generalNames", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 0 */
368 { 1, "generalName", ASN1_EOC
, ASN1_RAW
}, /* 1 */
369 { 0, "end loop", ASN1_EOC
, ASN1_END
}, /* 2 */
370 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
372 #define GENERAL_NAMES_GN 1
375 * Extracts one or several GNs and puts them into a chained list
377 void x509_parse_generalNames(chunk_t blob
, int level0
, bool implicit
, linked_list_t
*list
)
379 asn1_parser_t
*parser
;
383 parser
= asn1_parser_create(generalNamesObjects
, blob
);
384 parser
->set_top_level(parser
, level0
);
385 parser
->set_flags(parser
, implicit
, FALSE
);
387 while (parser
->iterate(parser
, &objectID
, &object
))
389 if (objectID
== GENERAL_NAMES_GN
)
391 identification_t
*gn
= parse_generalName(object
,
392 parser
->get_level(parser
)+1);
396 list
->insert_last(list
, (void *)gn
);
400 parser
->destroy(parser
);
404 * ASN.1 definition of a authorityKeyIdentifier extension
406 static const asn1Object_t authKeyIdentifierObjects
[] = {
407 { 0, "authorityKeyIdentifier", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
408 { 1, "keyIdentifier", ASN1_CONTEXT_S_0
, ASN1_OPT
|ASN1_BODY
}, /* 1 */
409 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 2 */
410 { 1, "authorityCertIssuer", ASN1_CONTEXT_C_1
, ASN1_OPT
|ASN1_OBJ
}, /* 3 */
411 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 4 */
412 { 1, "authorityCertSerialNumber", ASN1_CONTEXT_S_2
, ASN1_OPT
|ASN1_BODY
}, /* 5 */
413 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 6 */
414 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
416 #define AUTH_KEY_ID_KEY_ID 1
417 #define AUTH_KEY_ID_CERT_ISSUER 3
418 #define AUTH_KEY_ID_CERT_SERIAL 5
421 * Extracts an authoritykeyIdentifier
423 chunk_t
x509_parse_authorityKeyIdentifier(chunk_t blob
, int level0
,
424 chunk_t
*authKeySerialNumber
)
426 asn1_parser_t
*parser
;
429 chunk_t authKeyIdentifier
= chunk_empty
;
431 *authKeySerialNumber
= chunk_empty
;
433 parser
= asn1_parser_create(authKeyIdentifierObjects
, blob
);
434 parser
->set_top_level(parser
, level0
);
436 while (parser
->iterate(parser
, &objectID
, &object
))
440 case AUTH_KEY_ID_KEY_ID
:
441 authKeyIdentifier
= chunk_clone(object
);
443 case AUTH_KEY_ID_CERT_ISSUER
:
444 /* TODO: x509_parse_generalNames(object, level+1, TRUE); */
446 case AUTH_KEY_ID_CERT_SERIAL
:
447 *authKeySerialNumber
= object
;
453 parser
->destroy(parser
);
454 return authKeyIdentifier
;
458 * ASN.1 definition of a authorityInfoAccess extension
460 static const asn1Object_t authInfoAccessObjects
[] = {
461 { 0, "authorityInfoAccess", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 0 */
462 { 1, "accessDescription", ASN1_SEQUENCE
, ASN1_NONE
}, /* 1 */
463 { 2, "accessMethod", ASN1_OID
, ASN1_BODY
}, /* 2 */
464 { 2, "accessLocation", ASN1_EOC
, ASN1_RAW
}, /* 3 */
465 { 0, "end loop", ASN1_EOC
, ASN1_END
}, /* 4 */
466 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
468 #define AUTH_INFO_ACCESS_METHOD 2
469 #define AUTH_INFO_ACCESS_LOCATION 3
472 * Extracts an authorityInfoAcess location
474 static void parse_authorityInfoAccess(chunk_t blob
, int level0
,
475 private_x509_cert_t
*this)
477 asn1_parser_t
*parser
;
480 int accessMethod
= OID_UNKNOWN
;
482 parser
= asn1_parser_create(authInfoAccessObjects
, blob
);
483 parser
->set_top_level(parser
, level0
);
485 while (parser
->iterate(parser
, &objectID
, &object
))
489 case AUTH_INFO_ACCESS_METHOD
:
490 accessMethod
= asn1_known_oid(object
);
492 case AUTH_INFO_ACCESS_LOCATION
:
494 switch (accessMethod
)
499 identification_t
*id
;
502 id
= parse_generalName(object
,
503 parser
->get_level(parser
)+1);
506 /* parsing went wrong - abort */
510 if (accessMethod
== OID_OCSP
&&
511 asprintf(&uri
, "%Y", id
) > 0)
513 this->ocsp_uris
->insert_last(this->ocsp_uris
, uri
);
519 /* unkown accessMethod, ignoring */
530 parser
->destroy(parser
);
534 * ASN.1 definition of a extendedKeyUsage extension
536 static const asn1Object_t extendedKeyUsageObjects
[] = {
537 { 0, "extendedKeyUsage", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 0 */
538 { 1, "keyPurposeID", ASN1_OID
, ASN1_BODY
}, /* 1 */
539 { 0, "end loop", ASN1_EOC
, ASN1_END
}, /* 2 */
540 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
542 #define EXT_KEY_USAGE_PURPOSE_ID 1
545 * Extracts extendedKeyUsage OIDs - currently only OCSP_SIGING is returned
547 static bool parse_extendedKeyUsage(chunk_t blob
, int level0
)
549 asn1_parser_t
*parser
;
552 bool ocsp_signing
= FALSE
;
554 parser
= asn1_parser_create(extendedKeyUsageObjects
, blob
);
555 parser
->set_top_level(parser
, level0
);
557 while (parser
->iterate(parser
, &objectID
, &object
))
559 if (objectID
== EXT_KEY_USAGE_PURPOSE_ID
&&
560 asn1_known_oid(object
) == OID_OCSP_SIGNING
)
565 parser
->destroy(parser
);
570 * ASN.1 definition of crlDistributionPoints
572 static const asn1Object_t crlDistributionPointsObjects
[] = {
573 { 0, "crlDistributionPoints", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 0 */
574 { 1, "DistributionPoint", ASN1_SEQUENCE
, ASN1_NONE
}, /* 1 */
575 { 2, "distributionPoint", ASN1_CONTEXT_C_0
, ASN1_OPT
|ASN1_LOOP
}, /* 2 */
576 { 3, "fullName", ASN1_CONTEXT_C_0
, ASN1_OPT
|ASN1_OBJ
}, /* 3 */
577 { 3, "end choice", ASN1_EOC
, ASN1_END
}, /* 4 */
578 { 3, "nameRelToCRLIssuer",ASN1_CONTEXT_C_1
, ASN1_OPT
|ASN1_BODY
}, /* 5 */
579 { 3, "end choice", ASN1_EOC
, ASN1_END
}, /* 6 */
580 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 7 */
581 { 2, "reasons", ASN1_CONTEXT_C_1
, ASN1_OPT
|ASN1_BODY
}, /* 8 */
582 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 9 */
583 { 2, "crlIssuer", ASN1_CONTEXT_C_2
, ASN1_OPT
|ASN1_BODY
}, /* 10 */
584 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 11 */
585 { 0, "end loop", ASN1_EOC
, ASN1_END
}, /* 12 */
586 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
588 #define CRL_DIST_POINTS_FULLNAME 3
591 * Extracts one or several crlDistributionPoints into a list
593 static void parse_crlDistributionPoints(chunk_t blob
, int level0
,
594 private_x509_cert_t
*this)
596 asn1_parser_t
*parser
;
599 linked_list_t
*list
= linked_list_create();
601 parser
= asn1_parser_create(crlDistributionPointsObjects
, blob
);
602 parser
->set_top_level(parser
, level0
);
604 while (parser
->iterate(parser
, &objectID
, &object
))
606 if (objectID
== CRL_DIST_POINTS_FULLNAME
)
608 identification_t
*id
;
610 /* append extracted generalNames to existing chained list */
611 x509_parse_generalNames(object
, parser
->get_level(parser
)+1,
614 while (list
->remove_last(list
, (void**)&id
) == SUCCESS
)
618 if (asprintf(&uri
, "%Y", id
) > 0)
620 this->crl_uris
->insert_last(this->crl_uris
, uri
);
626 parser
->destroy(parser
);
631 * ASN.1 definition of an X.509v3 x509_cert
633 static const asn1Object_t certObjects
[] = {
634 { 0, "x509", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 0 */
635 { 1, "tbsCertificate", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 1 */
636 { 2, "DEFAULT v1", ASN1_CONTEXT_C_0
, ASN1_DEF
}, /* 2 */
637 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 3 */
638 { 2, "serialNumber", ASN1_INTEGER
, ASN1_BODY
}, /* 4 */
639 { 2, "signature", ASN1_EOC
, ASN1_RAW
}, /* 5 */
640 { 2, "issuer", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 6 */
641 { 2, "validity", ASN1_SEQUENCE
, ASN1_NONE
}, /* 7 */
642 { 3, "notBefore", ASN1_EOC
, ASN1_RAW
}, /* 8 */
643 { 3, "notAfter", ASN1_EOC
, ASN1_RAW
}, /* 9 */
644 { 2, "subject", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 10 */
645 { 2, "subjectPublicKeyInfo",ASN1_SEQUENCE
, ASN1_RAW
}, /* 11 */
646 { 2, "issuerUniqueID", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 12 */
647 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 13 */
648 { 2, "subjectUniqueID", ASN1_CONTEXT_C_2
, ASN1_OPT
}, /* 14 */
649 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 15 */
650 { 2, "optional extensions", ASN1_CONTEXT_C_3
, ASN1_OPT
}, /* 16 */
651 { 3, "extensions", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 17 */
652 { 4, "extension", ASN1_SEQUENCE
, ASN1_NONE
}, /* 18 */
653 { 5, "extnID", ASN1_OID
, ASN1_BODY
}, /* 19 */
654 { 5, "critical", ASN1_BOOLEAN
, ASN1_DEF
|ASN1_BODY
}, /* 20 */
655 { 5, "extnValue", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 21 */
656 { 3, "end loop", ASN1_EOC
, ASN1_END
}, /* 22 */
657 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 23 */
658 { 1, "signatureAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 24 */
659 { 1, "signatureValue", ASN1_BIT_STRING
, ASN1_BODY
}, /* 25 */
660 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
662 #define X509_OBJ_TBS_CERTIFICATE 1
663 #define X509_OBJ_VERSION 3
664 #define X509_OBJ_SERIAL_NUMBER 4
665 #define X509_OBJ_SIG_ALG 5
666 #define X509_OBJ_ISSUER 6
667 #define X509_OBJ_NOT_BEFORE 8
668 #define X509_OBJ_NOT_AFTER 9
669 #define X509_OBJ_SUBJECT 10
670 #define X509_OBJ_SUBJECT_PUBLIC_KEY_INFO 11
671 #define X509_OBJ_EXTN_ID 19
672 #define X509_OBJ_CRITICAL 20
673 #define X509_OBJ_EXTN_VALUE 21
674 #define X509_OBJ_ALGORITHM 24
675 #define X509_OBJ_SIGNATURE 25
678 * forward declaration
680 static bool issued_by(private_x509_cert_t
*this, certificate_t
*issuer
);
683 * Parses an X.509v3 certificate
685 static bool parse_certificate(private_x509_cert_t
*this)
687 asn1_parser_t
*parser
;
690 int extn_oid
= OID_UNKNOWN
;
691 int sig_alg
= OID_UNKNOWN
;
692 bool success
= FALSE
;
695 parser
= asn1_parser_create(certObjects
, this->encoding
);
697 while (parser
->iterate(parser
, &objectID
, &object
))
699 u_int level
= parser
->get_level(parser
)+1;
703 case X509_OBJ_TBS_CERTIFICATE
:
704 this->tbsCertificate
= object
;
706 case X509_OBJ_VERSION
:
707 this->version
= (object
.len
) ?
(1+(u_int
)*object
.ptr
) : 1;
708 DBG2(" v%d", this->version
);
710 case X509_OBJ_SERIAL_NUMBER
:
711 this->serialNumber
= object
;
713 case X509_OBJ_SIG_ALG
:
714 sig_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
716 case X509_OBJ_ISSUER
:
717 this->issuer
= identification_create_from_encoding(ID_DER_ASN1_DN
, object
);
718 DBG2(" '%Y'", this->issuer
);
720 case X509_OBJ_NOT_BEFORE
:
721 this->notBefore
= asn1_parse_time(object
, level
);
723 case X509_OBJ_NOT_AFTER
:
724 this->notAfter
= asn1_parse_time(object
, level
);
726 case X509_OBJ_SUBJECT
:
727 this->subject
= identification_create_from_encoding(ID_DER_ASN1_DN
, object
);
728 DBG2(" '%Y'", this->subject
);
730 case X509_OBJ_SUBJECT_PUBLIC_KEY_INFO
:
731 this->public_key
= lib
->creds
->create(lib
->creds
, CRED_PUBLIC_KEY
,
732 KEY_ANY
, BUILD_BLOB_ASN1_DER
, object
, BUILD_END
);
733 if (this->public_key
== NULL
)
738 case X509_OBJ_EXTN_ID
:
739 extn_oid
= asn1_known_oid(object
);
741 case X509_OBJ_CRITICAL
:
742 critical
= object
.len
&& *object
.ptr
;
743 DBG2(" %s", critical ?
"TRUE" : "FALSE");
745 case X509_OBJ_EXTN_VALUE
:
749 case OID_SUBJECT_KEY_ID
:
750 if (!asn1_parse_simple_object(&object
, ASN1_OCTET_STRING
,
751 level
, "keyIdentifier"))
755 this->subjectKeyID
= object
;
757 case OID_SUBJECT_ALT_NAME
:
758 x509_parse_generalNames(object
, level
, FALSE
,
759 this->subjectAltNames
);
761 case OID_BASIC_CONSTRAINTS
:
762 if (parse_basicConstraints(object
, level
))
764 this->flags
|= X509_CA
;
767 case OID_CRL_DISTRIBUTION_POINTS
:
768 parse_crlDistributionPoints(object
, level
, this);
770 case OID_AUTHORITY_KEY_ID
:
771 this->authKeyIdentifier
= x509_parse_authorityKeyIdentifier(object
,
772 level
, &this->authKeySerialNumber
);
774 case OID_AUTHORITY_INFO_ACCESS
:
775 parse_authorityInfoAccess(object
, level
, this);
777 case OID_EXTENDED_KEY_USAGE
:
778 if (parse_extendedKeyUsage(object
, level
))
780 this->flags
|= X509_OCSP_SIGNER
;
783 case OID_NS_REVOCATION_URL
:
784 case OID_NS_CA_REVOCATION_URL
:
785 case OID_NS_CA_POLICY_URL
:
787 if (!asn1_parse_simple_object(&object
, ASN1_IA5STRING
,
788 level
, oid_names
[extn_oid
].name
))
798 case X509_OBJ_ALGORITHM
:
799 this->algorithm
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
800 if (this->algorithm
!= sig_alg
)
802 DBG1(" signature algorithms do not agree");
806 case X509_OBJ_SIGNATURE
:
807 this->signature
= object
;
813 success
= parser
->success(parser
);
816 parser
->destroy(parser
);
821 /* check if the certificate is self-signed */
822 if (issued_by(this, &this->public.interface
.interface
))
824 this->flags
|= X509_SELF_SIGNED
;
826 /* create certificate hash */
827 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
830 DBG1(" unable to create hash of certificate, SHA1 not supported");
833 hasher
->allocate_hash(hasher
, this->encoding
, &this->encoding_hash
);
834 hasher
->destroy(hasher
);
840 * Implementation of certificate_t.get_type
842 static certificate_type_t
get_type(private_x509_cert_t
*this)
848 * Implementation of certificate_t.get_subject
850 static identification_t
* get_subject(private_x509_cert_t
*this)
852 return this->subject
;
856 * Implementation of certificate_t.get_issuer
858 static identification_t
* get_issuer(private_x509_cert_t
*this)
864 * Implementation of certificate_t.has_subject.
866 static id_match_t
has_subject(private_x509_cert_t
*this, identification_t
*subject
)
868 identification_t
*current
;
869 enumerator_t
*enumerator
;
870 id_match_t match
, best
;
872 if (this->encoding_hash
.ptr
&& subject
->get_type(subject
) == ID_KEY_ID
)
874 if (chunk_equals(this->encoding_hash
, subject
->get_encoding(subject
)))
876 return ID_MATCH_PERFECT
;
880 best
= this->subject
->matches(this->subject
, subject
);
881 enumerator
= this->subjectAltNames
->create_enumerator(this->subjectAltNames
);
882 while (enumerator
->enumerate(enumerator
, ¤t
))
884 match
= current
->matches(current
, subject
);
890 enumerator
->destroy(enumerator
);
895 * Implementation of certificate_t.has_subject.
897 static id_match_t
has_issuer(private_x509_cert_t
*this, identification_t
*issuer
)
899 /* issuerAltNames currently not supported */
900 return this->issuer
->matches(this->issuer
, issuer
);
904 * Implementation of certificate_t.issued_by
906 static bool issued_by(private_x509_cert_t
*this, certificate_t
*issuer
)
909 signature_scheme_t scheme
;
911 x509_t
*x509
= (x509_t
*)issuer
;
913 if (&this->public.interface
.interface
== issuer
)
915 if (this->flags
& X509_SELF_SIGNED
)
922 if (issuer
->get_type(issuer
) != CERT_X509
)
926 if (!(x509
->get_flags(x509
) & X509_CA
))
931 if (!this->issuer
->equals(this->issuer
, issuer
->get_subject(issuer
)))
936 /* determine signature scheme */
937 scheme
= signature_scheme_from_oid(this->algorithm
);
938 if (scheme
== SIGN_UNKNOWN
)
942 /* get the public key of the issuer */
943 key
= issuer
->get_public_key(issuer
);
948 valid
= key
->verify(key
, scheme
, this->tbsCertificate
, this->signature
);
954 * Implementation of certificate_t.get_public_key
956 static public_key_t
* get_public_key(private_x509_cert_t
*this)
958 this->public_key
->get_ref(this->public_key
);
959 return this->public_key
;
963 * Implementation of certificate_t.get_ref
965 static private_x509_cert_t
* get_ref(private_x509_cert_t
*this)
972 * Implementation of x509_cert_t.get_flags.
974 static x509_flag_t
get_flags(private_x509_cert_t
*this)
980 * Implementation of x509_cert_t.get_validity.
982 static bool get_validity(private_x509_cert_t
*this, time_t *when
,
983 time_t *not_before
, time_t *not_after
)
997 *not_before
= this->notBefore
;
1001 *not_after
= this->notAfter
;
1003 return (t
>= this->notBefore
&& t
<= this->notAfter
);
1007 * Implementation of certificate_t.is_newer.
1009 static bool is_newer(certificate_t
*this, certificate_t
*that
)
1011 time_t this_update
, that_update
, now
= time(NULL
);
1014 this->get_validity(this, &now
, &this_update
, NULL
);
1015 that
->get_validity(that
, &now
, &that_update
, NULL
);
1016 new = this_update
> that_update
;
1017 DBG1(" certificate from %T is %s - existing certificate from %T %s",
1018 &this_update
, FALSE
, new ?
"newer":"not newer",
1019 &that_update
, FALSE
, new ?
"replaced":"retained");
1024 * Implementation of certificate_t.get_encoding.
1026 static chunk_t
get_encoding(private_x509_cert_t
*this)
1028 return chunk_clone(this->encoding
);
1032 * Implementation of certificate_t.equals.
1034 static bool equals(private_x509_cert_t
*this, certificate_t
*other
)
1039 if (this == (private_x509_cert_t
*)other
)
1043 if (other
->get_type(other
) != CERT_X509
)
1047 if (other
->equals
== (void*)equals
)
1048 { /* skip allocation if we have the same implementation */
1049 return chunk_equals(this->encoding
, ((private_x509_cert_t
*)other
)->encoding
);
1051 encoding
= other
->get_encoding(other
);
1052 equal
= chunk_equals(this->encoding
, encoding
);
1058 * Implementation of x509_t.get_serial.
1060 static chunk_t
get_serial(private_x509_cert_t
*this)
1062 return this->serialNumber
;
1066 * Implementation of x509_t.get_authKeyIdentifier.
1068 static chunk_t
get_authKeyIdentifier(private_x509_cert_t
*this)
1070 return this->authKeyIdentifier
;
1074 * Implementation of x509_cert_t.create_subjectAltName_enumerator.
1076 static enumerator_t
* create_subjectAltName_enumerator(private_x509_cert_t
*this)
1078 return this->subjectAltNames
->create_enumerator(this->subjectAltNames
);
1082 * Implementation of x509_cert_t.create_ocsp_uri_enumerator.
1084 static enumerator_t
* create_ocsp_uri_enumerator(private_x509_cert_t
*this)
1086 return this->ocsp_uris
->create_enumerator(this->ocsp_uris
);
1090 * Implementation of x509_cert_t.create_crl_uri_enumerator.
1092 static enumerator_t
* create_crl_uri_enumerator(private_x509_cert_t
*this)
1094 return this->crl_uris
->create_enumerator(this->crl_uris
);
1098 * Implementation of certificate_t.destroy.
1100 static void destroy(private_x509_cert_t
*this)
1102 if (ref_put(&this->ref
))
1104 this->subjectAltNames
->destroy_offset(this->subjectAltNames
,
1105 offsetof(identification_t
, destroy
));
1106 this->crl_uris
->destroy_function(this->crl_uris
, free
);
1107 this->ocsp_uris
->destroy_function(this->ocsp_uris
, free
);
1108 DESTROY_IF(this->issuer
);
1109 DESTROY_IF(this->subject
);
1110 DESTROY_IF(this->public_key
);
1111 chunk_free(&this->authKeyIdentifier
);
1112 chunk_free(&this->encoding
);
1113 chunk_free(&this->encoding_hash
);
1115 { /* only parsed certificates point these fields to "encoded" */
1116 chunk_free(&this->signature
);
1117 chunk_free(&this->serialNumber
);
1118 chunk_free(&this->tbsCertificate
);
1125 * create an empty but initialized X.509 certificate
1127 static private_x509_cert_t
* create_empty(void)
1129 private_x509_cert_t
*this = malloc_thing(private_x509_cert_t
);
1131 this->public.interface
.interface
.get_type
= (certificate_type_t (*) (certificate_t
*))get_type
;
1132 this->public.interface
.interface
.get_subject
= (identification_t
* (*) (certificate_t
*))get_subject
;
1133 this->public.interface
.interface
.get_issuer
= (identification_t
* (*) (certificate_t
*))get_issuer
;
1134 this->public.interface
.interface
.has_subject
= (id_match_t (*) (certificate_t
*, identification_t
*))has_subject
;
1135 this->public.interface
.interface
.has_issuer
= (id_match_t (*) (certificate_t
*, identification_t
*))has_issuer
;
1136 this->public.interface
.interface
.issued_by
= (bool (*) (certificate_t
*, certificate_t
*))issued_by
;
1137 this->public.interface
.interface
.get_public_key
= (public_key_t
* (*) (certificate_t
*))get_public_key
;
1138 this->public.interface
.interface
.get_validity
= (bool (*) (certificate_t
*, time_t*, time_t*, time_t*))get_validity
;
1139 this->public.interface
.interface
.is_newer
= (bool (*) (certificate_t
*,certificate_t
*))is_newer
;
1140 this->public.interface
.interface
.get_encoding
= (chunk_t (*) (certificate_t
*))get_encoding
;
1141 this->public.interface
.interface
.equals
= (bool (*)(certificate_t
*, certificate_t
*))equals
;
1142 this->public.interface
.interface
.get_ref
= (certificate_t
* (*)(certificate_t
*))get_ref
;
1143 this->public.interface
.interface
.destroy
= (void (*)(certificate_t
*))destroy
;
1144 this->public.interface
.get_flags
= (x509_flag_t (*)(x509_t
*))get_flags
;
1145 this->public.interface
.get_serial
= (chunk_t (*)(x509_t
*))get_serial
;
1146 this->public.interface
.get_authKeyIdentifier
= (chunk_t (*)(x509_t
*))get_authKeyIdentifier
;
1147 this->public.interface
.create_subjectAltName_enumerator
= (enumerator_t
* (*)(x509_t
*))create_subjectAltName_enumerator
;
1148 this->public.interface
.create_crl_uri_enumerator
= (enumerator_t
* (*)(x509_t
*))create_crl_uri_enumerator
;
1149 this->public.interface
.create_ocsp_uri_enumerator
= (enumerator_t
* (*)(x509_t
*))create_ocsp_uri_enumerator
;
1151 this->encoding
= chunk_empty
;
1152 this->encoding_hash
= chunk_empty
;
1153 this->tbsCertificate
= chunk_empty
;
1155 this->serialNumber
= chunk_empty
;
1156 this->notBefore
= 0;
1158 this->public_key
= NULL
;
1159 this->subject
= NULL
;
1160 this->issuer
= NULL
;
1161 this->subjectAltNames
= linked_list_create();
1162 this->crl_uris
= linked_list_create();
1163 this->ocsp_uris
= linked_list_create();
1164 this->subjectKeyID
= chunk_empty
;
1165 this->authKeyIdentifier
= chunk_empty
;
1166 this->authKeySerialNumber
= chunk_empty
;
1167 this->algorithm
= 0;
1168 this->signature
= chunk_empty
;
1171 this->parsed
= FALSE
;
1177 * Generate and sign a new certificate
1179 static bool generate(private_x509_cert_t
*cert
, certificate_t
*sign_cert
,
1180 private_key_t
*sign_key
, int digest_alg
)
1182 chunk_t extensions
= chunk_empty
;
1183 chunk_t basicConstraints
= chunk_empty
, subjectAltNames
= chunk_empty
;
1184 chunk_t subjectKeyIdentifier
= chunk_empty
, authKeyIdentifier
= chunk_empty
;
1185 chunk_t crlDistributionPoints
= chunk_empty
, authorityInfoAccess
= chunk_empty
;
1186 identification_t
*issuer
, *subject
;
1188 signature_scheme_t scheme
;
1190 enumerator_t
*enumerator
;
1191 identification_t
*id
;
1194 subject
= cert
->subject
;
1197 issuer
= sign_cert
->get_subject(sign_cert
);
1198 if (!cert
->public_key
)
1206 if (!cert
->public_key
)
1208 cert
->public_key
= sign_key
->get_public_key(sign_key
);
1210 cert
->flags
|= X509_SELF_SIGNED
;
1212 cert
->issuer
= issuer
->clone(issuer
);
1213 if (!cert
->notBefore
)
1215 cert
->notBefore
= time(NULL
);
1217 if (!cert
->notAfter
)
1218 { /* defaults to 1 year from now */
1219 cert
->notAfter
= cert
->notBefore
+ 60 * 60 * 24 * 365;
1222 /* select signature scheme */
1223 switch (sign_key
->get_type(sign_key
))
1229 cert
->algorithm
= OID_MD5_WITH_RSA
;
1232 cert
->algorithm
= OID_SHA1_WITH_RSA
;
1235 cert
->algorithm
= OID_SHA224_WITH_RSA
;
1238 cert
->algorithm
= OID_SHA256_WITH_RSA
;
1241 cert
->algorithm
= OID_SHA384_WITH_RSA
;
1244 cert
->algorithm
= OID_SHA512_WITH_RSA
;
1254 cert
->algorithm
= OID_ECDSA_WITH_SHA1
;
1257 cert
->algorithm
= OID_ECDSA_WITH_SHA256
;
1260 cert
->algorithm
= OID_ECDSA_WITH_SHA384
;
1263 cert
->algorithm
= OID_ECDSA_WITH_SHA512
;
1272 scheme
= signature_scheme_from_oid(cert
->algorithm
);
1274 if (!cert
->public_key
->get_encoding(cert
->public_key
,
1275 KEY_PUB_SPKI_ASN1_DER
, &key_info
))
1280 enumerator
= cert
->subjectAltNames
->create_enumerator(cert
->subjectAltNames
);
1281 while (enumerator
->enumerate(enumerator
, &id
))
1286 switch (id
->get_type(id
))
1288 case ID_RFC822_ADDR
:
1289 context
= ASN1_CONTEXT_S_1
;
1292 context
= ASN1_CONTEXT_S_2
;
1296 context
= ASN1_CONTEXT_S_7
;
1299 DBG1("encoding %N as subjectAltName not supported",
1300 id_type_names
, id
->get_type(id
));
1301 enumerator
->destroy(enumerator
);
1303 free(subjectAltNames
.ptr
);
1306 name
= asn1_wrap(context
, "c", id
->get_encoding(id
));
1307 subjectAltNames
= chunk_cat("mm", subjectAltNames
, name
);
1309 enumerator
->destroy(enumerator
);
1310 if (subjectAltNames
.ptr
)
1312 subjectAltNames
= asn1_wrap(ASN1_SEQUENCE
, "mm",
1313 asn1_build_known_oid(OID_SUBJECT_ALT_NAME
),
1314 asn1_wrap(ASN1_OCTET_STRING
, "m",
1315 asn1_wrap(ASN1_SEQUENCE
, "m", subjectAltNames
)));
1318 /* encode CRL distribution points extension */
1319 enumerator
= cert
->crl_uris
->create_enumerator(cert
->crl_uris
);
1320 while (enumerator
->enumerate(enumerator
, &uri
))
1322 chunk_t distributionPoint
;
1324 distributionPoint
= asn1_wrap(ASN1_SEQUENCE
, "m",
1325 asn1_wrap(ASN1_CONTEXT_C_0
, "m",
1326 asn1_wrap(ASN1_CONTEXT_C_0
, "m",
1327 asn1_wrap(ASN1_CONTEXT_S_6
, "c",
1328 chunk_create(uri
, strlen(uri
))))));
1330 crlDistributionPoints
= chunk_cat("mm", crlDistributionPoints
,
1333 enumerator
->destroy(enumerator
);
1334 if (crlDistributionPoints
.ptr
)
1336 crlDistributionPoints
= asn1_wrap(ASN1_SEQUENCE
, "mm",
1337 asn1_build_known_oid(OID_CRL_DISTRIBUTION_POINTS
),
1338 asn1_wrap(ASN1_OCTET_STRING
, "m",
1339 asn1_wrap(ASN1_SEQUENCE
, "m", crlDistributionPoints
)));
1342 /* encode OCSP URIs in authorityInfoAccess extension */
1343 enumerator
= cert
->ocsp_uris
->create_enumerator(cert
->ocsp_uris
);
1344 while (enumerator
->enumerate(enumerator
, &uri
))
1346 chunk_t accessDescription
;
1348 accessDescription
= asn1_wrap(ASN1_SEQUENCE
, "mm",
1349 asn1_build_known_oid(OID_OCSP
),
1350 asn1_wrap(ASN1_CONTEXT_S_6
, "c",
1351 chunk_create(uri
, strlen(uri
))));
1352 authorityInfoAccess
= chunk_cat("mm", authorityInfoAccess
,
1355 enumerator
->destroy(enumerator
);
1356 if (authorityInfoAccess
.ptr
)
1358 authorityInfoAccess
= asn1_wrap(ASN1_SEQUENCE
, "mm",
1359 asn1_build_known_oid(OID_AUTHORITY_INFO_ACCESS
),
1360 asn1_wrap(ASN1_OCTET_STRING
, "m",
1361 asn1_wrap(ASN1_SEQUENCE
, "m", authorityInfoAccess
)));
1364 /* build CA basicConstraint for CA certificates */
1365 if (cert
->flags
& X509_CA
)
1369 basicConstraints
= asn1_wrap(ASN1_SEQUENCE
, "mmm",
1370 asn1_build_known_oid(OID_BASIC_CONSTRAINTS
),
1371 asn1_wrap(ASN1_BOOLEAN
, "c",
1372 chunk_from_chars(0xFF)),
1373 asn1_wrap(ASN1_OCTET_STRING
, "m",
1374 asn1_wrap(ASN1_SEQUENCE
, "m",
1375 asn1_wrap(ASN1_BOOLEAN
, "c",
1376 chunk_from_chars(0xFF)))));
1377 /* add subjectKeyIdentifier to CA certificates */
1378 if (cert
->public_key
->get_fingerprint(cert
->public_key
,
1379 KEY_ID_PUBKEY_SHA1
, &keyid
))
1381 subjectKeyIdentifier
= asn1_wrap(ASN1_SEQUENCE
, "mm",
1382 asn1_build_known_oid(OID_SUBJECT_KEY_ID
),
1383 asn1_wrap(ASN1_OCTET_STRING
, "m",
1384 asn1_wrap(ASN1_OCTET_STRING
, "c", keyid
)));
1388 { /* add the keyid authKeyIdentifier for non self-signed certificates */
1391 if (sign_key
->get_fingerprint(sign_key
, KEY_ID_PUBKEY_SHA1
, &keyid
))
1393 authKeyIdentifier
= asn1_wrap(ASN1_SEQUENCE
, "mm",
1394 asn1_build_known_oid(OID_AUTHORITY_KEY_ID
),
1395 asn1_wrap(ASN1_OCTET_STRING
, "m",
1396 asn1_wrap(ASN1_SEQUENCE
, "m",
1397 asn1_wrap(ASN1_CONTEXT_S_0
, "c", keyid
))));
1400 if (basicConstraints
.ptr
|| subjectAltNames
.ptr
|| authKeyIdentifier
.ptr
||
1401 crlDistributionPoints
.ptr
)
1403 extensions
= asn1_wrap(ASN1_CONTEXT_C_3
, "m",
1404 asn1_wrap(ASN1_SEQUENCE
, "mmmmmm",
1405 basicConstraints
, subjectKeyIdentifier
,
1406 authKeyIdentifier
, subjectAltNames
,
1407 crlDistributionPoints
, authorityInfoAccess
));
1410 cert
->tbsCertificate
= asn1_wrap(ASN1_SEQUENCE
, "mmmcmcmm",
1411 asn1_simple_object(ASN1_CONTEXT_C_0
, ASN1_INTEGER_2
),
1412 asn1_integer("c", cert
->serialNumber
),
1413 asn1_algorithmIdentifier(cert
->algorithm
),
1414 issuer
->get_encoding(issuer
),
1415 asn1_wrap(ASN1_SEQUENCE
, "mm",
1416 asn1_from_time(&cert
->notBefore
, ASN1_UTCTIME
),
1417 asn1_from_time(&cert
->notAfter
, ASN1_UTCTIME
)),
1418 subject
->get_encoding(subject
),
1419 key_info
, extensions
);
1421 if (!sign_key
->sign(sign_key
, scheme
, cert
->tbsCertificate
, &cert
->signature
))
1425 cert
->encoding
= asn1_wrap(ASN1_SEQUENCE
, "cmm", cert
->tbsCertificate
,
1426 asn1_algorithmIdentifier(cert
->algorithm
),
1427 asn1_bitstring("c", cert
->signature
));
1429 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
1434 hasher
->allocate_hash(hasher
, cert
->encoding
, &cert
->encoding_hash
);
1435 hasher
->destroy(hasher
);
1442 x509_cert_t
*x509_cert_load(certificate_type_t type
, va_list args
)
1444 chunk_t blob
= chunk_empty
;
1448 switch (va_arg(args
, builder_part_t
))
1450 case BUILD_BLOB_ASN1_DER
:
1451 blob
= va_arg(args
, chunk_t
);
1463 private_x509_cert_t
*cert
= create_empty();
1465 cert
->encoding
= chunk_clone(blob
);
1466 cert
->parsed
= TRUE
;
1467 if (parse_certificate(cert
))
1469 return &cert
->public;
1479 x509_cert_t
*x509_cert_gen(certificate_type_t type
, va_list args
)
1481 private_x509_cert_t
*cert
;
1482 certificate_t
*sign_cert
= NULL
;
1483 private_key_t
*sign_key
= NULL
;
1484 hash_algorithm_t digest_alg
= HASH_SHA1
;
1486 cert
= create_empty();
1489 switch (va_arg(args
, builder_part_t
))
1491 case BUILD_X509_FLAG
:
1492 cert
->flags
|= va_arg(args
, x509_flag_t
);
1494 case BUILD_SIGNING_KEY
:
1495 sign_key
= va_arg(args
, private_key_t
*);
1497 case BUILD_SIGNING_CERT
:
1498 sign_cert
= va_arg(args
, certificate_t
*);
1500 case BUILD_PUBLIC_KEY
:
1501 cert
->public_key
= va_arg(args
, public_key_t
*);
1502 cert
->public_key
->get_ref(cert
->public_key
);
1505 cert
->subject
= va_arg(args
, identification_t
*);
1506 cert
->subject
= cert
->subject
->clone(cert
->subject
);
1508 case BUILD_SUBJECT_ALTNAMES
:
1510 enumerator_t
*enumerator
;
1511 identification_t
*id
;
1512 linked_list_t
*list
;
1514 list
= va_arg(args
, linked_list_t
*);
1515 enumerator
= list
->create_enumerator(list
);
1516 while (enumerator
->enumerate(enumerator
, &id
))
1518 cert
->subjectAltNames
->insert_last(
1519 cert
->subjectAltNames
, id
->clone(id
));
1521 enumerator
->destroy(enumerator
);
1524 case BUILD_CRL_DISTRIBUTION_POINTS
:
1526 enumerator_t
*enumerator
;
1527 linked_list_t
*list
;
1530 list
= va_arg(args
, linked_list_t
*);
1531 enumerator
= list
->create_enumerator(list
);
1532 while (enumerator
->enumerate(enumerator
, &uri
))
1534 cert
->crl_uris
->insert_last(cert
->crl_uris
, strdup(uri
));
1536 enumerator
->destroy(enumerator
);
1539 case BUILD_OCSP_ACCESS_LOCATIONS
:
1541 enumerator_t
*enumerator
;
1542 linked_list_t
*list
;
1545 list
= va_arg(args
, linked_list_t
*);
1546 enumerator
= list
->create_enumerator(list
);
1547 while (enumerator
->enumerate(enumerator
, &uri
))
1549 cert
->ocsp_uris
->insert_last(cert
->ocsp_uris
, strdup(uri
));
1551 enumerator
->destroy(enumerator
);
1554 case BUILD_NOT_BEFORE_TIME
:
1555 cert
->notBefore
= va_arg(args
, time_t);
1557 case BUILD_NOT_AFTER_TIME
:
1558 cert
->notAfter
= va_arg(args
, time_t);
1561 cert
->serialNumber
= chunk_clone(va_arg(args
, chunk_t
));
1563 case BUILD_DIGEST_ALG
:
1564 digest_alg
= va_arg(args
, int);
1575 if (sign_key
&& generate(cert
, sign_cert
, sign_key
, digest_alg
))
1577 return &cert
->public;