Merge branch 'aburks-chapoly'

This commit is contained in:
toddouska
2015-02-24 12:35:08 -08:00
13 changed files with 653 additions and 92 deletions

View File

@ -6,7 +6,7 @@
# #
# #
AC_INIT([wolfssl],[3.4.0],[https://github.com/wolfssl/wolfssl/issues],[wolfssl],[http://www.wolfssl.com]) AC_INIT([wolfssl],[3.4.1],[https://github.com/wolfssl/wolfssl/issues],[wolfssl],[http://www.wolfssl.com])
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])

View File

@ -146,6 +146,9 @@ endif
if BUILD_CHACHA if BUILD_CHACHA
src_libwolfssl_la_SOURCES += wolfcrypt/src/chacha.c src_libwolfssl_la_SOURCES += wolfcrypt/src/chacha.c
if BUILD_POLY1305
src_libwolfssl_la_SOURCES += wolfcrypt/src/chacha20_poly1305.c
endif
endif endif
if !BUILD_INLINE if !BUILD_INLINE

View File

@ -5,6 +5,6 @@ includedir=${prefix}/include
Name: wolfssl Name: wolfssl
Description: wolfssl C library. Description: wolfssl C library.
Version: 3.4.0 Version: 3.4.1
Libs: -L${libdir} -lwolfssl Libs: -L${libdir} -lwolfssl
Cflags: -I${includedir} Cflags: -I${includedir}

View File

@ -43,6 +43,7 @@
#include <wolfssl/wolfcrypt/hc128.h> #include <wolfssl/wolfcrypt/hc128.h>
#include <wolfssl/wolfcrypt/rabbit.h> #include <wolfssl/wolfcrypt/rabbit.h>
#include <wolfssl/wolfcrypt/chacha.h> #include <wolfssl/wolfcrypt/chacha.h>
#include <wolfssl/wolfcrypt/chacha20_poly1305.h>
#include <wolfssl/wolfcrypt/aes.h> #include <wolfssl/wolfcrypt/aes.h>
#include <wolfssl/wolfcrypt/poly1305.h> #include <wolfssl/wolfcrypt/poly1305.h>
#include <wolfssl/wolfcrypt/camellia.h> #include <wolfssl/wolfcrypt/camellia.h>
@ -116,6 +117,7 @@ void bench_arc4(void);
void bench_hc128(void); void bench_hc128(void);
void bench_rabbit(void); void bench_rabbit(void);
void bench_chacha(void); void bench_chacha(void);
void bench_chacha20_poly1305_aead(void);
void bench_aes(int); void bench_aes(int);
void bench_aesgcm(void); void bench_aesgcm(void);
void bench_aesccm(void); void bench_aesccm(void);
@ -283,6 +285,9 @@ int benchmark_test(void *args)
#ifdef HAVE_CHACHA #ifdef HAVE_CHACHA
bench_chacha(); bench_chacha();
#endif #endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
bench_chacha20_poly1305_aead();
#endif
#ifndef NO_DES3 #ifndef NO_DES3
bench_des(); bench_des();
#endif #endif
@ -771,6 +776,40 @@ void bench_chacha(void)
} }
#endif /* HAVE_CHACHA*/ #endif /* HAVE_CHACHA*/
#if( defined( HAVE_CHACHA ) && defined( HAVE_POLY1305 ) )
void bench_chacha20_poly1305_aead(void)
{
double start, total, persec;
int i;
byte authTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
XMEMSET( authTag, 0, sizeof( authTag ) );
start = current_time(1);
BEGIN_INTEL_CYCLES
for (i = 0; i < numBlocks; i++)
{
wc_ChaCha20Poly1305_Encrypt(key, iv, NULL, 0, plain, sizeof(plain),
cipher, authTag );
}
END_INTEL_CYCLES
total = current_time(0) - start;
persec = 1 / total * numBlocks;
#ifdef BENCH_EMBEDDED
/* since using kB, convert to MB/s */
persec = persec / 1024;
#endif
printf("ChaCha-Poly %d %s took %5.3f seconds, %7.3f MB/s",
numBlocks, blockType, total, persec);
SHOW_INTEL_CYCLES
printf("\n");
}
#endif /* HAVE_CHACHA && HAVE_POLY1305 */
#ifndef NO_MD5 #ifndef NO_MD5
void bench_md5(void) void bench_md5(void)

