From 8c9767597963463382e3f1348a425a254ba6567a Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 30 Nov 2012 15:45:43 -0800 Subject: [PATCH] Lean PSK trimming 1. leave out memory and io callback functions, expect user supplied 2. leave out cert and DTLS related functions 3. SHA-1 compile option to use slower, rolled-up transform --- configure.ac | 3 +- ctaocrypt/benchmark/benchmark.c | 4 ++ ctaocrypt/src/random.c | 66 ++++++++++++++------------------- ctaocrypt/src/sha.c | 29 +++++++++++++++ ctaocrypt/test/test.c | 4 ++ cyassl/ctaocrypt/random.h | 4 ++ src/include.am | 10 ++--- src/internal.c | 12 +++--- src/ssl.c | 23 +++++++++--- 9 files changed, 100 insertions(+), 55 deletions(-) diff --git a/configure.ac b/configure.ac index 17c25a4e2..621a52447 100644 --- a/configure.ac +++ b/configure.ac @@ -217,8 +217,9 @@ AC_ARG_ENABLE(leanpsk, if test "$ENABLED_LEANPSK" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DCYASSL_LEANPSK -DHAVE_NULL_CIPHER -DNO_AES -DNO_FILESYSTEM -DNO_RSA -DNO_DSA -DNO_DH -DNO_CERTS -DNO_PWDBASED -DNO_DES3 -DNO_MD4 -DNO_MD5 -DNO_ERROR_STRINGS -DNO_OLD_TLS -DNO_RC4" + AM_CFLAGS="$AM_CFLAGS -DCYASSL_LEANPSK -DHAVE_NULL_CIPHER -DSINGLE_THREADED -DNO_AES -DNO_FILESYSTEM -DNO_RABBIT -DNO_RSA -DNO_DSA -DNO_DH -DNO_CERTS -DNO_PWDBASED -DNO_DES3 -DNO_MD4 -DNO_MD5 -DNO_ERROR_STRINGS -DNO_OLD_TLS -DNO_RC4 -DNO_WRITEV -DXMALLOC_USER -DNO_SESSION_CACHE -DNO_DEV_RANDOM -DCYASSL_USER_IO -DUSE_SLOW_SHA" ENABLED_SLOWMATH="no" + ENABLED_SINGLETHREADED="yes" fi AM_CONDITIONAL([BUILD_LEANPSK], [test "x$ENABLED_LEANPSK" = "xyes"]) diff --git a/ctaocrypt/benchmark/benchmark.c b/ctaocrypt/benchmark/benchmark.c index 0aa9c02fa..7ea6eaed6 100644 --- a/ctaocrypt/benchmark/benchmark.c +++ b/ctaocrypt/benchmark/benchmark.c @@ -85,7 +85,9 @@ int main(int argc, char** argv) #ifdef HAVE_AESGCM bench_aesgcm(); #endif +#ifndef NO_RC4 bench_arc4(); +#endif #ifdef HAVE_HC128 bench_hc128(); #endif @@ -232,6 +234,7 @@ void bench_des(void) #endif +#ifndef NO_RC4 void bench_arc4(void) { Arc4 enc; @@ -250,6 +253,7 @@ void bench_arc4(void) printf("ARC4 %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total, persec); } +#endif #ifdef HAVE_HC128 diff --git a/ctaocrypt/src/random.c b/ctaocrypt/src/random.c index a9ebb9850..1055c1389 100644 --- a/ctaocrypt/src/random.c +++ b/ctaocrypt/src/random.c @@ -83,14 +83,12 @@ enum { }; -static int Hash_df(byte* out, word32 outSz, byte type, byte* inA, word32 inASz, +static int Hash_df(RNG* rng, byte* out, word32 outSz, byte type, byte* inA, word32 inASz, byte* inB, word32 inBSz, byte* inC, word32 inCSz) { byte ctr; int i; int len; - Sha256 sha; - byte digest[SHA256_DIGEST_SIZE]; word32 bits = (outSz * 8); // reverse byte order #ifdef LITTLE_ENDIAN_ORDER @@ -101,31 +99,29 @@ static int Hash_df(byte* out, word32 outSz, byte type, byte* inA, word32 inASz, for (i = 0, ctr = 1; i < len; i++, ctr++) { - InitSha256(&sha); - Sha256Update(&sha, &ctr, sizeof(ctr)); - Sha256Update(&sha, (byte*)&bits, sizeof(bits)); + InitSha256(&rng->sha); + Sha256Update(&rng->sha, &ctr, sizeof(ctr)); + Sha256Update(&rng->sha, (byte*)&bits, sizeof(bits)); /* churning V is the only string that doesn't have * the type added */ if (type != dbrgInitV) - Sha256Update(&sha, &type, sizeof(type)); - Sha256Update(&sha, inA, inASz); + Sha256Update(&rng->sha, &type, sizeof(type)); + Sha256Update(&rng->sha, inA, inASz); if (inB != NULL && inBSz > 0) - Sha256Update(&sha, inB, inBSz); + Sha256Update(&rng->sha, inB, inBSz); if (inC != NULL && inCSz > 0) - Sha256Update(&sha, inC, inCSz); - Sha256Final(&sha, digest); + Sha256Update(&rng->sha, inC, inCSz); + Sha256Final(&rng->sha, rng->digest); if (outSz > SHA256_DIGEST_SIZE) { - XMEMCPY(out, digest, SHA256_DIGEST_SIZE); + XMEMCPY(out, rng->digest, SHA256_DIGEST_SIZE); outSz -= SHA256_DIGEST_SIZE; out += SHA256_DIGEST_SIZE; } else { - XMEMCPY(out, digest, outSz); + XMEMCPY(out, rng->digest, outSz); } } - XMEMSET(digest, 0, SHA256_DIGEST_SIZE); - XMEMSET(&sha, 0, sizeof(sha)); return DBRG_SUCCESS; } @@ -135,12 +131,12 @@ static int Hash_DBRG_Reseed(RNG* rng, byte* entropy, word32 entropySz) { byte seed[DBRG_SEED_LEN]; - Hash_df(seed, sizeof(seed), dbrgInitV, rng->V, sizeof(rng->V), + Hash_df(rng, seed, sizeof(seed), dbrgInitV, rng->V, sizeof(rng->V), entropy, entropySz, NULL, 0); XMEMCPY(rng->V, seed, sizeof(rng->V)); XMEMSET(seed, 0, sizeof(seed)); - Hash_df(rng->C, sizeof(rng->C), dbrgInitC, rng->V, sizeof(rng->V), + Hash_df(rng, rng->C, sizeof(rng->C), dbrgInitC, rng->V, sizeof(rng->V), NULL, 0, NULL, 0); rng->reseed_ctr = 1; return 0; @@ -157,33 +153,29 @@ static INLINE void array_add_one(byte* data, word32 dataSz) } } -static void Hash_gen(byte* out, word32 outSz, byte* V) +static void Hash_gen(RNG* rng, byte* out, word32 outSz, byte* V) { - Sha256 sha; byte data[DBRG_SEED_LEN]; - byte digest[SHA256_DIGEST_SIZE]; int i; int len = (outSz / SHA256_DIGEST_SIZE) + ((outSz % SHA256_DIGEST_SIZE) ? 1 : 0); XMEMCPY(data, V, sizeof(data)); for (i = 0; i < len; i++) { - InitSha256(&sha); - Sha256Update(&sha, data, sizeof(data)); - Sha256Final(&sha, digest); + InitSha256(&rng->sha); + Sha256Update(&rng->sha, data, sizeof(data)); + Sha256Final(&rng->sha, rng->digest); if (outSz > SHA256_DIGEST_SIZE) { - XMEMCPY(out, digest, SHA256_DIGEST_SIZE); + XMEMCPY(out, rng->digest, SHA256_DIGEST_SIZE); outSz -= SHA256_DIGEST_SIZE; out += SHA256_DIGEST_SIZE; array_add_one(data, DBRG_SEED_LEN); } else { - XMEMCPY(out, digest, outSz); + XMEMCPY(out, rng->digest, outSz); } } XMEMSET(data, 0, sizeof(data)); - XMEMSET(digest, 0, sizeof(digest)); - XMEMSET(&sha, 0, sizeof(sha)); } @@ -211,22 +203,18 @@ static int Hash_DBRG_Generate(RNG* rng, byte* out, word32 outSz) int ret; if (rng->reseed_ctr != RESEED_MAX) { - Sha256 sha; - byte digest[SHA256_DIGEST_SIZE]; byte type = dbrgGenerateH; - Hash_gen(out, outSz, rng->V); - InitSha256(&sha); - Sha256Update(&sha, &type, sizeof(type)); - Sha256Update(&sha, rng->V, sizeof(rng->V)); - Sha256Final(&sha, digest); - array_add(rng->V, sizeof(rng->V), digest, sizeof(digest)); + Hash_gen(rng, out, outSz, rng->V); + InitSha256(&rng->sha); + Sha256Update(&rng->sha, &type, sizeof(type)); + Sha256Update(&rng->sha, rng->V, sizeof(rng->V)); + Sha256Final(&rng->sha, rng->digest); + array_add(rng->V, sizeof(rng->V), rng->digest, sizeof(rng->digest)); array_add(rng->V, sizeof(rng->V), rng->C, sizeof(rng->C)); array_add(rng->V, sizeof(rng->V), (byte*)&rng->reseed_ctr, sizeof(rng->reseed_ctr)); rng->reseed_ctr++; - XMEMSET(&sha, 0, sizeof(sha)); - XMEMSET(digest, 0, sizeof(digest)); ret = DBRG_SUCCESS; } else { @@ -239,8 +227,8 @@ static int Hash_DBRG_Generate(RNG* rng, byte* out, word32 outSz) static void Hash_DBRG_Instantiate(RNG* rng, byte* seed, word32 seedSz) { XMEMSET(rng, 0, sizeof(*rng)); - Hash_df(rng->V, sizeof(rng->V), dbrgInitV, seed, seedSz, NULL, 0, NULL, 0); - Hash_df(rng->C, sizeof(rng->C), dbrgInitC, rng->V, sizeof(rng->V), + Hash_df(rng, rng->V, sizeof(rng->V), dbrgInitV, seed, seedSz, NULL, 0, NULL, 0); + Hash_df(rng, rng->C, sizeof(rng->C), dbrgInitC, rng->V, sizeof(rng->V), NULL, 0, NULL, 0); rng->reseed_ctr = 1; } diff --git a/ctaocrypt/src/sha.c b/ctaocrypt/src/sha.c index bad8c9f79..7347fbd40 100644 --- a/ctaocrypt/src/sha.c +++ b/ctaocrypt/src/sha.c @@ -87,6 +87,34 @@ static void Transform(Sha* sha) word32 d = sha->digest[3]; word32 e = sha->digest[4]; +#ifdef USE_SLOW_SHA + word32 t, i; + + for (i = 0; i < 16; i++) { + R0(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 20; i++) { + R1(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 40; i++) { + R2(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 60; i++) { + R3(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 80; i++) { + R4(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } +#else /* nearly 1 K bigger in code size but 25% faster */ /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); @@ -113,6 +141,7 @@ static void Transform(Sha* sha) R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); +#endif /* Add the working vars back into digest state[] */ sha->digest[0] += a; diff --git a/ctaocrypt/test/test.c b/ctaocrypt/test/test.c index fb5d02757..e27a0210a 100644 --- a/ctaocrypt/test/test.c +++ b/ctaocrypt/test/test.c @@ -245,10 +245,12 @@ void ctaocrypt_test(void* args) #endif +#ifndef NO_RC4 if ( (ret = arc4_test()) ) err_sys("ARC4 test failed!\n", ret); else printf( "ARC4 test passed!\n"); +#endif #ifndef NO_HC128 if ( (ret = hc128_test()) ) @@ -1068,6 +1070,7 @@ int hmac_sha384_test(void) #endif +#ifndef NO_RC4 int arc4_test(void) { byte cipher[16]; @@ -1131,6 +1134,7 @@ int arc4_test(void) return 0; } +#endif int hc128_test(void) diff --git a/cyassl/ctaocrypt/random.h b/cyassl/ctaocrypt/random.h index f23f9a559..2bc790dc5 100644 --- a/cyassl/ctaocrypt/random.h +++ b/cyassl/ctaocrypt/random.h @@ -27,6 +27,8 @@ #ifndef NO_RC4 #include +#else + #include #endif #ifdef __cplusplus @@ -73,6 +75,8 @@ typedef struct RNG { typedef struct RNG { OS_Seed seed; + Sha256 sha; + byte digest[SHA256_DIGEST_SIZE]; byte V[DBRG_SEED_LEN]; byte C[DBRG_SEED_LEN]; word64 reseed_ctr; diff --git a/src/include.am b/src/include.am index b8853cf44..413b77425 100644 --- a/src/include.am +++ b/src/include.am @@ -9,15 +9,12 @@ src_libcyassl_la_SOURCES = \ src/keys.c \ src/ssl.c \ src/tls.c \ - ctaocrypt/src/coding.c \ ctaocrypt/src/hmac.c \ ctaocrypt/src/random.c \ ctaocrypt/src/sha.c \ ctaocrypt/src/sha256.c \ - ctaocrypt/src/arc4.c \ ctaocrypt/src/logging.c \ - ctaocrypt/src/error.c \ - ctaocrypt/src/memory.c + ctaocrypt/src/error.c src_libcyassl_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${CYASSL_LIBRARY_VERSION} src_libcyassl_la_LIBADD = $(LIBM) src_libcyassl_la_CFLAGS = -DBUILDING_CYASSL $(AM_CFLAGS) @@ -26,13 +23,16 @@ src_libcyassl_la_CPPFLAGS = -DBUILDING_CYASSL $(AM_CPPFLAGS) if !BUILD_LEANPSK src_libcyassl_la_SOURCES += ctaocrypt/src/rsa.c \ ctaocrypt/src/des3.c \ + ctaocrypt/src/coding.c \ + ctaocrypt/src/arc4.c \ ctaocrypt/src/md4.c \ ctaocrypt/src/md5.c \ ctaocrypt/src/asn.c \ ctaocrypt/src/dh.c \ ctaocrypt/src/dsa.c \ ctaocrypt/src/pwdbased.c \ - ctaocrypt/src/aes.c + ctaocrypt/src/aes.c \ + ctaocrypt/src/memory.c endif if BUILD_AESNI diff --git a/src/internal.c b/src/internal.c index 4b59f4c27..ae0556cbc 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7643,11 +7643,13 @@ int SetCipherList(Suites* s, const char* list) return OUT_OF_ORDER_E; } - if (ssl->options.verifyPeer && ssl->options.failNoCert) - if (!ssl->options.havePeerCert) { - CYASSL_MSG("client didn't present peer cert"); - return NO_PEER_CERT; - } + #ifndef NO_CERTS + if (ssl->options.verifyPeer && ssl->options.failNoCert) + if (!ssl->options.havePeerCert) { + CYASSL_MSG("client didn't present peer cert"); + return NO_PEER_CERT; + } + #endif #ifdef CYASSL_CALLBACKS if (ssl->hsInfoOn) diff --git a/src/ssl.c b/src/ssl.c index 6efcef0b0..49c99cbb9 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -82,6 +82,7 @@ #endif /* min */ +#ifndef CYASSL_LEANPSK char* mystrnstr(const char* s1, const char* s2, unsigned int n) { unsigned int s2_len = (unsigned int)XSTRLEN(s2); @@ -99,6 +100,7 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n) return NULL; } +#endif CYASSL_CTX* CyaSSL_CTX_new(CYASSL_METHOD* method) @@ -163,6 +165,7 @@ void CyaSSL_free(CYASSL* ssl) } +#ifndef CYASSL_LEANPSK int CyaSSL_set_fd(CYASSL* ssl, int fd) { CYASSL_ENTER("SSL_set_fd"); @@ -191,8 +194,10 @@ int CyaSSL_get_fd(const CYASSL* ssl) CYASSL_LEAVE("SSL_get_fd", ssl->rfd); return ssl->rfd; } +#endif +#ifndef CYASSL_LEANPSK void CyaSSL_set_using_nonblock(CYASSL* ssl, int nonblock) { CYASSL_ENTER("CyaSSL_set_using_nonblock"); @@ -250,6 +255,7 @@ int CyaSSL_dtls_get_peer(CYASSL* ssl, void* peer, unsigned int* peerSz) return SSL_NOT_IMPLEMENTED; #endif } +#endif /* CYASSL_LEANPSK */ int CyaSSL_negotiate(CYASSL* ssl) @@ -276,6 +282,7 @@ int CyaSSL_negotiate(CYASSL* ssl) } +#ifndef CYASSL_LEANPSK /* object size based on build */ int CyaSSL_GetObjectSize(void) { @@ -302,6 +309,7 @@ int CyaSSL_GetObjectSize(void) return sizeof(CYASSL); } +#endif /* XXX should be NO_DH */ #ifndef NO_CERTS @@ -416,7 +424,7 @@ int CyaSSL_read(CYASSL* ssl, void* data, int sz) return CyaSSL_read_internal(ssl, data, sz, FALSE); } - +#ifndef CYASSL_LEANPSK int CyaSSL_send(CYASSL* ssl, const void* data, int sz, int flags) { int ret; @@ -449,7 +457,7 @@ int CyaSSL_recv(CYASSL* ssl, void* data, int sz, int flags) return ret; } - +#endif int CyaSSL_shutdown(CYASSL* ssl) { @@ -627,6 +635,7 @@ int CyaSSL_pending(CYASSL* ssl) } +#ifndef CYASSL_LEANPSK /* trun on handshake group messages for context */ int CyaSSL_CTX_set_group_messages(CYASSL_CTX* ctx) { @@ -637,6 +646,7 @@ int CyaSSL_CTX_set_group_messages(CYASSL_CTX* ctx) return SSL_SUCCESS; } +#endif #ifndef NO_CYASSL_CLIENT @@ -657,6 +667,7 @@ int CyaSSL_connect_cert(CYASSL* ssl) #endif +#ifndef CYASSL_LEANPSK /* trun on handshake group messages for ssl object */ int CyaSSL_set_group_messages(CYASSL* ssl) { @@ -721,6 +732,7 @@ int CyaSSL_SetVersion(CYASSL* ssl, int version) return SSL_SUCCESS; } +#endif #ifndef NO_CERTS @@ -2249,7 +2261,6 @@ int CyaSSL_CTX_use_NTRUPrivateKey_file(CYASSL_CTX* ctx, const char* file) #endif /* NO_FILESYSTEM */ -#endif /* !NO_CERTS */ void CyaSSL_CTX_set_verify(CYASSL_CTX* ctx, int mode, VerifyCallback vc) { @@ -2291,8 +2302,6 @@ void CyaSSL_set_verify(CYASSL* ssl, int mode, VerifyCallback vc) } -#ifndef NO_CERTS - /* store context CA Cache addition callback */ void CyaSSL_CTX_SetCACb(CYASSL_CTX* ctx, CallbackCACache cb) { @@ -2395,6 +2404,8 @@ int CyaSSL_set_cipher_list(CYASSL* ssl, const char* list) } +#ifndef CYASSL_LEANPSK + int CyaSSL_dtls_get_current_timeout(CYASSL* ssl) { (void)ssl; @@ -2421,6 +2432,8 @@ int CyaSSL_dtls_got_timeout(CYASSL* ssl) #endif } +#endif + /* client only parts */ #ifndef NO_CYASSL_CLIENT