#include <ipxe/tls.h>
/* Disambiguate the various error causes */
-#define EACCES_WRONG_NAME \
- __einfo_error ( EINFO_EACCES_WRONG_NAME )
-#define EINFO_EACCES_WRONG_NAME \
- __einfo_uniqify ( EINFO_EACCES, 0x02, "Incorrect server name" )
+#define EACCES_WRONG_NAME __einfo_error ( EINFO_EACCES_WRONG_NAME )
+#define EINFO_EACCES_WRONG_NAME \
+ __einfo_uniqify ( EINFO_EACCES, 0x02, \
+ "Incorrect server name" )
+#define EINVAL_CHANGE_CIPHER __einfo_error ( EINFO_EINVAL_CHANGE_CIPHER )
+#define EINFO_EINVAL_CHANGE_CIPHER \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, \
+ "Invalid Change Cipher record" )
+#define EINVAL_ALERT __einfo_error ( EINFO_EINVAL_ALERT )
+#define EINFO_EINVAL_ALERT \
+ __einfo_uniqify ( EINFO_EINVAL, 0x02, \
+ "Invalid Alert record" )
+#define EINVAL_HELLO __einfo_error ( EINFO_EINVAL_HELLO )
+#define EINFO_EINVAL_HELLO \
+ __einfo_uniqify ( EINFO_EINVAL, 0x03, \
+ "Invalid Server Hello record" )
+#define EINVAL_CERTIFICATE __einfo_error ( EINFO_EINVAL_CERTIFICATE )
+#define EINFO_EINVAL_CERTIFICATE \
+ __einfo_uniqify ( EINFO_EINVAL, 0x04, \
+ "Invalid Certificate" )
+#define EINVAL_CERTIFICATES __einfo_error ( EINFO_EINVAL_CERTIFICATES )
+#define EINFO_EINVAL_CERTIFICATES \
+ __einfo_uniqify ( EINFO_EINVAL, 0x05, \
+ "Invalid Server Certificate record" )
+#define EINVAL_HELLO_DONE __einfo_error ( EINFO_EINVAL_HELLO_DONE )
+#define EINFO_EINVAL_HELLO_DONE \
+ __einfo_uniqify ( EINFO_EINVAL, 0x06, \
+ "Invalid Server Hello Done record" )
+#define EINVAL_FINISHED __einfo_error ( EINFO_EINVAL_FINISHED )
+#define EINFO_EINVAL_FINISHED \
+ __einfo_uniqify ( EINFO_EINVAL, 0x07, \
+ "Invalid Server Finished record" )
+#define EINVAL_HANDSHAKE __einfo_error ( EINFO_EINVAL_HANDSHAKE )
+#define EINFO_EINVAL_HANDSHAKE \
+ __einfo_uniqify ( EINFO_EINVAL, 0x08, \
+ "Invalid Handshake record" )
+#define EINVAL_STREAM __einfo_error ( EINFO_EINVAL_STREAM )
+#define EINFO_EINVAL_STREAM \
+ __einfo_uniqify ( EINFO_EINVAL, 0x09, \
+ "Invalid stream-ciphered record" )
+#define EINVAL_BLOCK __einfo_error ( EINFO_EINVAL_BLOCK )
+#define EINFO_EINVAL_BLOCK \
+ __einfo_uniqify ( EINFO_EINVAL, 0x0a, \
+ "Invalid block-ciphered record" )
+#define EINVAL_PADDING __einfo_error ( EINFO_EINVAL_PADDING )
+#define EINFO_EINVAL_PADDING \
+ __einfo_uniqify ( EINFO_EINVAL, 0x0b, \
+ "Invalid block padding" )
+#define EINVAL_RX_STATE __einfo_error ( EINFO_EINVAL_RX_STATE )
+#define EINFO_EINVAL_RX_STATE \
+ __einfo_uniqify ( EINFO_EINVAL, 0x0c, \
+ "Invalid receive state" )
+#define EIO_ALERT __einfo_error ( EINFO_EIO_ALERT )
+#define EINFO_EIO_ALERT \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, \
+ "Unknown alert level" )
+#define ENOMEM_CONTEXT __einfo_error ( EINFO_ENOMEM_CONTEXT )
+#define EINFO_ENOMEM_CONTEXT \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x01, \
+ "Not enough space for crypto context" )
+#define ENOMEM_CERTIFICATE __einfo_error ( EINFO_ENOMEM_CERTIFICATE )
+#define EINFO_ENOMEM_CERTIFICATE \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x02, \
+ "Not enough space for certificate" )
+#define ENOMEM_CHAIN __einfo_error ( EINFO_ENOMEM_CHAIN )
+#define EINFO_ENOMEM_CHAIN \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x03, \
+ "Not enough space for certificate chain" )
+#define ENOMEM_TX_PLAINTEXT __einfo_error ( EINFO_ENOMEM_TX_PLAINTEXT )
+#define EINFO_ENOMEM_TX_PLAINTEXT \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x04, \
+ "Not enough space for transmitted plaintext" )
+#define ENOMEM_TX_CIPHERTEXT __einfo_error ( EINFO_ENOMEM_TX_CIPHERTEXT )
+#define EINFO_ENOMEM_TX_CIPHERTEXT \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x05, \
+ "Not enough space for transmitted ciphertext" )
+#define ENOMEM_RX_PLAINTEXT __einfo_error ( EINFO_ENOMEM_RX_PLAINTEXT )
+#define EINFO_ENOMEM_RX_PLAINTEXT \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x06, \
+ "Not enough space for received plaintext" )
+#define ENOMEM_RX_DATA __einfo_error ( EINFO_ENOMEM_RX_DATA )
+#define EINFO_ENOMEM_RX_DATA \
+ __einfo_uniqify ( EINFO_ENOMEM, 0x07, \
+ "Not enough space for received data" )
+#define ENOTSUP_CIPHER __einfo_error ( EINFO_ENOTSUP_CIPHER )
+#define EINFO_ENOTSUP_CIPHER \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \
+ "Unsupported cipher" )
+#define ENOTSUP_NULL __einfo_error ( EINFO_ENOTSUP_NULL )
+#define EINFO_ENOTSUP_NULL \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x02, \
+ "Refusing to use null cipher" )
+#define ENOTSUP_SIG_HASH __einfo_error ( EINFO_ENOTSUP_SIG_HASH )
+#define EINFO_ENOTSUP_SIG_HASH \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x03, \
+ "Unsupported signature and hash algorithm" )
+#define ENOTSUP_VERSION __einfo_error ( EINFO_ENOTSUP_VERSION )
+#define EINFO_ENOTSUP_VERSION \
+ __einfo_uniqify ( EINFO_ENOTSUP, 0x04, \
+ "Unsupported protocol version" )
+#define EPERM_ALERT __einfo_error ( EINFO_EPERM_ALERT )
+#define EINFO_EPERM_ALERT \
+ __einfo_uniqify ( EINFO_EPERM, 0x01, \
+ "Received fatal alert" )
+#define EPERM_VERIFY __einfo_error ( EINFO_EPERM_VERIFY )
+#define EINFO_EPERM_VERIFY \
+ __einfo_uniqify ( EINFO_EPERM, 0x02, \
+ "Handshake verification failed" )
+#define EPROTO_VERSION __einfo_error ( EINFO_EPROTO_VERSION )
+#define EINFO_EPROTO_VERSION \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, \
+ "Illegal protocol version upgrade" )
static int tls_send_plaintext ( struct tls_session *tls, unsigned int type,
const void *data, size_t len );
if ( ! dynamic ) {
DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto "
"context\n", tls, total );
- return -ENOMEM;
+ return -ENOMEM_CONTEXT;
}
/* Assign storage */
if ( ! suite ) {
DBGC ( tls, "TLS %p does not support cipher %04x\n",
tls, ntohs ( cipher_suite ) );
- return -ENOTSUP;
+ return -ENOTSUP_CIPHER;
}
/* Set ciphers */
/* Sanity check */
if ( pending->suite == &tls_cipher_suite_null ) {
DBGC ( tls, "TLS %p refusing to use null cipher\n", tls );
- return -ENOTSUP;
+ return -ENOTSUP_NULL;
}
tls_clear_cipher ( tls, active );
*/
certificate = zalloc ( sizeof ( *certificate ) );
if ( ! certificate )
- return -ENOMEM;
+ return -ENOMEM_CERTIFICATE;
/* Populate record */
certificate->type_length =
DBGC ( tls, "TLS %p could not identify (%s,%s) "
"signature and hash algorithm\n", tls,
pubkey->name, digest->name );
- rc = -ENOTSUP;
+ rc = -ENOTSUP_SIG_HASH;
goto err_sig_hash;
}
}
if ( ( len != 1 ) || ( *( ( uint8_t * ) data ) != 1 ) ) {
DBGC ( tls, "TLS %p received invalid Change Cipher\n", tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_CHANGE_CIPHER;
}
if ( ( rc = tls_change_cipher ( tls, &tls->rx_cipherspec_pending,
if ( end != ( data + len ) ) {
DBGC ( tls, "TLS %p received overlength Alert\n", tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_ALERT;
}
switch ( alert->level ) {
case TLS_ALERT_FATAL:
DBGC ( tls, "TLS %p received fatal alert %d\n",
tls, alert->description );
- return -EPERM;
+ return -EPERM_ALERT;
default:
DBGC ( tls, "TLS %p received unknown alert level %d"
"(alert %d)\n", tls, alert->level, alert->description );
- return -EIO;
+ return -EIO_ALERT;
}
}
if ( end > ( data + len ) ) {
DBGC ( tls, "TLS %p received underlength Server Hello\n", tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_HELLO;
}
/* Check and store protocol version */
if ( version < TLS_VERSION_TLS_1_0 ) {
DBGC ( tls, "TLS %p does not support protocol version %d.%d\n",
tls, ( version >> 8 ), ( version & 0xff ) );
- return -ENOTSUP;
+ return -ENOTSUP_VERSION;
}
if ( version > tls->version ) {
DBGC ( tls, "TLS %p server attempted to illegally upgrade to "
"protocol version %d.%d\n",
tls, ( version >> 8 ), ( version & 0xff ) );
- return -EPROTO;
+ return -EPROTO_VERSION;
}
tls->version = version;
DBGC ( tls, "TLS %p using protocol version %d.%d\n",
/* Create certificate chain */
tls->chain = x509_alloc_chain();
if ( ! tls->chain ) {
- rc = -ENOMEM;
+ rc = -ENOMEM_CHAIN;
goto err_alloc_chain;
}
if ( next > end ) {
DBGC ( tls, "TLS %p overlength certificate:\n", tls );
DBGC_HDA ( tls, 0, data, ( end - data ) );
- rc = -EINVAL;
+ rc = -EINVAL_CERTIFICATE;
goto err_overlength;
}
DBGC ( tls, "TLS %p received overlength Server Certificate\n",
tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_CERTIFICATES;
}
/* Parse certificate chain */
DBGC ( tls, "TLS %p received overlength Server Hello Done\n",
tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_HELLO_DONE;
}
/* Begin certificate validation */
if ( end != ( data + len ) ) {
DBGC ( tls, "TLS %p received overlength Finished\n", tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_FINISHED;
}
/* Verify data */
if ( memcmp ( verify_data, finished->verify_data,
sizeof ( verify_data ) ) != 0 ) {
DBGC ( tls, "TLS %p verification failed\n", tls );
- return -EPERM;
+ return -EPERM_VERIFY;
}
/* Mark server as finished */
DBGC ( tls, "TLS %p received overlength Handshake\n",
tls );
DBGC_HD ( tls, data, len );
- return -EINVAL;
+ return -EINVAL_HANDSHAKE;
}
switch ( handshake->type ) {
if ( ! plaintext ) {
DBGC ( tls, "TLS %p could not allocate %zd bytes for "
"plaintext\n", tls, plaintext_len );
- rc = -ENOMEM;
+ rc = -ENOMEM_TX_PLAINTEXT;
goto done;
}
if ( ! ciphertext ) {
DBGC ( tls, "TLS %p could not allocate %zd bytes for "
"ciphertext\n", tls, ciphertext_len );
- rc = -ENOMEM;
+ rc = -ENOMEM_TX_CIPHERTEXT;
goto done;
}
if ( plaintext_len < mac_len ) {
DBGC ( tls, "TLS %p received underlength record\n", tls );
DBGC_HD ( tls, plaintext, plaintext_len );
- return -EINVAL;
+ return -EINVAL_STREAM;
}
content_len = ( plaintext_len - mac_len );
content = plaintext;
if ( plaintext_len < 1 ) {
DBGC ( tls, "TLS %p received underlength record\n", tls );
DBGC_HD ( tls, plaintext, plaintext_len );
- return -EINVAL;
+ return -EINVAL_BLOCK;
}
/* TLSv1.1 and later use an explicit IV */
if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) {
DBGC ( tls, "TLS %p received underlength record\n", tls );
DBGC_HD ( tls, plaintext, plaintext_len );
- return -EINVAL;
+ return -EINVAL_BLOCK;
}
content_len = ( plaintext_len - iv_len - mac_len - padding_len - 1 );
iv = plaintext;
if ( *( ( uint8_t * ) ( padding + i ) ) != padding_len ) {
DBGC ( tls, "TLS %p received bad padding\n", tls );
DBGC_HD ( tls, plaintext, plaintext_len );
- return -EINVAL;
+ return -EINVAL_PADDING;
}
}
if ( ! plaintext ) {
DBGC ( tls, "TLS %p could not allocate %zd bytes for "
"decryption buffer\n", tls, record_len );
- rc = -ENOMEM;
+ rc = -ENOMEM_RX_PLAINTEXT;
goto done;
}
if ( ! tls->rx_data ) {
DBGC ( tls, "TLS %p could not allocate %zd bytes "
"for receive buffer\n", tls, data_len );
- return -ENOMEM;
+ return -ENOMEM_RX_DATA;
}
/* Move to data state */
break;
default:
assert ( 0 );
- rc = -EINVAL;
+ rc = -EINVAL_RX_STATE;
goto done;
}