4 * @brief Implementation of x509_t.
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
31 #include <definitions.h>
33 #include <asn1/asn1.h>
35 #include <utils/logger_manager.h>
36 #include <utils/linked_list.h>
37 #include <utils/identification.h>
39 #define CERT_WARNING_INTERVAL 30 /* days */
41 static logger_t
*logger
;
44 * Different kinds of generalNames
46 typedef enum generalNames_t generalNames_t
;
53 GN_DIRECTORY_NAME
= 4,
54 GN_EDI_PARTY_NAME
= 5,
60 typedef struct private_x509_t private_x509_t
;
63 * Private data of a x509_t object.
65 struct private_x509_t
{
67 * Public interface for this certificate.
72 * Time when certificate was installed
77 * X.509 Certificate in DER format
82 * Version of the X.509 certificate
87 * Serial number of the X.509 certificate
92 * ID representing the certificate issuer
94 identification_t
*issuer
;
97 * Start time of certificate validity
102 * End time of certificate validity
107 * ID representing the certificate subject
109 identification_t
*subject
;
112 * List of identification_t's representing subjectAltNames
114 linked_list_t
*subjectAltNames
;
117 * List of identification_t's representing crlDistributionPoints
119 linked_list_t
*crlDistributionPoints
;
122 * Subject RSA public key, if subjectPublicKeyAlgorithm == RSA
124 rsa_public_key_t
*public_key
;
127 * Subject Key Identifier
129 chunk_t subjectKeyID
;
132 * Authority Key Identifier
137 * Authority Key Serial Number
139 chunk_t authKeySerialNumber
;
142 * CA basic constraints flag
146 u_char authority_flags
;
147 chunk_t tbsCertificate
;
150 chunk_t subjectPublicKey
;
151 bool isOcspSigner
; /* ocsp */
152 chunk_t accessLocation
; /* ocsp */
153 /* signatureAlgorithm */
159 * ASN.1 definition of generalName
161 static const asn1Object_t generalNameObjects
[] = {
162 { 0, "otherName", ASN1_CONTEXT_C_0
, ASN1_OPT
|ASN1_BODY
}, /* 0 */
163 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 1 */
164 { 0, "rfc822Name", ASN1_CONTEXT_S_1
, ASN1_OPT
|ASN1_BODY
}, /* 2 */
165 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 3 */
166 { 0, "dnsName", ASN1_CONTEXT_S_2
, ASN1_OPT
|ASN1_BODY
}, /* 4 */
167 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 5 */
168 { 0, "x400Address", ASN1_CONTEXT_S_3
, ASN1_OPT
|ASN1_BODY
}, /* 6 */
169 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 7 */
170 { 0, "directoryName", ASN1_CONTEXT_C_4
, ASN1_OPT
|ASN1_BODY
}, /* 8 */
171 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 9 */
172 { 0, "ediPartyName", ASN1_CONTEXT_C_5
, ASN1_OPT
|ASN1_BODY
}, /* 10 */
173 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 11 */
174 { 0, "URI", ASN1_CONTEXT_S_6
, ASN1_OPT
|ASN1_BODY
}, /* 12 */
175 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 13 */
176 { 0, "ipAddress", ASN1_CONTEXT_S_7
, ASN1_OPT
|ASN1_BODY
}, /* 14 */
177 { 0, "end choice", ASN1_EOC
, ASN1_END
}, /* 15 */
178 { 0, "registeredID", ASN1_CONTEXT_S_8
, ASN1_OPT
|ASN1_BODY
}, /* 16 */
179 { 0, "end choice", ASN1_EOC
, ASN1_END
} /* 17 */
181 #define GN_OBJ_OTHER_NAME 0
182 #define GN_OBJ_RFC822_NAME 2
183 #define GN_OBJ_DNS_NAME 4
184 #define GN_OBJ_X400_ADDRESS 6
185 #define GN_OBJ_DIRECTORY_NAME 8
186 #define GN_OBJ_EDI_PARTY_NAME 10
187 #define GN_OBJ_URI 12
188 #define GN_OBJ_IP_ADDRESS 14
189 #define GN_OBJ_REGISTERED_ID 16
190 #define GN_OBJ_ROOF 18
193 * ASN.1 definition of otherName
195 static const asn1Object_t otherNameObjects
[] = {
196 {0, "type-id", ASN1_OID
, ASN1_BODY
}, /* 0 */
197 {0, "value", ASN1_CONTEXT_C_0
, ASN1_BODY
} /* 1 */
199 #define ON_OBJ_ID_TYPE 0
200 #define ON_OBJ_VALUE 1
201 #define ON_OBJ_ROOF 2
203 * ASN.1 definition of a basicConstraints extension
205 static const asn1Object_t basicConstraintsObjects
[] = {
206 { 0, "basicConstraints", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
207 { 1, "CA", ASN1_BOOLEAN
, ASN1_DEF
|ASN1_BODY
}, /* 1 */
208 { 1, "pathLenConstraint", ASN1_INTEGER
, ASN1_OPT
|ASN1_BODY
}, /* 2 */
209 { 1, "end opt", ASN1_EOC
, ASN1_END
} /* 3 */
211 #define BASIC_CONSTRAINTS_CA 1
212 #define BASIC_CONSTRAINTS_ROOF 4
215 * ASN.1 definition of time
217 static const asn1Object_t timeObjects
[] = {
218 { 0, "utcTime", ASN1_UTCTIME
, ASN1_OPT
|ASN1_BODY
}, /* 0 */
219 { 0, "end opt", ASN1_EOC
, ASN1_END
}, /* 1 */
220 { 0, "generalizeTime",ASN1_GENERALIZEDTIME
, ASN1_OPT
|ASN1_BODY
}, /* 2 */
221 { 0, "end opt", ASN1_EOC
, ASN1_END
} /* 3 */
224 #define TIME_GENERALIZED 2
228 * ASN.1 definition of a keyIdentifier
230 static const asn1Object_t keyIdentifierObjects
[] = {
231 { 0, "keyIdentifier", ASN1_OCTET_STRING
, ASN1_BODY
} /* 0 */
235 * ASN.1 definition of a authorityKeyIdentifier extension
237 static const asn1Object_t authorityKeyIdentifierObjects
[] = {
238 { 0, "authorityKeyIdentifier", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
239 { 1, "keyIdentifier", ASN1_CONTEXT_S_0
, ASN1_OPT
|ASN1_OBJ
}, /* 1 */
240 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 2 */
241 { 1, "authorityCertIssuer", ASN1_CONTEXT_C_1
, ASN1_OPT
|ASN1_OBJ
}, /* 3 */
242 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 4 */
243 { 1, "authorityCertSerialNumber",ASN1_CONTEXT_S_2
, ASN1_OPT
|ASN1_BODY
}, /* 5 */
244 { 1, "end opt", ASN1_EOC
, ASN1_END
} /* 6 */
246 #define AUTH_KEY_ID_KEY_ID 1
247 #define AUTH_KEY_ID_CERT_ISSUER 3
248 #define AUTH_KEY_ID_CERT_SERIAL 5
249 #define AUTH_KEY_ID_ROOF 7
252 * ASN.1 definition of a authorityInfoAccess extension
254 static const asn1Object_t authorityInfoAccessObjects
[] = {
255 { 0, "authorityInfoAccess", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 0 */
256 { 1, "accessDescription", ASN1_SEQUENCE
, ASN1_NONE
}, /* 1 */
257 { 2, "accessMethod", ASN1_OID
, ASN1_BODY
}, /* 2 */
258 { 2, "accessLocation", ASN1_EOC
, ASN1_RAW
}, /* 3 */
259 { 0, "end loop", ASN1_EOC
, ASN1_END
} /* 4 */
261 #define AUTH_INFO_ACCESS_METHOD 2
262 #define AUTH_INFO_ACCESS_LOCATION 3
263 #define AUTH_INFO_ACCESS_ROOF 5
266 * ASN.1 definition of a extendedKeyUsage extension
268 static const asn1Object_t extendedKeyUsageObjects
[] = {
269 { 0, "extendedKeyUsage", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 0 */
270 { 1, "keyPurposeID", ASN1_OID
, ASN1_BODY
}, /* 1 */
271 { 0, "end loop", ASN1_EOC
, ASN1_END
}, /* 2 */
274 #define EXT_KEY_USAGE_PURPOSE_ID 1
275 #define EXT_KEY_USAGE_ROOF 3
278 * ASN.1 definition of generalNames
280 static const asn1Object_t generalNamesObjects
[] = {
281 { 0, "generalNames", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 0 */
282 { 1, "generalName", ASN1_EOC
, ASN1_RAW
}, /* 1 */
283 { 0, "end loop", ASN1_EOC
, ASN1_END
} /* 2 */
285 #define GENERAL_NAMES_GN 1
286 #define GENERAL_NAMES_ROOF 3
290 * ASN.1 definition of crlDistributionPoints
292 static const asn1Object_t crlDistributionPointsObjects
[] = {
293 { 0, "crlDistributionPoints", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 0 */
294 { 1, "DistributionPoint", ASN1_SEQUENCE
, ASN1_NONE
}, /* 1 */
295 { 2, "distributionPoint", ASN1_CONTEXT_C_0
, ASN1_OPT
|ASN1_LOOP
}, /* 2 */
296 { 3, "fullName", ASN1_CONTEXT_C_0
, ASN1_OPT
|ASN1_OBJ
}, /* 3 */
297 { 3, "end choice", ASN1_EOC
, ASN1_END
}, /* 4 */
298 { 3, "nameRelToCRLIssuer",ASN1_CONTEXT_C_1
, ASN1_OPT
|ASN1_BODY
}, /* 5 */
299 { 3, "end choice", ASN1_EOC
, ASN1_END
}, /* 6 */
300 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 7 */
301 { 2, "reasons", ASN1_CONTEXT_C_1
, ASN1_OPT
|ASN1_BODY
}, /* 8 */
302 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 9 */
303 { 2, "crlIssuer", ASN1_CONTEXT_C_2
, ASN1_OPT
|ASN1_BODY
}, /* 10 */
304 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 11 */
305 { 0, "end loop", ASN1_EOC
, ASN1_END
}, /* 12 */
307 #define CRL_DIST_POINTS_FULLNAME 3
308 #define CRL_DIST_POINTS_ROOF 13
311 * ASN.1 definition of an X.509v3 x509
313 static const asn1Object_t certObjects
[] = {
314 { 0, "x509", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 0 */
315 { 1, "tbsCertificate", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 1 */
316 { 2, "DEFAULT v1", ASN1_CONTEXT_C_0
, ASN1_DEF
}, /* 2 */
317 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 3 */
318 { 2, "serialNumber", ASN1_INTEGER
, ASN1_BODY
}, /* 4 */
319 { 2, "signature", ASN1_EOC
, ASN1_RAW
}, /* 5 */
320 { 2, "issuer", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 6 */
321 { 2, "validity", ASN1_SEQUENCE
, ASN1_NONE
}, /* 7 */
322 { 3, "notBefore", ASN1_EOC
, ASN1_RAW
}, /* 8 */
323 { 3, "notAfter", ASN1_EOC
, ASN1_RAW
}, /* 9 */
324 { 2, "subject", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 10 */
325 { 2, "subjectPublicKeyInfo",ASN1_SEQUENCE
, ASN1_NONE
}, /* 11 */
326 { 3, "algorithm", ASN1_EOC
, ASN1_RAW
}, /* 12 */
327 { 3, "subjectPublicKey", ASN1_BIT_STRING
, ASN1_NONE
}, /* 13 */
328 { 4, "RSAPublicKey", ASN1_SEQUENCE
, ASN1_RAW
}, /* 14 */
329 { 2, "issuerUniqueID", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 15 */
330 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 16 */
331 { 2, "subjectUniqueID", ASN1_CONTEXT_C_2
, ASN1_OPT
}, /* 17 */
332 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 18 */
333 { 2, "optional extensions", ASN1_CONTEXT_C_3
, ASN1_OPT
}, /* 19 */
334 { 3, "extensions", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 20 */
335 { 4, "extension", ASN1_SEQUENCE
, ASN1_NONE
}, /* 21 */
336 { 5, "extnID", ASN1_OID
, ASN1_BODY
}, /* 22 */
337 { 5, "critical", ASN1_BOOLEAN
, ASN1_DEF
|ASN1_BODY
}, /* 23 */
338 { 5, "extnValue", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 24 */
339 { 3, "end loop", ASN1_EOC
, ASN1_END
}, /* 25 */
340 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 26 */
341 { 1, "signatureAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 27 */
342 { 1, "signatureValue", ASN1_BIT_STRING
, ASN1_BODY
} /* 28 */
344 #define X509_OBJ_CERTIFICATE 0
345 #define X509_OBJ_TBS_CERTIFICATE 1
346 #define X509_OBJ_VERSION 3
347 #define X509_OBJ_SERIAL_NUMBER 4
348 #define X509_OBJ_SIG_ALG 5
349 #define X509_OBJ_ISSUER 6
350 #define X509_OBJ_NOT_BEFORE 8
351 #define X509_OBJ_NOT_AFTER 9
352 #define X509_OBJ_SUBJECT 10
353 #define X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM 12
354 #define X509_OBJ_SUBJECT_PUBLIC_KEY 13
355 #define X509_OBJ_RSA_PUBLIC_KEY 14
356 #define X509_OBJ_EXTN_ID 22
357 #define X509_OBJ_CRITICAL 23
358 #define X509_OBJ_EXTN_VALUE 24
359 #define X509_OBJ_ALGORITHM 27
360 #define X509_OBJ_SIGNATURE 28
361 #define X509_OBJ_ROOF 29
364 static u_char ASN1_subjectAltName_oid_str
[] = {
365 0x06, 0x03, 0x55, 0x1D, 0x11
368 static const chunk_t ASN1_subjectAltName_oid
= chunk_from_buf(ASN1_subjectAltName_oid_str
);
372 * compare two X.509 x509s by comparing their signatures
374 static bool equals(const private_x509_t
*this, const private_x509_t
*other
)
376 return chunk_equals(this->signature
, other
->signature
);
380 * extracts the basicConstraints extension
382 static bool parse_basicConstraints(chunk_t blob
, int level0
)
390 asn1_init(&ctx
, blob
, level0
, FALSE
);
392 while (objectID
< BASIC_CONSTRAINTS_ROOF
) {
394 if (!extract_object(basicConstraintsObjects
, &objectID
, &object
,&level
, &ctx
))
398 if (objectID
== BASIC_CONSTRAINTS_CA
)
400 isCA
= object
.len
&& *object
.ptr
;
401 logger
->log(logger
, CONTROL
|LEVEL2
, " %s", isCA ?
"TRUE" : "FALSE");
409 * extracts an otherName
412 parse_otherName(chunk_t blob
, int level0
)
418 int oid
= OID_UNKNOWN
;
420 asn1_init(&ctx
, blob
, level0
, FALSE
);
422 while (objectID
< ON_OBJ_ROOF
)
424 if (!extract_object(otherNameObjects
, &objectID
, &object
, &level
, &ctx
))
430 oid
= known_oid(object
);
433 if (oid
== OID_XMPP_ADDR
)
435 if (!parse_asn1_simple_object(&object
, ASN1_UTF8STRING
, level
+ 1, "xmppAddr"))
448 * extracts a generalName
450 static identification_t
*parse_generalName(chunk_t blob
, int level0
)
458 asn1_init(&ctx
, blob
, level0
, FALSE
);
460 while (objectID
< GN_OBJ_ROOF
)
462 id_type_t id_type
= ID_ANY
;
464 if (!extract_object(generalNameObjects
, &objectID
, &object
, &level
, &ctx
))
469 case GN_OBJ_RFC822_NAME
:
470 id_type
= ID_RFC822_ADDR
;
472 case GN_OBJ_DNS_NAME
:
476 id_type
= ID_DER_ASN1_GN_URI
;
478 case GN_OBJ_DIRECTORY_NAME
:
479 id_type
= ID_DER_ASN1_DN
;
481 case GN_OBJ_IP_ADDRESS
:
482 id_type
= ID_IPV4_ADDR
;
484 case GN_OBJ_OTHER_NAME
:
485 if (!parse_otherName(object
, level
+ 1))
488 case GN_OBJ_X400_ADDRESS
:
489 case GN_OBJ_EDI_PARTY_NAME
:
490 case GN_OBJ_REGISTERED_ID
:
496 if (id_type
!= ID_ANY
)
498 identification_t
*gn
= identification_create_from_encoding(id_type
, object
);
499 logger
->log(logger
, CONTROL
|LEVEL2
, " '%s'", gn
->get_string(gn
));
509 * extracts one or several GNs and puts them into a chained list
511 static void parse_generalNames(chunk_t blob
, int level0
, bool implicit
, linked_list_t
*list
)
518 asn1_init(&ctx
, blob
, level0
, implicit
);
520 while (objectID
< GENERAL_NAMES_ROOF
)
522 if (!extract_object(generalNamesObjects
, &objectID
, &object
, &level
, &ctx
))
525 if (objectID
== GENERAL_NAMES_GN
)
527 identification_t
*gn
= parse_generalName(object
, level
+1);
530 list
->insert_last(list
, gn
);
538 * extracts and converts a UTCTIME or GENERALIZEDTIME object
540 time_t parse_time(chunk_t blob
, int level0
)
547 asn1_init(&ctx
, blob
, level0
, FALSE
);
549 while (objectID
< TIME_ROOF
)
551 if (!extract_object(timeObjects
, &objectID
, &object
, &level
, &ctx
))
554 if (objectID
== TIME_UTC
|| objectID
== TIME_GENERALIZED
)
556 return asn1totime(&object
, (objectID
== TIME_UTC
)
557 ? ASN1_UTCTIME
: ASN1_GENERALIZEDTIME
);
565 * extracts a keyIdentifier
567 static chunk_t
parse_keyIdentifier(chunk_t blob
, int level0
, bool implicit
)
574 asn1_init(&ctx
, blob
, level0
, implicit
);
576 extract_object(keyIdentifierObjects
, &objectID
, &object
, &level
, &ctx
);
581 * extracts an authoritykeyIdentifier
583 void parse_authorityKeyIdentifier(chunk_t blob
, int level0
, chunk_t
*authKeyID
, chunk_t
*authKeySerialNumber
)
590 asn1_init(&ctx
, blob
, level0
, FALSE
);
591 while (objectID
< AUTH_KEY_ID_ROOF
)
593 if (!extract_object(authorityKeyIdentifierObjects
, &objectID
, &object
, &level
, &ctx
))
599 case AUTH_KEY_ID_KEY_ID
:
600 *authKeyID
= parse_keyIdentifier(object
, level
+1, TRUE
);
602 case AUTH_KEY_ID_CERT_ISSUER
:
604 /* TODO: parse_generalNames(object, level+1, TRUE); */
607 case AUTH_KEY_ID_CERT_SERIAL
:
608 *authKeySerialNumber
= object
;
618 * extracts an authorityInfoAcess location
620 static void parse_authorityInfoAccess(chunk_t blob
, int level0
, chunk_t
*accessLocation
)
627 u_int accessMethod
= OID_UNKNOWN
;
629 asn1_init(&ctx
, blob
, level0
, FALSE
);
630 while (objectID
< AUTH_INFO_ACCESS_ROOF
)
632 if (!extract_object(authorityInfoAccessObjects
, &objectID
, &object
, &level
, &ctx
))
638 case AUTH_INFO_ACCESS_METHOD
:
639 accessMethod
= known_oid(object
);
641 case AUTH_INFO_ACCESS_LOCATION
:
643 switch (accessMethod
)
646 if (*object
.ptr
== ASN1_CONTEXT_S_6
)
648 if (asn1_length(&object
) == ASN1_INVALID_LENGTH
)
650 logger
->log(logger
, CONTROL
|LEVEL2
, " '%.*s'",(int)object
.len
, object
.ptr
);
651 /* only HTTP(S) URIs accepted */
652 if (strncasecmp(object
.ptr
, "http", 4) == 0)
654 *accessLocation
= object
;
658 logger
->log(logger
, ERROR
|LEVEL2
, "ignoring OCSP InfoAccessLocation with unkown protocol");
661 /* unkown accessMethod, ignoring */
674 * extracts extendedKeyUsage OIDs
676 static bool parse_extendedKeyUsage(chunk_t blob
, int level0
)
683 asn1_init(&ctx
, blob
, level0
, FALSE
);
684 while (objectID
< EXT_KEY_USAGE_ROOF
)
686 if (!extract_object(extendedKeyUsageObjects
, &objectID
, &object
, &level
, &ctx
))
690 if (objectID
== EXT_KEY_USAGE_PURPOSE_ID
&&
691 known_oid(object
) == OID_OCSP_SIGNING
)
701 * extracts one or several crlDistributionPoints and puts them into
704 static void parse_crlDistributionPoints(chunk_t blob
, int level0
, linked_list_t
*list
)
711 asn1_init(&ctx
, blob
, level0
, FALSE
);
712 while (objectID
< CRL_DIST_POINTS_ROOF
)
714 if (!extract_object(crlDistributionPointsObjects
, &objectID
, &object
, &level
, &ctx
))
718 if (objectID
== CRL_DIST_POINTS_FULLNAME
)
720 /* append extracted generalNames to existing chained list */
721 parse_generalNames(object
, level
+1, TRUE
, list
);
730 * Parses an X.509v3 certificate
732 bool parse_x509cert(chunk_t blob
, u_int level0
, private_x509_t
*cert
)
738 u_int extn_oid
= OID_UNKNOWN
;
741 asn1_init(&ctx
, blob
, level0
, FALSE
);
742 while (objectID
< X509_OBJ_ROOF
)
744 if (!extract_object(certObjects
, &objectID
, &object
, &level
, &ctx
))
748 /* those objects which will parsed further need the next higher level */
751 case X509_OBJ_CERTIFICATE
:
752 cert
->certificate
= object
;
754 case X509_OBJ_TBS_CERTIFICATE
:
755 cert
->tbsCertificate
= object
;
757 case X509_OBJ_VERSION
:
758 cert
->version
= (object
.len
) ?
(1+(u_int
)*object
.ptr
) : 1;
759 logger
->log(logger
, CONTROL
|LEVEL2
, " v%d", cert
->version
);
761 case X509_OBJ_SERIAL_NUMBER
:
762 cert
->serialNumber
= object
;
764 case X509_OBJ_SIG_ALG
:
765 cert
->sigAlg
= parse_algorithmIdentifier(object
, level
, NULL
);
767 case X509_OBJ_ISSUER
:
768 cert
->issuer
= identification_create_from_encoding(ID_DER_ASN1_DN
, object
);
769 logger
->log(logger
, CONTROL
|LEVEL1
, " '%s'", cert
->issuer
->get_string(cert
->issuer
));
771 case X509_OBJ_NOT_BEFORE
:
772 cert
->notBefore
= parse_time(object
, level
);
774 case X509_OBJ_NOT_AFTER
:
775 cert
->notAfter
= parse_time(object
, level
);
777 case X509_OBJ_SUBJECT
:
778 cert
->subject
= identification_create_from_encoding(ID_DER_ASN1_DN
, object
);
779 logger
->log(logger
, CONTROL
|LEVEL1
, " '%s'", cert
->subject
->get_string(cert
->subject
));
781 case X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM
:
782 if (parse_algorithmIdentifier(object
, level
, NULL
) != OID_RSA_ENCRYPTION
)
784 logger
->log(logger
, ERROR
|LEVEL1
, " unsupported public key algorithm");
788 case X509_OBJ_SUBJECT_PUBLIC_KEY
:
789 if (ctx
.blobs
[4].len
> 0 && *ctx
.blobs
[4].ptr
== 0x00)
791 /* skip initial bit string octet defining 0 unused bits */
792 ctx
.blobs
[4].ptr
++; ctx
.blobs
[4].len
--;
796 logger
->log(logger
, ERROR
|LEVEL1
, " invalid RSA public key format");
800 case X509_OBJ_RSA_PUBLIC_KEY
:
801 cert
->subjectPublicKey
= object
;
803 case X509_OBJ_EXTN_ID
:
804 extn_oid
= known_oid(object
);
806 case X509_OBJ_CRITICAL
:
807 critical
= object
.len
&& *object
.ptr
;
808 logger
->log(logger
, ERROR
|LEVEL2
, " %s", critical ?
"TRUE" : "FALSE");
810 case X509_OBJ_EXTN_VALUE
:
813 case OID_SUBJECT_KEY_ID
:
814 cert
->subjectKeyID
= parse_keyIdentifier(object
, level
, FALSE
);
816 case OID_SUBJECT_ALT_NAME
:
817 parse_generalNames(object
, level
, FALSE
, cert
->subjectAltNames
);
819 case OID_BASIC_CONSTRAINTS
:
820 cert
->isCA
= parse_basicConstraints(object
, level
);
822 case OID_CRL_DISTRIBUTION_POINTS
:
823 parse_crlDistributionPoints(object
, level
, cert
->crlDistributionPoints
);
825 case OID_AUTHORITY_KEY_ID
:
826 parse_authorityKeyIdentifier(object
, level
, &cert
->authKeyID
, &cert
->authKeySerialNumber
);
828 case OID_AUTHORITY_INFO_ACCESS
:
829 parse_authorityInfoAccess(object
, level
, &cert
->accessLocation
);
831 case OID_EXTENDED_KEY_USAGE
:
832 cert
->isOcspSigner
= parse_extendedKeyUsage(object
, level
);
834 case OID_NS_REVOCATION_URL
:
835 case OID_NS_CA_REVOCATION_URL
:
836 case OID_NS_CA_POLICY_URL
:
838 if (!parse_asn1_simple_object(&object
, ASN1_IA5STRING
, level
, oid_names
[extn_oid
].name
))
846 case X509_OBJ_ALGORITHM
:
847 cert
->algorithm
= parse_algorithmIdentifier(object
, level
, NULL
);
849 case X509_OBJ_SIGNATURE
:
850 cert
->signature
= object
;
857 time(&cert
->installed
);
862 * Implements x509_t.is_valid
864 static err_t
is_valid(const private_x509_t
*this, time_t *until
)
866 char buf
[TIMETOA_BUF
];
868 time_t current_time
= time(NULL
);
870 timetoa(buf
, BUF_LEN
, &this->notBefore
, TRUE
);
871 logger
->log(logger
, CONTROL
|LEVEL1
, " not before : %s", buf
);
872 timetoa(buf
, BUF_LEN
, ¤t_time
, TRUE
);
873 logger
->log(logger
, CONTROL
|LEVEL1
, " current time: %s", buf
);
874 timetoa(buf
, BUF_LEN
, &this->notAfter
, TRUE
);
875 logger
->log(logger
, CONTROL
|LEVEL1
, " not after : %s", buf
);
878 && (*until
== UNDEFINED_TIME
|| this->notAfter
< *until
))
880 *until
= this->notAfter
;
882 if (current_time
< this->notBefore
)
883 return "is not valid yet";
884 if (current_time
> this->notAfter
)
885 return "has expired";
886 logger
->log(logger
, CONTROL
|LEVEL1
, " certificate is valid", buf
);
891 * Implements x509_t.is_ca
893 static bool is_ca(const private_x509_t
*this)
899 * Implements x509_t.equals_subjectAltName
901 static bool equals_subjectAltName(const private_x509_t
*this, identification_t
*id
)
904 iterator_t
*iterator
= this->subjectAltNames
->create_iterator(this->subjectAltNames
, TRUE
);
906 while (iterator
->has_next(iterator
))
908 identification_t
*subjectAltName
;
910 iterator
->current(iterator
, (void**)&subjectAltName
);
911 if (id
->equals(id
, subjectAltName
))
917 iterator
->destroy(iterator
);
922 * Implements x509_t.get_public_key
924 static rsa_public_key_t
*get_public_key(const private_x509_t
*this)
926 return this->public_key
->clone(this->public_key
);
930 * Implements x509_t.get_subject
932 static identification_t
*get_subject(const private_x509_t
*this)
934 return this->subject
;
938 * Implements x509_t.get_issuer
940 static identification_t
*get_issuer(const private_x509_t
*this)
948 static void destroy(private_x509_t
*this)
950 identification_t
*id
;
951 while (this->subjectAltNames
->remove_last(this->subjectAltNames
, (void**)&id
) == SUCCESS
)
955 this->subjectAltNames
->destroy(this->subjectAltNames
);
957 while (this->crlDistributionPoints
->remove_last(this->crlDistributionPoints
, (void**)&id
) == SUCCESS
)
961 this->crlDistributionPoints
->destroy(this->crlDistributionPoints
);
964 this->issuer
->destroy(this->issuer
);
967 this->subject
->destroy(this->subject
);
969 if (this->public_key
)
970 this->public_key
->destroy(this->public_key
);
972 free(this->certificate
.ptr
);
977 * checks if the expiration date has been reached and warns during the
978 * warning_interval of the imminent expiration.
979 * strict=TRUE declares a fatal error, strict=FALSE issues a warning upon expiry.
981 char* check_expiry(time_t expiration_date
, int warning_interval
, bool strict
)
986 if (expiration_date
== UNDEFINED_TIME
)
987 return "ok (expires never)";
989 time_left
= (expiration_date
- time(NULL
));
991 return strict?
"fatal (expired)" : "warning (expired)";
994 static char buf
[35]; /* temporary storage */
995 const char* unit
= "second";
997 if (time_left
> 86400*warning_interval
)
1000 if (time_left
> 172800)
1005 else if (time_left
> 7200)
1010 else if (time_left
> 120)
1015 snprintf(buf
, sizeof(buf
), "warning (expires in %d %s%s)", time_left
, unit
, (time_left
== 1)?
"":"s");
1022 static void log_certificate(const private_x509_t
*this, logger_t
*logger
, bool utc
, bool has_key
)
1024 identification_t
*subject
= this->subject
;
1025 identification_t
*issuer
= this->issuer
;
1026 rsa_public_key_t
*pubkey
= this->public_key
;
1030 /* determine the current time */
1031 time_t now
= time(NULL
);
1033 timetoa(buf
, BUF_LEN
, &this->installed
, utc
);
1034 logger
->log(logger
, CONTROL
, "%s", buf
);
1035 logger
->log(logger
, CONTROL
, " subject: '%s'", subject
->get_string(subject
));
1036 logger
->log(logger
, CONTROL
, " issuer: '%s'", issuer
->get_string(issuer
));
1038 chunk_to_hex(buf
, BUF_LEN
, this->serialNumber
);
1039 logger
->log(logger
, CONTROL
, " serial: %s", buf
);
1041 timetoa(buf
, BUF_LEN
, &this->notBefore
, utc
);
1042 logger
->log(logger
, CONTROL
, " validity: not before %s %s", buf
,
1043 (this->notBefore
< now
)?
"ok":"fatal (not valid yet)");
1045 timetoa(buf
, BUF_LEN
, &this->notAfter
, utc
);
1046 logger
->log(logger
, CONTROL
, " not after %s %s", buf
,
1047 check_expiry(this->notAfter
, CERT_WARNING_INTERVAL
, TRUE
));
1049 logger
->log(logger
, CONTROL
, " pubkey: RSA %d bits%s",
1050 BITS_PER_BYTE
* pubkey
->get_keysize(pubkey
), has_key?
", has private key":"");
1051 chunk_to_hex(buf
, BUF_LEN
, pubkey
->get_keyid(pubkey
));
1052 logger
->log(logger
, CONTROL
, " keyid: %s", buf
);
1054 if (this->subjectKeyID
.ptr
!= NULL
)
1056 chunk_to_hex(buf
, BUF_LEN
, this->subjectKeyID
);
1057 logger
->log(logger
, CONTROL
, " subjkey: %s", buf
);
1059 if (this->authKeyID
.ptr
!= NULL
)
1061 chunk_to_hex(buf
, BUF_LEN
, this->authKeyID
);
1062 logger
->log(logger
, CONTROL
, " authkey: %s", buf
);
1064 if (this->authKeySerialNumber
.ptr
!= NULL
)
1066 chunk_to_hex(buf
, BUF_LEN
, this->authKeySerialNumber
);
1067 logger
->log(logger
, CONTROL
, " aserial: %s", buf
);
1072 * Described in header.
1074 x509_t
*x509_create_from_chunk(chunk_t chunk
)
1076 private_x509_t
*this = malloc_thing(private_x509_t
);
1079 this->subjectPublicKey
= CHUNK_INITIALIZER
;
1080 this->public_key
= NULL
;
1081 this->subject
= NULL
;
1082 this->issuer
= NULL
;
1083 this->subjectAltNames
= linked_list_create();
1084 this->crlDistributionPoints
= linked_list_create();
1085 this->subjectKeyID
= CHUNK_INITIALIZER
;
1086 this->authKeyID
= CHUNK_INITIALIZER
;
1087 this->authKeySerialNumber
= CHUNK_INITIALIZER
;
1089 /* public functions */
1090 this->public.equals
= (bool (*) (const x509_t
*,const x509_t
*))equals
;
1091 this->public.equals_subjectAltName
= (bool (*) (const x509_t
*,identification_t
*))equals_subjectAltName
;
1092 this->public.is_valid
= (err_t (*) (const x509_t
*,time_t*))is_valid
;
1093 this->public.is_ca
= (bool (*) (const x509_t
*))is_ca
;
1094 this->public.destroy
= (void (*) (x509_t
*))destroy
;
1095 this->public.get_public_key
= (rsa_public_key_t
* (*) (const x509_t
*))get_public_key
;
1096 this->public.get_subject
= (identification_t
* (*) (const x509_t
*))get_subject
;
1097 this->public.get_issuer
= (identification_t
* (*) (const x509_t
*))get_issuer
;
1098 this->public.log_certificate
= (void (*) (const x509_t
*,logger_t
*,bool,bool))log_certificate
;
1100 /* we do not use a per-instance logger right now, since its not always accessible */
1101 logger
= logger_manager
->get_logger(logger_manager
, ASN1
);
1103 if (!parse_x509cert(chunk
, 0, this))
1109 /* extract public key from certificate */
1110 this->public_key
= rsa_public_key_create_from_chunk(this->subjectPublicKey
);
1111 if (this->public_key
== NULL
)
1117 return &this->public;
1121 * Described in header.
1123 x509_t
*x509_create_from_file(const char *filename
, const char *label
)
1126 chunk_t chunk
= CHUNK_INITIALIZER
;
1127 x509_t
*cert
= NULL
;
1129 if (!pem_asn1_load_file(filename
, "", label
, &chunk
, &pgp
))
1132 cert
= x509_create_from_chunk(chunk
);