* @v key Private key
* @ret cert X.509 certificate, or NULL if not found
*/
-struct x509_certificate * certstore_find_key ( struct asn1_cursor *key ) {
+struct x509_certificate * certstore_find_key ( struct private_key *key ) {
struct x509_certificate *cert;
/* Search for certificate within store */
list_for_each_entry ( cert, &certstore.links, store.list ) {
if ( pubkey_match ( cert->signature_algorithm->pubkey,
- key->data, key->len,
+ key->builder.data, key->builder.len,
cert->subject.public_key.raw.data,
cert->subject.public_key.raw.len ) == 0 )
return certstore_found ( cert );
".previous\n\t" );
/** Private key */
-struct asn1_cursor private_key = {
- .data = private_key_data,
- .len = ( ( size_t ) private_key_len ),
+struct private_key private_key = {
+ .refcnt = REF_INIT ( ref_no_free ),
+ .builder = {
+ .data = private_key_data,
+ .len = ( ( size_t ) private_key_len ),
+ },
};
/** Default private key */
.type = &setting_type_hex,
};
+/**
+ * Free private key
+ *
+ * @v refcnt Reference counter
+ */
+void privkey_free ( struct refcnt *refcnt ) {
+ struct private_key *key =
+ container_of ( refcnt, struct private_key, refcnt );
+
+ free ( key->builder.data );
+ free ( key );
+}
+
/**
* Apply private key configuration settings
*
if ( ALLOW_KEY_OVERRIDE ) {
/* Restore default private key */
- memcpy ( &private_key, &default_private_key,
- sizeof ( private_key ) );
+ memcpy ( &private_key.builder, &default_private_key,
+ sizeof ( private_key.builder ) );
/* Fetch new private key, if any */
free ( key_data );
if ( ( len = fetch_raw_setting_copy ( NULL, &privkey_setting,
&key_data ) ) >= 0 ) {
- private_key.data = key_data;
- private_key.len = len;
+ private_key.builder.data = key_data;
+ private_key.builder.len = len;
}
}
/* Debug */
- if ( private_key.len ) {
+ if ( private_key.builder.len ) {
DBGC ( &private_key, "PRIVKEY using %s private key:\n",
( key_data ? "external" : "built-in" ) );
- DBGC_HDA ( &private_key, 0, private_key.data, private_key.len );
+ DBGC_HDA ( &private_key, 0, private_key.builder.data,
+ private_key.builder.len );
} else {
DBGC ( &private_key, "PRIVKEY has no private key\n" );
}
#include <ipxe/asn1.h>
#include <ipxe/x509.h>
+#include <ipxe/privkey.h>
extern struct x509_chain certstore;
extern struct x509_certificate * certstore_find ( struct asn1_cursor *raw );
-extern struct x509_certificate * certstore_find_key ( struct asn1_cursor *key );
+extern struct x509_certificate * certstore_find_key ( struct private_key *key );
extern void certstore_add ( struct x509_certificate *cert );
extern void certstore_del ( struct x509_certificate *cert );
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/asn1.h>
+#include <ipxe/refcnt.h>
-extern struct asn1_cursor private_key;
+/** A private key */
+struct private_key {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** ASN.1 object builder */
+ struct asn1_builder builder;
+};
+
+/**
+ * Get reference to private key
+ *
+ * @v key Private key
+ * @ret key Private key
+ */
+static inline __attribute__ (( always_inline )) struct private_key *
+privkey_get ( struct private_key *key ) {
+ ref_get ( &key->refcnt );
+ return key;
+}
+
+/**
+ * Drop reference to private key
+ *
+ * @v key Private key
+ */
+static inline __attribute__ (( always_inline )) void
+privkey_put ( struct private_key *key ) {
+ ref_put ( &key->refcnt );
+}
+
+/**
+ * Get private key ASN.1 cursor
+ *
+ * @v key Private key
+ * @ret cursor ASN.1 cursor
+ */
+static inline __attribute__ (( always_inline )) struct asn1_cursor *
+privkey_cursor ( struct private_key *key ) {
+ return asn1_built ( &key->builder );
+}
+
+extern void privkey_free ( struct refcnt *refcnt );
+
+/**
+ * Initialise empty private key
+ *
+ */
+static inline __attribute__ (( always_inline )) void
+privkey_init ( struct private_key *key ) {
+ ref_init ( &key->refcnt, privkey_free );
+}
+
+extern struct private_key private_key;
#endif /* _IPXE_PRIVKEY_H */
#include <ipxe/sha1.h>
#include <ipxe/sha256.h>
#include <ipxe/x509.h>
+#include <ipxe/privkey.h>
#include <ipxe/pending.h>
#include <ipxe/iobuf.h>
#include <ipxe/tables.h>
const char *name;
/** Root of trust */
struct x509_root *root;
+ /** Private key */
+ struct private_key *key;
/** Session ID */
uint8_t id[32];
struct digest_algorithm *handshake_digest;
/** Digest algorithm context used for handshake verification */
uint8_t *handshake_ctx;
+ /** Private key */
+ struct private_key *key;
/** Client certificate chain (if used) */
struct x509_chain *certs;
/** Secure renegotiation flag */
#define TLS_RX_ALIGN 16
extern int add_tls ( struct interface *xfer, const char *name,
- struct x509_root *root );
+ struct x509_root *root, struct private_key *key );
#endif /* _IPXE_TLS_H */
*/
static int https_filter ( struct http_connection *conn ) {
- return add_tls ( &conn->socket, conn->uri->host, NULL );
+ return add_tls ( &conn->socket, conn->uri->host, NULL, NULL );
}
/** HTTPS URI opener */
}
/* Add TLS filter */
- if ( ( rc = add_tls ( &syslogs, server, NULL ) ) != 0 ) {
+ if ( ( rc = add_tls ( &syslogs, server, NULL, NULL ) ) != 0 ) {
DBG ( "SYSLOGS cannot create TLS filter: %s\n",
strerror ( rc ) );
goto err_add_tls;
/* Free dynamically-allocated resources */
x509_root_put ( session->root );
+ privkey_put ( session->key );
free ( session->ticket );
/* Free session */
x509_chain_put ( tls->certs );
x509_chain_put ( tls->chain );
x509_root_put ( tls->root );
+ privkey_put ( tls->key );
/* Drop reference to session */
assert ( list_empty ( &tls->list ) );
struct digest_algorithm *digest = tls->handshake_digest;
struct x509_certificate *cert = x509_first ( tls->certs );
struct pubkey_algorithm *pubkey = cert->signature_algorithm->pubkey;
+ struct asn1_cursor *key = privkey_cursor ( tls->key );
uint8_t digest_out[ digest->digestsize ];
uint8_t ctx[ pubkey->ctxsize ];
struct tls_signature_hash_algorithm *sig_hash = NULL;
tls_verify_handshake ( tls, digest_out );
/* Initialise public-key algorithm */
- if ( ( rc = pubkey_init ( pubkey, ctx, private_key.data,
- private_key.len ) ) != 0 ) {
+ if ( ( rc = pubkey_init ( pubkey, ctx, key->data, key->len ) ) != 0 ) {
DBGC ( tls, "TLS %p could not initialise %s client private "
"key: %s\n", tls, pubkey->name, strerror ( rc ) );
goto err_pubkey_init;
tls->certs = NULL;
/* Determine client certificate to be sent */
- cert = certstore_find_key ( &private_key );
+ cert = certstore_find_key ( tls->key );
if ( ! cert ) {
DBGC ( tls, "TLS %p could not find certificate corresponding "
"to private key\n", tls );
/* Find existing matching session, if any */
list_for_each_entry ( session, &tls_sessions, list ) {
if ( ( strcmp ( name, session->name ) == 0 ) &&
- ( tls->root == session->root ) ) {
+ ( tls->root == session->root ) &&
+ ( tls->key == session->key ) ) {
ref_get ( &session->refcnt );
tls->session = session;
DBGC ( tls, "TLS %p joining session %s\n", tls, name );
strcpy ( name_copy, name );
session->name = name_copy;
session->root = x509_root_get ( tls->root );
+ session->key = privkey_get ( tls->key );
INIT_LIST_HEAD ( &session->conn );
list_add ( &session->list, &tls_sessions );
* @v xfer Data transfer interface
* @v name Host name
* @v root Root of trust (or NULL to use default)
+ * @v key Private key (or NULL to use default)
* @ret rc Return status code
*/
int add_tls ( struct interface *xfer, const char *name,
- struct x509_root *root ) {
+ struct x509_root *root, struct private_key *key ) {
struct tls_connection *tls;
int rc;
intf_init ( &tls->validator, &tls_validator_desc, &tls->refcnt );
process_init_stopped ( &tls->process, &tls_process_desc,
&tls->refcnt );
+ tls->key = privkey_get ( key ? key : &private_key );
tls->root = x509_root_get ( root ? root : &root_certificates );
tls->version = TLS_VERSION_TLS_1_2;
tls_clear_cipher ( tls, &tls->tx_cipherspec );