From f2c75a9e87efb55629607ba71d0ccb39aa560422 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 5 Sep 2013 12:14:30 -0700 Subject: [PATCH 1/2] ECDSA signatures need a zero padding for the ASN.1 storage of the R and S values --- ctaocrypt/src/asn.c | 13 ++++++++++--- ctaocrypt/src/integer.c | 22 ++++++++++++++++++++++ ctaocrypt/src/tfm.c | 25 +++++++++++++++++++++++++ cyassl/ctaocrypt/integer.h | 1 + cyassl/ctaocrypt/tfm.h | 2 ++ src/internal.c | 2 +- 6 files changed, 61 insertions(+), 4 deletions(-) diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index 6477c084a..f228f9f0c 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -4390,6 +4390,9 @@ int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s) word32 sSz; word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */ + /* If the leading bit on the INTEGER is a 1, add a leading zero */ + int rLeadingZero = mp_leading_bit(r); + int sLeadingZero = mp_leading_bit(s); int rLen = mp_unsigned_bin_size(r); /* big int size */ int sLen = mp_unsigned_bin_size(s); int err; @@ -4397,20 +4400,24 @@ int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s) if (*outLen < (rLen + sLen + headerSz + 2)) /* SEQ_TAG + LEN(ENUM) */ return BAD_FUNC_ARG; - idx = SetSequence(rLen + sLen + headerSz, out); + idx = SetSequence(rLen+rLeadingZero+sLen+sLeadingZero+headerSz, out); /* store r */ out[idx++] = ASN_INTEGER; - rSz = SetLength(rLen, &out[idx]); + rSz = SetLength(rLen + rLeadingZero, &out[idx]); idx += rSz; + if (rLeadingZero) + out[idx++] = 0; err = mp_to_unsigned_bin(r, &out[idx]); if (err != MP_OKAY) return err; idx += rLen; /* store s */ out[idx++] = ASN_INTEGER; - sSz = SetLength(sLen, &out[idx]); + sSz = SetLength(sLen + sLeadingZero, &out[idx]); idx += sSz; + if (sLeadingZero) + out[idx++] = 0; err = mp_to_unsigned_bin(s, &out[idx]); if (err != MP_OKAY) return err; idx += sLen; diff --git a/ctaocrypt/src/integer.c b/ctaocrypt/src/integer.c index 5c3315498..2d79da593 100644 --- a/ctaocrypt/src/integer.c +++ b/ctaocrypt/src/integer.c @@ -179,6 +179,28 @@ mp_count_bits (mp_int * a) } +int mp_leading_bit (mp_int * a) +{ + int bit = 0; + mp_int t; + + if (mp_init_copy(&t, a) != MP_OKAY) + return 0; + + while (mp_iszero(&t) == 0) { +#ifndef MP_8BIT + bit = (t.dp[0] & 0x80) != 0; +#else + bit = (t.dp[0] | ((t.dp[1] & 0x01) << 7)) & 0x80 != 0; +#endif + if (mp_div_2d (&t, 8, &t, NULL) != MP_OKAY) + break; + } + mp_clear(&t); + return bit; +} + + /* store in unsigned [big endian] format */ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) { diff --git a/ctaocrypt/src/tfm.c b/ctaocrypt/src/tfm.c index 706e1e653..9f71484d6 100644 --- a/ctaocrypt/src/tfm.c +++ b/ctaocrypt/src/tfm.c @@ -1706,6 +1706,25 @@ int fp_count_bits (fp_int * a) return r; } +int fp_leading_bit(fp_int *a) +{ + int bit = 0; + + if (a->used != 0) { + fp_digit q = a->dp[a->used - 1]; + int qSz = sizeof(fp_digit); + + while (qSz > 0) { + if ((unsigned char)q != 0) + bit = (q & 0x80) != 0; + q >>= 8; + qSz--; + } + } + + return bit; +} + void fp_lshd(fp_int *a, int x) { int y; @@ -1968,6 +1987,12 @@ int mp_count_bits (mp_int* a) } +int mp_leading_bit (mp_int* a) +{ + return fp_leading_bit(a); +} + + /* fast math conversion */ void mp_rshb (mp_int* a, int x) { diff --git a/cyassl/ctaocrypt/integer.h b/cyassl/ctaocrypt/integer.h index 8383fa602..2c4d80a7f 100644 --- a/cyassl/ctaocrypt/integer.h +++ b/cyassl/ctaocrypt/integer.h @@ -225,6 +225,7 @@ int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); /* functions added to support above needed, removed TOOM and KARATSUBA */ int mp_count_bits (mp_int * a); +int mp_leading_bit (mp_int * a); int mp_init_copy (mp_int * a, mp_int * b); int mp_copy (mp_int * a, mp_int * b); int mp_grow (mp_int * a, int size); diff --git a/cyassl/ctaocrypt/tfm.h b/cyassl/ctaocrypt/tfm.h index 636507eb4..2495f67ab 100644 --- a/cyassl/ctaocrypt/tfm.h +++ b/cyassl/ctaocrypt/tfm.h @@ -490,6 +490,7 @@ int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); /* radix conersions */ int fp_count_bits(fp_int *a); +int fp_leading_bit(fp_int *a); int fp_unsigned_bin_size(fp_int *a); void fp_read_unsigned_bin(fp_int *a, unsigned char *b, int c); @@ -655,6 +656,7 @@ int mp_copy(fp_int* a, fp_int* b); int mp_isodd(mp_int* a); int mp_iszero(mp_int* a); int mp_count_bits(mp_int *a); +int mp_leading_bit(mp_int *a); int mp_set_int(fp_int *a, fp_digit b); void mp_rshb(mp_int *a, int x); diff --git a/src/internal.c b/src/internal.c index 60b8eca50..4bc3ae8fb 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8433,7 +8433,7 @@ static void PickHashSigAlgo(CYASSL* ssl, ret = EccPrivateKeyDecode(ssl->buffers.key.buffer, &i, &dsaKey, ssl->buffers.key.length); if (ret != 0) return ret; - sigSz = ecc_sig_size(&dsaKey) + 2; /* worst case estimate */ + sigSz = ecc_sig_size(&dsaKey) + 4; /* worst case estimate */ } else { #ifndef NO_RSA From d7a08b1a76a3ea7f07d53c14b090397b35dfa8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mois=C3=A9s=20Guimar=C3=A3es?= Date: Fri, 6 Sep 2013 15:53:22 -0300 Subject: [PATCH 2/2] centralizing MAX_DIGEST_SIZE definition in hmac.h --- ctaocrypt/src/pwdbased.c | 6 +----- cyassl/ctaocrypt/hmac.h | 12 ++++++------ cyassl/internal.h | 12 +----------- cyassl/test.h | 2 +- src/internal.c | 8 ++++---- 5 files changed, 13 insertions(+), 27 deletions(-) diff --git a/ctaocrypt/src/pwdbased.c b/ctaocrypt/src/pwdbased.c index 61fcdd0ba..8a7fc1478 100644 --- a/ctaocrypt/src/pwdbased.c +++ b/ctaocrypt/src/pwdbased.c @@ -106,11 +106,7 @@ int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, int hLen; int j; Hmac hmac; -#ifdef CYASSL_SHA512 - byte buffer[SHA512_DIGEST_SIZE]; -#else - byte buffer[INNER_HASH_SIZE]; /* max size, doesn't handle 512 yet */ -#endif + byte buffer[MAX_DIGEST_SIZE]; if (hashType == MD5) { hLen = MD5_DIGEST_SIZE; diff --git a/cyassl/ctaocrypt/hmac.h b/cyassl/ctaocrypt/hmac.h index 0641afd2c..596d6e4c1 100644 --- a/cyassl/ctaocrypt/hmac.h +++ b/cyassl/ctaocrypt/hmac.h @@ -78,19 +78,19 @@ enum { /* Select the largest available hash for the buffer size. */ #if defined(CYASSL_SHA512) - INNER_HASH_SIZE = SHA512_DIGEST_SIZE, + MAX_DIGEST_SIZE = SHA512_DIGEST_SIZE, HMAC_BLOCK_SIZE = SHA512_BLOCK_SIZE #elif defined(CYASSL_SHA384) - INNER_HASH_SIZE = SHA384_DIGEST_SIZE, + MAX_DIGEST_SIZE = SHA384_DIGEST_SIZE, HMAC_BLOCK_SIZE = SHA384_BLOCK_SIZE #elif !defined(NO_SHA256) - INNER_HASH_SIZE = SHA256_DIGEST_SIZE, + MAX_DIGEST_SIZE = SHA256_DIGEST_SIZE, HMAC_BLOCK_SIZE = SHA256_BLOCK_SIZE #elif !defined(NO_SHA) - INNER_HASH_SIZE = SHA_DIGEST_SIZE, + MAX_DIGEST_SIZE = SHA_DIGEST_SIZE, HMAC_BLOCK_SIZE = SHA_BLOCK_SIZE #elif !defined(NO_MD5) - INNER_HASH_SIZE = MD5_DIGEST_SIZE, + MAX_DIGEST_SIZE = MD5_DIGEST_SIZE, HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE #else #error "You have to have some kind of hash if you want to use HMAC." @@ -122,7 +122,7 @@ typedef struct Hmac { Hash hash; word32 ipad[HMAC_BLOCK_SIZE / sizeof(word32)]; /* same block size all*/ word32 opad[HMAC_BLOCK_SIZE / sizeof(word32)]; - word32 innerHash[INNER_HASH_SIZE / sizeof(word32)]; /* max size */ + word32 innerHash[MAX_DIGEST_SIZE / sizeof(word32)]; byte macType; /* md5 sha or sha256 */ byte innerHashKeyed; /* keyed flag */ #ifdef HAVE_CAVIUM diff --git a/cyassl/internal.h b/cyassl/internal.h index 8c76de40f..ac7e086ac 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -37,6 +37,7 @@ #include #include #include +#include #ifndef NO_RC4 #include #endif @@ -519,17 +520,6 @@ enum { }; -#if defined(CYASSL_SHA384) - #define MAX_DIGEST_SIZE SHA384_DIGEST_SIZE -#elif !defined(NO_SHA256) - #define MAX_DIGEST_SIZE SHA256_DIGEST_SIZE -#elif !defined(NO_MD5) && !defined(NO_SHA) - #define MAX_DIGEST_SIZE (SHA_DIGEST_SIZE + MD5_DIGEST_SIZE) -#else - #error "You have configured the build so there isn't any hashing." -#endif - - enum Misc { ECC_BYTE = 0xC0, /* ECC first cipher suite byte */ diff --git a/cyassl/test.h b/cyassl/test.h index 50e51726f..3d82aa7b3 100644 --- a/cyassl/test.h +++ b/cyassl/test.h @@ -1389,7 +1389,7 @@ static INLINE int myDecryptVerifyCb(CYASSL* ssl, unsigned int padByte = 0; Hmac hmac; byte myInner[CYASSL_TLS_HMAC_INNER_SZ]; - byte verify[INNER_HASH_SIZE]; + byte verify[MAX_DIGEST_SIZE]; const char* tlsStr = "TLS"; /* example supports (d)tls aes */ diff --git a/src/internal.c b/src/internal.c index 4bc3ae8fb..414343740 100644 --- a/src/internal.c +++ b/src/internal.c @@ -98,7 +98,7 @@ typedef enum { } processReply; #ifndef NO_OLD_TLS -static void Hmac(CYASSL* ssl, byte* digest, const byte* in, word32 sz, +static void SSL_hmac(CYASSL* ssl, byte* digest, const byte* in, word32 sz, int content, int verify); #endif @@ -1416,7 +1416,7 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) ssl->options.resuming = 0; ssl->options.haveSessionId = 0; #ifndef NO_OLD_TLS - ssl->hmac = Hmac; /* default to SSLv3 */ + ssl->hmac = SSL_hmac; /* default to SSLv3 */ #else ssl->hmac = TLS_hmac; #endif @@ -3422,7 +3422,7 @@ static int DoHelloRequest(CYASSL* ssl, const byte* input, word32* inOutIdx) const byte* mac; int padSz = ssl->keys.encryptSz - HANDSHAKE_HEADER_SZ - ssl->specs.hash_size; - byte verify[SHA256_DIGEST_SIZE]; + byte verify[MAX_DIGEST_SIZE]; ssl->hmac(ssl, verify, input + *inOutIdx - HANDSHAKE_HEADER_SZ, HANDSHAKE_HEADER_SZ, handshake, 1); @@ -4954,7 +4954,7 @@ int SendChangeCipher(CYASSL* ssl) #ifndef NO_OLD_TLS -static void Hmac(CYASSL* ssl, byte* digest, const byte* in, word32 sz, +static void SSL_hmac(CYASSL* ssl, byte* digest, const byte* in, word32 sz, int content, int verify) { byte result[MAX_DIGEST_SIZE];