- Added support for TLS v1.1
- Renamed some SSL defines to prevent future naming confusion
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index fa172c2..67eff47 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -294,6 +294,9 @@
memcpy( ssl->mac_enc, keyblk, ssl->maclen );
memcpy( ssl->mac_dec, keyblk + ssl->maclen, ssl->maclen );
+ /*
+ * This is not used in TLS v1.1.
+ */
memcpy( ssl->iv_enc, key2 + ssl->keylen, ssl->ivlen );
memcpy( ssl->iv_dec, key2 + ssl->keylen + ssl->ivlen,
ssl->ivlen );
@@ -306,6 +309,9 @@
memcpy( ssl->mac_dec, keyblk, ssl->maclen );
memcpy( ssl->mac_enc, keyblk + ssl->maclen, ssl->maclen );
+ /*
+ * This is not used in TLS v1.1.
+ */
memcpy( ssl->iv_dec, key1 + ssl->keylen, ssl->ivlen );
memcpy( ssl->iv_enc, key1 + ssl->keylen + ssl->ivlen,
ssl->ivlen );
@@ -545,6 +551,9 @@
}
else
{
+ unsigned char *enc_msg;
+ int enc_msglen;
+
padlen = ssl->ivlen - ( ssl->out_msglen + 1 ) % ssl->ivlen;
if( padlen == ssl->ivlen )
padlen = 0;
@@ -554,9 +563,38 @@
ssl->out_msglen += padlen + 1;
+ enc_msglen = ssl->out_msglen;
+ enc_msg = ssl->out_msg;
+
+ /*
+ * Prepend per-record IV for block cipher in TLS v1.1 as per
+ * Method 1 (6.2.3.2. in RFC4346)
+ */
+ if( ssl->minor_ver == SSL_MINOR_VERSION_2 )
+ {
+ /*
+ * Generate IV
+ */
+ for( i = 0; i < ssl->ivlen; i++ )
+ ssl->iv_enc[i] = ssl->f_rng( ssl->p_rng );
+
+ /*
+ * Shift message for ivlen bytes and prepend IV
+ */
+ memmove( ssl->out_msg + ssl->ivlen, ssl->out_msg, ssl->out_msglen );
+ memcpy( ssl->out_msg, ssl->iv_enc, ssl->ivlen );
+
+ /*
+ * Fix pointer positions and message length with added IV
+ */
+ enc_msg = ssl->out_msg + ssl->ivlen;
+ enc_msglen = ssl->out_msglen;
+ ssl->out_msglen += ssl->ivlen;
+ }
+
SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
- "including %d bytes of padding",
- ssl->out_msglen, padlen + 1 ) );
+ "including %d bytes of IV and %d bytes of padding",
+ ssl->out_msglen, ssl->ivlen, padlen + 1 ) );
SSL_DEBUG_BUF( 4, "before encrypt: output payload",
ssl->out_msg, ssl->out_msglen );
@@ -566,8 +604,8 @@
case 8:
#if defined(POLARSSL_DES_C)
des3_crypt_cbc( (des3_context *) ssl->ctx_enc,
- DES_ENCRYPT, ssl->out_msglen,
- ssl->iv_enc, ssl->out_msg, ssl->out_msg );
+ DES_ENCRYPT, enc_msglen,
+ ssl->iv_enc, enc_msg, enc_msg );
break;
#endif
@@ -579,8 +617,8 @@
ssl->session->cipher == SSL_EDH_RSA_AES_256_SHA)
{
aes_crypt_cbc( (aes_context *) ssl->ctx_enc,
- AES_ENCRYPT, ssl->out_msglen,
- ssl->iv_enc, ssl->out_msg, ssl->out_msg );
+ AES_ENCRYPT, enc_msglen,
+ ssl->iv_enc, enc_msg, enc_msg);
break;
}
#endif
@@ -592,8 +630,8 @@
ssl->session->cipher == SSL_EDH_RSA_CAMELLIA_256_SHA)
{
camellia_crypt_cbc( (camellia_context *) ssl->ctx_enc,
- CAMELLIA_ENCRYPT, ssl->out_msglen,
- ssl->iv_enc, ssl->out_msg, ssl->out_msg );
+ CAMELLIA_ENCRYPT, enc_msglen,
+ ssl->iv_enc, enc_msg, enc_msg );
break;
}
#endif
@@ -635,6 +673,10 @@
}
else
{
+ unsigned char *dec_msg;
+ unsigned char *dec_msg_result;
+ int dec_msglen;
+
/*
* Decrypt and check the padding
*/
@@ -645,13 +687,30 @@
return( POLARSSL_ERR_SSL_INVALID_MAC );
}
+ dec_msglen = ssl->in_msglen;
+ dec_msg = ssl->in_msg;
+ dec_msg_result = ssl->in_msg;
+
+ /*
+ * Initialize for prepended IV for block cipher in TLS v1.1
+ */
+ if( ssl->minor_ver == SSL_MINOR_VERSION_2 )
+ {
+ dec_msg += ssl->ivlen;
+ dec_msglen -= ssl->ivlen;
+ ssl->in_msglen -= ssl->ivlen;
+
+ for( i = 0; i < ssl->ivlen; i++ )
+ ssl->iv_dec[i] = ssl->in_msg[i];
+ }
+
switch( ssl->ivlen )
{
#if defined(POLARSSL_DES_C)
case 8:
des3_crypt_cbc( (des3_context *) ssl->ctx_dec,
- DES_DECRYPT, ssl->in_msglen,
- ssl->iv_dec, ssl->in_msg, ssl->in_msg );
+ DES_DECRYPT, dec_msglen,
+ ssl->iv_dec, dec_msg, dec_msg_result );
break;
#endif
@@ -663,8 +722,8 @@
ssl->session->cipher == SSL_EDH_RSA_AES_256_SHA)
{
aes_crypt_cbc( (aes_context *) ssl->ctx_dec,
- AES_DECRYPT, ssl->in_msglen,
- ssl->iv_dec, ssl->in_msg, ssl->in_msg );
+ AES_DECRYPT, dec_msglen,
+ ssl->iv_dec, dec_msg, dec_msg_result );
break;
}
#endif
@@ -676,8 +735,8 @@
ssl->session->cipher == SSL_EDH_RSA_CAMELLIA_256_SHA)
{
camellia_crypt_cbc( (camellia_context *) ssl->ctx_dec,
- CAMELLIA_DECRYPT, ssl->in_msglen,
- ssl->iv_dec, ssl->in_msg, ssl->in_msg );
+ CAMELLIA_DECRYPT, dec_msglen,
+ ssl->iv_dec, dec_msg, dec_msg_result );
break;
}
#endif
@@ -982,8 +1041,7 @@
return( POLARSSL_ERR_SSL_INVALID_RECORD );
}
- if( ssl->in_hdr[2] != SSL_MINOR_VERSION_0 &&
- ssl->in_hdr[2] != SSL_MINOR_VERSION_1 )
+ if( ssl->in_hdr[2] > ssl->max_minor_ver )
{
SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
return( POLARSSL_ERR_SSL_INVALID_RECORD );
@@ -1093,14 +1151,14 @@
/*
* Ignore non-fatal alerts, except close_notify
*/
- if( ssl->in_msg[0] == SSL_ALERT_FATAL )
+ if( ssl->in_msg[0] == SSL_ALERT_LEVEL_FATAL )
{
SSL_DEBUG_MSG( 1, ( "is a fatal alert message" ) );
return( POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE | ssl->in_msg[1] );
}
- if( ssl->in_msg[0] == SSL_ALERT_WARNING &&
- ssl->in_msg[1] == SSL_ALERT_CLOSE_NOTIFY )
+ if( ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING &&
+ ssl->in_msg[1] == SSL_ALERT_MSG_CLOSE_NOTIFY )
{
SSL_DEBUG_MSG( 2, ( "is a close notify message" ) );
return( POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY );
@@ -1142,8 +1200,8 @@
{
ssl->out_msglen = 2;
ssl->out_msgtype = SSL_MSG_ALERT;
- ssl->out_msg[0] = SSL_ALERT_WARNING;
- ssl->out_msg[1] = SSL_ALERT_NO_CERTIFICATE;
+ ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING;
+ ssl->out_msg[1] = SSL_ALERT_MSG_NO_CERT;
SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) );
goto write_msg;
@@ -1241,10 +1299,10 @@
if( ssl->endpoint == SSL_IS_SERVER &&
ssl->minor_ver == SSL_MINOR_VERSION_0 )
{
- if( ssl->in_msglen == 2 &&
- ssl->in_msgtype == SSL_MSG_ALERT &&
- ssl->in_msg[0] == SSL_ALERT_WARNING &&
- ssl->in_msg[1] == SSL_ALERT_NO_CERTIFICATE )
+ if( ssl->in_msglen == 2 &&
+ ssl->in_msgtype == SSL_MSG_ALERT &&
+ ssl->in_msg[0] == SSL_ALERT_LEVEL_WARNING &&
+ ssl->in_msg[1] == SSL_ALERT_MSG_NO_CERT )
{
SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
@@ -2026,8 +2084,8 @@
{
ssl->out_msgtype = SSL_MSG_ALERT;
ssl->out_msglen = 2;
- ssl->out_msg[0] = SSL_ALERT_WARNING;
- ssl->out_msg[1] = SSL_ALERT_CLOSE_NOTIFY;
+ ssl->out_msg[0] = SSL_ALERT_LEVEL_WARNING;
+ ssl->out_msg[1] = SSL_ALERT_MSG_CLOSE_NOTIFY;
if( ( ret = ssl_write_record( ssl ) ) != 0 )
{