From 277598e34a0909700a7f778a2ff46761545ba9cc Mon Sep 17 00:00:00 2001 From: Jonas Norling Date: Wed, 4 Jun 2014 13:15:45 +0200 Subject: [PATCH 1/2] Use same sequence number calculation in tls.c and internal.c The DTLS sequence number used when decrypting CCM/GCM was taken from the internal state, instead of from the actual message record. If any DTLS messages were dropped, the expectation of the next sequence number was wrong. This lead to a failed MAC check on the next message to arrive, and an alert was generated. --- src/internal.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/internal.c b/src/internal.c index 4d54e9978..180793eba 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4740,6 +4740,14 @@ static int DoDtlsHandShakeMsg(CYASSL* ssl, byte* input, word32* inOutIdx, || defined(HAVE_AESGCM) static INLINE word32 GetSEQIncrement(CYASSL* ssl, int verify) { +#ifdef CYASSL_DTLS + if (ssl->options.dtls) { + if (verify) + return ssl->keys.dtls_state.curSeq; /* explicit from peer */ + else + return ssl->keys.dtls_sequence_number - 1; /* already incremented */ + } +#endif if (verify) return ssl->keys.peer_sequence_number++; else From e9297f092debf2a62533527f2c540f2089b8b095 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 29 Jul 2014 15:19:51 -0700 Subject: [PATCH 2/2] updated HashDRBG so private data not available via struct declaration in header file --- ctaocrypt/src/random.c | 138 ++++++++++++++++++++++---------------- cyassl/ctaocrypt/random.h | 10 ++- 2 files changed, 83 insertions(+), 65 deletions(-) diff --git a/ctaocrypt/src/random.c b/ctaocrypt/src/random.c index 7442fe123..4bdc3b303 100644 --- a/ctaocrypt/src/random.c +++ b/ctaocrypt/src/random.c @@ -101,9 +101,18 @@ enum { }; +typedef struct DRBG { + Sha256 sha; + byte digest[SHA256_DIGEST_SIZE]; + byte V[DRBG_SEED_LEN]; + byte C[DRBG_SEED_LEN]; + word32 reseedCtr; +} DRBG; + + /* Hash Derivation Function */ /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ -static int Hash_df(RNG* rng, byte* out, word32 outSz, byte type, +static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type, const byte* inA, word32 inASz, const byte* inB, word32 inBSz) { @@ -120,38 +129,38 @@ static int Hash_df(RNG* rng, byte* out, word32 outSz, byte type, for (i = 0, ctr = 1; i < len; i++, ctr++) { - if (InitSha256(&rng->sha) != 0) + if (InitSha256(&drbg->sha) != 0) return DRBG_FAILURE; - if (Sha256Update(&rng->sha, &ctr, sizeof(ctr)) != 0) + if (Sha256Update(&drbg->sha, &ctr, sizeof(ctr)) != 0) return DRBG_FAILURE; - if (Sha256Update(&rng->sha, (byte*)&bits, sizeof(bits)) != 0) + if (Sha256Update(&drbg->sha, (byte*)&bits, sizeof(bits)) != 0) return DRBG_FAILURE; /* churning V is the only string that doesn't have * the type added */ if (type != drbgInitV) - if (Sha256Update(&rng->sha, &type, sizeof(type)) != 0) + if (Sha256Update(&drbg->sha, &type, sizeof(type)) != 0) return DRBG_FAILURE; - if (Sha256Update(&rng->sha, inA, inASz) != 0) + if (Sha256Update(&drbg->sha, inA, inASz) != 0) return DRBG_FAILURE; if (inB != NULL && inBSz > 0) - if (Sha256Update(&rng->sha, inB, inBSz) != 0) + if (Sha256Update(&drbg->sha, inB, inBSz) != 0) return DRBG_FAILURE; - if (Sha256Final(&rng->sha, rng->digest) != 0) + if (Sha256Final(&drbg->sha, drbg->digest) != 0) return DRBG_FAILURE; if (outSz > OUTPUT_BLOCK_LEN) { - XMEMCPY(out, rng->digest, OUTPUT_BLOCK_LEN); + XMEMCPY(out, drbg->digest, OUTPUT_BLOCK_LEN); outSz -= OUTPUT_BLOCK_LEN; out += OUTPUT_BLOCK_LEN; } else { - XMEMCPY(out, rng->digest, outSz); + XMEMCPY(out, drbg->digest, outSz); } } @@ -160,24 +169,24 @@ static int Hash_df(RNG* rng, byte* out, word32 outSz, byte type, /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ -static int Hash_DRBG_Reseed(RNG* rng, const byte* entropy, word32 entropySz) +static int Hash_DRBG_Reseed(DRBG* drbg, const byte* entropy, word32 entropySz) { byte seed[DRBG_SEED_LEN]; - if (Hash_df(rng, seed, sizeof(seed), drbgReseed, rng->V, sizeof(rng->V), + if (Hash_df(drbg, seed, sizeof(seed), drbgReseed, drbg->V, sizeof(drbg->V), entropy, entropySz) != DRBG_SUCCESS) { return DRBG_FAILURE; } - XMEMCPY(rng->V, seed, sizeof(rng->V)); + XMEMCPY(drbg->V, seed, sizeof(drbg->V)); XMEMSET(seed, 0, sizeof(seed)); - if (Hash_df(rng, rng->C, sizeof(rng->C), drbgInitC, rng->V, - sizeof(rng->V), NULL, 0) != DRBG_SUCCESS) { + if (Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V, + sizeof(drbg->V), NULL, 0) != DRBG_SUCCESS) { return DRBG_FAILURE; } - rng->reseedCtr = 1; + drbg->reseedCtr = 1; return DRBG_SUCCESS; } @@ -194,7 +203,7 @@ static INLINE void array_add_one(byte* data, word32 dataSz) /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ -static int Hash_gen(RNG* rng, byte* out, word32 outSz, const byte* V) +static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V) { byte data[DRBG_SEED_LEN]; int i; @@ -203,21 +212,21 @@ static int Hash_gen(RNG* rng, byte* out, word32 outSz, const byte* V) XMEMCPY(data, V, sizeof(data)); for (i = 0; i < len; i++) { - if (InitSha256(&rng->sha) != 0 || - Sha256Update(&rng->sha, data, sizeof(data)) != 0 || - Sha256Final(&rng->sha, rng->digest) != 0) { + if (InitSha256(&drbg->sha) != 0 || + Sha256Update(&drbg->sha, data, sizeof(data)) != 0 || + Sha256Final(&drbg->sha, drbg->digest) != 0) { return DRBG_FAILURE; } if (outSz > OUTPUT_BLOCK_LEN) { - XMEMCPY(out, rng->digest, OUTPUT_BLOCK_LEN); + XMEMCPY(out, drbg->digest, OUTPUT_BLOCK_LEN); outSz -= OUTPUT_BLOCK_LEN; out += OUTPUT_BLOCK_LEN; array_add_one(data, DRBG_SEED_LEN); } else { - XMEMCPY(out, rng->digest, outSz); + XMEMCPY(out, drbg->digest, outSz); } } XMEMSET(data, 0, sizeof(data)); @@ -246,30 +255,31 @@ static INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen) /* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */ -static int Hash_DRBG_Generate(RNG* rng, byte* out, word32 outSz) +static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz) { int ret = DRBG_NEED_RESEED; - if (rng->reseedCtr != RESEED_INTERVAL) { + if (drbg->reseedCtr != RESEED_INTERVAL) { byte type = drbgGenerateH; - word32 reseedCtr = rng->reseedCtr; + word32 reseedCtr = drbg->reseedCtr; - rng->reseedCtr++; - if (Hash_gen(rng, out, outSz, rng->V) != 0 || - InitSha256(&rng->sha) != 0 || - Sha256Update(&rng->sha, &type, sizeof(type)) != 0 || - Sha256Update(&rng->sha, rng->V, sizeof(rng->V)) != 0 || - Sha256Final(&rng->sha, rng->digest) != 0) { + drbg->reseedCtr++; + if (Hash_gen(drbg, out, outSz, drbg->V) != 0 || + InitSha256(&drbg->sha) != 0 || + Sha256Update(&drbg->sha, &type, sizeof(type)) != 0 || + Sha256Update(&drbg->sha, drbg->V, sizeof(drbg->V)) != 0 || + Sha256Final(&drbg->sha, drbg->digest) != 0) { ret = DRBG_FAILURE; } else { - 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(drbg->V, sizeof(drbg->V), + drbg->digest, sizeof(drbg->digest)); + array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C)); #ifdef LITTLE_ENDIAN_ORDER reseedCtr = ByteReverseWord32(reseedCtr); #endif - array_add(rng->V, sizeof(rng->V), + array_add(drbg->V, sizeof(drbg->V), (byte*)&reseedCtr, sizeof(reseedCtr)); ret = DRBG_SUCCESS; } @@ -280,19 +290,19 @@ static int Hash_DRBG_Generate(RNG* rng, byte* out, word32 outSz) /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ -static int Hash_DRBG_Instantiate(RNG* rng, const byte* seed, word32 seedSz, - const byte* nonce, word32 nonceSz) +static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz, + const byte* nonce, word32 nonceSz) { int ret = DRBG_FAILURE; - XMEMSET(rng, 0, sizeof(*rng)); + XMEMSET(drbg, 0, sizeof(DRBG)); - if (Hash_df(rng, rng->V, sizeof(rng->V), drbgInitV, seed, seedSz, + if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz, nonce, nonceSz) == DRBG_SUCCESS && - Hash_df(rng, rng->C, sizeof(rng->C), drbgInitC, rng->V, - sizeof(rng->V), NULL, 0) == DRBG_SUCCESS) { + Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V, + sizeof(drbg->V), NULL, 0) == DRBG_SUCCESS) { - rng->reseedCtr = 1; + drbg->reseedCtr = 1; ret = DRBG_SUCCESS; } @@ -301,9 +311,9 @@ static int Hash_DRBG_Instantiate(RNG* rng, const byte* seed, word32 seedSz, /* Returns: DRBG_SUCCESS */ -static int Hash_DRBG_Uninstantiate(RNG* rng) +static int Hash_DRBG_Uninstantiate(DRBG* drbg) { - XMEMSET(rng, 0, sizeof(*rng)); + XMEMSET(drbg, 0, sizeof(DRBG)); return DRBG_SUCCESS; } @@ -319,11 +329,16 @@ int InitRng(RNG* rng) if (rng != NULL) { byte entropy[ENTROPY_NONCE_SZ]; + rng->drbg = XMALLOC(sizeof(DRBG), NULL, DYNAMIC_TYPE_RNG); + if (rng->drbg == NULL) { + rng->status = DRBG_FAILED; + ret = MEMORY_E; + } /* This doesn't use a separate nonce. The entropy input will be * the default size plus the size of the nonce making the seed * size. */ - if (GenerateSeed(&rng->seed, entropy, ENTROPY_NONCE_SZ) == 0 && - Hash_DRBG_Instantiate(rng, entropy, ENTROPY_NONCE_SZ, + else if (GenerateSeed(&rng->seed, entropy, ENTROPY_NONCE_SZ) == 0 && + Hash_DRBG_Instantiate(rng->drbg, entropy, ENTROPY_NONCE_SZ, NULL, 0) == DRBG_SUCCESS) { rng->status = DRBG_OK; ret = 0; @@ -351,7 +366,7 @@ int RNG_GenerateBlock(RNG* rng, byte* output, word32 sz) if (rng->status != DRBG_OK) return RNG_FAILURE_E; - ret = Hash_DRBG_Generate(rng, output, sz); + ret = Hash_DRBG_Generate(rng->drbg, output, sz); if (ret == DRBG_SUCCESS) { ret = 0; } @@ -359,8 +374,9 @@ int RNG_GenerateBlock(RNG* rng, byte* output, word32 sz) byte entropy[ENTROPY_SZ]; if (GenerateSeed(&rng->seed, entropy, ENTROPY_SZ) == 0 && - Hash_DRBG_Reseed(rng, entropy, ENTROPY_SZ) == DRBG_SUCCESS && - Hash_DRBG_Generate(rng, output, sz) == DRBG_SUCCESS) { + Hash_DRBG_Reseed(rng->drbg, + entropy, ENTROPY_SZ) == DRBG_SUCCESS && + Hash_DRBG_Generate(rng->drbg, output, sz) == DRBG_SUCCESS) { ret = 0; } @@ -391,10 +407,14 @@ int FreeRng(RNG* rng) int ret = BAD_FUNC_ARG; if (rng != NULL) { - if (Hash_DRBG_Uninstantiate(rng) == DRBG_SUCCESS) + if (Hash_DRBG_Uninstantiate(rng->drbg) == DRBG_SUCCESS) ret = 0; else ret = RNG_FAILURE_E; + + XFREE(rng->drbg, NULL, DYNAMIC_TYPE_RNG); + rng->drbg = NULL; + rng->status = DRBG_NOT_INIT; } return ret; @@ -405,35 +425,35 @@ int RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, const byte* entropyB, word32 entropyBSz, const byte* output, word32 outputSz) { - RNG rng; + DRBG drbg; byte check[SHA256_DIGEST_SIZE * 4]; - if (Hash_DRBG_Instantiate(&rng, entropyA, entropyASz, NULL, 0) != 0) + if (Hash_DRBG_Instantiate(&drbg, entropyA, entropyASz, NULL, 0) != 0) return -1; if (reseed) { - if (Hash_DRBG_Reseed(&rng, entropyB, entropyBSz) != 0) { - Hash_DRBG_Uninstantiate(&rng); + if (Hash_DRBG_Reseed(&drbg, entropyB, entropyBSz) != 0) { + Hash_DRBG_Uninstantiate(&drbg); return -1; } } - if (Hash_DRBG_Generate(&rng, check, sizeof(check)) != 0) { - Hash_DRBG_Uninstantiate(&rng); + if (Hash_DRBG_Generate(&drbg, check, sizeof(check)) != 0) { + Hash_DRBG_Uninstantiate(&drbg); return -1; } - if (Hash_DRBG_Generate(&rng, check, sizeof(check)) != 0) { - Hash_DRBG_Uninstantiate(&rng); + if (Hash_DRBG_Generate(&drbg, check, sizeof(check)) != 0) { + Hash_DRBG_Uninstantiate(&drbg); return -1; } if (outputSz != sizeof(check) || XMEMCMP(output, check, sizeof(check))) { - Hash_DRBG_Uninstantiate(&rng); + Hash_DRBG_Uninstantiate(&drbg); return -1; } - Hash_DRBG_Uninstantiate(&rng); + Hash_DRBG_Uninstantiate(&drbg); return 0; } diff --git a/cyassl/ctaocrypt/random.h b/cyassl/ctaocrypt/random.h index 728c22209..29b94ad80 100644 --- a/cyassl/ctaocrypt/random.h +++ b/cyassl/ctaocrypt/random.h @@ -75,15 +75,13 @@ int GenerateSeed(OS_Seed* os, byte* seed, word32 sz); #define DRBG_SEED_LEN (440/8) +struct DRBG; /* Private DRBG state */ + + /* Hash-based Deterministic Random Bit Generator */ typedef struct RNG { OS_Seed seed; - - Sha256 sha; - byte digest[SHA256_DIGEST_SIZE]; - byte V[DRBG_SEED_LEN]; - byte C[DRBG_SEED_LEN]; - word32 reseedCtr; + struct DRBG* drbg; byte status; } RNG;