| #ifndef _IPXE_TLS_H |
| #define _IPXE_TLS_H |
| |
| /** |
| * @file |
| * |
| * Transport Layer Security Protocol |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); |
| |
| #include <stdint.h> |
| #include <ipxe/refcnt.h> |
| #include <ipxe/interface.h> |
| #include <ipxe/process.h> |
| #include <ipxe/crypto.h> |
| #include <ipxe/md5.h> |
| #include <ipxe/sha1.h> |
| #include <ipxe/x509.h> |
| #include <ipxe/privkey.h> |
| #include <ipxe/pending.h> |
| #include <ipxe/iobuf.h> |
| #include <ipxe/tables.h> |
| |
| struct tls_connection; |
| |
| /** A TLS header */ |
| struct tls_header { |
| /** Content type |
| * |
| * This is a TLS_TYPE_XXX constant |
| */ |
| uint8_t type; |
| /** Protocol version |
| * |
| * This is a TLS_VERSION_XXX constant |
| */ |
| uint16_t version; |
| /** Length of payload */ |
| uint16_t length; |
| } __attribute__ (( packed )); |
| |
| /** TLS version 1.1 */ |
| #define TLS_VERSION_TLS_1_1 0x0302 |
| |
| /** TLS version 1.2 */ |
| #define TLS_VERSION_TLS_1_2 0x0303 |
| |
| /** Maximum supported TLS version */ |
| #define TLS_VERSION_MAX TLS_VERSION_TLS_1_2 |
| |
| /** Change cipher content type */ |
| #define TLS_TYPE_CHANGE_CIPHER 20 |
| |
| /** Change cipher spec magic byte */ |
| #define TLS_CHANGE_CIPHER_SPEC 1 |
| |
| /** Alert content type */ |
| #define TLS_TYPE_ALERT 21 |
| |
| /** Handshake content type */ |
| #define TLS_TYPE_HANDSHAKE 22 |
| |
| /** Application data content type */ |
| #define TLS_TYPE_DATA 23 |
| |
| /* Handshake message types */ |
| #define TLS_HELLO_REQUEST 0 |
| #define TLS_CLIENT_HELLO 1 |
| #define TLS_SERVER_HELLO 2 |
| #define TLS_NEW_SESSION_TICKET 4 |
| #define TLS_CERTIFICATE 11 |
| #define TLS_SERVER_KEY_EXCHANGE 12 |
| #define TLS_CERTIFICATE_REQUEST 13 |
| #define TLS_SERVER_HELLO_DONE 14 |
| #define TLS_CERTIFICATE_VERIFY 15 |
| #define TLS_CLIENT_KEY_EXCHANGE 16 |
| #define TLS_FINISHED 20 |
| |
| /* TLS alert levels */ |
| #define TLS_ALERT_WARNING 1 |
| #define TLS_ALERT_FATAL 2 |
| |
| /* TLS cipher specifications */ |
| #define TLS_RSA_WITH_NULL_MD5 0x0001 |
| #define TLS_RSA_WITH_NULL_SHA 0x0002 |
| #define TLS_RSA_WITH_AES_128_CBC_SHA 0x002f |
| #define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 |
| #define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 |
| #define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 |
| #define TLS_RSA_WITH_AES_128_CBC_SHA256 0x003c |
| #define TLS_RSA_WITH_AES_256_CBC_SHA256 0x003d |
| #define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 |
| #define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006b |
| #define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009c |
| #define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009d |
| #define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009e |
| #define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009f |
| #define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xc013 |
| #define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xc014 |
| #define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xc027 |
| #define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xc028 |
| #define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xc02f |
| #define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xc030 |
| |
| /* TLS hash algorithm identifiers */ |
| #define TLS_MD5_ALGORITHM 1 |
| #define TLS_SHA1_ALGORITHM 2 |
| #define TLS_SHA224_ALGORITHM 3 |
| #define TLS_SHA256_ALGORITHM 4 |
| #define TLS_SHA384_ALGORITHM 5 |
| #define TLS_SHA512_ALGORITHM 6 |
| |
| /* TLS signature algorithm identifiers */ |
| #define TLS_RSA_ALGORITHM 1 |
| |
| /* TLS server name extension */ |
| #define TLS_SERVER_NAME 0 |
| #define TLS_SERVER_NAME_HOST_NAME 0 |
| |
| /* TLS maximum fragment length extension */ |
| #define TLS_MAX_FRAGMENT_LENGTH 1 |
| #define TLS_MAX_FRAGMENT_LENGTH_512 1 |
| #define TLS_MAX_FRAGMENT_LENGTH_1024 2 |
| #define TLS_MAX_FRAGMENT_LENGTH_2048 3 |
| #define TLS_MAX_FRAGMENT_LENGTH_4096 4 |
| |
| /* TLS named curve extension */ |
| #define TLS_NAMED_CURVE 10 |
| #define TLS_NAMED_CURVE_X25519 29 |
| |
| /* TLS signature algorithms extension */ |
| #define TLS_SIGNATURE_ALGORITHMS 13 |
| |
| /* TLS session ticket extension */ |
| #define TLS_SESSION_TICKET 35 |
| |
| /* TLS renegotiation information extension */ |
| #define TLS_RENEGOTIATION_INFO 0xff01 |
| |
| /** TLS authentication header */ |
| struct tls_auth_header { |
| /** Sequence number */ |
| uint64_t seq; |
| /** TLS header */ |
| struct tls_header header; |
| } __attribute__ (( packed )); |
| |
| /** TLS verification data */ |
| struct tls_verify_data { |
| /** Client verification data */ |
| uint8_t client[12]; |
| /** Server verification data */ |
| uint8_t server[12]; |
| } __attribute__ (( packed )); |
| |
| /** TLS RX state machine state */ |
| enum tls_rx_state { |
| TLS_RX_HEADER = 0, |
| TLS_RX_DATA, |
| }; |
| |
| /** TLS TX pending flags */ |
| enum tls_tx_pending { |
| TLS_TX_CLIENT_HELLO = 0x0001, |
| TLS_TX_CERTIFICATE = 0x0002, |
| TLS_TX_CLIENT_KEY_EXCHANGE = 0x0004, |
| TLS_TX_CERTIFICATE_VERIFY = 0x0008, |
| TLS_TX_CHANGE_CIPHER = 0x0010, |
| TLS_TX_FINISHED = 0x0020, |
| }; |
| |
| /** A TLS key exchange algorithm */ |
| struct tls_key_exchange_algorithm { |
| /** Algorithm name */ |
| const char *name; |
| /** |
| * Transmit Client Key Exchange record |
| * |
| * @v tls TLS connection |
| * @ret rc Return status code |
| */ |
| int ( * exchange ) ( struct tls_connection *tls ); |
| }; |
| |
| /** A TLS cipher suite */ |
| struct tls_cipher_suite { |
| /** Key exchange algorithm */ |
| struct tls_key_exchange_algorithm *exchange; |
| /** Public-key encryption algorithm */ |
| struct pubkey_algorithm *pubkey; |
| /** Bulk encryption cipher algorithm */ |
| struct cipher_algorithm *cipher; |
| /** MAC digest algorithm */ |
| struct digest_algorithm *digest; |
| /** Handshake digest algorithm (for TLSv1.2 and above) */ |
| struct digest_algorithm *handshake; |
| /** Numeric code (in network-endian order) */ |
| uint16_t code; |
| /** Key length */ |
| uint8_t key_len; |
| /** Fixed initialisation vector length */ |
| uint8_t fixed_iv_len; |
| /** Record initialisation vector length */ |
| uint8_t record_iv_len; |
| /** MAC length */ |
| uint8_t mac_len; |
| }; |
| |
| /** TLS cipher suite table */ |
| #define TLS_CIPHER_SUITES \ |
| __table ( struct tls_cipher_suite, "tls_cipher_suites" ) |
| |
| /** Declare a TLS cipher suite */ |
| #define __tls_cipher_suite( pref ) \ |
| __table_entry ( TLS_CIPHER_SUITES, pref ) |
| |
| /** TLS named curved type */ |
| #define TLS_NAMED_CURVE_TYPE 3 |
| |
| /** A TLS named curve */ |
| struct tls_named_curve { |
| /** Elliptic curve */ |
| struct elliptic_curve *curve; |
| /** Numeric code (in network-endian order) */ |
| uint16_t code; |
| }; |
| |
| /** TLS named curve table */ |
| #define TLS_NAMED_CURVES \ |
| __table ( struct tls_named_curve, "tls_named_curves" ) |
| |
| /** Declare a TLS named curve */ |
| #define __tls_named_curve( pref ) \ |
| __table_entry ( TLS_NAMED_CURVES, pref ) |
| |
| /** A TLS cipher specification */ |
| struct tls_cipherspec { |
| /** Cipher suite */ |
| struct tls_cipher_suite *suite; |
| /** Dynamically-allocated storage */ |
| void *dynamic; |
| /** Public key encryption context */ |
| void *pubkey_ctx; |
| /** Bulk encryption cipher context */ |
| void *cipher_ctx; |
| /** MAC secret */ |
| void *mac_secret; |
| /** Fixed initialisation vector */ |
| void *fixed_iv; |
| }; |
| |
| /** A TLS signature and hash algorithm identifier */ |
| struct tls_signature_hash_id { |
| /** Hash algorithm */ |
| uint8_t hash; |
| /** Signature algorithm */ |
| uint8_t signature; |
| } __attribute__ (( packed )); |
| |
| /** A TLS signature algorithm */ |
| struct tls_signature_hash_algorithm { |
| /** Digest algorithm */ |
| struct digest_algorithm *digest; |
| /** Public-key algorithm */ |
| struct pubkey_algorithm *pubkey; |
| /** Numeric code */ |
| struct tls_signature_hash_id code; |
| }; |
| |
| /** TLS signature hash algorithm table |
| * |
| * Note that the default (TLSv1.1 and earlier) algorithm using |
| * MD5+SHA1 is never explicitly specified. |
| */ |
| #define TLS_SIG_HASH_ALGORITHMS \ |
| __table ( struct tls_signature_hash_algorithm, \ |
| "tls_sig_hash_algorithms" ) |
| |
| /** Declare a TLS signature hash algorithm */ |
| #define __tls_sig_hash_algorithm \ |
| __table_entry ( TLS_SIG_HASH_ALGORITHMS, 01 ) |
| |
| /** TLS client random data */ |
| struct tls_client_random { |
| /** GMT Unix time */ |
| uint32_t gmt_unix_time; |
| /** Random data */ |
| uint8_t random[28]; |
| } __attribute__ (( packed )); |
| |
| /** An MD5+SHA1 context */ |
| struct md5_sha1_context { |
| /** MD5 context */ |
| uint8_t md5[MD5_CTX_SIZE]; |
| /** SHA-1 context */ |
| uint8_t sha1[SHA1_CTX_SIZE]; |
| } __attribute__ (( packed )); |
| |
| /** MD5+SHA1 context size */ |
| #define MD5_SHA1_CTX_SIZE sizeof ( struct md5_sha1_context ) |
| |
| /** An MD5+SHA1 digest */ |
| struct md5_sha1_digest { |
| /** MD5 digest */ |
| uint8_t md5[MD5_DIGEST_SIZE]; |
| /** SHA-1 digest */ |
| uint8_t sha1[SHA1_DIGEST_SIZE]; |
| } __attribute__ (( packed )); |
| |
| /** MD5+SHA1 digest size */ |
| #define MD5_SHA1_DIGEST_SIZE sizeof ( struct md5_sha1_digest ) |
| |
| /** A TLS session */ |
| struct tls_session { |
| /** Reference counter */ |
| struct refcnt refcnt; |
| /** List of sessions */ |
| struct list_head list; |
| |
| /** Server name */ |
| const char *name; |
| /** Root of trust */ |
| struct x509_root *root; |
| /** Private key */ |
| struct private_key *key; |
| |
| /** Session ID */ |
| uint8_t id[32]; |
| /** Length of session ID */ |
| size_t id_len; |
| /** Session ticket */ |
| void *ticket; |
| /** Length of session ticket */ |
| size_t ticket_len; |
| /** Master secret */ |
| uint8_t master_secret[48]; |
| |
| /** List of connections */ |
| struct list_head conn; |
| }; |
| |
| /** A TLS connection */ |
| struct tls_connection { |
| /** Reference counter */ |
| struct refcnt refcnt; |
| |
| /** Session */ |
| struct tls_session *session; |
| /** List of connections within the same session */ |
| struct list_head list; |
| /** Session ID */ |
| uint8_t session_id[32]; |
| /** Length of session ID */ |
| size_t session_id_len; |
| /** New session ticket */ |
| void *new_session_ticket; |
| /** Length of new session ticket */ |
| size_t new_session_ticket_len; |
| |
| /** Plaintext stream */ |
| struct interface plainstream; |
| /** Ciphertext stream */ |
| struct interface cipherstream; |
| |
| /** Protocol version */ |
| uint16_t version; |
| /** Current TX cipher specification */ |
| struct tls_cipherspec tx_cipherspec; |
| /** Next TX cipher specification */ |
| struct tls_cipherspec tx_cipherspec_pending; |
| /** Current RX cipher specification */ |
| struct tls_cipherspec rx_cipherspec; |
| /** Next RX cipher specification */ |
| struct tls_cipherspec rx_cipherspec_pending; |
| /** Master secret */ |
| uint8_t master_secret[48]; |
| /** Server random bytes */ |
| uint8_t server_random[32]; |
| /** Client random bytes */ |
| struct tls_client_random client_random; |
| /** Server Key Exchange record (if any) */ |
| void *server_key; |
| /** Server Key Exchange record length */ |
| size_t server_key_len; |
| /** Digest algorithm used for handshake verification */ |
| 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 */ |
| int secure_renegotiation; |
| /** Verification data */ |
| struct tls_verify_data verify; |
| |
| /** Root of trust */ |
| struct x509_root *root; |
| /** Server certificate chain */ |
| struct x509_chain *chain; |
| /** Certificate validator */ |
| struct interface validator; |
| |
| /** Client security negotiation pending operation */ |
| struct pending_operation client_negotiation; |
| /** Server security negotiation pending operation */ |
| struct pending_operation server_negotiation; |
| /** Certificate validation pending operation */ |
| struct pending_operation validation; |
| |
| /** TX sequence number */ |
| uint64_t tx_seq; |
| /** TX pending transmissions */ |
| unsigned int tx_pending; |
| /** TX process */ |
| struct process process; |
| |
| /** RX sequence number */ |
| uint64_t rx_seq; |
| /** RX state */ |
| enum tls_rx_state rx_state; |
| /** Current received record header */ |
| struct tls_header rx_header; |
| /** Current received record header (static I/O buffer) */ |
| struct io_buffer rx_header_iobuf; |
| /** List of received data buffers */ |
| struct list_head rx_data; |
| /** Received handshake fragment */ |
| struct io_buffer *rx_handshake; |
| }; |
| |
| /** RX I/O buffer size |
| * |
| * The maximum fragment length extension is optional, and many common |
| * implementations (including OpenSSL) do not support it. We must |
| * therefore be prepared to receive records of up to 16kB in length. |
| * The chance of an allocation of this size failing is non-negligible, |
| * so we must split received data into smaller allocations. |
| */ |
| #define TLS_RX_BUFSIZE 4096 |
| |
| /** Minimum RX I/O buffer size |
| * |
| * To simplify manipulations, we ensure that no RX I/O buffer is |
| * smaller than this size. This allows us to assume that the MAC and |
| * padding are entirely contained within the final I/O buffer. |
| */ |
| #define TLS_RX_MIN_BUFSIZE 512 |
| |
| /** RX I/O buffer alignment */ |
| #define TLS_RX_ALIGN 16 |
| |
| extern struct tls_key_exchange_algorithm tls_pubkey_exchange_algorithm; |
| extern struct tls_key_exchange_algorithm tls_dhe_exchange_algorithm; |
| extern struct tls_key_exchange_algorithm tls_ecdhe_exchange_algorithm; |
| |
| extern int add_tls ( struct interface *xfer, const char *name, |
| struct x509_root *root, struct private_key *key ); |
| |
| #endif /* _IPXE_TLS_H */ |