aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-03-23 17:02:55 -0400
committerJack Lloyd <[email protected]>2016-03-23 17:02:55 -0400
commit858cf5c82260e45e5bf51ff17b63f493d8295356 (patch)
tree3186029f089ffdb3e1c9e0ac004018d0953ff5e8 /src/lib
parent646ddaef38845a7ce33e4dcc7a02500a674c7033 (diff)
Add IETF standard ChaCha20Poly1305 ciphersuites to TLS
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/tls/tls_record.cpp66
-rw-r--r--src/lib/tls/tls_record.h12
-rw-r--r--src/lib/tls/tls_suite_info.cpp28
3 files changed, 83 insertions, 23 deletions
diff --git a/src/lib/tls/tls_record.cpp b/src/lib/tls/tls_record.cpp
index bdb37baad..efa6e2d18 100644
--- a/src/lib/tls/tls_record.cpp
+++ b/src/lib/tls/tls_record.cpp
@@ -53,12 +53,16 @@ Connection_Cipher_State::Connection_Cipher_State(Protocol_Version version,
m_aead->set_key(cipher_key + mac_key);
BOTAN_ASSERT_EQUAL(iv.length(), nonce_bytes_from_handshake(), "Matching nonce sizes");
- m_nonce = iv.bits_of();
+ m_nonce = unlock(iv.bits_of());
BOTAN_ASSERT(nonce_bytes_from_record() == 0 || nonce_bytes_from_record() == 8,
"Ciphersuite uses implemented IV length");
- m_nonce.resize(m_nonce.size() + 8);
+ if(m_nonce.size() != 12)
+ {
+ m_nonce.resize(m_nonce.size() + 8);
+ }
+
return;
}
@@ -77,20 +81,45 @@ Connection_Cipher_State::Connection_Cipher_State(Protocol_Version version,
m_mac->set_key(mac_key);
}
-const secure_vector<byte>& Connection_Cipher_State::aead_nonce(u64bit seq)
+std::vector<byte> Connection_Cipher_State::aead_nonce(u64bit seq)
{
- store_be(seq, &m_nonce[nonce_bytes_from_handshake()]);
- return m_nonce;
+ if(nonce_bytes_from_handshake() == 12)
+ {
+ std::vector<byte> nonce(12);
+ store_be(seq, nonce.data() + 4);
+ xor_buf(nonce, m_nonce.data(), m_nonce.size());
+ return nonce;
+ }
+ else
+ {
+ std::vector<byte> nonce = m_nonce;
+ store_be(seq, &nonce[nonce_bytes_from_handshake()]);
+ return nonce;
+ }
}
-const secure_vector<byte>&
+std::vector<byte>
Connection_Cipher_State::aead_nonce(const byte record[], size_t record_len, u64bit seq)
{
- if(nonce_bytes_from_record())
+ if(nonce_bytes_from_handshake() == 12)
+ {
+ /*
+ Assumes if the suite specifies 12 bytes come from the handshake then
+ use the XOR nonce construction from draft-ietf-tls-chacha20-poly1305
+ */
+
+ std::vector<byte> nonce(12);
+ store_be(seq, nonce.data() + 4);
+ xor_buf(nonce, m_nonce.data(), m_nonce.size());
+ return nonce;
+ }
+ else if(nonce_bytes_from_record() > 0)
{
if(record_len < nonce_bytes_from_record())
throw Decoding_Error("Invalid AEAD packet too short to be valid");
- copy_mem(&m_nonce[nonce_bytes_from_handshake()], record, nonce_bytes_from_record());
+ std::vector<byte> nonce = m_nonce;
+ copy_mem(&nonce[nonce_bytes_from_handshake()], record, nonce_bytes_from_record());
+ return nonce;
}
else
{
@@ -98,18 +127,21 @@ Connection_Cipher_State::aead_nonce(const byte record[], size_t record_len, u64b
nonce_len == 0 is assumed to mean no nonce in the message but
instead the AEAD uses the seq number in network order.
*/
- store_be(seq, &m_nonce[nonce_bytes_from_handshake()]);
+ std::vector<byte> nonce = m_nonce;
+ store_be(seq, &nonce[nonce_bytes_from_handshake()]);
+ return nonce;
}
- return m_nonce;
}
-const secure_vector<byte>&
+std::vector<byte>
Connection_Cipher_State::format_ad(u64bit msg_sequence,
byte msg_type,
Protocol_Version version,
u16bit msg_length)
{
- m_ad.clear();
+ std::vector<byte> m_ad;
+ m_ad.reserve(13);
+
for(size_t i = 0; i != 8; ++i)
m_ad.push_back(get_byte(i, msg_sequence));
m_ad.push_back(msg_type);
@@ -156,7 +188,7 @@ void write_record(secure_vector<byte>& output,
{
const size_t ctext_size = aead->output_length(msg_length);
- const secure_vector<byte>& nonce = cs->aead_nonce(seq);
+ const std::vector<byte> nonce = cs->aead_nonce(seq);
// wrong if start returns something
const size_t rec_size = ctext_size + cs->nonce_bytes_from_record();
@@ -167,7 +199,11 @@ void write_record(secure_vector<byte>& output,
aead->set_ad(cs->format_ad(seq, msg_type, version, msg_length));
- output += std::make_pair(&nonce[cs->nonce_bytes_from_handshake()], cs->nonce_bytes_from_record());
+ if(cs->nonce_bytes_from_record() > 0)
+ {
+ output += std::make_pair(&nonce[cs->nonce_bytes_from_handshake()], cs->nonce_bytes_from_record());
+ }
+
BOTAN_ASSERT(aead->start(nonce).empty(), "AEAD doesn't return anything from start");
const size_t offset = output.size();
@@ -350,7 +386,7 @@ void decrypt_record(secure_vector<byte>& output,
{
if(AEAD_Mode* aead = cs.aead())
{
- const secure_vector<byte>& nonce = cs.aead_nonce(record_contents, record_len, record_sequence);
+ const std::vector<byte> nonce = cs.aead_nonce(record_contents, record_len, record_sequence);
const byte* msg = &record_contents[cs.nonce_bytes_from_record()];
const size_t msg_length = record_len - cs.nonce_bytes_from_record();
diff --git a/src/lib/tls/tls_record.h b/src/lib/tls/tls_record.h
index d7aa82e71..e3b0b9b58 100644
--- a/src/lib/tls/tls_record.h
+++ b/src/lib/tls/tls_record.h
@@ -42,13 +42,13 @@ class Connection_Cipher_State
AEAD_Mode* aead() { return m_aead.get(); }
- const secure_vector<byte>& aead_nonce(u64bit seq);
+ std::vector<byte> aead_nonce(u64bit seq);
- const secure_vector<byte>& aead_nonce(const byte record[], size_t record_len, u64bit seq);
+ std::vector<byte> aead_nonce(const byte record[], size_t record_len, u64bit seq);
- const secure_vector<byte>& format_ad(u64bit seq, byte type,
- Protocol_Version version,
- u16bit ptext_length);
+ std::vector<byte> format_ad(u64bit seq, byte type,
+ Protocol_Version version,
+ u16bit ptext_length);
BlockCipher* block_cipher() { return m_block_cipher.get(); }
@@ -82,7 +82,7 @@ class Connection_Cipher_State
std::unique_ptr<MessageAuthenticationCode> m_mac;
std::unique_ptr<AEAD_Mode> m_aead;
- secure_vector<byte> m_nonce, m_ad;
+ std::vector<byte> m_nonce;
size_t m_block_size = 0;
size_t m_nonce_bytes_from_handshake;
diff --git a/src/lib/tls/tls_suite_info.cpp b/src/lib/tls/tls_suite_info.cpp
index 0bebecb82..84e2a30a8 100644
--- a/src/lib/tls/tls_suite_info.cpp
+++ b/src/lib/tls/tls_suite_info.cpp
@@ -2,8 +2,8 @@
* TLS cipher suite information
*
* This file was automatically generated from the IANA assignments
-* (tls-parameters.txt hash 6a934405ed41aa4d6113dad17f815867741430ac)
-* by ./src/scripts/tls_suite_info.py on 2016-01-06
+* (tls-parameters.txt hash fe280cb8b13bfdd306a975ab39fda238f77ae3bc)
+* by ./src/scripts/tls_suite_info.py on 2016-03-23
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -159,6 +159,12 @@ std::vector<u16bit> Ciphersuite::all_known_ciphersuite_ids()
0xCC13,
0xCC14,
0xCC15,
+ 0xCCA8,
+ 0xCCA9,
+ 0xCCAA,
+ 0xCCAB,
+ 0xCCAC,
+ 0xCCAD,
0xFFF0,
0xFFF1,
0xFFF2,
@@ -604,6 +610,24 @@ Ciphersuite Ciphersuite::by_id(u16bit suite)
case 0xCC15: // DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
return Ciphersuite(0xCC15, "RSA", "DH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256");
+ case 0xCCA8: // ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+ return Ciphersuite(0xCCA8, "RSA", "ECDH", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256");
+
+ case 0xCCA9: // ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
+ return Ciphersuite(0xCCA9, "ECDSA", "ECDH", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256");
+
+ case 0xCCAA: // DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+ return Ciphersuite(0xCCAA, "RSA", "DH", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256");
+
+ case 0xCCAB: // PSK_WITH_CHACHA20_POLY1305_SHA256
+ return Ciphersuite(0xCCAB, "", "PSK", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256");
+
+ case 0xCCAC: // ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+ return Ciphersuite(0xCCAC, "", "ECDHE_PSK", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256");
+
+ case 0xCCAD: // DHE_PSK_WITH_CHACHA20_POLY1305_SHA256
+ return Ciphersuite(0xCCAD, "", "DHE_PSK", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256");
+
case 0xFFF0: // ECDHE_RSA_WITH_AES_128_OCB_SHA256
return Ciphersuite(0xFFF0, "RSA", "ECDH", "AES-128/OCB(12)", 16, 4, 0, "AEAD", 0, "SHA-256");