View File

@ -32,7 +32,6 @@
#include "dc_rtc_api.h" /* to get current time */ #include "dc_rtc_api.h" /* to get current time */
#endif #endif
#include <wolfssl/wolfcrypt/integer.h>
#include <wolfssl/wolfcrypt/asn.h> #include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/coding.h> #include <wolfssl/wolfcrypt/coding.h>
#include <wolfssl/wolfcrypt/md2.h> #include <wolfssl/wolfcrypt/md2.h>

View File

@ -0,0 +1,289 @@
/* chacha.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
#include <wolfssl/wolfcrypt/chacha20_poly1305.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/chacha.h>
#include <wolfssl/wolfcrypt/poly1305.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#ifdef CHACHA_AEAD_TEST
#include <stdio.h>
#endif
#define CHACHA20_POLY1305_AEAD_INITIAL_COUNTER 0
#define CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT 16
static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]);
static int calculateAuthTag(
const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
const byte* inAAD, const word32 inAADLen,
const byte *inCiphertext, const word32 inCiphertextLen,
byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]);
static int constantTimeCompare(const byte *a, const byte *b, word32 len);
int wc_ChaCha20Poly1305_Encrypt(
const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
const byte* inAAD, const word32 inAADLen,
const byte* inPlaintext, const word32 inPlaintextLen,
byte* outCiphertext,
byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
{
int err;
byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE];
ChaCha chaChaCtx;
/* Validate function arguments */
if (!inKey || !inIV ||
!inPlaintext || !inPlaintextLen ||
!outCiphertext ||
!outAuthTag)
{
return BAD_FUNC_ARG;
}
XMEMSET(poly1305Key, 0, sizeof(poly1305Key));
/* Create the Poly1305 key */
err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE);
if (err != 0) return err;
err = wc_Chacha_SetIV(&chaChaCtx, inIV,
CHACHA20_POLY1305_AEAD_INITIAL_COUNTER);
if (err != 0) return err;
err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key,
CHACHA20_POLY1305_AEAD_KEYSIZE);
if (err != 0) return err;
/* Encrypt the plaintext using ChaCha20 */
err = wc_Chacha_Process(&chaChaCtx, outCiphertext, inPlaintext,
inPlaintextLen);
/* Calculate the Poly1305 auth tag */
if (err == 0)
err = calculateAuthTag(poly1305Key,
inAAD, inAADLen,
outCiphertext, inPlaintextLen,
outAuthTag);
ForceZero(poly1305Key, sizeof(poly1305Key));
return err;
}
int wc_ChaCha20Poly1305_Decrypt(
const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
const byte* inAAD, const word32 inAADLen,
const byte* inCiphertext, const word32 inCiphertextLen,
const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE],
byte* outPlaintext)
{
int err;
byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE];
ChaCha chaChaCtx;
byte calculatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
/* Validate function arguments */
if (!inKey || !inIV ||
!inCiphertext || !inCiphertextLen ||
!inAuthTag ||
!outPlaintext)
{
return BAD_FUNC_ARG;
}
XMEMSET(calculatedAuthTag, 0, sizeof(calculatedAuthTag));
XMEMSET(poly1305Key, 0, sizeof(poly1305Key));
/* Create the Poly1305 key */
err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE);
if (err != 0) return err;
err = wc_Chacha_SetIV(&chaChaCtx, inIV,
CHACHA20_POLY1305_AEAD_INITIAL_COUNTER);
if (err != 0) return err;
err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key,
CHACHA20_POLY1305_AEAD_KEYSIZE);
if (err != 0) return err;
/* Calculate the Poly1305 auth tag */
err = calculateAuthTag(poly1305Key,
inAAD, inAADLen,
inCiphertext, inCiphertextLen,
calculatedAuthTag);
/* Compare the calculated auth tag with the received one */
if (err == 0 && constantTimeCompare(inAuthTag, calculatedAuthTag,
CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) != 0)
{
err = MAC_CMP_FAILED_E;
}
/* Decrypt the received ciphertext */
if (err == 0)
err = wc_Chacha_Process(&chaChaCtx, outPlaintext, inCiphertext,
inCiphertextLen);
ForceZero(poly1305Key, sizeof(poly1305Key));
return err;
}
static int calculateAuthTag(
const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
const byte *inAAD, const word32 inAADLen,
const byte *inCiphertext, const word32 inCiphertextLen,
byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
{
int err;
Poly1305 poly1305Ctx;
byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1];
word32 paddingLen;
byte little64[8];
XMEMSET(padding, 0, sizeof(padding));
paddingLen = 0;
/* Initialize Poly1305 */
err = wc_Poly1305SetKey(&poly1305Ctx, inAuthKey,
CHACHA20_POLY1305_AEAD_KEYSIZE);
if (err)
{
return err;
}
/* Create the authTag by MAC'ing the following items: */
/* -- AAD */
if (inAAD && inAADLen)
{
err = wc_Poly1305Update(&poly1305Ctx, inAAD, inAADLen);
/* -- padding1: pad the AAD to 16 bytes */
paddingLen = -inAADLen & (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1);
if (paddingLen)
{
err += wc_Poly1305Update(&poly1305Ctx, padding, paddingLen);
}
if (err)
{
return err;
}
}
/* -- Ciphertext */
err = wc_Poly1305Update(&poly1305Ctx, inCiphertext, inCiphertextLen);
if (err)
{
return err;
}
/* -- padding2: pad the ciphertext to 16 bytes */
paddingLen = -inCiphertextLen &
(CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1);
if (paddingLen)
{
err = wc_Poly1305Update(&poly1305Ctx, padding, paddingLen);
if (err)
{
return err;
}
}
/* -- AAD length as a 64-bit little endian integer */
word32ToLittle64(inAADLen, little64);
err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64));
if (err)
{
return err;
}
/* -- Ciphertext length as a 64-bit little endian integer */
word32ToLittle64(inCiphertextLen, little64);
err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64));
if (err)
{
return err;
}
/* Finalize the auth tag */
err = wc_Poly1305Final(&poly1305Ctx, outAuthTag);
return err;
}
static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8])
{
XMEMSET(outLittle64, 0, 8);
outLittle64[0] = (inLittle32 & 0x000000FF);
outLittle64[1] = (inLittle32 & 0x0000FF00) >> 8;
outLittle64[2] = (inLittle32 & 0x00FF0000) >> 16;
outLittle64[3] = (inLittle32 & 0xFF000000) >> 24;
}
static int constantTimeCompare(const byte *a, const byte *b, word32 len)
{
word32 i;
byte result = 0;
for (i = 0; i < len; i++)
{
result |= a[i] ^ b[i];
}
return (int)result;
}
#endif /* HAVE_CHACHA && HAVE_POLY1305 */

