update ChaCha20-Poly1305 to most recent RFCs

This commit is contained in:
Jacob Barthelmeh
2016-01-27 14:03:05 -07:00
parent 3b6f2b0330
commit 7d71d756f3
9 changed files with 487 additions and 188 deletions

View File

@@ -1071,16 +1071,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#endif
tcp_connect(&sockfd, host, port, doDTLS, ssl);
#ifdef HAVE_POLY1305
/* use old poly to connect with google and wolfssl.com server */
if (!XSTRNCMP(domain, "www.google.com", 14) ||
!XSTRNCMP(domain, "www.wolfssl.com", 15)) {
if (wolfSSL_use_old_poly(ssl, 1) != 0)
err_sys("unable to set to old poly");
}
#endif
wolfSSL_set_fd(ssl, sockfd);
#ifdef HAVE_CRL
if (disableCRL == 0) {

View File

@@ -1263,6 +1263,28 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA,
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
if (tls1_2 && haveECDSAsig) {
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] =
TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
if (tls1_2 && haveRSA) {
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
if (tls1_2 && haveRSA) {
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256;
}
#endif
#ifdef BUILD_TLS_RSA_WITH_NULL_SHA
if (tls && haveRSA) {
suites->suites[idx++] = 0;
@@ -3726,6 +3748,23 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
if (requirement == REQUIRES_DHE)
return 1;
break;
case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
if (requirement == REQUIRES_ECC_DSA)
return 1;
break;
case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
if (requirement == REQUIRES_DHE)
return 1;
break;
}
}
@@ -5999,65 +6038,6 @@ static INLINE void AeadIncrementExpIV(WOLFSSL* ssl)
#if defined(HAVE_POLY1305) && defined(HAVE_CHACHA)
/*more recent rfc's concatonate input for poly1305 differently*/
static int Poly1305Tag(WOLFSSL* ssl, byte* additional, const byte* out,
byte* cipher, word16 sz, byte* tag)
{
int ret = 0;
int paddingSz = 0;
int msglen = (sz - ssl->specs.aead_mac_size);
word32 keySz = 32;
int blockSz = 16;
byte padding[16];
if (msglen < 0)
return INPUT_CASE_ERROR;
XMEMSET(padding, 0, sizeof(padding));
if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, cipher, keySz)) != 0)
return ret;
/* additional input to poly1305 */
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional, blockSz)) != 0)
return ret;
/* cipher input */
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, msglen)) != 0)
return ret;
/* handle padding for cipher input to make it 16 bytes long */
if (msglen % 16 != 0) {
paddingSz = (16 - (sz - ssl->specs.aead_mac_size) % 16);
if (paddingSz < 0)
return INPUT_CASE_ERROR;
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, paddingSz))
!= 0)
return ret;
}
/* add size of AD and size of cipher to poly input */
XMEMSET(padding, 0, sizeof(padding));
padding[0] = blockSz;
/* 32 bit size of cipher to 64 bit endian */
padding[8] = msglen & 0xff;
padding[9] = (msglen >> 8) & 0xff;
padding[10] = (msglen >>16) & 0xff;
padding[11] = (msglen >>24) & 0xff;
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, sizeof(padding)))
!= 0)
return ret;
/* generate tag */
if ((ret = wc_Poly1305Final(ssl->auth.poly1305, tag)) != 0)
return ret;
return ret;
}
/* Used for the older version of creating AEAD tags with Poly1305 */
static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
byte* cipher, word16 sz, byte* tag)
@@ -6077,9 +6057,6 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out,
if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, cipher, keySz)) != 0)
return ret;
/* add TLS compressed length and additional input to poly1305 */
additional[AEAD_AUTH_DATA_SZ - 2] = (msglen >> 8) & 0xff;
additional[AEAD_AUTH_DATA_SZ - 1] = msglen & 0xff;
if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional,
AEAD_AUTH_DATA_SZ)) != 0)
return ret;
@@ -6118,42 +6095,49 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
word16 sz)
{
const byte* additionalSrc = input - RECORD_HEADER_SZ;
int ret = 0;
int ret = 0;
word32 msgLen = (sz - ssl->specs.aead_mac_size);
byte tag[POLY1305_AUTH_SZ];
byte additional[CHACHA20_BLOCK_SIZE];
byte nonce[AEAD_NONCE_SZ];
byte cipher[CHACHA20_256_KEY_SIZE]; /* generated key for poly1305 */
byte add[AEAD_AUTH_DATA_SZ];
byte nonce[CHACHA20_IV_SIZE];
byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for poly1305 */
#ifdef CHACHA_AEAD_TEST
int i;
#endif
XMEMSET(tag, 0, sizeof(tag));
XMEMSET(nonce, 0, AEAD_NONCE_SZ);
XMEMSET(cipher, 0, sizeof(cipher));
XMEMSET(additional, 0, CHACHA20_BLOCK_SIZE);
XMEMSET(tag, 0, sizeof(tag));
XMEMSET(nonce, 0, sizeof(nonce));
XMEMSET(poly, 0, sizeof(poly));
XMEMSET(add, 0, sizeof(add));
/* get nonce */
c32toa(ssl->keys.sequence_number, nonce + AEAD_IMP_IV_SZ
+ AEAD_SEQ_OFFSET);
if (ssl->options.oldPoly != 0) {
/* get nonce */
c32toa(ssl->keys.sequence_number, nonce + AEAD_IMP_IV_SZ
+ AEAD_SEQ_OFFSET);
}
/* opaque SEQ number stored for AD */
c32toa(GetSEQIncrement(ssl, 0), additional + AEAD_SEQ_OFFSET);
c32toa(GetSEQIncrement(ssl, 0), add + AEAD_SEQ_OFFSET);
/* Store the type, version. Unfortunately, they are in
* the input buffer ahead of the plaintext. */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
c16toa(ssl->keys.dtls_epoch, additional);
c16toa(ssl->keys.dtls_epoch, add);
additionalSrc -= DTLS_HANDSHAKE_EXTRA;
}
#endif
XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3);
/* add TLS message size to additional data */
add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
add[AEAD_AUTH_DATA_SZ - 1] = msgLen & 0xff;
XMEMCPY(add + AEAD_TYPE_OFFSET, additionalSrc, 3);
#ifdef CHACHA_AEAD_TEST
printf("Encrypt Additional : ");
for (i = 0; i < CHACHA20_BLOCK_SIZE; i++) {
printf("%02x", additional[i]);
for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) {
printf("%02x", add[i]);
}
printf("\n\n");
printf("input before encryption :\n");
@@ -6165,36 +6149,65 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
printf("\n");
#endif
/* set the nonce for chacha and get poly1305 key */
if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0)) != 0)
return ret;
if (ssl->options.oldPoly == 0) {
/* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte
* record sequence number XORed with client_write_IV/server_write_IV */
XMEMCPY(nonce, ssl->keys.aead_enc_imp_IV, CHACHA20_IV_SIZE);
nonce[4] ^= add[0];
nonce[5] ^= add[1];
nonce[6] ^= add[2];
nonce[7] ^= add[3];
nonce[8] ^= add[4];
nonce[9] ^= add[5];
nonce[10] ^= add[6];
nonce[11] ^= add[7];
}
if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, cipher,
cipher, sizeof(cipher))) != 0)
/* set the nonce for chacha and get poly1305 key */
if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0)) != 0) {
ForceZero(nonce, AEAD_NONCE_SZ);
return ret;
}
ForceZero(nonce, AEAD_NONCE_SZ); /* done with nonce, clear it */
/* create Poly1305 key using chacha20 keystream */
if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, poly,
poly, sizeof(poly))) != 0)
return ret;
/* encrypt the plain text */
if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, out, input,
sz - ssl->specs.aead_mac_size)) != 0)
if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, out,
input, msgLen)) != 0) {
ForceZero(poly, sizeof(poly));
return ret;
}
/* get the tag : future use of hmac could go here*/
if (ssl->options.oldPoly == 1) {
if ((ret = Poly1305TagOld(ssl, additional, (const byte* )out,
cipher, sz, tag)) != 0)
/* get the poly1305 tag using either old padding scheme or more recent */
if (ssl->options.oldPoly != 0) {
if ((ret = Poly1305TagOld(ssl, add, (const byte* )out,
poly, sz, tag)) != 0) {
ForceZero(poly, sizeof(poly));
return ret;
}
}
else {
if ((ret = Poly1305Tag(ssl, additional, (const byte* )out,
cipher, sz, tag)) != 0)
if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly,
sizeof(poly))) != 0) {
ForceZero(poly, sizeof(poly));
return ret;
}
if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add,
sizeof(add), out, msgLen, tag, sizeof(tag))) != 0) {
ForceZero(poly, sizeof(poly));
return ret;
}
}
ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
/* append tag to ciphertext */
XMEMCPY(out + sz - ssl->specs.aead_mac_size, tag, sizeof(tag));
XMEMCPY(out + msgLen, tag, sizeof(tag));
AeadIncrementExpIV(ssl);
ForceZero(nonce, AEAD_NONCE_SZ);
#ifdef CHACHA_AEAD_TEST
printf("mac tag :\n");
@@ -6219,16 +6232,12 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
word16 sz)
{
byte additional[CHACHA20_BLOCK_SIZE];
byte nonce[AEAD_NONCE_SZ];
byte add[AEAD_AUTH_DATA_SZ];
byte nonce[CHACHA20_IV_SIZE];
byte tag[POLY1305_AUTH_SZ];
byte cipher[CHACHA20_256_KEY_SIZE]; /* generated key for mac */
int ret = 0;
XMEMSET(tag, 0, sizeof(tag));
XMEMSET(cipher, 0, sizeof(cipher));
XMEMSET(nonce, 0, AEAD_NONCE_SZ);
XMEMSET(additional, 0, CHACHA20_BLOCK_SIZE);
byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */
int ret = 0;
int msgLen = (sz - ssl->specs.aead_mac_size);
#ifdef CHACHA_AEAD_TEST
int i;
@@ -6241,64 +6250,100 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
printf("\n");
#endif
/* get nonce */
c32toa(ssl->keys.peer_sequence_number, nonce + AEAD_IMP_IV_SZ
+ AEAD_SEQ_OFFSET);
XMEMSET(tag, 0, sizeof(tag));
XMEMSET(poly, 0, sizeof(poly));
XMEMSET(nonce, 0, sizeof(nonce));
XMEMSET(add, 0, sizeof(add));
if (ssl->options.oldPoly != 0) {
/* get nonce */
c32toa(ssl->keys.peer_sequence_number, nonce + AEAD_IMP_IV_SZ
+ AEAD_SEQ_OFFSET);
}
/* sequence number field is 64-bits, we only use 32-bits */
c32toa(GetSEQIncrement(ssl, 1), additional + AEAD_SEQ_OFFSET);
c32toa(GetSEQIncrement(ssl, 1), add + AEAD_SEQ_OFFSET);
/* get AD info */
additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
add[AEAD_TYPE_OFFSET] = ssl->curRL.type;
add[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
add[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
/* Store the type, version. */
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls)
c16toa(ssl->keys.dtls_state.curEpoch, additional);
c16toa(ssl->keys.dtls_state.curEpoch, add);
#endif
/* add TLS message size to additional data */
add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff;
add[AEAD_AUTH_DATA_SZ - 1] = msgLen & 0xff;
#ifdef CHACHA_AEAD_TEST
printf("Decrypt Additional : ");
for (i = 0; i < CHACHA20_BLOCK_SIZE; i++) {
printf("%02x", additional[i]);
for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) {
printf("%02x", add[i]);
}
printf("\n\n");
#endif
if (ssl->options.oldPoly == 0) {
/* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte
* record sequence number XORed with client_write_IV/server_write_IV */
XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, CHACHA20_IV_SIZE);
nonce[4] ^= add[0];
nonce[5] ^= add[1];
nonce[6] ^= add[2];
nonce[7] ^= add[3];
nonce[8] ^= add[4];
nonce[9] ^= add[5];
nonce[10] ^= add[6];
nonce[11] ^= add[7];
}
/* set nonce and get poly1305 key */
if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0)) != 0)
if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0)) != 0) {
ForceZero(nonce, AEAD_NONCE_SZ);
return ret;
}
ForceZero(nonce, AEAD_NONCE_SZ); /* done with nonce, clear it */
/* use chacha20 keystream to get poly1305 key for tag */
if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, poly,
poly, sizeof(poly))) != 0)
return ret;
if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, cipher,
cipher, sizeof(cipher))) != 0)
return ret;
/* get the tag : future use of hmac could go here*/
if (ssl->options.oldPoly == 1) {
if ((ret = Poly1305TagOld(ssl, additional, input, cipher,
sz, tag)) != 0)
/* get the tag using Poly1305 */
if (ssl->options.oldPoly != 0) {
if ((ret = Poly1305TagOld(ssl, add, input, poly, sz, tag)) != 0) {
ForceZero(poly, sizeof(poly));
return ret;
}
}
else {
if ((ret = Poly1305Tag(ssl, additional, input, cipher,
sz, tag)) != 0)
if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly,
sizeof(poly))) != 0) {
ForceZero(poly, sizeof(poly));
return ret;
}
if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add,
sizeof(add), (byte*)input, msgLen, tag, sizeof(tag))) != 0) {
ForceZero(poly, sizeof(poly));
return ret;
}
}
ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */
/* check mac sent along with packet */
if (ConstantCompare(input + sz - ssl->specs.aead_mac_size, tag,
ssl->specs.aead_mac_size) != 0) {
WOLFSSL_MSG("Mac did not match");
/* check tag sent along with packet */
if (ConstantCompare(input + msgLen, tag, ssl->specs.aead_mac_size) != 0) {
WOLFSSL_MSG("MAC did not match");
SendAlert(ssl, alert_fatal, bad_record_mac);
ForceZero(nonce, AEAD_NONCE_SZ);
return VERIFY_MAC_ERROR;
}
/* if mac was good decrypt message */
if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain, input,
sz - ssl->specs.aead_mac_size)) != 0)
/* if the tag was good decrypt message */
if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain,
input, msgLen)) != 0)
return ret;
#ifdef CHACHA_AEAD_TEST
@@ -9837,6 +9882,18 @@ static const char* const cipher_names[] =
"DHE-RSA-CHACHA20-POLY1305",
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
"ECDHE-RSA-CHACHA20-POLY1305-OLD",
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
"ECDHE-ECDSA-CHACHA20-POLY1305-OLD",
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
"DHE-RSA-CHACHA20-POLY1305-OLD",
#endif
#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
"ADH-AES128-SHA",
#endif
@@ -10239,6 +10296,18 @@ static int cipher_name_idx[] =
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256,
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256,
#endif
#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA
TLS_DH_anon_WITH_AES_128_CBC_SHA,
#endif

