This commit is contained in:
JacobBarthelmeh 2014-07-21 15:12:12 -06:00
commit ff58f65418
18 changed files with 2064 additions and 20 deletions

View File

@ -401,6 +401,21 @@ fi
AM_CONDITIONAL([BUILD_AESNI], [test "x$ENABLED_AESNI" = "xyes"])
# POLY1305
AC_ARG_ENABLE([poly1305],
[ --enable-poly1305 Enable CyaSSL POLY1305 support (default: disabled)],
[ ENABLED_POLY1305=$enableval ],
[ ENABLED_POLY1305=no ]
)
if test "$ENABLED_POLY1305" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DHAVE_POLY1305"
fi
AM_CONDITIONAL([BUILD_POLY1305], [test "x$ENABLED_POLY1305" = "xyes"])
# Camellia
AC_ARG_ENABLE([camellia],
[ --enable-camellia Enable CyaSSL Camellia support (default: disabled)],
@ -1062,6 +1077,21 @@ fi
AM_CONDITIONAL([BUILD_RABBIT], [test "x$ENABLED_RABBIT" = "xyes"])
# CHACHA
AC_ARG_ENABLE([chacha],
[ --enable-chacha Enable CHACHA (default: disabled)],
[ ENABLED_CHACHA=$enableval ],
[ ENABLED_CHACHA=no ]
)
if test "$ENABLED_CHACHA" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DHAVE_CHACHA"
fi
AM_CONDITIONAL([BUILD_CHACHA], [test "x$ENABLED_CHACHA" = "xyes"])
# FIPS
AC_ARG_ENABLE([fips],
[ --enable-fips Enable FIPS 140-2 (default: disabled)],
@ -1797,11 +1827,13 @@ echo " * certgen: $ENABLED_CERTGEN"
echo " * certreq: $ENABLED_CERTREQ"
echo " * HC-128: $ENABLED_HC128"
echo " * RABBIT: $ENABLED_RABBIT"
echo " * CHACHA: $ENABLED_CHACHA"
echo " * Hash DRBG: $ENABLED_HASHDRBG"
echo " * PWDBASED: $ENABLED_PWDBASED"
echo " * HKDF: $ENABLED_HKDF"
echo " * MD4: $ENABLED_MD4"
echo " * PSK: $ENABLED_PSK"
echo " * Poly1305: $ENABLED_POLY1305"
echo " * LEANPSK: $ENABLED_LEANPSK"
echo " * RSA: $ENABLED_RSA"
echo " * DSA: $ENABLED_DSA"

View File

@ -34,7 +34,9 @@
#include <cyassl/ctaocrypt/arc4.h>
#include <cyassl/ctaocrypt/hc128.h>
#include <cyassl/ctaocrypt/rabbit.h>
#include <cyassl/ctaocrypt/chacha.h>
#include <cyassl/ctaocrypt/aes.h>
#include <cyassl/ctaocrypt/poly1305.h>
#include <cyassl/ctaocrypt/camellia.h>
#include <cyassl/ctaocrypt/md5.h>
#include <cyassl/ctaocrypt/sha.h>
@ -85,10 +87,12 @@ void bench_des(void);
void bench_arc4(void);
void bench_hc128(void);
void bench_rabbit(void);
void bench_chacha(void);
void bench_aes(int);
void bench_aesgcm(void);
void bench_aesccm(void);
void bench_aesctr(void);
void bench_poly1305(void);
void bench_camellia(void);
void bench_md5(void);
@ -189,6 +193,9 @@ int benchmark_test(void *args)
#ifndef NO_RABBIT
bench_rabbit();
#endif
#ifdef HAVE_CHACHA
bench_chacha();
#endif
#ifndef NO_DES3
bench_des();
#endif
@ -198,6 +205,9 @@ int benchmark_test(void *args)
#ifndef NO_MD5
bench_md5();
#endif
#ifdef HAVE_POLY1305
bench_poly1305();
#endif
#ifndef NO_SHA
bench_sha();
#endif
@ -425,6 +435,41 @@ void bench_aesccm(void)
#endif
#ifdef HAVE_POLY1305
void bench_poly1305()
{
Poly1305 enc;
byte mac[16];
double start, total, persec;
int i;
int ret;
ret = Poly1305SetKey(&enc, key, 32);
if (ret != 0) {
printf("Poly1305SetKey failed, ret = %d\n", ret);
return;
}
start = current_time(1);
for(i = 0; i < numBlocks; i++)
Poly1305Update(&enc, plain, sizeof(plain));
Poly1305Final(&enc, mac);
total = current_time(0) - start;
persec = 1 / total * numBlocks;
#ifdef BENCH_EMBEDDED
/* since using kB, convert to MB/s */
persec = persec / 1024;
#endif
printf("POLY1305 %d %s took %5.3f seconds, %7.3f MB/s\n", numBlocks,
blockType, total, persec);
}
#endif /* HAVE_POLY1305 */
#ifdef HAVE_CAMELLIA
void bench_camellia(void)
{
@ -580,6 +625,33 @@ void bench_rabbit(void)
#endif /* NO_RABBIT */
#ifdef HAVE_CHACHA
void bench_chacha(void)
{
ChaCha enc;
double start, total, persec;
int i;
Chacha_SetKey(&enc, key, 16);
start = current_time(1);
for (i = 0; i < numBlocks; i++) {
Chacha_SetIV(&enc, iv, 0);
Chacha_Process(&enc, cipher, plain, sizeof(plain));
}
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 %d %s took %5.3f seconds, %7.3f MB/s\n", numBlocks, blockType, total, persec);
}
#endif /* HAVE_CHACHA*/
#ifndef NO_MD5
void bench_md5(void)
{

View File

@ -216,6 +216,10 @@
RelativePath=".\include\rabbit.h"
>
</File>
<File
RelativePath=".\include\chacha.h"
>
</File>
<File
RelativePath=".\include\random.h"
>
@ -297,13 +301,17 @@
>
</File>
<File
RelativePath=".\src\wc_port.c"
RelativePath=".\src\port.c"
>
</File>
<File
RelativePath=".\src\rabbit.c"
>
</File>
<File
RelativePath=".\src\chacha.c"
>
</File>
<File
RelativePath=".\src\random.c"
>

250
ctaocrypt/src/chacha.c Normal file
View File

@ -0,0 +1,250 @@
/* chacha.c
*
* Copyright (C) 2006-2014 wolfSSL Inc.
*
* This file is part of CyaSSL.
*
* CyaSSL 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.
*
* CyaSSL 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
*
* based from
* chacha-ref.c version 20080118
* D. J. Bernstein
* Public domain.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <cyassl/ctaocrypt/settings.h>
#ifdef HAVE_CHACHA
#include <cyassl/ctaocrypt/chacha.h>
#include <cyassl/ctaocrypt/error-crypt.h>
#include <cyassl/ctaocrypt/logging.h>
#ifdef NO_INLINE
#include <cyassl/ctaocrypt/misc.h>
#else
#include <ctaocrypt/src/misc.c>
#endif
#ifdef CHACHA_AEAD_TEST
#include <stdio.h>
#endif
#ifdef BIG_ENDIAN_ORDER
#define LITTLE32(x) ByteReverseWord32(x)
#else
#define LITTLE32(x) (x)
#endif
/* Number of rounds */
#define ROUNDS 20
#define U32C(v) (v##U)
#define U32V(v) ((word32)(v) & U32C(0xFFFFFFFF))
#define U8TO32_LITTLE(p) LITTLE32(((word32*)(p))[0])
#define ROTATE(v,c) rotlFixed(v, c)
#define XOR(v,w) ((v) ^ (w))
#define PLUS(v,w) (U32V((v) + (w)))
#define PLUSONE(v) (PLUS((v),1))
#define QUARTERROUND(a,b,c,d) \
x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
/**
* Set up iv(nonce). Earlier versions used 64 bits instead of 96, this version
* uses the typical AEAD 96 bit nonce and can do record sizes of 256 GB.
*/
int Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter)
{
word32 temp[3]; /* used for alignment of memory */
XMEMSET(temp, 0, 12);
if (ctx == NULL)
return BAD_FUNC_ARG;
#ifdef CHACHA_AEAD_TEST
word32 i;
printf("NONCE : ");
for (i = 0; i < 12; i++) {
printf("%02x", inIv[i]);
}
printf("\n\n");
#endif
XMEMCPY(temp, inIv, 12);
ctx->X[12] = counter; /* block counter */
ctx->X[13] = temp[0]; /* fixed variable from nonce */
ctx->X[14] = temp[1]; /* counter from nonce */
ctx->X[15] = temp[2]; /* counter from nonce */
return 0;
}
/* "expand 32-byte k" as unsigned 32 byte */
static const word32 sigma[4] = {0x61707865, 0x3320646e, 0x79622d32, 0x6b206574};
/* "expand 16-byte k" as unsigned 16 byte */
static const word32 tau[4] = {0x61707865, 0x3120646e, 0x79622d36, 0x6b206574};
/**
* Key setup. 8 word iv (nonce)
*/
int Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz)
{
const word32* constants;
const byte* k;
if (ctx == NULL)
return BAD_FUNC_ARG;
#ifdef XSTREAM_ALIGN
word32 alignKey[keySz / 4];
if ((word)key % 4) {
CYASSL_MSG("ChachaSetKey unaligned key");
XMEMCPY(alignKey, key, sizeof(alignKey));
k = (byte*)alignKey;
}
else {
k = key;
}
#else
k = key;
#endif /* XSTREAM_ALIGN */
#ifdef CHACHA_AEAD_TEST
word32 i;
printf("ChaCha key used :\n");
for (i = 0; i < keySz; i++) {
printf("%02x", key[i]);
if ((i + 1) % 8 == 0)
printf("\n");
}
printf("\n\n");
#endif
ctx->X[4] = U8TO32_LITTLE(k + 0);
ctx->X[5] = U8TO32_LITTLE(k + 4);
ctx->X[6] = U8TO32_LITTLE(k + 8);
ctx->X[7] = U8TO32_LITTLE(k + 12);
if (keySz == 32) {
k += 16;
constants = sigma;
}
else {
/* key size of 128 */
if (keySz != 16)
return BAD_FUNC_ARG;
constants = tau;
}
ctx->X[ 8] = U8TO32_LITTLE(k + 0);
ctx->X[ 9] = U8TO32_LITTLE(k + 4);
ctx->X[10] = U8TO32_LITTLE(k + 8);
ctx->X[11] = U8TO32_LITTLE(k + 12);
ctx->X[ 0] = U8TO32_LITTLE(constants + 0);
ctx->X[ 1] = U8TO32_LITTLE(constants + 1);
ctx->X[ 2] = U8TO32_LITTLE(constants + 2);
ctx->X[ 3] = U8TO32_LITTLE(constants + 3);
return 0;
}
/**
* Converts word into bytes with rotations having been done.
*/
static INLINE void Chacha_wordtobyte(word32 output[16], const word32 input[16])
{
word32 x[16];
word32 i;
for (i = 0; i < 16; i++) {
x[i] = input[i];
}
for (i = (ROUNDS); i > 0; i -= 2) {
QUARTERROUND(0, 4, 8, 12)
QUARTERROUND(1, 5, 9, 13)
QUARTERROUND(2, 6, 10, 14)
QUARTERROUND(3, 7, 11, 15)
QUARTERROUND(0, 5, 10, 15)
QUARTERROUND(1, 6, 11, 12)
QUARTERROUND(2, 7, 8, 13)
QUARTERROUND(3, 4, 9, 14)
}
for (i = 0; i < 16; i++) {
x[i] = PLUS(x[i], input[i]);
}
for (i = 0; i < 16; i++) {
output[i] = LITTLE32(x[i]);
}
}
/**
* Encrypt a stream of bytes
*/
static void Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c,
word32 bytes)
{
byte* output;
word32 temp[16]; /* used to make sure aligned */
word32 i;
output = (byte*)temp;
if (!bytes) return;
for (;;) {
Chacha_wordtobyte(temp, ctx->X);
ctx->X[12] = PLUSONE(ctx->X[12]);
if (bytes <= 64) {
for (i = 0; i < bytes; ++i) {
c[i] = m[i] ^ output[i];
}
return;
}
for (i = 0; i < 64; ++i) {
c[i] = m[i] ^ output[i];
}
bytes -= 64;
c += 64;
m += 64;
}
}
/**
* API to encrypt/decrypt a message of any size.
*/
int Chacha_Process(ChaCha* ctx, byte* output, const byte* input, word32 msglen)
{
if (ctx == NULL)
return BAD_FUNC_ARG;
Chacha_encrypt_bytes(ctx, input, output, msglen);
return 0;
}
#endif /* HAVE_CHACHA*/

538
ctaocrypt/src/poly1305.c Normal file
View File

@ -0,0 +1,538 @@
/* poly1305.c
*
* Copyright (C) 2006-2014 wolfSSL Inc.
*
* This file is part of CyaSSL.
*
* CyaSSL 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.
*
* CyaSSL 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
*
* Based off the public domain implementations by Andrew Moon
* and Daniel J. Bernstein
*/
#ifdef HAVE_POLY1305
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <cyassl/ctaocrypt/settings.h>
#include <cyassl/ctaocrypt/poly1305.h>
#include <cyassl/ctaocrypt/error-crypt.h>
#include <cyassl/ctaocrypt/logging.h>
#ifdef NO_INLINE
#include <cyassl/ctaocrypt/misc.h>
#else
#include <ctaocrypt/src/misc.c>
#endif
#ifdef CHACHA_AEAD_TEST
#include <stdio.h>
#endif
#ifdef _MSC_VER
/* 4127 warning constant while(1) */
#pragma warning(disable: 4127)
#endif
#if defined(POLY130564)
#if defined(_MSC_VER)
#define POLY1305_NOINLINE __declspec(noinline)
#elif defined(__GNUC__)
#define POLY1305_NOINLINE __attribute__((noinline))
#else
#define POLY1305_NOINLINE
#endif
#if defined(_MSC_VER)
#include <intrin.h>
typedef struct word128 {
word64 lo;
word64 hi;
} word128;
#define MUL(out, x, y) out.lo = _umul128((x), (y), &out.hi)
#define ADD(out, in) { word64 t = out.lo; out.lo += in.lo;
out.hi += (out.lo < t) + in.hi; }
#define ADDLO(out, in) { word64 t = out.lo; out.lo += in;
out.hi += (out.lo < t); }
#define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift)))
#define LO(in) (in.lo)
#elif defined(__GNUC__)
#if defined(__SIZEOF_INT128__)
typedef unsigned __int128 word128;
#else
typedef unsigned word128 __attribute__((mode(TI)));
#endif
#define MUL(out, x, y) out = ((word128)x * y)
#define ADD(out, in) out += in
#define ADDLO(out, in) out += in
#define SHR(in, shift) (word64)(in >> (shift))
#define LO(in) (word64)(in)
#endif
static word64 U8TO64(const byte* p) {
return
(((word64)(p[0] & 0xff) ) |
((word64)(p[1] & 0xff) << 8) |
((word64)(p[2] & 0xff) << 16) |
((word64)(p[3] & 0xff) << 24) |
((word64)(p[4] & 0xff) << 32) |
((word64)(p[5] & 0xff) << 40) |
((word64)(p[6] & 0xff) << 48) |
((word64)(p[7] & 0xff) << 56));
}
static void U64TO8(byte* p, word64 v) {
p[0] = (v ) & 0xff;
p[1] = (v >> 8) & 0xff;
p[2] = (v >> 16) & 0xff;
p[3] = (v >> 24) & 0xff;
p[4] = (v >> 32) & 0xff;
p[5] = (v >> 40) & 0xff;
p[6] = (v >> 48) & 0xff;
p[7] = (v >> 56) & 0xff;
}
#else /* if not 64 bit then use 32 bit */
static word32 U8TO32(const byte *p) {
return
(((word32)(p[0] & 0xff) ) |
((word32)(p[1] & 0xff) << 8) |
((word32)(p[2] & 0xff) << 16) |
((word32)(p[3] & 0xff) << 24));
}
static void U32TO8(byte *p, word32 v) {
p[0] = (v ) & 0xff;
p[1] = (v >> 8) & 0xff;
p[2] = (v >> 16) & 0xff;
p[3] = (v >> 24) & 0xff;
}
#endif
static void poly1305_blocks(Poly1305* ctx, const unsigned char *m,
size_t bytes) {
#ifdef POLY130564
const word64 hibit = (ctx->final) ? 0 : ((word64)1 << 40); /* 1 << 128 */
word64 r0,r1,r2;
word64 s1,s2;
word64 h0,h1,h2;
word64 c;
word128 d0,d1,d2,d;
r0 = ctx->r[0];
r1 = ctx->r[1];
r2 = ctx->r[2];
h0 = ctx->h[0];
h1 = ctx->h[1];
h2 = ctx->h[2];
s1 = r1 * (5 << 2);
s2 = r2 * (5 << 2);
while (bytes >= POLY1305_BLOCK_SIZE) {
word64 t0,t1;
/* h += m[i] */
t0 = U8TO64(&m[0]);
t1 = U8TO64(&m[8]);
h0 += (( t0 ) & 0xfffffffffff);
h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
h2 += (((t1 >> 24) ) & 0x3ffffffffff) | hibit;
/* h *= r */
MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d);
MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d);
MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d);
/* (partial) h %= p */
c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff;
ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff;
ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff;
h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff;
h1 += c;
m += POLY1305_BLOCK_SIZE;
bytes -= POLY1305_BLOCK_SIZE;
}
ctx->h[0] = h0;
ctx->h[1] = h1;
ctx->h[2] = h2;
#else /* if not 64 bit then use 32 bit */
const word32 hibit = (ctx->final) ? 0 : (1 << 24); /* 1 << 128 */
word32 r0,r1,r2,r3,r4;
word32 s1,s2,s3,s4;
word32 h0,h1,h2,h3,h4;
word64 d0,d1,d2,d3,d4;
word32 c;
r0 = ctx->r[0];
r1 = ctx->r[1];
r2 = ctx->r[2];
r3 = ctx->r[3];
r4 = ctx->r[4];
s1 = r1 * 5;
s2 = r2 * 5;
s3 = r3 * 5;
s4 = r4 * 5;
h0 = ctx->h[0];
h1 = ctx->h[1];
h2 = ctx->h[2];
h3 = ctx->h[3];
h4 = ctx->h[4];
while (bytes >= POLY1305_BLOCK_SIZE) {
/* h += m[i] */
h0 += (U8TO32(m+ 0) ) & 0x3ffffff;
h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff;
h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff;
h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff;
h4 += (U8TO32(m+12) >> 8) | hibit;
/* h *= r */
d0 = ((word64)h0 * r0) + ((word64)h1 * s4) + ((word64)h2 * s3) +
((word64)h3 * s2) + ((word64)h4 * s1);
d1 = ((word64)h0 * r1) + ((word64)h1 * r0) + ((word64)h2 * s4) +
((word64)h3 * s3) + ((word64)h4 * s2);
d2 = ((word64)h0 * r2) + ((word64)h1 * r1) + ((word64)h2 * r0) +
((word64)h3 * s4) + ((word64)h4 * s3);
d3 = ((word64)h0 * r3) + ((word64)h1 * r2) + ((word64)h2 * r1) +
((word64)h3 * r0) + ((word64)h4 * s4);
d4 = ((word64)h0 * r4) + ((word64)h1 * r3) + ((word64)h2 * r2) +
((word64)h3 * r1) + ((word64)h4 * r0);
/* (partial) h %= p */
c = (word32)(d0 >> 26); h0 = (word32)d0 & 0x3ffffff;
d1 += c; c = (word32)(d1 >> 26); h1 = (word32)d1 & 0x3ffffff;
d2 += c; c = (word32)(d2 >> 26); h2 = (word32)d2 & 0x3ffffff;
d3 += c; c = (word32)(d3 >> 26); h3 = (word32)d3 & 0x3ffffff;
d4 += c; c = (word32)(d4 >> 26); h4 = (word32)d4 & 0x3ffffff;
h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff;
h1 += c;
m += POLY1305_BLOCK_SIZE;
bytes -= POLY1305_BLOCK_SIZE;
}
ctx->h[0] = h0;
ctx->h[1] = h1;
ctx->h[2] = h2;
ctx->h[3] = h3;
ctx->h[4] = h4;
#endif /* end of 64 bit cpu blocks or 32 bit cpu */
}
int Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) {
if (keySz != 32 || ctx == NULL)
return BAD_FUNC_ARG;
#ifdef CHACHA_AEAD_TEST
word32 k;
printf("Poly key used:\n");
for (k = 0; k < keySz; k++) {
printf("%02x", key[k]);
if ((k+1) % 8 == 0)
printf("\n");
}
printf("\n");
#endif
#if defined(POLY130564)
word64 t0,t1;
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
t0 = U8TO64(key + 0);
t1 = U8TO64(key + 8);
ctx->r[0] = ( t0 ) & 0xffc0fffffff;
ctx->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
ctx->r[2] = ((t1 >> 24) ) & 0x00ffffffc0f;
/* h (accumulator) = 0 */
ctx->h[0] = 0;
ctx->h[1] = 0;
ctx->h[2] = 0;
/* save pad for later */
ctx->pad[0] = U8TO64(key + 16);
ctx->pad[1] = U8TO64(key + 24);
#else /* if not 64 bit then use 32 bit */
/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
ctx->r[0] = (U8TO32(key + 0) ) & 0x3ffffff;
ctx->r[1] = (U8TO32(key + 3) >> 2) & 0x3ffff03;
ctx->r[2] = (U8TO32(key + 6) >> 4) & 0x3ffc0ff;
ctx->r[3] = (U8TO32(key + 9) >> 6) & 0x3f03fff;
ctx->r[4] = (U8TO32(key + 12) >> 8) & 0x00fffff;
/* h = 0 */
ctx->h[0] = 0;
ctx->h[1] = 0;
ctx->h[2] = 0;
ctx->h[3] = 0;
ctx->h[4] = 0;
/* save pad for later */
ctx->pad[0] = U8TO32(key + 16);
ctx->pad[1] = U8TO32(key + 20);
ctx->pad[2] = U8TO32(key + 24);
ctx->pad[3] = U8TO32(key + 28);
#endif
ctx->leftover = 0;
ctx->final = 0;
return 0;
}
int Poly1305Final(Poly1305* ctx, byte* mac) {
if (ctx == NULL)
return BAD_FUNC_ARG;
#if defined(POLY130564)
word64 h0,h1,h2,c;
word64 g0,g1,g2;
word64 t0,t1;
/* process the remaining block */
if (ctx->leftover) {
size_t i = ctx->leftover;
ctx->buffer[i] = 1;
for (i = i + 1; i < POLY1305_BLOCK_SIZE; i++)
ctx->buffer[i] = 0;
ctx->final = 1;
poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE);
}
/* fully carry h */
h0 = ctx->h[0];
h1 = ctx->h[1];
h2 = ctx->h[2];
c = (h1 >> 44); h1 &= 0xfffffffffff;
h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff;
h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
h1 += c;
/* compute h + -p */
g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff;
g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff;
g2 = h2 + c - ((word64)1 << 42);
/* select h if h < p, or h + -p if h >= p */
c = (g2 >> ((sizeof(word64) * 8) - 1)) - 1;
g0 &= c;
g1 &= c;
g2 &= c;
c = ~c;
h0 = (h0 & c) | g0;
h1 = (h1 & c) | g1;
h2 = (h2 & c) | g2;
/* h = (h + pad) */
t0 = ctx->pad[0];
t1 = ctx->pad[1];
h0 += (( t0 ) & 0xfffffffffff) ;
c = (h0 >> 44); h0 &= 0xfffffffffff;
h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c;
c = (h1 >> 44); h1 &= 0xfffffffffff;
h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c;
h2 &= 0x3ffffffffff;
/* mac = h % (2^128) */
h0 = ((h0 ) | (h1 << 44));
h1 = ((h1 >> 20) | (h2 << 24));
U64TO8(mac + 0, h0);
U64TO8(mac + 8, h1);
/* zero out the state */
ctx->h[0] = 0;
ctx->h[1] = 0;
ctx->h[2] = 0;
ctx->r[0] = 0;
ctx->r[1] = 0;
ctx->r[2] = 0;
ctx->pad[0] = 0;
ctx->pad[1] = 0;
#else /* if not 64 bit then use 32 bit */
word32 h0,h1,h2,h3,h4,c;
word32 g0,g1,g2,g3,g4;
word64 f;
word32 mask;
/* process the remaining block */
if (ctx->leftover) {
size_t i = ctx->leftover;
ctx->buffer[i++] = 1;
for (; i < POLY1305_BLOCK_SIZE; i++)
ctx->buffer[i] = 0;
ctx->final = 1;
poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE);
}
/* fully carry h */
h0 = ctx->h[0];
h1 = ctx->h[1];
h2 = ctx->h[2];
h3 = ctx->h[3];
h4 = ctx->h[4];
c = h1 >> 26; h1 = h1 & 0x3ffffff;
h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
h1 += c;
/* compute h + -p */
g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
g4 = h4 + c - (1 << 26);
/* select h if h < p, or h + -p if h >= p */
mask = (g4 >> ((sizeof(word32) * 8) - 1)) - 1;
g0 &= mask;
g1 &= mask;
g2 &= mask;
g3 &= mask;
g4 &= mask;
mask = ~mask;
h0 = (h0 & mask) | g0;
h1 = (h1 & mask) | g1;
h2 = (h2 & mask) | g2;
h3 = (h3 & mask) | g3;
h4 = (h4 & mask) | g4;
/* h = h % (2^128) */
h0 = ((h0 ) | (h1 << 26)) & 0xffffffff;
h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
/* mac = (h + pad) % (2^128) */
f = (word64)h0 + ctx->pad[0] ; h0 = (word32)f;
f = (word64)h1 + ctx->pad[1] + (f >> 32); h1 = (word32)f;
f = (word64)h2 + ctx->pad[2] + (f >> 32); h2 = (word32)f;
f = (word64)h3 + ctx->pad[3] + (f >> 32); h3 = (word32)f;
U32TO8(mac + 0, h0);
U32TO8(mac + 4, h1);
U32TO8(mac + 8, h2);
U32TO8(mac + 12, h3);
/* zero out the state */
ctx->h[0] = 0;
ctx->h[1] = 0;
ctx->h[2] = 0;
ctx->h[3] = 0;
ctx->h[4] = 0;
ctx->r[0] = 0;
ctx->r[1] = 0;
ctx->r[2] = 0;
ctx->r[3] = 0;
ctx->r[4] = 0;
ctx->pad[0] = 0;
ctx->pad[1] = 0;
ctx->pad[2] = 0;
ctx->pad[3] = 0;
#endif
return 0;
}
int Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) {
if (ctx == NULL)
return BAD_FUNC_ARG;
#ifdef CHACHA_AEAD_TEST
word32 k;
printf("Raw input to poly:\n");
for (k = 0; k < bytes; k++) {
printf("%02x", m[k]);
if ((k+1) % 16 == 0)
printf("\n");
}
printf("\n");
#endif
size_t i;
/* handle leftover */
if (ctx->leftover) {
size_t want = (POLY1305_BLOCK_SIZE - ctx->leftover);
if (want > bytes)
want = bytes;
for (i = 0; i < want; i++)
ctx->buffer[ctx->leftover + i] = m[i];
bytes -= want;
m += want;
ctx->leftover += want;
if (ctx->leftover < POLY1305_BLOCK_SIZE)
return 0;
poly1305_blocks(ctx, ctx->buffer, POLY1305_BLOCK_SIZE);
ctx->leftover = 0;
}
/* process full blocks */
if (bytes >= POLY1305_BLOCK_SIZE) {
size_t want = (bytes & ~(POLY1305_BLOCK_SIZE - 1));
poly1305_blocks(ctx, m, want);
m += want;
bytes -= want;
}
/* store leftover */
if (bytes) {
for (i = 0; i < bytes; i++)
ctx->buffer[ctx->leftover + i] = m[i];
ctx->leftover += bytes;
}
return 0;
}
#endif /* HAVE_POLY1305 */

