summaryrefslogblamecommitdiffstats
path: root/src/include/ipxe/tls.h
blob: cf3277820165258189070c8492d59044ded63234 (plain) (tree)
1
2
3
4
5
6
7
8
9

                   
 




                                    
 
                                       
 
                   
                        
                           




                         
                         
                         
                       
                        
 

                      















                                             


                                  


                                  


                                           


                                 


                                    












                                    
                                















                                           
                                               
                                           
                                               

                                              

                                                  



                                                  





                                                    
 


                                    
                              
                              

                              



                                         
                               


                                   






                                           



                                 


                                        


                                  


                                             







                                 







                                       





                                 


                                     

                                            


                                           

  












                                                          

                         

                                                    
                                              
                                        
                                               
                                        
                                   
                                        

                                                                 

                                                     





                                                  

                         

  







                                                                         


















                                                                         



                                       





                                             

                         

                                          

  

















                                                    












                                                                         







                               





















                                                              

                    

                                

                               
 

                          

                               

                                
 



                                   



                                       



















                                                          



                                           
 
                               
                                     
                                
                                      
 

                               







                                                    




                                  
                                               



                                                  



                                                                       

                                

                                                 



                                        
 
                            
                               

                                       


                                    



                                                            

                                                       
 

                                 

                                       






                                   

                                             



                                                                 

                                          

  




















                                                                      
                                                                       
                                                                    
                                                                      
 
                                                              
                                                                       
 
                        
#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 */