blob: 7202a169508a33206234218a42b168d20fcbfd3a [file]
#ifndef _IPXE_TLSKEY_H
#define _IPXE_TLSKEY_H
/** @file
*
* TLS key schedules
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
FILE_SECBOOT ( PERMITTED );
#include <stdint.h>
#include <ipxe/crypto.h>
struct tls_phase;
/** A TLS endpoint */
struct tls_endpoint {
/** Endpoint index */
uint8_t index;
/** Name (for key expansion labels) */
const char name[ 7 /* "[client|server]" + NUL */ ];
} __attribute__ (( packed ));
/** Client endpoint index */
#define TLS_CLIENT 0
/** Server endpoint index */
#define TLS_SERVER 1
/** Number of random bytes */
#define TLS_RANDOM_LEN 32
/** TLS client or server random bytes */
struct tls_random {
/** Random bytes */
uint8_t bytes[TLS_RANDOM_LEN];
} __attribute__ (( packed ));
/** A message hash prefix */
struct tls_message_hash {
/** Message type */
uint8_t type;
/** Must be zero */
uint16_t zero;
/** Hash length */
uint8_t len;
} __attribute__ (( packed ));
/** A TLS message hash */
#define TLS_MESSAGE_HASH 254
/** A TLS running handshake transcript digest */
struct tls_transcript {
/** Digest context */
void *ctx;
/**
* Running digest value
*
* This is continuously updated to represent the digest value
* over the transcript up to and including the most recently
* digested handshake record.
*/
void *running;
/**
* Running digest value up to the most recent Finished (if any)
*
* If no Finished record has been digested, then this mirrors
* the continuously running digest value.
*
* If any Finished record has been digested, then this
* represents the digest value over the transcript up to and
* including the most recently digested Finished record.
*/
void *finishing;
/** Transcript flags */
unsigned int flags;
};
/** Transcript digest includes a Hello record containing the local nonce */
#define TLSKEY_TSF_NONCED 0x0001
/** Transcript digest includes a Finished record */
#define TLSKEY_TSF_FINISHED 0x0002
/** A TLS key derivation function secret */
struct tls_kdf_secret {
/** Secret */
void *secret;
/** Key flags */
unsigned int flags;
};
/** Key derivation function has key material */
#define TLSKEY_KDF_KEYED 0x0001
/** Key derivation function has a master secret */
#define TLSKEY_KDF_MASTER 0x0002
/** Key derivation function has an extended master secret */
#define TLSKEY_KDF_EMS 0x0004
/** A TLS traffic secret */
struct tls_traffic_secret {
/** Secret */
void *secret;
/** Phase */
const struct tls_phase *phase;
};
/** A TLS key schedule */
struct tls_key_schedule {
/** Key schedule operations */
const struct tls_key_schedule_operations *op;
/** Digest algorithm */
struct digest_algorithm *digest;
/** Secret size */
size_t secretsize;
/** Dynamically-allocated storage */
void *dynamic;
/** Secret(s) */
void *secret;
/** Flags */
unsigned int flags;
/** Running handshake transcript digest */
struct tls_transcript transcript;
/** Local endpoint random bytes */
struct tls_random nonce;
/** Client and server random bytes */
struct tls_random random[2];
/** Key derivation function secret */
struct tls_kdf_secret kdf;
/** Traffic secrets */
struct tls_traffic_secret traffic[2];
};
/** A TLS pre-shared key */
struct tls_preshared_key {
/** Key schedule operations (if set) */
const struct tls_key_schedule_operations *op;
/** Digest algorithm (if set) */
struct digest_algorithm *digest;
/** Key flags */
unsigned int flags;
/** Key material */
union {
/**
* Master secret
*
* For TLSv1.2 and earlier, session resumption works
* by simply copying the 48-byte raw master secret
* value.
*
* For TLSv1.1 and earlier, this 48-byte master secret
* logically comprises two halves: 24 bytes for MD5
* and 24 bytes for SHA-1.
*/
union {
uint8_t raw[48];
struct {
uint8_t md5[24];
uint8_t sha1[24];
} __attribute__ (( packed ));
} master_secret;
/**
* Resumption secret
*
* For TLSv1.3 and later, session resumption uses a
* pre-shared resumption secret value generated using
* the HKDF Derive-Secret function.
*
* The longest possible value for any supported HKDF
* digest algorithm is 48 bytes, when using SHA-384.
*/
uint8_t resumption[48];
} key;
};
/** TLS key schedule operations */
struct tls_key_schedule_operations {
/** Name */
const char *name;
/**
* Key schedule accumulates all shared secrets
*
* The ability to demonstrate possession of the key material
* is sufficient to demonstrate possession of the most
* recently applied shared secret.
*
* This flag indicates that the ability to demonstrate
* possession of the key material is also sufficient to
* demonstrate possession of all previously applied shared
* secrets.
*/
int accumulates;
/** Key flags preserved when loading key material */
unsigned int mask;
/**
* Calculate secret size
*
* @v digest Digest algorithm
* @ret secretsize Secret size, or zero if unsupported
*/
size_t ( * secretsize ) ( struct digest_algorithm *digest );
/**
* Expand key material
*
* @v digest Digest algorithm
* @v secret Secret
* @v label Label string
* @v seed Seed material
* @v seed_len Length of seed material
* @v out Output buffer
* @v out_len Length of output buffer
*/
void ( * expand ) ( struct digest_algorithm *digest,
const void *secret, const char *label,
const void *seed, size_t seed_len,
void *out, size_t out_len );
/**
* Reset key schedule
*
* @v tlskey Key schedule
*/
void ( * reset ) ( struct tls_key_schedule *tlskey );
/**
* Apply a new shared secret
*
* @v tlskey Key schedule
* @v shared New shared secret
* @v shared_len Length of new shared secret
* @ret rc Return status code
*/
int ( * apply ) ( struct tls_key_schedule *tlskey,
const void *shared, size_t shared_len );
/**
* Generate master secret
*
* @v tlskey Key schedule
* @v ems Extended master secret extension is enabled
* @ret rc Return status code
*/
int ( * master ) ( struct tls_key_schedule *tlskey, int ems );
/**
* Generate verification data
*
* @v tlskey Key schedule
* @v end Verification endpoint
* @v verify Verification data
* @v verify_len Length of verification data
* @ret rc Return status code
*/
int ( * verify ) ( struct tls_key_schedule *tlskey,
const struct tls_endpoint *end,
void *verify, size_t verify_len );
/**
* Generate traffic secrets
*
* @v tlskey Key schedule
* @v writer Writer endpoint
* @v phase Traffic phase
* @ret rc Return status code
*/
int ( * traffic ) ( struct tls_key_schedule *tlskey,
const struct tls_endpoint *writer,
const struct tls_phase *phase );
/**
* Generate cipher key material
*
* @v tlskey Key schedule
* @v writer Writer endpoint
* @v key Cipher key to fill in
* @v key_len Length of cipher key
* @v iv Fixed portion of IV to fill in
* @v iv_len Length of fixed portion of IV
* @v mac MAC secret to fill in
* @v mac_len Length of MAC secret
* @ret rc Return status code
*/
int ( * cipher ) ( struct tls_key_schedule *tlskey,
const struct tls_endpoint *writer,
void *key, size_t key_len, void *iv,
size_t iv_len, void *mac, size_t mac_len );
/**
* Generate signable digest value
*
* @v tlskey Key schedule
* @v end Endpoint
* @v digest Signature digest algorithm
* @v data Additional data
* @v len Length of additional data
* @v tbs Signature digest value to fill in
* @ret rc Return status code
*/
int ( * tbshash ) ( struct tls_key_schedule *tlskey,
const struct tls_endpoint *end,
struct digest_algorithm *digest,
const void *data, size_t len, void *tbs );
/**
* Save pre-shared key
*
* @v tlskey Key schedule
* @v nonce Ticket nonce
* @v nonce_len Length of ticket nonce
* @v psk Pre-shared key to fill in
* @ret rc Return status code
*/
int ( * save ) ( struct tls_key_schedule *tlskey, const void *nonce,
size_t nonce_len, struct tls_preshared_key *psk );
/**
* Load pre-shared key
*
* @v tlskey Key schedule
* @v psk Pre-shared key
* @ret rc Return status code
*/
int ( * load ) ( struct tls_key_schedule *tlskey,
const struct tls_preshared_key *psk );
/**
* Generate pre-shared key binder value
*
* @v psk Pre-shared key
* @v hash Partial transcript hash
* @v binder Binder value to fill in
* @v binder_len Length of binder value
* @ret rc Return status code
*/
int ( * bind ) ( const struct tls_preshared_key *psk,
const void *hash, void *binder, size_t binder_len );
};
/**
* Check if key schedule accumulates shared secrets
*
* @v tlskey Key schedule
* @ret is_accumulating Key schedule accumulates all shared secrets
*/
static inline __attribute__ (( always_inline )) int
tlskey_is_accumulating ( struct tls_key_schedule *tlskey ) {
const struct tls_key_schedule_operations *op = tlskey->op;
return ( op && op->accumulates );
}
extern const struct tls_endpoint tls_client;
extern const struct tls_endpoint tls_server;
extern const struct tls_phase tls_early;
extern const struct tls_phase tls_handshake;
extern const struct tls_phase tls_application;
extern const struct tls_key_schedule_operations tlskey_hkdf;
extern const struct tls_key_schedule_operations tlskey_hash;
extern const struct tls_key_schedule_operations tlskey_md5_sha1;
extern int tlskey_start ( struct tls_key_schedule *tlskey,
const struct tls_key_schedule_operations *op,
struct digest_algorithm *digest,
const struct tls_random *random );
extern void tlskey_stop ( struct tls_key_schedule *tlskey );
extern void tlskey_digest ( struct tls_key_schedule *tlskey,
const void *data, size_t len );
extern void tlskey_message ( struct tls_key_schedule *tlskey );
extern void tlskey_reset ( struct tls_key_schedule *tlskey );
extern int tlskey_apply ( struct tls_key_schedule *tlskey,
const void *shared, size_t shared_len );
extern int tlskey_master ( struct tls_key_schedule *tlskey, int ems );
extern int tlskey_verify ( struct tls_key_schedule *tlskey,
const struct tls_endpoint *end,
void *verify, size_t verify_len );
extern int tlskey_traffic ( struct tls_key_schedule *tlskey,
const struct tls_endpoint *writer,
const struct tls_phase *phase );
extern int tlskey_cipher ( struct tls_key_schedule *tlskey,
const struct tls_endpoint *writer,
void *key, size_t key_len, void *iv,
size_t iv_len, void *mac, size_t mac_len );
extern int tlskey_tbshash ( struct tls_key_schedule *tlskey,
const struct tls_endpoint *end,
struct digest_algorithm *digest,
const void *data, size_t len, void *tbs );
extern int tlskey_save ( struct tls_key_schedule *tlskey, const void *nonce,
size_t nonce_len, struct tls_preshared_key *psk );
extern int tlskey_load ( struct tls_key_schedule *tlskey, int ems,
const struct tls_preshared_key *psk );
extern int tlskey_bind ( const struct tls_preshared_key *psk,
const void *prefix, size_t prefix_len,
void *binder, size_t binder_len );
#endif /* _IPXE_TLSKEY_H */