View File

@ -48,12 +48,14 @@
#include <cyassl/ctaocrypt/rsa.h>
#include <cyassl/ctaocrypt/des3.h>
#include <cyassl/ctaocrypt/aes.h>
#include <cyassl/ctaocrypt/poly1305.h>
#include <cyassl/ctaocrypt/camellia.h>
#include <cyassl/ctaocrypt/hmac.h>
#include <cyassl/ctaocrypt/dh.h>
#include <cyassl/ctaocrypt/dsa.h>
#include <cyassl/ctaocrypt/hc128.h>
#include <cyassl/ctaocrypt/rabbit.h>
#include <cyassl/ctaocrypt/chacha.h>
#include <cyassl/ctaocrypt/pwdbased.h>
#include <cyassl/ctaocrypt/ripemd.h>
#ifdef HAVE_ECC
@ -152,9 +154,11 @@ int hkdf_test(void);
int arc4_test(void);
int hc128_test(void);
int rabbit_test(void);
int chacha_test(void);
int des_test(void);
int des3_test(void);
int aes_test(void);
int poly1305_test(void);
int aesgcm_test(void);
int gmac_test(void);
int aesccm_test(void);
@ -367,6 +371,13 @@ void ctaocrypt_test(void* args)
printf( "Rabbit test passed!\n");
#endif
#ifdef HAVE_CHACHA
if ( (ret = chacha_test()) != 0)
err_sys("Chacha test failed!\n", ret);
else
printf( "Chacha test passed!\n");
#endif
#ifndef NO_DES3
if ( (ret = des_test()) != 0)
err_sys("DES test failed!\n", ret);
@ -387,6 +398,13 @@ void ctaocrypt_test(void* args)
else
printf( "AES test passed!\n");
#ifdef HAVE_POLY1305
if ( (ret = poly1305_test()) != 0)
err_sys("POLY1305 test failed!\n", ret);
else
printf( "POLY1305 test passed!\n");
#endif
#ifdef HAVE_AESGCM
if ( (ret = aesgcm_test()) != 0)
err_sys("AES-GCM test failed!\n", ret);
@ -1816,6 +1834,107 @@ int rabbit_test(void)
#endif /* NO_RABBIT */
#ifdef HAVE_CHACHA
int chacha_test(void)
{
byte cipher[32];
byte plain[32];
byte input[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
word32 keySz;
int i;
int times = 4;
const byte key1[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
const byte key2[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01
};
const byte key3[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
/* 128 bit key */
const byte key4[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
const byte* keys[] = {key1, key2, key3, key4};
const byte ivs1[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const byte ivs2[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const byte ivs3[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
const byte ivs4[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const byte* ivs[] = {ivs1, ivs2, ivs3, ivs4};
byte a[] = {0x76,0xb8,0xe0,0xad,0xa0,0xf1,0x3d,0x90};
byte b[] = {0x45,0x40,0xf0,0x5a,0x9f,0x1f,0xb2,0x96};
byte c[] = {0xde,0x9c,0xba,0x7b,0xf3,0xd6,0x9e,0xf5};
byte d[] = {0x89,0x67,0x09,0x52,0x60,0x83,0x64,0xfd};
byte* test_chacha[4];
test_chacha[0] = a;
test_chacha[1] = b;
test_chacha[2] = c;
test_chacha[3] = d;
for (i = 0; i < times; ++i) {
if (i < 3) {
keySz = 32;
}
else {
keySz = 16;
}
ChaCha enc;
ChaCha dec;
XMEMCPY(plain, keys[i], keySz);
XMEMSET(cipher, 0, 32);
XMEMCPY(cipher + 4, ivs[i], 8);
Chacha_SetKey(&enc, keys[i], keySz);
Chacha_SetKey(&dec, keys[i], keySz);
Chacha_SetIV(&enc, cipher,0);
Chacha_SetIV(&dec, cipher,0);
XMEMCPY(plain, input, 8);
Chacha_Process(&enc, cipher, plain, (word32)8);
Chacha_Process(&dec, plain, cipher, (word32)8);
if (memcmp(test_chacha[i], cipher, 8))
return -130 - 5 - i;
if (memcmp(plain, input, 8))
return -130 - i;
}
return 0;
}
#endif /* HAVE_CHACHA */
#ifndef NO_DES3
int des_test(void)
{
@ -2126,6 +2245,96 @@ int aes_test(void)
return 0;
}
#ifdef HAVE_POLY1305
int poly1305_test(void)
{
int ret = 0;
int i;
byte tag[16];
Poly1305 enc;
const byte msg[] =
{
0x43,0x72,0x79,0x70,0x74,0x6f,0x67,0x72,
0x61,0x70,0x68,0x69,0x63,0x20,0x46,0x6f,
0x72,0x75,0x6d,0x20,0x52,0x65,0x73,0x65,
0x61,0x72,0x63,0x68,0x20,0x47,0x72,0x6f,
0x75,0x70
};
const byte msg2[] =
{
0x48,0x65,0x6c,0x6c,0x6f,0x20,0x77,0x6f,0x72,
0x6c,0x64,0x21
};
const byte msg3[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
const byte correct[] =
{
0xa8,0x06,0x1d,0xc1,0x30,0x51,0x36,0xc6,
0xc2,0x2b,0x8b,0xaf,0x0c,0x01,0x27,0xa9
};
const byte correct2[] =
{
0xa6,0xf7,0x45,0x00,0x8f,0x81,0xc9,0x16,
0xa2,0x0d,0xcc,0x74,0xee,0xf2,0xb2,0xf0
};
const byte correct3[] =
{
0x49,0xec,0x78,0x09,0x0e,0x48,0x1e,0xc6,
0xc2,0x6b,0x33,0xb9,0x1c,0xcc,0x03,0x07
};
const byte key[] = {
0x85,0xd6,0xbe,0x78,0x57,0x55,0x6d,0x33,
0x7f,0x44,0x52,0xfe,0x42,0xd5,0x06,0xa8,
0x01,0x03,0x80,0x8a,0xfb,0x0d,0xb2,0xfd,
0x4a,0xbf,0xf6,0xaf,0x41,0x49,0xf5,0x1b
};
const byte key2[] = {
0x74,0x68,0x69,0x73,0x20,0x69,0x73,0x20,
0x33,0x32,0x2d,0x62,0x79,0x74,0x65,0x20,
0x6b,0x65,0x79,0x20,0x66,0x6f,0x72,0x20,
0x50,0x6f,0x6c,0x79,0x31,0x33,0x30,0x35
};
const byte* msgs[] = {msg, msg2, msg3};
word32 szm[] = {sizeof(msg),sizeof(msg2),sizeof(msg3)};
const byte* keys[] = {key, key2, key2};
const byte* tests[] = {correct, correct2, correct3};
for (i = 0; i < 3; i++) {
ret = Poly1305SetKey(&enc, keys[i], 32);
if (ret != 0)
return -1001;
ret = Poly1305Update(&enc, msgs[i], szm[i]);
if (ret != 0)
return -1005;
ret = Poly1305Final(&enc, tag);
if (ret != 0)
return -60;
if (memcmp(tag, tests[i], sizeof(tag)))
return -61;
}
return 0;
}
#endif /* HAVE_POLY1305 */
#ifdef HAVE_AESGCM
int aesgcm_test(void)
{

55
cyassl/ctaocrypt/chacha.h Normal file
View File

@ -0,0 +1,55 @@
/* chacha.h
*
* Copyright (C) 2006-2014 wolfSSL Inc.
*
* This file is part of CyaSSL.
*
* CyaSSL 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.
*
* CyaSSL 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
*/
#ifndef CHACHA_H
#define CHACHA_H
#include "types.h"
#ifdef __cplusplus
extern "C" {
#endif
enum {
CHACHA_ENC_TYPE = 7 /* cipher unique type */
};
typedef struct ChaCha {
word32 X[16]; /* state of cipher */
} ChaCha;
CYASSL_API int Chacha_Process(ChaCha* ctx, byte* cipher, const byte* plain,
word32 msglen);
CYASSL_API int Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz);
/**
* IV(nonce) changes with each record
* counter is for what value the block counter should start ... usually 0
*/
CYASSL_API int Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@ -6,6 +6,7 @@ nobase_include_HEADERS+= \
cyassl/ctaocrypt/arc4.h \
cyassl/ctaocrypt/asn.h \
cyassl/ctaocrypt/asn_public.h \
cyassl/ctaocrypt/poly1305.h \
cyassl/ctaocrypt/camellia.h \
cyassl/ctaocrypt/coding.h \
cyassl/ctaocrypt/compress.h \
@ -26,6 +27,7 @@ nobase_include_HEADERS+= \
cyassl/ctaocrypt/wc_port.h \
cyassl/ctaocrypt/pwdbased.h \
cyassl/ctaocrypt/rabbit.h \
cyassl/ctaocrypt/chacha.h \
cyassl/ctaocrypt/random.h \
cyassl/ctaocrypt/ripemd.h \
cyassl/ctaocrypt/rsa.h \

View File

@ -0,0 +1,82 @@
/* poly1305.h
*
* Copyright (C) 2006-2014 wolfSSL Inc.
*
* This file is part of CyaSSL.
*
* CyaSSL 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.
*
* CyaSSL 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_POLY1305
#ifndef CTAO_CRYPT_POLY1305_H
#define CTAO_CRYPT_POLY1305_H
#include <cyassl/ctaocrypt/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/* auto detect between 32bit / 64bit */
#define HAS_SIZEOF_INT128_64BIT (defined(__SIZEOF_INT128__) && defined(__LP64__))
#define HAS_MSVC_64BIT (defined(_MSC_VER) && defined(_M_X64))
#define HAS_GCC_4_4_64BIT (defined(__GNUC__) && defined(__LP64__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4))))
#if (HAS_SIZEOF_INT128_64BIT || HAS_MSVC_64BIT || HAS_GCC_4_4_64BIT)
#define POLY130564
#else
#define POLY130532
#endif
enum {
POLY1305 = 7,
POLY1305_BLOCK_SIZE = 16,
POLY1305_DIGEST_SIZE = 16,
POLY1305_PAD_SIZE = 56
};
/* Poly1305 state */
typedef struct Poly1305 {
#if defined(POLY130564)
word64 r[3];
word64 h[3];
word64 pad[2];
#else
word32 r[5];
word32 h[5];
word32 pad[4];
#endif
size_t leftover;
unsigned char buffer[POLY1305_BLOCK_SIZE];
unsigned char final;
} Poly1305;
/* does init */
CYASSL_API int Poly1305SetKey(Poly1305* poly1305, const byte* key, word32 kySz);
CYASSL_API int Poly1305Update(Poly1305* poly1305, const byte*, word32);
CYASSL_API int Poly1305Final(Poly1305* poly1305, byte* tag);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* CTAO_CRYPT_POLY1305_H */
#endif /* HAVE_POLY1305 */

View File

@ -31,10 +31,12 @@
#include <cyassl/ctaocrypt/des3.h>
#include <cyassl/ctaocrypt/hc128.h>
#include <cyassl/ctaocrypt/rabbit.h>
#include <cyassl/ctaocrypt/chacha.h>
#include <cyassl/ctaocrypt/asn.h>
#include <cyassl/ctaocrypt/md5.h>
#include <cyassl/ctaocrypt/sha.h>
#include <cyassl/ctaocrypt/aes.h>
#include <cyassl/ctaocrypt/poly1305.h>
#include <cyassl/ctaocrypt/camellia.h>
#include <cyassl/ctaocrypt/logging.h>
#include <cyassl/ctaocrypt/hmac.h>
@ -464,9 +466,25 @@ void c32to24(word32 in, word24 out);
#define BUILD_ARC4
#endif
#ifdef HAVE_CHACHA
#define CHACHA20_BLOCK_SIZE 16
/* ChaCha - Poly AEAD suites */
#if defined(HAVE_POLY1305) && !defined(NO_SHA256)
#if defined(HAVE_ECC)
#if !defined(NO_RSA)
#define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
#endif
#if !defined(NO_DSA)
#define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
#endif
#endif
#if !defined(NO_DH) && !defined(NO_RSA)
#define BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
#endif
#endif /* end of ChaCha - Poly AEAD suites */
#endif
#if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
#if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) || defined(HAVE_CHACHA)
#define HAVE_AEAD
#endif
@ -591,13 +609,18 @@ enum {
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xbe,
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0xc4,
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0x13,
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0x14,
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0x15,
/* Renegotiation Indication Extension Special Suite */
TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0xff
};
enum Misc {
ECC_BYTE = 0xC0, /* ECC first cipher suite byte */
ECC_BYTE = 0xC0, /* ECC first cipher suite byte */
CHACHA_BYTE = 0xCC, /* ChaCha first cipher suite */
SEND_CERT = 1,
SEND_BLANK_CERT = 2,
@ -720,6 +743,12 @@ enum Misc {
CAMELLIA_256_KEY_SIZE = 32, /* for 256 bit */
CAMELLIA_IV_SIZE = 16, /* always block size */
CHACHA20_256_KEY_SIZE = 32, /* for 256 bit */
CHACHA20_128_KEY_SIZE = 16, /* for 128 bit */
CHACHA20_IV_SIZE = 8, /* 64 bits for iv */
POLY1305_AUTH_SZ = 16, /* 128 bits */
HC_128_KEY_SIZE = 16, /* 128 bits */
HC_128_IV_SIZE = 16, /* also 128 bits */
@ -1494,6 +1523,12 @@ typedef struct Ciphers {
#ifdef HAVE_CAMELLIA
Camellia* cam;
#endif
#ifdef HAVE_CHACHA
ChaCha* chacha;
#endif
#ifdef HAVE_POLY1305
Poly1305* poly1305;
#endif
#ifdef HAVE_HC128
HC128* hc128;
#endif
@ -1680,6 +1715,10 @@ typedef struct Options {
byte usingNonblock; /* set when using nonblocking socket */
byte saveArrays; /* save array Memory for user get keys
or psk */
#ifdef HAVE_POLY1305
byte oldPoly; /* set when to use old rfc way of poly*/
#endif
#ifndef NO_PSK
byte havePSK; /* psk key set by user */
psk_client_callback client_psk_cb;

View File

@ -217,6 +217,10 @@ CYASSL_API int CyaSSL_use_RSAPrivateKey_file(CYASSL*, const char*, int);
const char*, int);
#endif
#ifdef HAVE_POLY1305
CYASSL_API int CyaSSL_use_old_poly(CYASSL*, int);
#endif
#ifdef HAVE_NTRU
CYASSL_API int CyaSSL_CTX_use_NTRUPrivateKey_file(CYASSL_CTX*, const char*);
/* load NTRU private key blob */
@ -1064,6 +1068,7 @@ enum BulkCipherAlgorithm {
cyassl_aes,
cyassl_aes_gcm,
cyassl_aes_ccm,
cyassl_chacha,
cyassl_camellia,
cyassl_hc128, /* CyaSSL extensions */
cyassl_rabbit

View File

@ -622,6 +622,15 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
else {
tcp_connect(&sockfd, host, port, 0);
}
#ifdef HAVE_POLY1305
/* use old poly to connect with google server */
if (!XMEMCMP(domain, "www.google.com", 15)) {
if (CyaSSL_use_old_poly(ssl, 1) != 0)
err_sys("unable to set to old poly");
}
#endif
CyaSSL_set_fd(ssl, sockfd);
#ifdef HAVE_CRL
if (CyaSSL_EnableCRL(ssl, CYASSL_CRL_CHECKALL) != SSL_SUCCESS)

View File

@ -55,6 +55,10 @@ if BUILD_AES
src_libcyassl_la_SOURCES += ctaocrypt/src/aes.c
endif
if BUILD_POLY1305
src_libcyassl_la_SOURCES += ctaocrypt/src/poly1305.c
endif
if BUILD_DES3
src_libcyassl_la_SOURCES += ctaocrypt/src/des3.c
endif
@ -119,6 +123,10 @@ if BUILD_RABBIT
src_libcyassl_la_SOURCES += ctaocrypt/src/rabbit.c
endif
if BUILD_CHACHA
src_libcyassl_la_SOURCES += ctaocrypt/src/chacha.c
endif
if !BUILD_INLINE
src_libcyassl_la_SOURCES += ctaocrypt/src/misc.c
endif

View File

@ -38,7 +38,7 @@
#include "ntru_crypto.h"
#endif
#if defined(DEBUG_CYASSL) || defined(SHOW_SECRETS)
#if defined(DEBUG_CYASSL) || defined(SHOW_SECRETS) || defined(CHACHA_AEAD_TEST)
#ifdef FREESCALE_MQX
#include <fio.h>
#else
@ -203,7 +203,8 @@ static INLINE void c16toa(word16 u16, byte* c)
}
#if !defined(NO_OLD_TLS) || defined(HAVE_AESCCM) || defined(HAVE_AESGCM)
#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \
|| defined(HAVE_AESGCM)
/* convert 32 bit integer to opaque */
static INLINE void c32toa(word32 u32, byte* c)
{
@ -527,6 +528,14 @@ void InitCiphers(CYASSL* ssl)
#ifdef BUILD_RABBIT
ssl->encrypt.rabbit = NULL;
ssl->decrypt.rabbit = NULL;
#endif
#ifdef HAVE_CHACHA
ssl->encrypt.chacha = NULL;
ssl->decrypt.chacha = NULL;
#endif
#ifdef HAVE_POLY1305
ssl->encrypt.poly1305 = NULL;
ssl->decrypt.poly1305 = NULL;
#endif
ssl->encrypt.setup = 0;
ssl->decrypt.setup = 0;
@ -579,6 +588,14 @@ void FreeCiphers(CYASSL* ssl)
XFREE(ssl->encrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef HAVE_CHACHA
XFREE(ssl->encrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
#ifdef HAVE_POLY1305
XFREE(ssl->encrypt.poly1305, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.poly1305, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif
}
@ -891,6 +908,27 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveRSA, byte havePSK,
}
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
if (tls && haveRSA) {
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
if (tls1_2 && haveECDSAsig) {
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
}
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
if (tls && haveRSA) {
suites->suites[idx++] = CHACHA_BYTE;
suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
}
#endif
#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
if (tls && haveRSAsig && haveStaticECC) {
suites->suites[idx++] = ECC_BYTE;
@ -3145,6 +3183,30 @@ static int BuildFinished(CYASSL* ssl, Hashes* hashes, const byte* sender)
the key exchange so ECHDE_RSA requires an rsa key thus rsa_kea */
static int CipherRequires(byte first, byte second, int requirement)
{
if (first == CHACHA_BYTE) {
switch (second) {
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
break;
case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
if (requirement == REQUIRES_ECC_DSA)
return 1;
break;
case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
if (requirement == REQUIRES_RSA)
return 1;
if (requirement == REQUIRES_DHE)
return 1;
break;
}
}
/* ECC extensions */
if (first == ECC_BYTE) {
@ -4671,7 +4733,8 @@ static int DoDtlsHandShakeMsg(CYASSL* ssl, byte* input, word32* inOutIdx,
#endif
#if !defined(NO_OLD_TLS) || defined(HAVE_AESCCM) || defined(HAVE_AESGCM)
#if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \
|| defined(HAVE_AESGCM)
static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify)
{
if (verify)
@ -4690,6 +4753,334 @@ static INLINE void AeadIncrementExpIV(CYASSL* ssl)
if (++ssl->keys.aead_exp_IV[i]) return;
}
}
#ifdef HAVE_POLY1305
/*more recent rfc's concatonate input for poly1305 differently*/
static int Poly1305Tag(CYASSL* 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;
byte padding[16];
if (msglen < 0)
return INPUT_CASE_ERROR;
XMEMSET(padding, 0, sizeof(padding));
if ((ret = Poly1305SetKey(ssl->encrypt.poly1305, cipher, keySz)) != 0)
return ret;
/* additional input to poly1305 */
if ((ret = Poly1305Update(ssl->encrypt.poly1305, additional,
CHACHA20_BLOCK_SIZE)) != 0)
return ret;
/* cipher input */
if ((ret = Poly1305Update(ssl->encrypt.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 = Poly1305Update(ssl->encrypt.poly1305, padding, paddingSz))
!= 0)
return ret;
}
/* add size of AD and size of cipher to poly input */
XMEMSET(padding, 0, sizeof(padding));
padding[0] = CHACHA20_BLOCK_SIZE;
/* 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 = Poly1305Update(ssl->encrypt.poly1305, padding, sizeof(padding)))
!= 0)
return ret;
/* generate tag */
if ((ret = Poly1305Final(ssl->encrypt.poly1305, tag)) != 0)
return ret;
return ret;
}
/* Used for the older version of creating AEAD tags with Poly1305 */
static int Poly1305TagOld(CYASSL* ssl, byte* additional, const byte* out,
byte* cipher, word16 sz, byte* tag)
{
int ret = 0;
int msglen = (sz - ssl->specs.aead_mac_size);
word32 keySz = 32;
byte padding[8]; /* used to temporarly store lengths */
#ifdef CHACHA_AEAD_TEST
printf("Using old version of poly1305 input.\n");
#endif
if (msglen < 0)
return INPUT_CASE_ERROR;
if ((ret = Poly1305SetKey(ssl->encrypt.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 = Poly1305Update(ssl->encrypt.poly1305, additional,
AEAD_AUTH_DATA_SZ)) != 0)
return ret;
/* length of additional input plus padding */
XMEMSET(padding, 0, sizeof(padding));
padding[0] = AEAD_AUTH_DATA_SZ;
if ((ret = Poly1305Update(ssl->encrypt.poly1305, padding,
sizeof(padding))) != 0)
return ret;
/* add cipher info and then its length */
XMEMSET(padding, 0, sizeof(padding));
if ((ret = Poly1305Update(ssl->encrypt.poly1305, out, msglen)) != 0)
return ret;
/* 32 bit size of cipher to 64 bit endian */
padding[0] = msglen & 0xff;
padding[1] = (msglen >> 8) & 0xff;
padding[2] = (msglen >> 16) & 0xff;
padding[3] = (msglen >> 24) & 0xff;
if ((ret = Poly1305Update(ssl->encrypt.poly1305, padding, sizeof(padding)))
!= 0)
return ret;
/* generate tag */
if ((ret = Poly1305Final(ssl->encrypt.poly1305, tag)) != 0)
return ret;
return ret;
}
#endif /*HAVE_POLY1305*/
#ifdef HAVE_CHACHA
static int ChachaAEADEncrypt(CYASSL* ssl, byte* out, const byte* input,
word16 sz)
{
int offset = 5; /*where to find type,version in record header */
const byte* additionalSrc = input - offset;
int ret = 0;
byte tag[ssl->specs.aead_mac_size];
byte additional[CHACHA20_BLOCK_SIZE];
byte nonce[AEAD_NONCE_SZ];
byte cipher[32]; /* generated key for poly1305 */
XMEMSET(tag, 0, sizeof(tag));
XMEMSET(nonce, 0, AEAD_NONCE_SZ);
XMEMSET(cipher, 0, sizeof(cipher));
XMEMSET(additional, 0, CHACHA20_BLOCK_SIZE);
/* 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);
/* Store the type, version. Unfortunately, they are in
* the input buffer ahead of the plaintext. */
#ifdef CYASSL_DTLS
if (ssl->options.dtls) {
c16toa(ssl->keys.dtls_epoch, additional);
additionalSrc -= DTLS_HANDSHAKE_EXTRA;
}
#endif
XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3);
#ifdef CHACHA_AEAD_TEST
int i;
printf("Encrypt Additional : ");
for (i = 0; i < CHACHA20_BLOCK_SIZE; i++) {
printf("%02x", additional[i]);
}
printf("\n\n");
printf("input before encryption :\n");
for (i = 0; i < sz; i++) {
printf("%02x", input[i]);
if ((i + 1) % 16 == 0)
printf("\n");
}
printf("\n");
#endif
/* set the nonce for chacha and get poly1305 key */
if ((ret = Chacha_SetIV(ssl->encrypt.chacha, nonce, 0)) != 0)
return ret;
if ((ret = Chacha_Process(ssl->encrypt.chacha, cipher,
cipher, 32)) != 0)
return ret;
/* encrypt the plain text */
if ((ret = Chacha_Process(ssl->encrypt.chacha, out, input,
sz - ssl->specs.aead_mac_size)) != 0)
return ret;
#ifdef HAVE_POLY1305
/* 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)
return ret;
}
else {
if ((ret = Poly1305Tag(ssl, additional, (const byte* )out,
cipher, sz, tag)) != 0)
return ret;
}
#endif
/* append tag to ciphertext */
XMEMCPY(out + sz - ssl->specs.aead_mac_size, tag, sizeof(tag));
AeadIncrementExpIV(ssl);
XMEMSET(nonce, 0, AEAD_NONCE_SZ);
#ifdef CHACHA_AEAD_TEST
printf("mac tag :\n");
for (i = 0; i < 16; i++) {
printf("%02x", tag[i]);
if ((i + 1) % 16 == 0)
printf("\n");
}
printf("\n\noutput after encrypt :\n");
for (i = 0; i < sz; i++) {
printf("%02x", out[i]);
if ((i + 1) % 16 == 0)
printf("\n");
}
printf("\n");
#endif
return ret;
}
static int ChachaAEADDecrypt(CYASSL* ssl, byte* plain, const byte* input,
word16 sz)
{
byte additional[CHACHA20_BLOCK_SIZE];
byte nonce[AEAD_NONCE_SZ];
byte tag[ssl->specs.aead_mac_size];
byte cipher[32]; /* generated key for mac */
int i;
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);
#ifdef CHACHA_AEAD_TEST
printf("input before decrypt :\n");
for (i = 0; i < sz; i++) {
printf("%02x", input[i]);
if ((i + 1) % 16 == 0)
printf("\n");
}
printf("\n");
#endif
/* 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);
/* get AD info */
additional[AEAD_TYPE_OFFSET] = ssl->curRL.type;
additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor;
additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor;
/* Store the type, version. */
#ifdef CYASSL_DTLS
if (ssl->options.dtls)
c16toa(ssl->keys.dtls_state.curEpoch, additional);
#endif
#ifdef CHACHA_AEAD_TEST
printf("Decrypt Additional : ");
for (i = 0; i < CHACHA20_BLOCK_SIZE; i++) {
printf("%02x", additional[i]);
}
printf("\n\n");
#endif
/* set nonce and get poly1305 key */
if ((ret = Chacha_SetIV(ssl->decrypt.chacha, nonce, 0)) != 0)
return ret;
if ((ret = Chacha_Process(ssl->decrypt.chacha, cipher,
cipher, sizeof(cipher))) != 0)
return ret;
#ifdef HAVE_POLY1305
/* 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)
return ret;
}
else {
if ((ret = Poly1305Tag(ssl, additional, input, cipher,
sz, tag)) != 0)
return ret;
}
#endif
/* check mac sent along with packet */
ret = 0;
for (i = 0; i < ssl->specs.aead_mac_size; i++) {
if ((input + sz - ssl->specs.aead_mac_size)[i] != tag[i])
ret = 1;
}
if (ret == 1) {
CYASSL_MSG("Mac did not match");
SendAlert(ssl, alert_fatal, bad_record_mac);
XMEMSET(nonce, 0, AEAD_NONCE_SZ);
return VERIFY_MAC_ERROR;
}
/* if mac was good decrypt message */
if ((ret = Chacha_Process(ssl->decrypt.chacha, plain, input,
sz - ssl->specs.aead_mac_size)) != 0)
return ret;
#ifdef CHACHA_AEAD_TEST
printf("plain after decrypt :\n");
for (i = 0; i < sz; i++) {
printf("%02x", plain[i]);
if ((i + 1) % 16 == 0)
printf("\n");
}
printf("\n");
#endif
return ret;
}
#endif /* HAVE_CHACHA */
#endif
@ -4825,6 +5216,11 @@ static INLINE int Encrypt(CYASSL* ssl, byte* out, const byte* input, word16 sz)
return RabbitProcess(ssl->encrypt.rabbit, out, input, sz);
#endif
#ifdef HAVE_CHACHA
case cyassl_chacha:
return ChachaAEADEncrypt(ssl, out, input, sz);
#endif
#ifdef HAVE_NULL_CIPHER
case cyassl_cipher_null:
if (input != out) {
@ -4970,6 +5366,11 @@ static INLINE int Decrypt(CYASSL* ssl, byte* plain, const byte* input,
return RabbitProcess(ssl->decrypt.rabbit, plain, input, sz);
#endif
#ifdef HAVE_CHACHA
case cyassl_chacha:
return ChachaAEADDecrypt(ssl, plain, input, sz);
#endif
#ifdef HAVE_NULL_CIPHER
case cyassl_cipher_null:
if (input != plain) {
@ -5011,8 +5412,9 @@ static int SanityCheckCipherText(CYASSL* ssl, word32 encryptSz)
minLength += ssl->specs.block_size; /* explicit IV */
}
else if (ssl->specs.cipher_type == aead) {
minLength = ssl->specs.aead_mac_size + AEAD_EXP_IV_SZ;
/* explicit IV + authTag size */
minLength = ssl->specs.aead_mac_size; /* authTag size */
if (ssl->specs.bulk_cipher_algorithm != cyassl_chacha)
minLength += AEAD_EXP_IV_SZ; /* explicit IV */
}
if (encryptSz < minLength) {
@ -5320,7 +5722,8 @@ int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx)
ivExtra = ssl->specs.block_size;
}
else if (ssl->specs.cipher_type == aead) {
ivExtra = AEAD_EXP_IV_SZ;
if (ssl->specs.bulk_cipher_algorithm != cyassl_chacha)
ivExtra = AEAD_EXP_IV_SZ;
}
dataSz = msgSz - ivExtra - ssl->keys.padSz;
@ -5711,7 +6114,8 @@ int ProcessReply(CYASSL* ssl)
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
ssl->buffers.inputBuffer.idx += ssl->specs.block_size;
/* go past TLSv1.1 IV */
if (ssl->specs.cipher_type == aead)
if (ssl->specs.cipher_type == aead &&
ssl->specs.bulk_cipher_algorithm != cyassl_chacha)
ssl->buffers.inputBuffer.idx += AEAD_EXP_IV_SZ;
#endif /* ATOMIC_USER */
}
@ -5728,7 +6132,8 @@ int ProcessReply(CYASSL* ssl)
if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
ssl->buffers.inputBuffer.idx += ssl->specs.block_size;
/* go past TLSv1.1 IV */
if (ssl->specs.cipher_type == aead)
if (ssl->specs.cipher_type == aead &&
ssl->specs.bulk_cipher_algorithm != cyassl_chacha)
ssl->buffers.inputBuffer.idx += AEAD_EXP_IV_SZ;
ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer +
@ -6160,7 +6565,9 @@ static int BuildMessage(CYASSL* ssl, byte* output, int outSz,
#ifdef HAVE_AEAD
if (ssl->specs.cipher_type == aead) {
ivSz = AEAD_EXP_IV_SZ;
if (ssl->specs.bulk_cipher_algorithm != cyassl_chacha)
ivSz = AEAD_EXP_IV_SZ;
sz += (ivSz + ssl->specs.aead_mac_size - digestSz);
XMEMCPY(iv, ssl->keys.aead_exp_IV, AEAD_EXP_IV_SZ);
}
@ -7428,6 +7835,18 @@ static const char* const cipher_names[] =
"ECDH-ECDSA-AES256-SHA384",
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
"ECDHE-RSA-CHACHA20-POLY1305",
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
"ECDHE-ECDSA-CHACHA20-POLY1305",
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
"DHE-RSA-CHACHA20-POLY1305",
#endif
};
@ -7801,7 +8220,19 @@ static int cipher_name_idx[] =
#endif
#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
#endif
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
#endif
};
@ -7848,8 +8279,12 @@ int SetCipherList(Suites* s, const char* list)
for (i = 0; i < suiteSz; i++)
if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) {
if (XSTRSTR(name, "EC") || XSTRSTR(name, "CCM"))
s->suites[idx++] = ECC_BYTE; /* ECC suite */
if (XSTRSTR(name, "CHACHA"))
s->suites[idx++] = CHACHA_BYTE;
else if (XSTRSTR(name, "EC") || XSTRSTR(name, "CCM")) {
s->suites[idx++] = ECC_BYTE; /* ECC suite */
}
else
s->suites[idx++] = 0x00; /* normal */
s->suites[idx++] = (byte)cipher_name_idx[i];

View File

@ -28,7 +28,7 @@
#include <cyassl/internal.h>
#include <cyassl/error-ssl.h>
#ifdef SHOW_SECRETS
#if defined(SHOW_SECRETS) || defined(CHACHA_AEAD_TEST)
#ifdef FREESCALE_MQX
#include <fio.h>
#else
@ -49,6 +49,69 @@ int SetCipherSpecs(CYASSL* ssl)
}
#endif /* NO_CYASSL_CLIENT */
/* Chacha extensions, 0xcc */
if (ssl->options.cipherSuite0 == CHACHA_BYTE) {
switch (ssl->options.cipherSuite) {
#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
ssl->specs.bulk_cipher_algorithm = cyassl_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;
break;
#endif
#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
ssl->specs.bulk_cipher_algorithm = cyassl_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;
break;
#endif
#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
ssl->specs.bulk_cipher_algorithm = cyassl_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;
break;
#endif
default:
CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs ChaCha");
return UNSUPPORTED_SUITE;
}
}
/* ECC extensions, or AES-CCM */
if (ssl->options.cipherSuite0 == ECC_BYTE) {
@ -792,7 +855,8 @@ int SetCipherSpecs(CYASSL* ssl)
return UNSUPPORTED_SUITE;
} /* switch */
} /* if */
if (ssl->options.cipherSuite0 != ECC_BYTE) { /* normal suites */
if (ssl->options.cipherSuite0 != ECC_BYTE &&
ssl->options.cipherSuite0 != CHACHA_BYTE) { /* normal suites */
switch (ssl->options.cipherSuite) {
#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
@ -1774,7 +1838,62 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
dec->setup = 1;
}
#endif
#ifdef HAVE_POLY1305
/* set up memory space for poly1305 */
if (enc->poly1305 == NULL)
enc->poly1305 = (Poly1305*)malloc(sizeof(Poly1305));
if (enc->poly1305 == NULL)
return MEMORY_E;
if (dec->poly1305 == NULL)
dec->poly1305 =
(Poly1305*)XMALLOC(sizeof(Poly1305), heap, DYNAMIC_TYPE_CIPHER);
if (dec->poly1305 == NULL)
return MEMORY_E;
#endif
#ifdef HAVE_CHACHA
if (specs->bulk_cipher_algorithm == cyassl_chacha) {
int chachaRet;
if (enc->chacha == NULL)
enc->chacha = (ChaCha*)malloc(sizeof(ChaCha));
if (enc->chacha == NULL)
return MEMORY_E;
if (dec->chacha == NULL)
dec->chacha =
(ChaCha*)XMALLOC(sizeof(ChaCha), heap, DYNAMIC_TYPE_CIPHER);
if (dec->chacha == NULL)
return MEMORY_E;
if (side == CYASSL_CLIENT_END) {
chachaRet = 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);
if (chachaRet != 0) return chachaRet;
chachaRet = 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);
if (chachaRet != 0) return chachaRet;
}
else {
chachaRet = 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);
if (chachaRet != 0) return chachaRet;
chachaRet = 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);
if (chachaRet != 0) return chachaRet;
}
enc->setup = 1;
dec->setup = 1;
}
#endif
#ifdef HAVE_HC128
if (specs->bulk_cipher_algorithm == cyassl_hc128) {
int hcRet;

View File

@ -194,6 +194,16 @@ void CyaSSL_free(CYASSL* ssl)
CYASSL_LEAVE("SSL_free", 0);
}
#ifdef HAVE_POLY1305
/* set if to use old poly 1 for yes 0 to use new poly */
int CyaSSL_use_old_poly(CYASSL* ssl, int value)
{
CYASSL_ENTER("SSL_use_old_poly");
ssl->options.oldPoly = value;
CYASSL_LEAVE("SSL_use_old_poly", 0);
return 0;
}
#endif
int CyaSSL_set_fd(CYASSL* ssl, int fd)
{
@ -324,6 +334,9 @@ int CyaSSL_GetObjectSize(void)
#endif
#ifndef NO_RABBIT
printf(" sizeof rabbit = %lu\n", sizeof(Rabbit));
#endif
#ifdef HAVE_CHACHA
printf(" sizeof chacha = %lu\n", sizeof(Chacha));
#endif
printf("sizeof cipher specs = %lu\n", sizeof(CipherSpecs));
printf("sizeof keys = %lu\n", sizeof(Keys));
@ -8362,6 +8375,25 @@ CYASSL_X509* CyaSSL_X509_load_certificate_file(const char* fname, int format)
CYASSL_ENTER("SSL_CIPHER_get_name");
#ifndef NO_ERROR_STRINGS
if (cipher) {
#if defined(HAVE_CHACHA)
if (cipher->ssl->options.cipherSuite0 == CHACHA_BYTE) {
/* ChaCha suites */
switch (cipher->ssl->options.cipherSuite) {
#ifdef HAVE_CHACHA
#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";
#endif
case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256";
#endif
}
}
#endif
#if defined(HAVE_ECC) || defined(HAVE_AESCCM)
/* Awkwardly, the ECC cipher suites use the ECC_BYTE as expected,
* but the AES-CCM cipher suites also use it, even the ones that
@ -8508,8 +8540,10 @@ CYASSL_X509* CyaSSL_X509_load_certificate_file(const char* fname, int format)
}
}
#endif /* ECC */
if (cipher->ssl->options.cipherSuite0 != ECC_BYTE) {
/* normal suites */
if (cipher->ssl->options.cipherSuite0 != ECC_BYTE &&
cipher->ssl->options.cipherSuite0 != CHACHA_BYTE) {
/* normal suites */
switch (cipher->ssl->options.cipherSuite) {
#ifndef NO_RSA
#ifndef NO_RC4

View File

@ -1,3 +1,69 @@
# server DTLSv1 DHE-RSA-CHACHA20-POLY1305
-u
-v 2
-l DHE-RSA-CHACHA20-POLY1305
# client DTLSv1 DHE-RSA-CHACHA20-POLY1305
-u
-v 2
-l DHE-RSA-CHACHA20-POLY1305
# server DTLSv1 ECDHE-RSA-CHACHA20-POLY1305
-u
-v 2
-l ECDHE-RSA-CHACHA20-POLY1305
# client DTLSv1 ECDHE-RSA-CHACHA20-POLY1305
-u
-v 2
-l ECDHE-RSA-CHACHA20-POLY1305
# server DTLSv1 ECDHE-EDCSA-CHACHA20-POLY1305
-u
-v 2
-l ECDHE-ECDSA-CHACHA20-POLY1305
-c ./certs/server-ecc.pem
-k ./certs/ecc-key.pem
# client DTLSv1 ECDHE-ECDSA-CHACHA20-POLY1305
-u
-v 2
-l ECDHE-ECDSA-CHACHA20-POLY1305
-A ./certs/server-ecc.pem
# server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305
-u
-v 3
-l DHE-RSA-CHACHA20-POLY1305
# client DTLSv1.2 DHE-RSA-CHACHA20-POLY1305
-u
-v 3
-l DHE-RSA-CHACHA20-POLY1305
# server DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305
-u
-v 3
-l ECDHE-RSA-CHACHA20-POLY1305
# client DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305
-u
-v 3
-l ECDHE-RSA-CHACHA20-POLY1305
# server DTLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305
-u
-v 3
-l ECDHE-ECDSA-CHACHA20-POLY1305
-c ./certs/server-ecc.pem
-k ./certs/ecc-key.pem
# client DTLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305
-u
-v 3
-l ECDHE-ECDSA-CHACHA20-POLY1305
-A ./certs/server-ecc.pem
# server DTLSv1 RC4-SHA
-u
-v 2

View File

@ -1,3 +1,84 @@
# 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
# client TLSv1.1 DHE-RSA-CHACHA20-POLY1305
-v 2
-l DHE-RSA-CHACHA20-POLY1305
# server TLSv1.1 ECDHE-RSA-CHACHA20-POLY1305
-v 2
-l ECDHE-RSA-CHACHA20-POLY1305
# client TLSv1.1 ECDHE-RSA-CHACHA20-POLY1305
-v 2
-l ECDHE-RSA-CHACHA20-POLY1305
# server TLSv1.1 ECDHE-EDCSA-CHACHA20-POLY1305
-v 2
-l ECDHE-ECDSA-CHACHA20-POLY1305
-c ./certs/server-ecc.pem
-k ./certs/ecc-key.pem
# client TLSv1.1 ECDHE-ECDSA-CHACHA20-POLY1305
-v 2
-l ECDHE-ECDSA-CHACHA20-POLY1305
-A ./certs/server-ecc.pem
# server TLSv1.2 DHE-RSA-CHACHA20-POLY1305
-v 3
-l DHE-RSA-CHACHA20-POLY1305
# client TLSv1.2 DHE-RSA-CHACHA20-POLY1305
-v 3
-l DHE-RSA-CHACHA20-POLY1305
# server TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305
-v 3
-l ECDHE-RSA-CHACHA20-POLY1305
# client TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305
-v 3
-l ECDHE-RSA-CHACHA20-POLY1305
# server TLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305
-v 3
-l ECDHE-ECDSA-CHACHA20-POLY1305
-c ./certs/server-ecc.pem
-k ./certs/ecc-key.pem
# client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305
-v 3
-l ECDHE-ECDSA-CHACHA20-POLY1305
-A ./certs/server-ecc.pem
# server SSLv3 RC4-SHA
-v 0
-l RC4-SHA