View File

@@ -60,6 +60,62 @@ int SetCipherSpecs(WOLFSSL* ssl)
if (ssl->options.cipherSuite0 == CHACHA_BYTE) {
switch (ssl->options.cipherSuite) {
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = CHACHA20_256_KEY_SIZE;
ssl->specs.block_size = CHACHA20_BLOCK_SIZE;
ssl->specs.iv_size = CHACHA20_IV_SIZE;
ssl->specs.aead_mac_size = POLY1305_AUTH_SZ;
ssl->options.oldPoly = 1; /* use old poly1305 padding */
break;
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = ecc_diffie_hellman_kea;
ssl->specs.sig_algo = ecc_dsa_sa_algo;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = CHACHA20_256_KEY_SIZE;
ssl->specs.block_size = CHACHA20_BLOCK_SIZE;
ssl->specs.iv_size = CHACHA20_IV_SIZE;
ssl->specs.aead_mac_size = POLY1305_AUTH_SZ;
ssl->options.oldPoly = 1; /* use old poly1305 padding */
break;
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256:
ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
ssl->specs.cipher_type = aead;
ssl->specs.mac_algorithm = sha256_mac;
ssl->specs.kea = diffie_hellman_kea;
ssl->specs.sig_algo = rsa_sa_algo;
ssl->specs.hash_size = SHA256_DIGEST_SIZE;
ssl->specs.pad_size = PAD_SHA;
ssl->specs.static_ecdh = 0;
ssl->specs.key_size = CHACHA20_256_KEY_SIZE;
ssl->specs.block_size = CHACHA20_BLOCK_SIZE;
ssl->specs.iv_size = CHACHA20_IV_SIZE;
ssl->specs.aead_mac_size = POLY1305_AUTH_SZ;
ssl->options.oldPoly = 1; /* use old poly1305 padding */
break;
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
ssl->specs.bulk_cipher_algorithm = wolfssl_chacha;
@@ -74,6 +130,7 @@ int SetCipherSpecs(WOLFSSL* ssl)
ssl->specs.block_size = CHACHA20_BLOCK_SIZE;
ssl->specs.iv_size = CHACHA20_IV_SIZE;
ssl->specs.aead_mac_size = POLY1305_AUTH_SZ;
ssl->options.oldPoly = 0; /* use recent padding RFC */
break;
#endif
@@ -92,6 +149,7 @@ int SetCipherSpecs(WOLFSSL* ssl)
ssl->specs.block_size = CHACHA20_BLOCK_SIZE;
ssl->specs.iv_size = CHACHA20_IV_SIZE;
ssl->specs.aead_mac_size = POLY1305_AUTH_SZ;
ssl->options.oldPoly = 0; /* use recent padding RFC */
break;
#endif
@@ -110,6 +168,7 @@ int SetCipherSpecs(WOLFSSL* ssl)
ssl->specs.block_size = CHACHA20_BLOCK_SIZE;
ssl->specs.iv_size = CHACHA20_IV_SIZE;
ssl->specs.aead_mac_size = POLY1305_AUTH_SZ;
ssl->options.oldPoly = 0; /* use recent padding RFC */
break;
#endif
@@ -1916,14 +1975,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
chachaRet = wc_Chacha_SetKey(enc->chacha, keys->client_write_key,
specs->key_size);
XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
AEAD_IMP_IV_SZ);
CHACHA20_IV_SIZE);
if (chachaRet != 0) return chachaRet;
}
if (dec) {
chachaRet = wc_Chacha_SetKey(dec->chacha, keys->server_write_key,
specs->key_size);
XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
AEAD_IMP_IV_SZ);
CHACHA20_IV_SIZE);
if (chachaRet != 0) return chachaRet;
}
}
@@ -1932,14 +1991,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
chachaRet = wc_Chacha_SetKey(enc->chacha, keys->server_write_key,
specs->key_size);
XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
AEAD_IMP_IV_SZ);
CHACHA20_IV_SIZE);
if (chachaRet != 0) return chachaRet;
}
if (dec) {
chachaRet = wc_Chacha_SetKey(dec->chacha, keys->client_write_key,
specs->key_size);
XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
AEAD_IMP_IV_SZ);
CHACHA20_IV_SIZE);
if (chachaRet != 0) return chachaRet;
}
}
@@ -2489,10 +2548,10 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side)
/* Initialize encrypt implicit IV by encrypt side */
if (ssl->options.side == WOLFSSL_CLIENT_END) {
XMEMCPY(ssl->keys.aead_enc_imp_IV,
keys->client_write_IV, AEAD_IMP_IV_SZ);
keys->client_write_IV, AEAD_NONCE_SZ);
} else {
XMEMCPY(ssl->keys.aead_enc_imp_IV,
keys->server_write_IV, AEAD_IMP_IV_SZ);
keys->server_write_IV, AEAD_NONCE_SZ);
}
}
#endif
@@ -2504,10 +2563,10 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side)
/* Initialize decrypt implicit IV by decrypt side */
if (ssl->options.side == WOLFSSL_SERVER_END) {
XMEMCPY(ssl->keys.aead_dec_imp_IV,
keys->client_write_IV, AEAD_IMP_IV_SZ);
keys->client_write_IV, AEAD_NONCE_SZ);
} else {
XMEMCPY(ssl->keys.aead_dec_imp_IV,
keys->server_write_IV, AEAD_IMP_IV_SZ);
keys->server_write_IV, AEAD_NONCE_SZ);
}
}
#endif