View File

@ -316,6 +316,9 @@ const char* wc_GetErrorString(int error)
case THREAD_STORE_SET_E: case THREAD_STORE_SET_E:
return "Thread Storage Set error"; return "Thread Storage Set error";
case MAC_CMP_FAILED_E:
return "MAC comparison failed";
default: default:
return "unknown error number"; return "unknown error number";

View File

@ -56,6 +56,7 @@
#include <wolfssl/wolfcrypt/hc128.h> #include <wolfssl/wolfcrypt/hc128.h>
#include <wolfssl/wolfcrypt/rabbit.h> #include <wolfssl/wolfcrypt/rabbit.h>
#include <wolfssl/wolfcrypt/chacha.h> #include <wolfssl/wolfcrypt/chacha.h>
#include <wolfssl/wolfcrypt/chacha20_poly1305.h>
#include <wolfssl/wolfcrypt/pwdbased.h> #include <wolfssl/wolfcrypt/pwdbased.h>
#include <wolfssl/wolfcrypt/ripemd.h> #include <wolfssl/wolfcrypt/ripemd.h>
#include <wolfssl/wolfcrypt/error-crypt.h> #include <wolfssl/wolfcrypt/error-crypt.h>
@ -162,7 +163,7 @@ int arc4_test(void);
int hc128_test(void); int hc128_test(void);
int rabbit_test(void); int rabbit_test(void);
int chacha_test(void); int chacha_test(void);
int chacha_poly_test(void); int chacha20_poly1305_aead_test(void);
int des_test(void); int des_test(void);
int des3_test(void); int des3_test(void);
int aes_test(void); int aes_test(void);
@ -415,10 +416,10 @@ int wolfcrypt_test(void* args)
#endif #endif
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
if ( (ret = chacha_poly_test()) != 0) if ( (ret = chacha20_poly1305_aead_test()) != 0)
return err_sys("CHACHA-POLY AEAD test failed!\n", ret); return err_sys("ChaCha20-Poly1305 AEAD test failed!\n", ret);
else else
printf( "ChachaAEAD test passed!\n"); printf( "ChaCha20-Poly1305 AEAD test passed!\n");
#endif #endif
#ifndef NO_DES3 #ifndef NO_DES3
@ -2074,116 +2075,260 @@ int poly1305_test(void)
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
int chacha_poly_test(void) int chacha20_poly1305_aead_test(void)
{ {
/* Test #1 from Section 2.8.2 of draft-irtf-cfrg-chacha20-poly1305-10 */
/* https://tools.ietf.org/html/draft-irtf-cfrg-chacha20-poly1305-10 */
const byte key[] = { const byte key1[] = {
0x42,0x90,0xbc,0xb1,0x54,0x17,0x35,0x31, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0xf3,0x14,0xaf,0x57,0xf3,0xbe,0x3b,0x50, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x06,0xda,0x37,0x1e,0xce,0x27,0x2a,0xfa, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x1b,0x5d,0xbd,0xd1,0x10,0x0a,0x10,0x07 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
}; };
const byte input[] = { const byte plaintext1[] = {
0x86,0xd0,0x99,0x74,0x84,0x0b,0xde,0xd2, 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
0xa5,0xca 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
0x74, 0x2e
}; };
const byte nonce[] = { const byte iv1[] = {
0x00,0x00,0x00,0x00,0xcd,0x7c,0xf6,0x7b, 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43,
0xe3,0x9c,0x79,0x4a 0x44, 0x45, 0x46, 0x47
}; };
const byte ad[] = { /* aditional data */ const byte aad1[] = { /* additional data */
0x87,0xe2,0x29,0xd4,0x50,0x08,0x45,0xa0, 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
0x79,0xc0,0x0a,0x00,0x00,0x00,0x00,0x00, 0xc4, 0xc5, 0xc6, 0xc7
0x00,0x00
}; };
const byte test[] = { /* expected output from operation */ const byte cipher1[] = { /* expected output from operation */
0xe3,0xe4,0x46,0xf7,0xed,0xe9,0xa1,0x9b, 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
0x62,0xa4,0x98,0xa5,0x9a,0x87,0xf9,0x82, 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
0xa1,0xfe,0xcb,0xac,0xd3,0xff,0xe8,0x29, 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
0x31,0x04 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
}; };
const byte authTag1[] = { /* expected output from operation */
0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
};
byte polyKey[64]; /* Test #2 from Appendix A.2 in draft-irtf-cfrg-chacha20-poly1305-10 */
byte cipher[32]; /* https://tools.ietf.org/html/draft-irtf-cfrg-chacha20-poly1305-10 */
byte tag[16]; /* tag made from Poly1305 MAC algorithm */
byte out[48]; /* cipher (32) + tag size of (16) */
byte msg[10]; /* message after decryption */
word32 keySz = 32;
int ret = 0;
ChaCha chaEnc, chaDec; const byte key2[] = {
Poly1305 polyEnc, polyDec; 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a,
0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0,
0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09,
0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0
};
XMEMSET(polyKey, 0, sizeof(polyKey)); const byte plaintext2[] = {
XMEMSET(cipher, 0, sizeof(cipher)); 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
XMEMSET(tag, 0, sizeof(tag)); 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x20,
XMEMSET(out, 0, sizeof(out)); 0x61, 0x72, 0x65, 0x20, 0x64, 0x72, 0x61, 0x66,
XMEMSET(msg, 0, sizeof(msg)); 0x74, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
0x6e, 0x74, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x69,
0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20,
0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20,
0x6f, 0x66, 0x20, 0x73, 0x69, 0x78, 0x20, 0x6d,
0x6f, 0x6e, 0x74, 0x68, 0x73, 0x20, 0x61, 0x6e,
0x64, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65,
0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64,
0x2c, 0x20, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63,
0x65, 0x64, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x6f,
0x62, 0x73, 0x6f, 0x6c, 0x65, 0x74, 0x65, 0x64,
0x20, 0x62, 0x79, 0x20, 0x6f, 0x74, 0x68, 0x65,
0x72, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
0x6e, 0x74, 0x73, 0x20, 0x61, 0x74, 0x20, 0x61,
0x6e, 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x2e,
0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x69,
0x6e, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x70, 0x72,
0x69, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20,
0x75, 0x73, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x65, 0x74, 0x2d, 0x44, 0x72, 0x61,
0x66, 0x74, 0x73, 0x20, 0x61, 0x73, 0x20, 0x72,
0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65,
0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61,
0x6c, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x20,
0x63, 0x69, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65,
0x6d, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20,
0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x73, 0x20,
0x2f, 0xe2, 0x80, 0x9c, 0x77, 0x6f, 0x72, 0x6b,
0x20, 0x69, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x67,
0x72, 0x65, 0x73, 0x73, 0x2e, 0x2f, 0xe2, 0x80,
0x9d
};
/***** ENCRYPTION ******/ const byte iv2[] = {
0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08
};
/* Initialise chacha / poly and get poly key */ const byte aad2[] = { /* additional data */
ret += wc_Chacha_SetKey(&chaEnc, key, keySz); 0xf3, 0x33, 0x88, 0x86, 0x00, 0x00, 0x00, 0x00,
ret += wc_Chacha_SetIV(&chaEnc, nonce, 0); /* start with counter at 0 */ 0x00, 0x00, 0x4e, 0x91
/* AEAD poly key is created by first run of ChaCha */ };
ret += wc_Chacha_Process(&chaEnc, polyKey, polyKey, 64);
ret += wc_Poly1305SetKey(&polyEnc, polyKey, 32);
/* encrypt the plain text then append tag */ const byte cipher2[] = { /* expected output from operation */
ret += wc_Chacha_SetIV(&chaEnc, nonce, 1); 0x64, 0xa0, 0x86, 0x15, 0x75, 0x86, 0x1a, 0xf4,
ret += wc_Chacha_Process(&chaEnc, cipher, input, sizeof(input)); 0x60, 0xf0, 0x62, 0xc7, 0x9b, 0xe6, 0x43, 0xbd,
/* tag is created with using ad and cipher (SSL/TLS uses padding as well) */ 0x5e, 0x80, 0x5c, 0xfd, 0x34, 0x5c, 0xf3, 0x89,
ret += wc_Poly1305Update(&polyEnc, ad, sizeof(ad)); 0xf1, 0x08, 0x67, 0x0a, 0xc7, 0x6c, 0x8c, 0xb2,
ret += wc_Poly1305Update(&polyEnc, cipher, sizeof(input)); 0x4c, 0x6c, 0xfc, 0x18, 0x75, 0x5d, 0x43, 0xee,
ret += wc_Poly1305Final(&polyEnc, tag); 0xa0, 0x9e, 0xe9, 0x4e, 0x38, 0x2d, 0x26, 0xb0,
XMEMCPY(out, cipher, sizeof(input)); /* copy cipher to first of out */ 0xbd, 0xb7, 0xb7, 0x3c, 0x32, 0x1b, 0x01, 0x00,
XMEMCPY(out + sizeof(input), tag, sizeof(tag)); /* append tag to out */ 0xd4, 0xf0, 0x3b, 0x7f, 0x35, 0x58, 0x94, 0xcf,
0x33, 0x2f, 0x83, 0x0e, 0x71, 0x0b, 0x97, 0xce,
0x98, 0xc8, 0xa8, 0x4a, 0xbd, 0x0b, 0x94, 0x81,
0x14, 0xad, 0x17, 0x6e, 0x00, 0x8d, 0x33, 0xbd,
0x60, 0xf9, 0x82, 0xb1, 0xff, 0x37, 0xc8, 0x55,
0x97, 0x97, 0xa0, 0x6e, 0xf4, 0xf0, 0xef, 0x61,
0xc1, 0x86, 0x32, 0x4e, 0x2b, 0x35, 0x06, 0x38,
0x36, 0x06, 0x90, 0x7b, 0x6a, 0x7c, 0x02, 0xb0,
0xf9, 0xf6, 0x15, 0x7b, 0x53, 0xc8, 0x67, 0xe4,
0xb9, 0x16, 0x6c, 0x76, 0x7b, 0x80, 0x4d, 0x46,
0xa5, 0x9b, 0x52, 0x16, 0xcd, 0xe7, 0xa4, 0xe9,
0x90, 0x40, 0xc5, 0xa4, 0x04, 0x33, 0x22, 0x5e,
0xe2, 0x82, 0xa1, 0xb0, 0xa0, 0x6c, 0x52, 0x3e,
0xaf, 0x45, 0x34, 0xd7, 0xf8, 0x3f, 0xa1, 0x15,
0x5b, 0x00, 0x47, 0x71, 0x8c, 0xbc, 0x54, 0x6a,
0x0d, 0x07, 0x2b, 0x04, 0xb3, 0x56, 0x4e, 0xea,
0x1b, 0x42, 0x22, 0x73, 0xf5, 0x48, 0x27, 0x1a,
0x0b, 0xb2, 0x31, 0x60, 0x53, 0xfa, 0x76, 0x99,
0x19, 0x55, 0xeb, 0xd6, 0x31, 0x59, 0x43, 0x4e,
0xce, 0xbb, 0x4e, 0x46, 0x6d, 0xae, 0x5a, 0x10,
0x73, 0xa6, 0x72, 0x76, 0x27, 0x09, 0x7a, 0x10,
0x49, 0xe6, 0x17, 0xd9, 0x1d, 0x36, 0x10, 0x94,
0xfa, 0x68, 0xf0, 0xff, 0x77, 0x98, 0x71, 0x30,
0x30, 0x5b, 0xea, 0xba, 0x2e, 0xda, 0x04, 0xdf,
0x99, 0x7b, 0x71, 0x4d, 0x6c, 0x6f, 0x2c, 0x29,
0xa6, 0xad, 0x5c, 0xb4, 0x02, 0x2b, 0x02, 0x70,
0x9b
};
const byte authTag2[] = { /* expected output from operation */
0xee, 0xad, 0x9d, 0x67, 0x89, 0x0c, 0xbb, 0x22,
0x39, 0x23, 0x36, 0xfe, 0xa1, 0x85, 0x1f, 0x38
};
/****** TEST *****/ byte generatedCiphertext[272];
byte generatedPlaintext[272];
byte generatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
int err;
/* encrypted AEAD msg is now in out[] it's length is sizeof input + tag size XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext));
to test correctness we will compare the out[] to the expected output */ XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag));
if (memcmp(out, test, sizeof(test))) XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext));
return -1062;
/* Test #1 */
/****** DECRYPTION ******/ err = wc_ChaCha20Poly1305_Encrypt(key1, iv1,
aad1, sizeof(aad1),
plaintext1, sizeof(plaintext1),
generatedCiphertext, generatedAuthTag);
if (err)
{
return err;
}
XMEMSET(polyKey, 0, sizeof(polyKey)); /* -- Check the ciphertext and authtag */
XMEMSET(tag, 0, sizeof(tag));
/* Initialise chacha / poly and get poly key */ if (XMEMCMP(generatedCiphertext, cipher1, sizeof(cipher1)))
ret += wc_Chacha_SetKey(&chaDec, key, keySz); {
ret += wc_Chacha_SetIV(&chaDec, nonce, 0); /* start with counter at 0 */
/* AEAD poly key is created by first run of ChaCha */
ret += wc_Chacha_Process(&chaDec, polyKey, polyKey, 64);
ret += wc_Poly1305SetKey(&polyDec, polyKey, 32);
/* compare generated tag to what was sent */
ret += wc_Poly1305Update(&polyDec, ad, sizeof(ad));
ret += wc_Poly1305Update(&polyDec, out, sizeof(input)); /* cipher sent */
ret += wc_Poly1305Final(&polyDec, tag);
/* comparison of tags should be in constant time when implemented */
if (memcmp(tag, out + sizeof(input), sizeof(tag))) /* compare tags */
return -1063;
/* decrypt the cipher text */
ret += wc_Chacha_Process(&chaDec, msg, out, sizeof(input));
/****** TEST *****/
/* plain text msg has been recieved compare it to expected for test */
if (memcmp(msg, input, sizeof(input)))
return -1064; return -1064;
}
return ret; if (XMEMCMP(generatedAuthTag, authTag1, sizeof(authTag1)))
{
return -1065;
}
/* -- Verify decryption works */
err = wc_ChaCha20Poly1305_Decrypt(key1, iv1,
aad1, sizeof(aad1),
cipher1, sizeof(cipher1),
authTag1, generatedPlaintext);
if (err)
{
return err;
}
if (XMEMCMP(generatedPlaintext, plaintext1, sizeof( plaintext1)))
{
return -1066;
}
XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext));
XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag));
XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext));
/* Test #2 */
err = wc_ChaCha20Poly1305_Encrypt(key2, iv2,
aad2, sizeof(aad2),
plaintext2, sizeof(plaintext2),
generatedCiphertext, generatedAuthTag);
if (err)
{
return err;
}
/* -- Check the ciphertext and authtag */
if (XMEMCMP(generatedCiphertext, cipher2, sizeof(cipher2)))
{
return -1067;
}
if (XMEMCMP(generatedAuthTag, authTag2, sizeof(authTag2)))
{
return -1068;
}
/* -- Verify decryption works */
err = wc_ChaCha20Poly1305_Decrypt(key2, iv2,
aad2, sizeof(aad2),
cipher2, sizeof(cipher2),
authTag2, generatedPlaintext);
if (err)
{
return err;
}
if (XMEMCMP(generatedPlaintext, plaintext2, sizeof(plaintext2)))
{
return -1069;
}
return err;
} }
#endif /* HAVE_CHACHA && HAVE_POLY1305 */ #endif /* HAVE_CHACHA && HAVE_POLY1305 */

