diff options
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/ipxe/cms.h | 53 | ||||
| -rw-r--r-- | src/include/ipxe/tls.h | 3 | ||||
| -rw-r--r-- | src/include/ipxe/x509.h | 156 |
3 files changed, 174 insertions, 38 deletions
diff --git a/src/include/ipxe/cms.h b/src/include/ipxe/cms.h index f355bf1cb..eadeca4b8 100644 --- a/src/include/ipxe/cms.h +++ b/src/include/ipxe/cms.h @@ -13,37 +13,62 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <ipxe/asn1.h> #include <ipxe/crypto.h> #include <ipxe/x509.h> +#include <ipxe/refcnt.h> #include <ipxe/uaccess.h> /** CMS signer information */ struct cms_signer_info { - /** Issuer name */ - struct asn1_cursor issuer; - /** Serial number */ - struct asn1_cursor serial; + /** List of signer information blocks */ + struct list_head list; + + /** Certificate chain */ + struct x509_chain *chain; + /** Digest algorithm */ struct digest_algorithm *digest; /** Public-key algorithm */ struct pubkey_algorithm *pubkey; + /** Signature */ - const void *signature; + void *signature; /** Length of signature */ size_t signature_len; }; /** A CMS signature */ struct cms_signature { - /** Raw certificate list */ - struct asn1_cursor certificates; - /** Signer information - * - * We currently use only the first signer information block. - */ - struct cms_signer_info info; + /** Reference count */ + struct refcnt refcnt; + /** List of all certificates */ + struct x509_chain *certificates; + /** List of signer information blocks */ + struct list_head info; }; -extern int cms_parse ( struct cms_signature *sig, const void *data, - size_t len ); +/** + * Get reference to CMS signature + * + * @v sig CMS signature + * @ret sig CMS signature + */ +static inline __attribute__ (( always_inline )) struct cms_signature * +cms_get ( struct cms_signature *sig ) { + ref_get ( &sig->refcnt ); + return sig; +} + +/** + * Drop reference to CMS signature + * + * @v sig CMS signature + */ +static inline __attribute__ (( always_inline )) void +cms_put ( struct cms_signature *sig ) { + ref_put ( &sig->refcnt ); +} + +extern int cms_signature ( const void *data, size_t len, + struct cms_signature **sig ); extern int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len, const char *name, time_t time, struct x509_root *root ); diff --git a/src/include/ipxe/tls.h b/src/include/ipxe/tls.h index 772233369..07f5d3eb2 100644 --- a/src/include/ipxe/tls.h +++ b/src/include/ipxe/tls.h @@ -235,6 +235,9 @@ struct tls_session { /** Public-key algorithm used for Certificate Verify (if sent) */ struct pubkey_algorithm *verify_pubkey; + /** Server certificate chain */ + struct x509_chain *chain; + /** TX sequence number */ uint64_t tx_seq; /** TX pending transmissions */ diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h index 271ed2e44..b9db20479 100644 --- a/src/include/ipxe/x509.h +++ b/src/include/ipxe/x509.h @@ -13,6 +13,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <stddef.h> #include <time.h> #include <ipxe/asn1.h> +#include <ipxe/refcnt.h> +#include <ipxe/list.h> /** An X.509 bit string */ struct x509_bit_string { @@ -50,14 +52,6 @@ struct x509_validity { struct x509_time not_after; }; -/** An X.509 string */ -struct x509_string { - /** String (not NUL-terminated) */ - const void *data; - /** Length of name */ - size_t len; -}; - /** An X.509 certificate public key */ struct x509_public_key { /** Raw public key */ @@ -71,7 +65,7 @@ struct x509_subject { /** Raw subject */ struct asn1_cursor raw; /** Common name */ - struct x509_string name; + char *name; /** Public key information */ struct x509_public_key public_key; }; @@ -92,6 +86,13 @@ struct x509_basic_constraints { unsigned int path_len; }; +/** Unlimited path length + * + * We use -2U, since this quantity represents one *fewer* than the + * maximum number of remaining certificates in a chain. + */ +#define X509_PATH_LEN_UNLIMITED -2U + /** An X.509 certificate key usage */ struct x509_key_usage { /** Key usage extension is present */ @@ -131,7 +132,7 @@ enum x509_extended_key_usage_bits { /** X.509 certificate OCSP responder */ struct x509_ocsp_responder { /** URI */ - struct x509_string uri; + char *uri; }; /** X.509 certificate authority information access */ @@ -154,6 +155,16 @@ struct x509_extensions { /** An X.509 certificate */ struct x509_certificate { + /** Reference count */ + struct refcnt refcnt; + /** List of certificates in cache */ + struct list_head list; + + /** Certificate has been validated */ + int valid; + /** Maximum number of subsequent certificates in chain */ + unsigned int path_remaining; + /** Raw certificate */ struct asn1_cursor raw; /** Version */ @@ -176,6 +187,80 @@ struct x509_certificate { struct x509_extensions extensions; }; +/** + * Get reference to X.509 certificate + * + * @v cert X.509 certificate + * @ret cert X.509 certificate + */ +static inline __attribute__ (( always_inline )) struct x509_certificate * +x509_get ( struct x509_certificate *cert ) { + ref_get ( &cert->refcnt ); + return cert; +} + +/** + * Drop reference to X.509 certificate + * + * @v cert X.509 certificate + */ +static inline __attribute__ (( always_inline )) void +x509_put ( struct x509_certificate *cert ) { + ref_put ( &cert->refcnt ); +} + +/** A link in an X.509 certificate chain */ +struct x509_link { + /** List of links */ + struct list_head list; + /** Certificate */ + struct x509_certificate *cert; +}; + +/** An X.509 certificate chain */ +struct x509_chain { + /** Reference count */ + struct refcnt refcnt; + /** List of links */ + struct list_head links; +}; + +/** + * Get reference to X.509 certificate chain + * + * @v chain X.509 certificate chain + * @ret chain X.509 certificate chain + */ +static inline __attribute__ (( always_inline )) struct x509_chain * +x509_chain_get ( struct x509_chain *chain ) { + ref_get ( &chain->refcnt ); + return chain; +} + +/** + * Drop reference to X.509 certificate chain + * + * @v chain X.509 certificate chain + */ +static inline __attribute__ (( always_inline )) void +x509_chain_put ( struct x509_chain *chain ) { + ref_put ( &chain->refcnt ); +} + +/** + * Get first certificate in X.509 certificate chain + * + * @v chain X.509 certificate chain + * @ret cert X.509 certificate, or NULL + */ +static inline __attribute__ (( always_inline )) struct x509_certificate * +x509_first ( struct x509_chain *chain ) { + struct x509_link *link; + + link = list_first_entry ( &chain->links, struct x509_link, list ); + return ( link ? link->cert : NULL ); +} + /** An X.509 extension */ struct x509_extension { /** Name */ @@ -228,22 +313,45 @@ struct x509_root { const void *fingerprints; }; -extern int x509_parse ( struct x509_certificate *cert, - const void *data, size_t len ); -extern int x509_validate_issuer ( struct x509_certificate *cert, - struct x509_certificate *issuer ); +extern int x509_certificate ( const void *data, size_t len, + struct x509_certificate **cert ); + +extern struct x509_chain * x509_alloc_chain ( void ); +extern int x509_append ( struct x509_chain *chain, + struct x509_certificate *cert ); +extern int x509_validate_chain ( struct x509_chain *chain, time_t time, + struct x509_root *root ); + +/* Functions exposed only for unit testing */ +extern int x509_check_issuer ( struct x509_certificate *cert, + struct x509_certificate *issuer ); extern void x509_fingerprint ( struct x509_certificate *cert, struct digest_algorithm *digest, void *fingerprint ); -extern int x509_validate_root ( struct x509_certificate *cert, - struct x509_root *root ); -extern int x509_validate_time ( struct x509_certificate *cert, time_t time ); -extern int x509_validate_chain ( int ( * parse_next ) - ( struct x509_certificate *cert, - const struct x509_certificate *previous, - void *context ), - void *context, time_t time, - struct x509_root *root, - struct x509_certificate *first ); +extern int x509_check_root ( struct x509_certificate *cert, + struct x509_root *root ); +extern int x509_check_time ( struct x509_certificate *cert, time_t time ); + +/** + * Invalidate X.509 certificate + * + * @v cert X.509 certificate + */ +static inline void x509_invalidate ( struct x509_certificate *cert ) { + cert->valid = 0; + cert->path_remaining = 0; +} + +/** + * Invalidate X.509 certificate chain + * + * @v chain X.509 certificate chain + */ +static inline void x509_invalidate_chain ( struct x509_chain *chain ) { + struct x509_link *link; + + list_for_each_entry ( link, &chain->links, list ) + x509_invalidate ( link->cert ); +} #endif /* _IPXE_X509_H */ |