View File

@@ -235,6 +235,8 @@ void wolfSSL_free(WOLFSSL* ssl)
int wolfSSL_use_old_poly(WOLFSSL* ssl, int value)
{
WOLFSSL_ENTER("SSL_use_old_poly");
WOLFSSL_MSG("Warning SSL connection auto detects old/new and this function"
"is depriciated");
ssl->options.oldPoly = value;
WOLFSSL_LEAVE("SSL_use_old_poly", 0);
return 0;
@@ -423,7 +425,7 @@ int wolfSSL_GetObjectSize(void)
printf(" sizeof rabbit = %lu\n", sizeof(Rabbit));
#endif
#ifdef HAVE_CHACHA
printf(" sizeof chacha = %lu\n", sizeof(Chacha));
printf(" sizeof chacha = %lu\n", sizeof(ChaCha));
#endif
printf("sizeof cipher specs = %lu\n", sizeof(CipherSpecs));
printf("sizeof keys = %lu\n", sizeof(Keys));
@@ -10169,16 +10171,25 @@ const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher)
if (cipher->ssl->options.cipherSuite0 == CHACHA_BYTE) {
/* ChaCha suites */
switch (cipher->ssl->options.cipherSuite) {
#ifdef HAVE_CHACHA
#ifdef HAVE_POLY1305
#ifndef NO_RSA
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
return "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
return "TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256";
case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
return "TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256";
#endif
case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256";
case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
return "TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256";
#endif
}
}

