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
;
142 linked_list_t
*crl_uris
;
147 linked_list_t
*ocsp_uris
;
150 * References to this cert
156 * Convert a GeneralName to an identification_t.
158 static identification_t
*general_name2id(GENERAL_NAME
*name
)
167 return identification_create_from_encoding(ID_RFC822_ADDR
,
168 openssl_asn1_str2chunk(name
->d
.rfc822Name
));
170 return identification_create_from_encoding(ID_FQDN
,
171 openssl_asn1_str2chunk(name
->d
.dNSName
));
173 return identification_create_from_encoding(ID_DER_ASN1_GN_URI
,
174 openssl_asn1_str2chunk(name
->d
.uniformResourceIdentifier
));
177 chunk_t chunk
= openssl_asn1_str2chunk(name
->d
.iPAddress
);
180 return identification_create_from_encoding(ID_IPV4_ADDR
, chunk
);
184 return identification_create_from_encoding(ID_IPV6_ADDR
, chunk
);
189 return openssl_x509_name2id(name
->d
.directoryName
);
195 METHOD(x509_t
, get_flags
, x509_flag_t
,
196 private_openssl_x509_t
*this)
201 METHOD(x509_t
, get_serial
, chunk_t
,
202 private_openssl_x509_t
*this)
204 return openssl_asn1_str2chunk(X509_get_serialNumber(this->x509
));
207 METHOD(x509_t
, get_subjectKeyIdentifier
, chunk_t
,
208 private_openssl_x509_t
*this)
212 if (this->subjectKeyIdentifier
.len
)
214 return this->subjectKeyIdentifier
;
216 if (this->pubkey
->get_fingerprint(this->pubkey
, KEYID_PUBKEY_SHA1
,
224 METHOD(x509_t
, get_authKeyIdentifier
, chunk_t
,
225 private_openssl_x509_t
*this)
227 if (this->authKeyIdentifier
.len
)
229 return this->authKeyIdentifier
;
234 METHOD(x509_t
, get_pathLenConstraint
, int,
235 private_openssl_x509_t
*this)
237 return this->pathlen
;
240 METHOD(x509_t
, create_subjectAltName_enumerator
, enumerator_t
*,
241 private_openssl_x509_t
*this)
243 return this->subjectAltNames
->create_enumerator(this->subjectAltNames
);
246 METHOD(x509_t
, create_crl_uri_enumerator
, enumerator_t
*,
247 private_openssl_x509_t
*this)
249 return this->crl_uris
->create_enumerator(this->crl_uris
);
252 METHOD(x509_t
, create_ocsp_uri_enumerator
, enumerator_t
*,
253 private_openssl_x509_t
*this)
255 return this->ocsp_uris
->create_enumerator(this->ocsp_uris
);
258 METHOD(x509_t
, create_ipAddrBlock_enumerator
, enumerator_t
*,
259 private_openssl_x509_t
*this)
262 return enumerator_create_empty();
265 METHOD(certificate_t
, get_type
, certificate_type_t
,
266 private_openssl_x509_t
*this)
271 METHOD(certificate_t
, get_subject
, identification_t
*,
272 private_openssl_x509_t
*this)
274 return this->subject
;
277 METHOD(certificate_t
, get_issuer
, identification_t
*,
278 private_openssl_x509_t
*this)
283 METHOD(certificate_t
, has_subject
, id_match_t
,
284 private_openssl_x509_t
*this, identification_t
*subject
)
286 identification_t
*current
;
287 enumerator_t
*enumerator
;
288 id_match_t match
, best
;
290 if (subject
->get_type(subject
) == ID_KEY_ID
)
292 if (chunk_equals(this->hash
, subject
->get_encoding(subject
)))
294 return ID_MATCH_PERFECT
;
297 best
= this->subject
->matches(this->subject
, subject
);
298 enumerator
= create_subjectAltName_enumerator(this);
299 while (enumerator
->enumerate(enumerator
, ¤t
))
301 match
= current
->matches(current
, subject
);
307 enumerator
->destroy(enumerator
);
311 METHOD(certificate_t
, has_issuer
, id_match_t
,
312 private_openssl_x509_t
*this, identification_t
*issuer
)
314 /* issuerAltNames currently not supported */
315 return this->issuer
->matches(this->issuer
, issuer
);
318 METHOD(certificate_t
, issued_by
, bool,
319 private_openssl_x509_t
*this, certificate_t
*issuer
)
323 x509_t
*x509
= (x509_t
*)issuer
;
326 if (&this->public.x509
.interface
== issuer
)
328 if (this->flags
& X509_SELF_SIGNED
)
335 if (issuer
->get_type(issuer
) != CERT_X509
)
339 if (!(x509
->get_flags(x509
) & X509_CA
))
343 if (!this->issuer
->equals(this->issuer
, issuer
->get_subject(issuer
)))
348 if (this->scheme
== SIGN_UNKNOWN
)
352 key
= issuer
->get_public_key(issuer
);
357 tbs
= openssl_i2chunk(X509_CINF
, this->x509
->cert_info
);
358 valid
= key
->verify(key
, this->scheme
, tbs
,
359 openssl_asn1_str2chunk(this->x509
->signature
));
365 METHOD(certificate_t
, get_public_key
, public_key_t
*,
366 private_openssl_x509_t
*this)
368 return this->pubkey
->get_ref(this->pubkey
);
371 METHOD(certificate_t
, get_validity
, bool,
372 private_openssl_x509_t
*this,
373 time_t *when
, time_t *not_before
, time_t *not_after
)
387 *not_before
= this->notBefore
;
391 *not_after
= this->notAfter
;
393 return (t
>= this->notBefore
&& t
<= this->notAfter
);
396 METHOD(certificate_t
, get_encoding
, chunk_t
,
397 private_openssl_x509_t
*this)
399 return chunk_clone(this->encoding
);
402 METHOD(certificate_t
, equals
, bool,
403 private_openssl_x509_t
*this, certificate_t
*other
)
408 if (this == (private_openssl_x509_t
*)other
)
412 if (other
->get_type(other
) != CERT_X509
)
416 if (other
->equals
== (void*)equals
)
417 { /* skip allocation if we have the same implementation */
418 encoding
= ((private_openssl_x509_t
*)other
)->encoding
;
419 return chunk_equals(this->encoding
, encoding
);
421 encoding
= other
->get_encoding(other
);
422 equal
= chunk_equals(this->encoding
, encoding
);
427 METHOD(certificate_t
, get_ref
, certificate_t
*,
428 private_openssl_x509_t
*this)
431 return &this->public.x509
.interface
;
434 METHOD(certificate_t
, destroy
, void,
435 private_openssl_x509_t
*this)
437 if (ref_put(&this->ref
))
441 X509_free(this->x509
);
443 DESTROY_IF(this->subject
);
444 DESTROY_IF(this->issuer
);
445 DESTROY_IF(this->pubkey
);
446 free(this->subjectKeyIdentifier
.ptr
);
447 free(this->authKeyIdentifier
.ptr
);
448 free(this->encoding
.ptr
);
449 free(this->hash
.ptr
);
450 this->subjectAltNames
->destroy_offset(this->subjectAltNames
,
451 offsetof(identification_t
, destroy
));
452 this->issuerAltNames
->destroy_offset(this->issuerAltNames
,
453 offsetof(identification_t
, destroy
));
454 this->crl_uris
->destroy_function(this->crl_uris
, free
);
455 this->ocsp_uris
->destroy_function(this->ocsp_uris
, free
);
461 * Create an empty certificate
463 static private_openssl_x509_t
*create_empty()
465 private_openssl_x509_t
*this;
471 .get_type
= _get_type
,
472 .get_subject
= _get_subject
,
473 .get_issuer
= _get_issuer
,
474 .has_subject
= _has_subject
,
475 .has_issuer
= _has_issuer
,
476 .issued_by
= _issued_by
,
477 .get_public_key
= _get_public_key
,
478 .get_validity
= _get_validity
,
479 .get_encoding
= _get_encoding
,
484 .get_flags
= _get_flags
,
485 .get_serial
= _get_serial
,
486 .get_subjectKeyIdentifier
= _get_subjectKeyIdentifier
,
487 .get_authKeyIdentifier
= _get_authKeyIdentifier
,
488 .get_pathLenConstraint
= _get_pathLenConstraint
,
489 .create_subjectAltName_enumerator
= _create_subjectAltName_enumerator
,
490 .create_crl_uri_enumerator
= _create_crl_uri_enumerator
,
491 .create_ocsp_uri_enumerator
= _create_ocsp_uri_enumerator
,
492 .create_ipAddrBlock_enumerator
= _create_ipAddrBlock_enumerator
,
495 .subjectAltNames
= linked_list_create(),
496 .issuerAltNames
= linked_list_create(),
497 .crl_uris
= linked_list_create(),
498 .ocsp_uris
= linked_list_create(),
499 .pathlen
= X509_NO_PATH_LEN_CONSTRAINT
,
507 * parse an extionsion containing GENERAL_NAMES into a list
509 static bool parse_generalNames_ext(linked_list_t
*list
,
512 GENERAL_NAMES
*names
;
514 identification_t
*id
;
517 names
= X509V3_EXT_d2i(ext
);
523 num
= sk_GENERAL_NAME_num(names
);
524 for (i
= 0; i
< num
; i
++)
526 name
= sk_GENERAL_NAME_value(names
, i
);
527 id
= general_name2id(name
);
530 list
->insert_last(list
, id
);
532 GENERAL_NAME_free(name
);
534 sk_GENERAL_NAME_free(names
);
539 * parse basic constraints
541 static bool parse_basicConstraints_ext(private_openssl_x509_t
*this,
544 BASIC_CONSTRAINTS
*constraints
;
546 constraints
= (BASIC_CONSTRAINTS
*)X509V3_EXT_d2i(ext
);
551 this->flags
|= X509_CA
;
553 if (constraints
->pathlen
)
555 this->pathlen
= ASN1_INTEGER_get(constraints
->pathlen
);
557 BASIC_CONSTRAINTS_free(constraints
);
564 * Parse CRL distribution points
566 static bool parse_crlDistributionPoints_ext(private_openssl_x509_t
*this,
569 CRL_DIST_POINTS
*cdps
;
571 identification_t
*id
;
573 int i
, j
, point_num
, name_num
;
575 cdps
= X509V3_EXT_d2i(ext
);
580 point_num
= sk_DIST_POINT_num(cdps
);
581 for (i
= 0; i
< point_num
; i
++)
583 cdp
= sk_DIST_POINT_value(cdps
, i
);
586 if (cdp
->distpoint
&& cdp
->distpoint
->type
== 0 &&
587 cdp
->distpoint
->name
.fullname
)
589 name_num
= sk_GENERAL_NAME_num(cdp
->distpoint
->name
.fullname
);
590 for (j
= 0; j
< name_num
; j
++)
592 id
= general_name2id(sk_GENERAL_NAME_value(
593 cdp
->distpoint
->name
.fullname
, j
));
596 if (asprintf(&uri
, "%Y", id
) > 0)
598 this->crl_uris
->insert_first(this->crl_uris
, uri
);
604 DIST_POINT_free(cdp
);
607 sk_DIST_POINT_free(cdps
);
612 * Parse authorityInfoAccess with OCSP URIs
614 static bool parse_authorityInfoAccess_ext(private_openssl_x509_t
*this,
617 AUTHORITY_INFO_ACCESS
*infos
;
618 ACCESS_DESCRIPTION
*desc
;
619 identification_t
*id
;
623 infos
= X509V3_EXT_d2i(ext
);
628 num
= sk_ACCESS_DESCRIPTION_num(infos
);
629 for (i
= 0; i
< num
; i
++)
631 desc
= sk_ACCESS_DESCRIPTION_value(infos
, i
);
634 if (openssl_asn1_known_oid(desc
->method
) == OID_OCSP
)
636 id
= general_name2id(desc
->location
);
639 if (asprintf(&uri
, "%Y", id
) > 0)
641 this->ocsp_uris
->insert_first(this->ocsp_uris
, uri
);
646 ACCESS_DESCRIPTION_free(desc
);
649 sk_ACCESS_DESCRIPTION_free(infos
);
654 * Parse authorityKeyIdentifier extension
656 static bool parse_authKeyIdentifier_ext(private_openssl_x509_t
*this,
659 AUTHORITY_KEYID
*keyid
;
661 keyid
= (AUTHORITY_KEYID
*)X509V3_EXT_d2i(ext
);
664 free(this->authKeyIdentifier
.ptr
);
665 this->authKeyIdentifier
= chunk_clone(
666 openssl_asn1_str2chunk(keyid
->keyid
));
667 AUTHORITY_KEYID_free(keyid
);
674 * Parse subjectKeyIdentifier extension
676 static bool parse_subjectKeyIdentifier_ext(private_openssl_x509_t
*this,
681 ostr
= openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext
));
682 /* quick and dirty unwrap of octet string */
684 ostr
.ptr
[0] == V_ASN1_OCTET_STRING
&& ostr
.ptr
[1] == ostr
.len
- 2)
686 free(this->subjectKeyIdentifier
.ptr
);
687 this->subjectKeyIdentifier
= chunk_clone(chunk_skip(ostr
, 2));
694 * Parse X509 extensions we are interested in
696 static bool parse_extensions(private_openssl_x509_t
*this)
698 STACK_OF(X509_EXTENSION
) *extensions
;
701 extensions
= this->x509
->cert_info
->extensions
;
704 num
= sk_X509_EXTENSION_num(extensions
);
706 for (i
= 0; i
< num
; i
++)
711 ext
= sk_X509_EXTENSION_value(extensions
, i
);
712 switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext
)))
714 case NID_info_access
:
715 ok
= parse_authorityInfoAccess_ext(this, ext
);
717 case NID_authority_key_identifier
:
718 ok
= parse_authKeyIdentifier_ext(this, ext
);
720 case NID_subject_key_identifier
:
721 ok
= parse_subjectKeyIdentifier_ext(this, ext
);
723 case NID_subject_alt_name
:
724 ok
= parse_generalNames_ext(this->subjectAltNames
, ext
);
726 case NID_issuer_alt_name
:
727 ok
= parse_generalNames_ext(this->issuerAltNames
, ext
);
729 case NID_basic_constraints
:
730 ok
= parse_basicConstraints_ext(this, ext
);
732 case NID_crl_distribution_points
:
733 ok
= parse_crlDistributionPoints_ext(this, ext
);
749 * Parse a DER encoded x509 certificate
751 static bool parse_certificate(private_openssl_x509_t
*this)
753 const unsigned char *ptr
= this->encoding
.ptr
;
757 this->x509
= d2i_X509(NULL
, &ptr
, this->encoding
.len
);
762 this->subject
= openssl_x509_name2id(X509_get_subject_name(this->x509
));
763 this->issuer
= openssl_x509_name2id(X509_get_issuer_name(this->x509
));
765 switch (openssl_asn1_known_oid(this->x509
->cert_info
->key
->algor
->algorithm
))
767 case OID_RSA_ENCRYPTION
:
768 this->pubkey
= lib
->creds
->create(lib
->creds
,
769 CRED_PUBLIC_KEY
, KEY_RSA
, BUILD_BLOB_ASN1_DER
,
770 openssl_asn1_str2chunk(X509_get0_pubkey_bitstr(this->x509
)),
773 case OID_EC_PUBLICKEY
:
774 /* for ECDSA, we need the full subjectPublicKeyInfo, as it contains
775 * the curve parameters. */
776 chunk
= openssl_i2chunk(X509_PUBKEY
, X509_get_X509_PUBKEY(this->x509
));
777 this->pubkey
= lib
->creds
->create(lib
->creds
,
778 CRED_PUBLIC_KEY
, KEY_ECDSA
, BUILD_BLOB_ASN1_DER
,
783 DBG1(DBG_LIB
, "unsupported public key algorithm");
786 if (!this->subject
|| !this->issuer
|| !this->pubkey
)
791 this->notBefore
= openssl_asn1_to_time(X509_get_notBefore(this->x509
));
792 this->notAfter
= openssl_asn1_to_time(X509_get_notAfter(this->x509
));
795 openssl_asn1_obj2chunk(this->x509
->cert_info
->signature
->algorithm
),
796 openssl_asn1_obj2chunk(this->x509
->sig_alg
->algorithm
)))
800 this->scheme
= signature_scheme_from_oid(openssl_asn1_known_oid(
801 this->x509
->sig_alg
->algorithm
));
803 if (!parse_extensions(this))
808 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
813 hasher
->allocate_hash(hasher
, this->encoding
, &this->hash
);
814 hasher
->destroy(hasher
);
816 if (issued_by(this, &this->public.x509
.interface
))
818 this->flags
|= X509_SELF_SIGNED
;
823 openssl_x509_t
*openssl_x509_load(certificate_type_t type
, va_list args
)
825 chunk_t blob
= chunk_empty
;
826 x509_flag_t flags
= 0;
830 switch (va_arg(args
, builder_part_t
))
832 case BUILD_BLOB_ASN1_DER
:
833 blob
= va_arg(args
, chunk_t
);
835 case BUILD_X509_FLAG
:
836 flags
|= va_arg(args
, x509_flag_t
);
848 private_openssl_x509_t
*this;
850 this = create_empty();
851 this->encoding
= chunk_clone(blob
);
852 this->flags
|= flags
;
853 if (parse_certificate(this))
855 return &this->public;
857 DBG1(DBG_LIB
, "OpenSSL X.509 parsing failed");