2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * Copyright (C) 2010 secunet Security Networks AG
18 * Copyright (C) 2010 Thomas Egerer
20 * Permission is hereby granted, free of charge, to any person obtaining a copy
21 * of this software and associated documentation files (the "Software"), to deal
22 * in the Software without restriction, including without limitation the rights
23 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24 * copies of the Software, and to permit persons to whom the Software is
25 * furnished to do so, subject to the following conditions:
27 * The above copyright notice and this permission notice shall be included in
28 * all copies or substantial portions of the Software.
30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
41 #include <openssl/x509.h>
42 #include <openssl/x509v3.h>
44 #include "openssl_x509.h"
45 #include "openssl_util.h"
49 #include <utils/linked_list.h>
52 typedef struct private_openssl_x509_t private_openssl_x509_t
;
55 * Private data of an openssl_x509_t object.
57 struct private_openssl_x509_t
{
60 * Public openssl_x509_t interface.
62 openssl_x509_t
public;
65 * OpenSSL certificate representation
70 * DER encoded certificate
75 * SHA1 hash of the certificate
92 identification_t
*subject
;
97 identification_t
*issuer
;
100 * Certificates public key
102 public_key_t
*pubkey
;
105 * subjectKeyIdentifier as read from cert
107 chunk_t subjectKeyIdentifier
;
110 * authorityKeyIdentifier as read from cert
112 chunk_t authKeyIdentifier
;
115 * Start time of certificate validity
120 * End time of certificate validity
125 * Signature scheme of the certificate
127 signature_scheme_t scheme
;
132 linked_list_t
*subjectAltNames
;
137 linked_list_t
*issuerAltNames
;
140 * List of CRL URIs, as x509_cdp_t
142 linked_list_t
*crl_uris
;
147 linked_list_t
*ocsp_uris
;
150 * References to this cert
156 * Destroy a CRL URI struct
158 static void crl_uri_destroy(x509_cdp_t
*this)
161 DESTROY_IF(this->issuer
);
166 * Convert a GeneralName to an identification_t.
168 static identification_t
*general_name2id(GENERAL_NAME
*name
)
177 return identification_create_from_encoding(ID_RFC822_ADDR
,
178 openssl_asn1_str2chunk(name
->d
.rfc822Name
));
180 return identification_create_from_encoding(ID_FQDN
,
181 openssl_asn1_str2chunk(name
->d
.dNSName
));
183 return identification_create_from_encoding(ID_DER_ASN1_GN_URI
,
184 openssl_asn1_str2chunk(name
->d
.uniformResourceIdentifier
));
187 chunk_t chunk
= openssl_asn1_str2chunk(name
->d
.iPAddress
);
190 return identification_create_from_encoding(ID_IPV4_ADDR
, chunk
);
194 return identification_create_from_encoding(ID_IPV6_ADDR
, chunk
);
199 return openssl_x509_name2id(name
->d
.directoryName
);
201 if (OBJ_obj2nid(name
->d
.otherName
->type_id
) == NID_ms_upn
&&
202 name
->d
.otherName
->value
->type
== V_ASN1_UTF8STRING
)
204 return identification_create_from_encoding(ID_RFC822_ADDR
,
205 openssl_asn1_str2chunk(
206 name
->d
.otherName
->value
->value
.utf8string
));
214 METHOD(x509_t
, get_flags
, x509_flag_t
,
215 private_openssl_x509_t
*this)
220 METHOD(x509_t
, get_serial
, chunk_t
,
221 private_openssl_x509_t
*this)
223 return openssl_asn1_str2chunk(X509_get_serialNumber(this->x509
));
226 METHOD(x509_t
, get_subjectKeyIdentifier
, chunk_t
,
227 private_openssl_x509_t
*this)
231 if (this->subjectKeyIdentifier
.len
)
233 return this->subjectKeyIdentifier
;
235 if (this->pubkey
->get_fingerprint(this->pubkey
, KEYID_PUBKEY_SHA1
,
243 METHOD(x509_t
, get_authKeyIdentifier
, chunk_t
,
244 private_openssl_x509_t
*this)
246 if (this->authKeyIdentifier
.len
)
248 return this->authKeyIdentifier
;
253 METHOD(x509_t
, get_constraint
, int,
254 private_openssl_x509_t
*this, x509_constraint_t type
)
259 return this->pathlen
;
261 return X509_NO_CONSTRAINT
;
265 METHOD(x509_t
, create_subjectAltName_enumerator
, enumerator_t
*,
266 private_openssl_x509_t
*this)
268 return this->subjectAltNames
->create_enumerator(this->subjectAltNames
);
271 METHOD(x509_t
, create_crl_uri_enumerator
, enumerator_t
*,
272 private_openssl_x509_t
*this)
274 return this->crl_uris
->create_enumerator(this->crl_uris
);
277 METHOD(x509_t
, create_ocsp_uri_enumerator
, enumerator_t
*,
278 private_openssl_x509_t
*this)
280 return this->ocsp_uris
->create_enumerator(this->ocsp_uris
);
283 METHOD(certificate_t
, get_type
, certificate_type_t
,
284 private_openssl_x509_t
*this)
289 METHOD(certificate_t
, get_subject
, identification_t
*,
290 private_openssl_x509_t
*this)
292 return this->subject
;
295 METHOD(certificate_t
, get_issuer
, identification_t
*,
296 private_openssl_x509_t
*this)
301 METHOD(certificate_t
, has_subject
, id_match_t
,
302 private_openssl_x509_t
*this, identification_t
*subject
)
304 identification_t
*current
;
305 enumerator_t
*enumerator
;
306 id_match_t match
, best
;
309 if (subject
->get_type(subject
) == ID_KEY_ID
)
311 encoding
= subject
->get_encoding(subject
);
313 if (chunk_equals(this->hash
, encoding
))
315 return ID_MATCH_PERFECT
;
317 if (this->subjectKeyIdentifier
.len
&&
318 chunk_equals(this->subjectKeyIdentifier
, encoding
))
320 return ID_MATCH_PERFECT
;
323 this->pubkey
->has_fingerprint(this->pubkey
, encoding
))
325 return ID_MATCH_PERFECT
;
328 best
= this->subject
->matches(this->subject
, subject
);
329 enumerator
= create_subjectAltName_enumerator(this);
330 while (enumerator
->enumerate(enumerator
, ¤t
))
332 match
= current
->matches(current
, subject
);
338 enumerator
->destroy(enumerator
);
342 METHOD(certificate_t
, has_issuer
, id_match_t
,
343 private_openssl_x509_t
*this, identification_t
*issuer
)
345 /* issuerAltNames currently not supported */
346 return this->issuer
->matches(this->issuer
, issuer
);
349 METHOD(certificate_t
, issued_by
, bool,
350 private_openssl_x509_t
*this, certificate_t
*issuer
)
354 x509_t
*x509
= (x509_t
*)issuer
;
357 if (&this->public.x509
.interface
== issuer
)
359 if (this->flags
& X509_SELF_SIGNED
)
366 if (issuer
->get_type(issuer
) != CERT_X509
)
370 if (!(x509
->get_flags(x509
) & X509_CA
))
374 if (!this->issuer
->equals(this->issuer
, issuer
->get_subject(issuer
)))
379 if (this->scheme
== SIGN_UNKNOWN
)
383 key
= issuer
->get_public_key(issuer
);
388 tbs
= openssl_i2chunk(X509_CINF
, this->x509
->cert_info
);
389 valid
= key
->verify(key
, this->scheme
, tbs
,
390 openssl_asn1_str2chunk(this->x509
->signature
));
396 METHOD(certificate_t
, get_public_key
, public_key_t
*,
397 private_openssl_x509_t
*this)
399 return this->pubkey
->get_ref(this->pubkey
);
402 METHOD(certificate_t
, get_validity
, bool,
403 private_openssl_x509_t
*this,
404 time_t *when
, time_t *not_before
, time_t *not_after
)
418 *not_before
= this->notBefore
;
422 *not_after
= this->notAfter
;
424 return (t
>= this->notBefore
&& t
<= this->notAfter
);
427 METHOD(certificate_t
, get_encoding
, bool,
428 private_openssl_x509_t
*this, cred_encoding_type_t type
, chunk_t
*encoding
)
430 if (type
== CERT_ASN1_DER
)
432 *encoding
= chunk_clone(this->encoding
);
435 return lib
->encoding
->encode(lib
->encoding
, type
, NULL
, encoding
,
436 CRED_PART_X509_ASN1_DER
, this->encoding
, CRED_PART_END
);
440 METHOD(certificate_t
, equals
, bool,
441 private_openssl_x509_t
*this, certificate_t
*other
)
446 if (this == (private_openssl_x509_t
*)other
)
450 if (other
->get_type(other
) != CERT_X509
)
454 if (other
->equals
== (void*)equals
)
455 { /* skip allocation if we have the same implementation */
456 encoding
= ((private_openssl_x509_t
*)other
)->encoding
;
457 return chunk_equals(this->encoding
, encoding
);
459 if (!other
->get_encoding(other
, CERT_ASN1_DER
, &encoding
))
463 equal
= chunk_equals(this->encoding
, encoding
);
468 METHOD(certificate_t
, get_ref
, certificate_t
*,
469 private_openssl_x509_t
*this)
472 return &this->public.x509
.interface
;
475 METHOD(certificate_t
, destroy
, void,
476 private_openssl_x509_t
*this)
478 if (ref_put(&this->ref
))
482 X509_free(this->x509
);
484 DESTROY_IF(this->subject
);
485 DESTROY_IF(this->issuer
);
486 DESTROY_IF(this->pubkey
);
487 free(this->subjectKeyIdentifier
.ptr
);
488 free(this->authKeyIdentifier
.ptr
);
489 free(this->encoding
.ptr
);
490 free(this->hash
.ptr
);
491 this->subjectAltNames
->destroy_offset(this->subjectAltNames
,
492 offsetof(identification_t
, destroy
));
493 this->issuerAltNames
->destroy_offset(this->issuerAltNames
,
494 offsetof(identification_t
, destroy
));
495 this->crl_uris
->destroy_function(this->crl_uris
, (void*)crl_uri_destroy
);
496 this->ocsp_uris
->destroy_function(this->ocsp_uris
, free
);
502 * Create an empty certificate
504 static private_openssl_x509_t
*create_empty()
506 private_openssl_x509_t
*this;
512 .get_type
= _get_type
,
513 .get_subject
= _get_subject
,
514 .get_issuer
= _get_issuer
,
515 .has_subject
= _has_subject
,
516 .has_issuer
= _has_issuer
,
517 .issued_by
= _issued_by
,
518 .get_public_key
= _get_public_key
,
519 .get_validity
= _get_validity
,
520 .get_encoding
= _get_encoding
,
525 .get_flags
= _get_flags
,
526 .get_serial
= _get_serial
,
527 .get_subjectKeyIdentifier
= _get_subjectKeyIdentifier
,
528 .get_authKeyIdentifier
= _get_authKeyIdentifier
,
529 .get_constraint
= _get_constraint
,
530 .create_subjectAltName_enumerator
= _create_subjectAltName_enumerator
,
531 .create_crl_uri_enumerator
= _create_crl_uri_enumerator
,
532 .create_ocsp_uri_enumerator
= _create_ocsp_uri_enumerator
,
533 .create_ipAddrBlock_enumerator
= (void*)enumerator_create_empty
,
534 .create_name_constraint_enumerator
= (void*)enumerator_create_empty
,
535 .create_cert_policy_enumerator
= (void*)enumerator_create_empty
,
536 .create_policy_mapping_enumerator
= (void*)enumerator_create_empty
,
539 .subjectAltNames
= linked_list_create(),
540 .issuerAltNames
= linked_list_create(),
541 .crl_uris
= linked_list_create(),
542 .ocsp_uris
= linked_list_create(),
543 .pathlen
= X509_NO_CONSTRAINT
,
551 * parse an extionsion containing GENERAL_NAMES into a list
553 static bool parse_generalNames_ext(linked_list_t
*list
,
556 GENERAL_NAMES
*names
;
558 identification_t
*id
;
561 names
= X509V3_EXT_d2i(ext
);
567 num
= sk_GENERAL_NAME_num(names
);
568 for (i
= 0; i
< num
; i
++)
570 name
= sk_GENERAL_NAME_value(names
, i
);
571 id
= general_name2id(name
);
574 list
->insert_last(list
, id
);
576 GENERAL_NAME_free(name
);
578 sk_GENERAL_NAME_free(names
);
583 * parse basic constraints
585 static bool parse_basicConstraints_ext(private_openssl_x509_t
*this,
588 BASIC_CONSTRAINTS
*constraints
;
590 constraints
= (BASIC_CONSTRAINTS
*)X509V3_EXT_d2i(ext
);
595 this->flags
|= X509_CA
;
597 if (constraints
->pathlen
)
599 this->pathlen
= ASN1_INTEGER_get(constraints
->pathlen
);
601 BASIC_CONSTRAINTS_free(constraints
);
608 * Parse CRL distribution points
610 static bool parse_crlDistributionPoints_ext(private_openssl_x509_t
*this,
613 CRL_DIST_POINTS
*cdps
;
615 identification_t
*id
, *issuer
;
618 int i
, j
, k
, point_num
, name_num
, issuer_num
;
620 cdps
= X509V3_EXT_d2i(ext
);
625 point_num
= sk_DIST_POINT_num(cdps
);
626 for (i
= 0; i
< point_num
; i
++)
628 cdp
= sk_DIST_POINT_value(cdps
, i
);
631 if (cdp
->distpoint
&& cdp
->distpoint
->type
== 0 &&
632 cdp
->distpoint
->name
.fullname
)
634 name_num
= sk_GENERAL_NAME_num(cdp
->distpoint
->name
.fullname
);
635 for (j
= 0; j
< name_num
; j
++)
637 id
= general_name2id(sk_GENERAL_NAME_value(
638 cdp
->distpoint
->name
.fullname
, j
));
641 if (asprintf(&uri
, "%Y", id
) > 0)
645 issuer_num
= sk_GENERAL_NAME_num(cdp
->CRLissuer
);
646 for (k
= 0; k
< issuer_num
; k
++)
648 issuer
= general_name2id(
649 sk_GENERAL_NAME_value(cdp
->CRLissuer
, k
));
656 this->crl_uris
->insert_last(
657 this->crl_uris
, entry
);
667 this->crl_uris
->insert_last(this->crl_uris
, entry
);
675 DIST_POINT_free(cdp
);
678 sk_DIST_POINT_free(cdps
);
683 * Parse authorityInfoAccess with OCSP URIs
685 static bool parse_authorityInfoAccess_ext(private_openssl_x509_t
*this,
688 AUTHORITY_INFO_ACCESS
*infos
;
689 ACCESS_DESCRIPTION
*desc
;
690 identification_t
*id
;
694 infos
= X509V3_EXT_d2i(ext
);
699 num
= sk_ACCESS_DESCRIPTION_num(infos
);
700 for (i
= 0; i
< num
; i
++)
702 desc
= sk_ACCESS_DESCRIPTION_value(infos
, i
);
705 if (openssl_asn1_known_oid(desc
->method
) == OID_OCSP
)
707 id
= general_name2id(desc
->location
);
710 if (asprintf(&uri
, "%Y", id
) > 0)
712 this->ocsp_uris
->insert_first(this->ocsp_uris
, uri
);
717 ACCESS_DESCRIPTION_free(desc
);
720 sk_ACCESS_DESCRIPTION_free(infos
);
725 * Parse authorityKeyIdentifier extension
727 static bool parse_authKeyIdentifier_ext(private_openssl_x509_t
*this,
730 AUTHORITY_KEYID
*keyid
;
732 keyid
= (AUTHORITY_KEYID
*)X509V3_EXT_d2i(ext
);
735 free(this->authKeyIdentifier
.ptr
);
736 this->authKeyIdentifier
= chunk_clone(
737 openssl_asn1_str2chunk(keyid
->keyid
));
738 AUTHORITY_KEYID_free(keyid
);
745 * Parse subjectKeyIdentifier extension
747 static bool parse_subjectKeyIdentifier_ext(private_openssl_x509_t
*this,
752 ostr
= openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext
));
753 /* quick and dirty unwrap of octet string */
755 ostr
.ptr
[0] == V_ASN1_OCTET_STRING
&& ostr
.ptr
[1] == ostr
.len
- 2)
757 free(this->subjectKeyIdentifier
.ptr
);
758 this->subjectKeyIdentifier
= chunk_clone(chunk_skip(ostr
, 2));
765 * Parse X509 extensions we are interested in
767 static bool parse_extensions(private_openssl_x509_t
*this)
769 STACK_OF(X509_EXTENSION
) *extensions
;
772 extensions
= this->x509
->cert_info
->extensions
;
775 num
= sk_X509_EXTENSION_num(extensions
);
777 for (i
= 0; i
< num
; i
++)
782 ext
= sk_X509_EXTENSION_value(extensions
, i
);
783 switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext
)))
785 case NID_info_access
:
786 ok
= parse_authorityInfoAccess_ext(this, ext
);
788 case NID_authority_key_identifier
:
789 ok
= parse_authKeyIdentifier_ext(this, ext
);
791 case NID_subject_key_identifier
:
792 ok
= parse_subjectKeyIdentifier_ext(this, ext
);
794 case NID_subject_alt_name
:
795 ok
= parse_generalNames_ext(this->subjectAltNames
, ext
);
797 case NID_issuer_alt_name
:
798 ok
= parse_generalNames_ext(this->issuerAltNames
, ext
);
800 case NID_basic_constraints
:
801 ok
= parse_basicConstraints_ext(this, ext
);
803 case NID_crl_distribution_points
:
804 ok
= parse_crlDistributionPoints_ext(this, ext
);
807 ok
= X509_EXTENSION_get_critical(ext
) == 0 ||
808 !lib
->settings
->get_bool(lib
->settings
,
809 "libstrongswan.x509.enforce_critical", TRUE
);
812 DBG1(DBG_LIB
, "found unsupported critical X.509 extension");
826 * Parse ExtendedKeyUsage
828 static void parse_extKeyUsage(private_openssl_x509_t
*this)
830 EXTENDED_KEY_USAGE
*usage
;
833 usage
= X509_get_ext_d2i(this->x509
, NID_ext_key_usage
, NULL
, NULL
);
836 for (i
= 0; i
< sk_ASN1_OBJECT_num(usage
); i
++)
838 switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(usage
, i
)))
840 case NID_server_auth
:
841 this->flags
|= X509_SERVER_AUTH
;
843 case NID_client_auth
:
844 this->flags
|= X509_CLIENT_AUTH
;
847 this->flags
|= X509_OCSP_SIGNER
;
853 sk_ASN1_OBJECT_pop_free(usage
, ASN1_OBJECT_free
);
858 * Parse a DER encoded x509 certificate
860 static bool parse_certificate(private_openssl_x509_t
*this)
862 const unsigned char *ptr
= this->encoding
.ptr
;
866 this->x509
= d2i_X509(NULL
, &ptr
, this->encoding
.len
);
871 if (X509_get_version(this->x509
) < 0 || X509_get_version(this->x509
) > 2)
873 DBG1(DBG_LIB
, "unsupported x509 version: %d",
874 X509_get_version(this->x509
) + 1);
878 this->subject
= openssl_x509_name2id(X509_get_subject_name(this->x509
));
879 this->issuer
= openssl_x509_name2id(X509_get_issuer_name(this->x509
));
881 switch (openssl_asn1_known_oid(this->x509
->cert_info
->key
->algor
->algorithm
))
883 case OID_RSA_ENCRYPTION
:
884 this->pubkey
= lib
->creds
->create(lib
->creds
,
885 CRED_PUBLIC_KEY
, KEY_RSA
, BUILD_BLOB_ASN1_DER
,
886 openssl_asn1_str2chunk(X509_get0_pubkey_bitstr(this->x509
)),
889 case OID_EC_PUBLICKEY
:
890 /* for ECDSA, we need the full subjectPublicKeyInfo, as it contains
891 * the curve parameters. */
892 chunk
= openssl_i2chunk(X509_PUBKEY
, X509_get_X509_PUBKEY(this->x509
));
893 this->pubkey
= lib
->creds
->create(lib
->creds
,
894 CRED_PUBLIC_KEY
, KEY_ECDSA
, BUILD_BLOB_ASN1_DER
,
899 DBG1(DBG_LIB
, "unsupported public key algorithm");
902 if (!this->subject
|| !this->issuer
|| !this->pubkey
)
907 this->notBefore
= openssl_asn1_to_time(X509_get_notBefore(this->x509
));
908 this->notAfter
= openssl_asn1_to_time(X509_get_notAfter(this->x509
));
911 openssl_asn1_obj2chunk(this->x509
->cert_info
->signature
->algorithm
),
912 openssl_asn1_obj2chunk(this->x509
->sig_alg
->algorithm
)))
916 this->scheme
= signature_scheme_from_oid(openssl_asn1_known_oid(
917 this->x509
->sig_alg
->algorithm
));
919 if (!parse_extensions(this))
923 parse_extKeyUsage(this);
925 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
930 hasher
->allocate_hash(hasher
, this->encoding
, &this->hash
);
931 hasher
->destroy(hasher
);
933 if (issued_by(this, &this->public.x509
.interface
))
935 this->flags
|= X509_SELF_SIGNED
;
940 openssl_x509_t
*openssl_x509_load(certificate_type_t type
, va_list args
)
942 chunk_t blob
= chunk_empty
;
943 x509_flag_t flags
= 0;
947 switch (va_arg(args
, builder_part_t
))
949 case BUILD_BLOB_ASN1_DER
:
950 blob
= va_arg(args
, chunk_t
);
952 case BUILD_X509_FLAG
:
953 flags
|= va_arg(args
, x509_flag_t
);
965 private_openssl_x509_t
*this;
967 this = create_empty();
968 this->encoding
= chunk_clone(blob
);
969 this->flags
|= flags
;
970 if (parse_certificate(this))
972 return &this->public;
974 DBG1(DBG_LIB
, "OpenSSL X.509 parsing failed");