View File

@@ -1,30 +1,3 @@
# server TLSv1 DHE-RSA-CHACHA20-POLY1305
-v 1
-l DHE-RSA-CHACHA20-POLY1305
# client TLSv1 DHE-RSA-CHACHA20-POLY1305
-v 1
-l DHE-RSA-CHACHA20-POLY1305
# server TLSv1 ECDHE-EDCSA-CHACHA20-POLY1305
-v 1
-l ECDHE-ECDSA-CHACHA20-POLY1305
-c ./certs/server-ecc.pem
-k ./certs/ecc-key.pem
# client TLSv1 ECDHE-ECDSA-CHACHA20-POLY1305
-v 1
-l ECDHE-ECDSA-CHACHA20-POLY1305
-A ./certs/server-ecc.pem
# server TLSv1 ECDHE-RSA-CHACHA20-POLY1305
-v 1
-l ECDHE-RSA-CHACHA20-POLY1305
# client TLSv1 ECDHE-RSA-CHACHA20-POLY1305
-v 1
-l ECDHE-RSA-CHACHA20-POLY1305
# server TLSv1.1 DHE-RSA-CHACHA20-POLY1305
-v 2
-l DHE-RSA-CHACHA20-POLY1305
@@ -34,7 +7,7 @@
-l DHE-RSA-CHACHA20-POLY1305
# server TLSv1.1 ECDHE-RSA-CHACHA20-POLY1305
-v 2
-v 2
-l ECDHE-RSA-CHACHA20-POLY1305
# client TLSv1.1 ECDHE-RSA-CHACHA20-POLY1305
@@ -61,7 +34,7 @@
-l DHE-RSA-CHACHA20-POLY1305
# server TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305
-v 3
-v 3
-l ECDHE-RSA-CHACHA20-POLY1305
# client TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305
@@ -79,6 +52,33 @@
-l ECDHE-ECDSA-CHACHA20-POLY1305
-A ./certs/server-ecc.pem
# server TLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD
-v 3
-l DHE-RSA-CHACHA20-POLY1305-OLD
# client TLSv1.2 DHE-RSA-CHACHA20-POLY1305-OLD
-v 3
-l DHE-RSA-CHACHA20-POLY1305-OLD
# server TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD
-v 3
-l ECDHE-RSA-CHACHA20-POLY1305-OLD
# client TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305-OLD
-v 3
-l ECDHE-RSA-CHACHA20-POLY1305-OLD
# server TLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305-OLD
-v 3
-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD
-c ./certs/server-ecc.pem
-k ./certs/ecc-key.pem
# client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305-OLD
-v 3
-l ECDHE-ECDSA-CHACHA20-POLY1305-OLD
-A ./certs/server-ecc.pem
# server SSLv3 RC4-SHA
-v 0
-l RC4-SHA