View File

@ -26,8 +26,8 @@
extern "C" { extern "C" {
#endif #endif
#define LIBWOLFSSL_VERSION_STRING "3.4.0" #define LIBWOLFSSL_VERSION_STRING "3.4.1"
#define LIBWOLFSSL_VERSION_HEX 0x03004000 #define LIBWOLFSSL_VERSION_HEX 0x03004001
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -25,6 +25,7 @@
#define WOLF_CRYPT_ASN_H #define WOLF_CRYPT_ASN_H
#include <wolfssl/wolfcrypt/types.h> #include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/wolfcrypt/integer.h>
#ifndef NO_RSA #ifndef NO_RSA
#include <wolfssl/wolfcrypt/rsa.h> #include <wolfssl/wolfcrypt/rsa.h>
#endif #endif

View File

@ -0,0 +1,79 @@
/* chacha20_poly1305.h
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* This implementation of the ChaCha20-Poly1305 AEAD is based on "ChaCha20
* and Poly1305 for IETF protocols" (draft-irtf-cfrg-chacha20-poly1305-10):
* https://tools.ietf.org/html/draft-irtf-cfrg-chacha20-poly1305-10
*/
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
#ifndef WOLF_CRYPT_CHACHA20_POLY1305_H
#define WOLF_CRYPT_CHACHA20_POLY1305_H
#include <wolfssl/wolfcrypt/types.h>
#ifdef __cplusplus
extern "C" {
#endif
#define CHACHA20_POLY1305_AEAD_KEYSIZE 32
#define CHACHA20_POLY1305_AEAD_IV_SIZE 12
#define CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE 16
enum {
CHACHA20_POLY_1305_ENC_TYPE = 8 /* cipher unique type */
};
/*
* The IV for this implementation is 96 bits to give the most flexibility.
*
* Some protocols may have unique per-invocation inputs that are not
* 96-bit in length. For example, IPsec may specify a 64-bit nonce. In
* such a case, it is up to the protocol document to define how to
* transform the protocol nonce into a 96-bit nonce, for example by
* concatenating a constant value.
*/
WOLFSSL_API
int wc_ChaCha20Poly1305_Encrypt(
const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
const byte* inAAD, const word32 inAADLen,
const byte* inPlaintext, const word32 inPlaintextLen,
byte* outCiphertext,
byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]);
WOLFSSL_API
int wc_ChaCha20Poly1305_Decrypt(
const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
const byte* inAAD, const word32 inAADLen,
const byte* inCiphertext, const word32 inCiphertextLen,
const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE],
byte* outPlaintext);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WOLF_CRYPT_CHACHA20_POLY1305_H */
#endif /* HAVE_CHACHA && HAVE_POLY1305 */

View File

@ -146,6 +146,8 @@ enum {
THREAD_STORE_KEY_E = -211, /* Thread local storage key create failure */ THREAD_STORE_KEY_E = -211, /* Thread local storage key create failure */
THREAD_STORE_SET_E = -212, /* Thread local storage key set failure */ THREAD_STORE_SET_E = -212, /* Thread local storage key set failure */
MAC_CMP_FAILED_E = -213, /* MAC comparison failed */
MIN_CODE_E = -300 /* errors -101 - -299 */ MIN_CODE_E = -300 /* errors -101 - -299 */
}; };

View File

@ -32,6 +32,7 @@ nobase_include_HEADERS+= \
wolfssl/wolfcrypt/pwdbased.h \ wolfssl/wolfcrypt/pwdbased.h \
wolfssl/wolfcrypt/rabbit.h \ wolfssl/wolfcrypt/rabbit.h \
wolfssl/wolfcrypt/chacha.h \ wolfssl/wolfcrypt/chacha.h \
wolfssl/wolfcrypt/chacha20_poly1305.h \
wolfssl/wolfcrypt/random.h \ wolfssl/wolfcrypt/random.h \
wolfssl/wolfcrypt/ripemd.h \ wolfssl/wolfcrypt/ripemd.h \
wolfssl/wolfcrypt/rsa.h \ wolfssl/wolfcrypt/rsa.h \