View File

@@ -127,6 +127,16 @@
}
#endif
static void U32TO64(word32 v, byte* p) {
XMEMSET(p, 0, 8);
p[0] = (v & 0xFF);
p[1] = (v >> 8) & 0xFF;
p[2] = (v >> 16) & 0xFF;
p[3] = (v >> 24) & 0xFF;
}
static void poly1305_blocks(Poly1305* ctx, const unsigned char *m,
size_t bytes) {
@@ -550,5 +560,81 @@ int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) {
}
return 0;
}
/* Takes in an initialized Poly1305 struct that has a key loaded and creates
a MAC (tag) using recent TLS AEAD padding scheme.
ctx : Initialized Poly1305 struct to use
additional : Additional data to use
addSz : Size of additional buffer
input : Input buffer to create tag from
sz : Size of input buffer
tag : Buffer to hold created tag
tagSz : Size of input tag buffer (must be at least
WC_POLY1305_MAC_SZ(16))
*/
int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz,
byte* input, word32 sz, byte* tag, word32 tagSz)
{
int ret;
byte padding[WC_POLY1305_PAD_SZ - 1];
word32 paddingLen;
byte little64[8];
XMEMSET(padding, 0, sizeof(padding));
/* sanity check on arguments */
if (ctx == NULL || input == NULL || tag == NULL ||
tagSz < WC_POLY1305_MAC_SZ) {
return BAD_FUNC_ARG;
}
if (additional == NULL && addSz > 0) {
return BAD_FUNC_ARG;
}
/* additional data plus padding */
if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) {
return ret;
}
paddingLen = -addSz & (WC_POLY1305_PAD_SZ - 1);
if (paddingLen) {
if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) {
return ret;
}
}
/* input plus padding */
if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) {
return ret;
}
paddingLen = -sz & (WC_POLY1305_PAD_SZ - 1);
if (paddingLen) {
if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) {
return ret;
}
}
/* size of additional data and input as little endian 64 bit types */
U32TO64(addSz, little64);
ret = wc_Poly1305Update(ctx, little64, sizeof(little64));
if (ret)
{
return ret;
}
U32TO64(sz, little64);
ret = wc_Poly1305Update(ctx, little64, sizeof(little64));
if (ret)
{
return ret;
}
/* Finalize the auth tag */
ret = wc_Poly1305Final(ctx, tag);
return ret;
}
#endif /* HAVE_POLY1305 */

View File

@@ -2090,6 +2090,31 @@ int poly1305_test(void)
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
const byte msg4[] =
{
0xd3,0x1a,0x8d,0x34,0x64,0x8e,0x60,0xdb,
0x7b,0x86,0xaf,0xbc,0x53,0xef,0x7e,0xc2,
0xa4,0xad,0xed,0x51,0x29,0x6e,0x08,0xfe,
0xa9,0xe2,0xb5,0xa7,0x36,0xee,0x62,0xd6,
0x3d,0xbe,0xa4,0x5e,0x8c,0xa9,0x67,0x12,
0x82,0xfa,0xfb,0x69,0xda,0x92,0x72,0x8b,
0x1a,0x71,0xde,0x0a,0x9e,0x06,0x0b,0x29,
0x05,0xd6,0xa5,0xb6,0x7e,0xcd,0x3b,0x36,
0x92,0xdd,0xbd,0x7f,0x2d,0x77,0x8b,0x8c,
0x98,0x03,0xae,0xe3,0x28,0x09,0x1b,0x58,
0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94,
0x55,0x85,0x80,0x8b,0x48,0x31,0xd7,0xbc,
0x3f,0xf4,0xde,0xf0,0x8e,0x4b,0x7a,0x9d,
0xe5,0x76,0xd2,0x65,0x86,0xce,0xc6,0x4b,
0x61,0x16
};
byte additional[] =
{
0x50,0x51,0x52,0x53,0xc0,0xc1,0xc2,0xc3,
0xc4,0xc5,0xc6,0xc7
};
const byte correct[] =
{
0xa8,0x06,0x1d,0xc1,0x30,0x51,0x36,0xc6,
@@ -2109,6 +2134,12 @@ int poly1305_test(void)
0xc2,0x6b,0x33,0xb9,0x1c,0xcc,0x03,0x07
};
const byte correct4[] =
{
0x1a,0xe1,0x0b,0x59,0x4f,0x09,0xe2,0x6a,
0x7e,0x90,0x2e,0xcb,0xd0,0x60,0x06,0x91
};
const byte key[] = {
0x85,0xd6,0xbe,0x78,0x57,0x55,0x6d,0x33,
0x7f,0x44,0x52,0xfe,0x42,0xd5,0x06,0xa8,
@@ -2123,6 +2154,13 @@ int poly1305_test(void)
0x50,0x6f,0x6c,0x79,0x31,0x33,0x30,0x35
};
const byte key4[] = {
0x7b,0xac,0x2b,0x25,0x2d,0xb4,0x47,0xaf,
0x09,0xb6,0x7a,0x55,0xa4,0xe9,0x55,0x84,
0x0a,0xe1,0xd6,0x73,0x10,0x75,0xd9,0xeb,
0x2a,0x93,0x75,0x78,0x3e,0xd5,0x53,0xff
};
const byte* msgs[] = {msg, msg2, msg3};
word32 szm[] = {sizeof(msg),sizeof(msg2),sizeof(msg3)};
const byte* keys[] = {key, key2, key2};
@@ -2145,6 +2183,32 @@ int poly1305_test(void)
return -61;
}
/* Check TLS MAC function from 2.8.2 https://tools.ietf.org/html/rfc7539 */
XMEMSET(tag, 0, sizeof(tag));
ret = wc_Poly1305SetKey(&enc, key4, sizeof(key4));
if (ret != 0)
return -62;
ret = wc_Poly1305_MAC(&enc, additional, sizeof(additional),
(byte*)msg4, sizeof(msg4), tag, sizeof(tag));
if (ret != 0)
return -63;
if (memcmp(tag, correct4, sizeof(tag)))
return -64;
/* Check fail of TLS MAC function if altering additional data */
XMEMSET(tag, 0, sizeof(tag));
additional[0] = additional[0] + 1;
ret = wc_Poly1305_MAC(&enc, additional, sizeof(additional),
(byte*)msg4, sizeof(msg4), tag, sizeof(tag));
if (ret != 0)
return -65;
if (memcmp(tag, correct4, sizeof(tag)) == 0)
return -66;
return 0;
}
#endif /* HAVE_POLY1305 */

View File

@@ -521,6 +521,18 @@ typedef byte word24[3];
#endif /* NO_SHA */
#endif
#endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256) \
&& !defined(NO_OLD_POLY1305)
#ifdef HAVE_ECC
#define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256
#ifndef NO_RSA
#define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
#endif
#endif
#if !defined(NO_DH) && !defined(NO_RSA)
#define BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256
#endif
#endif
#endif /* !WOLFSSL_MAX_STRENGTH */
@@ -787,9 +799,14 @@ enum {
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0xc4,
/* chacha20-poly1305 suites first byte is 0xCC (CHACHA_BYTE) */
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0x13,
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0x14,
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0x15,
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xa8,
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xa9,
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xaa,
/* chacha20-poly1305 earlier version of nonce and padding (CHACHA_BYTE) */
TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x13,
TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x14,
TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x15,
/* Renegotiation Indication Extension Special Suite */
TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0xff
@@ -933,7 +950,7 @@ enum Misc {
CHACHA20_256_KEY_SIZE = 32, /* for 256 bit */
CHACHA20_128_KEY_SIZE = 16, /* for 128 bit */
CHACHA20_IV_SIZE = 8, /* 64 bits for iv */
CHACHA20_IV_SIZE = 12, /* 96 bits for iv */
POLY1305_AUTH_SZ = 16, /* 128 bits */
@@ -1448,8 +1465,8 @@ typedef struct Keys {
byte server_write_IV[AES_IV_SIZE];
#ifdef HAVE_AEAD
byte aead_exp_IV[AEAD_EXP_IV_SZ];
byte aead_enc_imp_IV[AEAD_IMP_IV_SZ];
byte aead_dec_imp_IV[AEAD_IMP_IV_SZ];
byte aead_enc_imp_IV[AEAD_NONCE_SZ]; /* full size needed for chacha-poly */
byte aead_dec_imp_IV[AEAD_NONCE_SZ];
#endif
word32 peer_sequence_number;

View File

@@ -46,9 +46,11 @@ enum {
POLY1305 = 7,
POLY1305_BLOCK_SIZE = 16,
POLY1305_DIGEST_SIZE = 16,
POLY1305_PAD_SIZE = 56
};
#define WC_POLY1305_PAD_SZ 16
#define WC_POLY1305_MAC_SZ 16
/* Poly1305 state */
typedef struct Poly1305 {
#if defined(POLY130564)
@@ -71,7 +73,8 @@ typedef struct Poly1305 {
WOLFSSL_API int wc_Poly1305SetKey(Poly1305* poly1305, const byte* key, word32 kySz);
WOLFSSL_API int wc_Poly1305Update(Poly1305* poly1305, const byte*, word32);
WOLFSSL_API int wc_Poly1305Final(Poly1305* poly1305, byte* tag);
WOLFSSL_API int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz,
byte* input, word32 sz, byte* tag, word32 tagSz);
#ifdef __cplusplus
} /* extern "C" */
#endif