From a54f51d88693cbcf08b09de1ff4f775ed03583e3 Mon Sep 17 00:00:00 2001 From: toddouska Date: Thu, 3 May 2012 08:18:59 -0700 Subject: [PATCH 1/6] first static ECDH suite --- ctaocrypt/src/asn.c | 2 +- cyassl/ctaocrypt/asn.h | 1 + cyassl/internal.h | 13 +++++-- src/internal.c | 80 +++++++++++++++++++++++++++++++++++------- src/keys.c | 48 ++++++++++++++++++++++++- src/ssl.c | 32 ++++++++++++++++- 6 files changed, 159 insertions(+), 17 deletions(-) diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index f38a4472a..4d99584d1 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -1599,7 +1599,7 @@ static int GetValidity(DecodedCert* cert, int verify) } -static int DecodeToKey(DecodedCert* cert, int verify) +int DecodeToKey(DecodedCert* cert, int verify) { int badDate = 0; int ret; diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index b26f48457..148e71ce3 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -267,6 +267,7 @@ CYASSL_TEST_API int ParseCert(DecodedCert*, int type, int verify, CYASSL_LOCAL int ParseCertRelative(DecodedCert*, int type, int verify, Signer* signer); +CYASSL_LOCAL int DecodeToKey(DecodedCert*, int verify); CYASSL_LOCAL word32 EncodeSignature(byte* out, const byte* digest, word32 digSz, int hashOID); diff --git a/cyassl/internal.h b/cyassl/internal.h index d72fee138..2bfe15346 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -169,6 +169,8 @@ void c32to24(word32 in, word24 out); #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA #endif #if !defined(NO_RC4) #define BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA @@ -235,6 +237,10 @@ enum { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x12, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0x08, + /* static ECDH, first byte is 0xC0 (ECC_BYTE) */ + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0x05, + + /* CyaSSL extension - eSTREAM */ TLS_RSA_WITH_HC_128_CBC_MD5 = 0xFB, TLS_RSA_WITH_HC_128_CBC_SHA = 0xFC, @@ -620,7 +626,8 @@ struct CYASSL_CTX { byte sendVerify; /* for client side */ byte haveDH; /* server DH parms set by user */ byte haveNTRU; /* server private NTRU key loaded */ - byte haveECDSA; /* server private ECDSA key loaded */ + byte haveECDSA; /* server cert signed w/ ECDSA loaded */ + byte haveStaticECC; /* static server ECC private key */ byte partialWrite; /* only one msg per write call */ byte quietShutdown; /* don't send close notify */ byte groupMessages; /* group handshake messages before sending */ @@ -671,6 +678,7 @@ typedef struct CipherSpecs { byte sig_algo; byte hash_size; byte pad_size; + byte static_ecdh; word16 key_size; word16 iv_size; word16 block_size; @@ -933,7 +941,8 @@ typedef struct Options { byte usingCompression; /* are we using compression */ byte haveDH; /* server DH parms set by user */ byte haveNTRU; /* server NTRU private key loaded */ - byte haveECDSA; /* server ECDSA private key loaded */ + byte haveECDSA; /* server ECDSA signed cert */ + byte haveStaticECC; /* static server ECC private key */ byte havePeerCert; /* do we have peer's cert */ byte usingPSK_cipher; /* whether we're using psk as cipher */ byte sendAlertState; /* nonblocking resume */ diff --git a/src/internal.c b/src/internal.c index 929b3687f..fe349cc04 100644 --- a/src/internal.c +++ b/src/internal.c @@ -335,6 +335,7 @@ int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method) ctx->haveDH = 0; ctx->haveNTRU = 0; /* start off */ ctx->haveECDSA = 0; /* start off */ + ctx->haveStaticECC = 0; /* start off */ ctx->heap = ctx; /* defaults to self */ #ifndef NO_PSK ctx->havePSK = 0; @@ -444,6 +445,9 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, int tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR; int haveRSA = 1; + /* TAO temp fix */ + int haveStaticECC = 1; + (void)tls; /* shut up compiler */ (void)haveDH; (void)havePSK; @@ -495,6 +499,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + if (tls && haveECDSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA; + } +#endif + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA if (tls && haveECDSA) { suites->suites[idx++] = ECC_BYTE; @@ -755,7 +766,8 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) ssl->options.haveDH = 0; ssl->options.haveNTRU = ctx->haveNTRU; ssl->options.haveECDSA = ctx->haveECDSA; - ssl->options.havePeerCert = 0; + ssl->options.haveStaticECC = ctx->haveStaticECC; + ssl->options.havePeerCert = 0; ssl->options.usingPSK_cipher = 0; ssl->options.sendAlertState = 0; #ifndef NO_PSK @@ -3544,8 +3556,13 @@ const char* const cipher_names[] = #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - "DHE-RSA-AES256-SHA256" + "DHE-RSA-AES256-SHA256", #endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + "ECDH-ECDSA-AES256-SHA" +#endif + }; @@ -3663,8 +3680,13 @@ int cipher_name_idx[] = #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, #endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA +#endif + }; @@ -4068,6 +4090,7 @@ int SetCipherList(Suites* s, const char* list) return ret; } else + CYASSL_MSG("Unsupported cipher suite, DoServerHello"); return UNSUPPORTED_SUITE; } else { @@ -4449,14 +4472,24 @@ int SetCipherList(Suites* s, const char* list) #endif /* HAVE_NTRU */ #ifdef HAVE_ECC } else if (ssl->specs.kea == ecc_diffie_hellman_kea) { - ecc_key myKey; - word32 size = sizeof(encSecret); + ecc_key myKey; + ecc_key* peerKey = &myKey; + word32 size = sizeof(encSecret); - if (!ssl->peerEccKeyPresent || !ssl->peerEccKey.dp) - return NO_PEER_KEY; + if (ssl->specs.static_ecdh) { + /* TODO: EccDsa is really fixed Ecc change naming */ + if (!ssl->peerEccDsaKeyPresent || !ssl->peerEccDsaKey.dp) + return NO_PEER_KEY; + peerKey = &ssl->peerEccDsaKey; + } + else { + if (!ssl->peerEccKeyPresent || !ssl->peerEccKey.dp) + return NO_PEER_KEY; + peerKey = &ssl->peerEccKey; + } ecc_init(&myKey); - ret = ecc_make_key(&ssl->rng, ssl->peerEccKey.dp->size, &myKey); + ret = ecc_make_key(&ssl->rng, peerKey->dp->size, &myKey); if (ret != 0) return ECC_MAKEKEY_ERROR; @@ -4469,7 +4502,7 @@ int SetCipherList(Suites* s, const char* list) ret = ECC_EXPORT_ERROR; else { size = sizeof(ssl->arrays.preMasterSecret); - ret = ecc_shared_secret(&myKey, &ssl->peerEccKey, + ret = ecc_shared_secret(&myKey, peerKey, ssl->arrays.preMasterSecret, &size); if (ret != 0) ret = ECC_SHARED_ERROR; @@ -4880,9 +4913,15 @@ int SetCipherList(Suites* s, const char* list) RsaKey rsaKey; ecc_key dsaKey; + if (ssl->specs.static_ecdh) { + CYASSL_MSG("Using Static ECDH, not sending ServerKeyExchagne"); + return 0; + } + /* curve type, named curve, length(1) */ length = ENUM_LEN + CURVE_LEN + ENUM_LEN; /* pub key size */ + CYASSL_MSG("Using ephemeral ECDH"); if (ecc_export_x963(&ssl->eccTempKey, exportBuf, &expSz) != 0) return ECC_EXPORT_ERROR; length += expSz; @@ -5386,8 +5425,10 @@ int SetCipherList(Suites* s, const char* list) ssl->options.resuming = 0; break; /* session lookup failed */ } - if (MatchSuite(ssl, &clSuites) < 0) + if (MatchSuite(ssl, &clSuites) < 0) { + CYASSL_MSG("Unsupported cipher suite, OldClientHello"); return UNSUPPORTED_SUITE; + } RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN); if (ssl->options.tls) @@ -5540,8 +5581,10 @@ int SetCipherList(Suites* s, const char* list) CYASSL_MSG("Session lookup for resume failed"); break; /* session lookup failed */ } - if (MatchSuite(ssl, &clSuites) < 0) + if (MatchSuite(ssl, &clSuites) < 0) { + CYASSL_MSG("Unsupported cipher suite, ClientHello"); return UNSUPPORTED_SUITE; + } RNG_GenerateBlock(&ssl->rng, ssl->arrays.serverRandom, RAN_LEN); if (ssl->options.tls) @@ -5839,7 +5882,20 @@ int SetCipherList(Suites* s, const char* list) ssl->peerEccKeyPresent = 1; size = sizeof(ssl->arrays.preMasterSecret); - ret = ecc_shared_secret(&ssl->eccTempKey, &ssl->peerEccKey, + if (ssl->specs.static_ecdh) { + ecc_key staticKey; + word32 i = 0; + + ecc_init(&staticKey); + ret = EccPrivateKeyDecode(ssl->buffers.key.buffer, &i, + &staticKey, ssl->buffers.key.length); + if (ret == 0) + ret = ecc_shared_secret(&staticKey, &ssl->peerEccKey, + ssl->arrays.preMasterSecret, &size); + ecc_free(&staticKey); + } + else + ret = ecc_shared_secret(&ssl->eccTempKey, &ssl->peerEccKey, ssl->arrays.preMasterSecret, &size); if (ret != 0) return ECC_SHARED_ERROR; diff --git a/src/keys.c b/src/keys.c index 31f3a7309..917524956 100644 --- a/src/keys.c +++ b/src/keys.c @@ -48,6 +48,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.sig_algo = rsa_sa_algo; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -64,6 +65,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.sig_algo = rsa_sa_algo; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = DES3_KEY_SIZE; ssl->specs.block_size = DES_BLOCK_SIZE; ssl->specs.iv_size = DES_IV_SIZE; @@ -80,6 +82,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.sig_algo = rsa_sa_algo; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = RC4_KEY_SIZE; ssl->specs.iv_size = 0; ssl->specs.block_size = 0; @@ -96,6 +99,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.sig_algo = ecc_dsa_sa_algo; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = DES3_KEY_SIZE; ssl->specs.block_size = DES_BLOCK_SIZE; ssl->specs.iv_size = DES_IV_SIZE; @@ -112,6 +116,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.sig_algo = ecc_dsa_sa_algo; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = RC4_KEY_SIZE; ssl->specs.iv_size = 0; ssl->specs.block_size = 0; @@ -128,6 +133,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.sig_algo = rsa_sa_algo; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -144,6 +150,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.sig_algo = ecc_dsa_sa_algo; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -160,6 +167,24 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.sig_algo = ecc_dsa_sa_algo; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -168,6 +193,7 @@ int SetCipherSpecs(CYASSL* ssl) #endif default: + CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC"); return UNSUPPORTED_SUITE; } /* switch */ } /* if */ @@ -183,6 +209,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = rsa_kea; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = RC4_KEY_SIZE; ssl->specs.iv_size = 0; ssl->specs.block_size = 0; @@ -198,6 +225,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = ntru_kea; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = RC4_KEY_SIZE; ssl->specs.iv_size = 0; ssl->specs.block_size = 0; @@ -213,6 +241,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = rsa_kea; ssl->specs.hash_size = MD5_DIGEST_SIZE; ssl->specs.pad_size = PAD_MD5; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = RC4_KEY_SIZE; ssl->specs.iv_size = 0; ssl->specs.block_size = 0; @@ -228,6 +257,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = rsa_kea; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = DES3_KEY_SIZE; ssl->specs.block_size = DES_BLOCK_SIZE; ssl->specs.iv_size = DES_IV_SIZE; @@ -243,6 +273,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = ntru_kea; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = DES3_KEY_SIZE; ssl->specs.block_size = DES_BLOCK_SIZE; ssl->specs.iv_size = DES_IV_SIZE; @@ -258,6 +289,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = rsa_kea; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -273,6 +305,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = rsa_kea; ssl->specs.hash_size = SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -288,6 +321,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = ntru_kea; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -303,6 +337,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = rsa_kea; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -318,6 +353,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = rsa_kea; ssl->specs.hash_size = SHA256_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -333,6 +369,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = ntru_kea; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -348,6 +385,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = psk_kea; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -364,6 +402,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = psk_kea; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -381,6 +420,7 @@ int SetCipherSpecs(CYASSL* ssl) 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 = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -397,6 +437,7 @@ int SetCipherSpecs(CYASSL* ssl) 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 = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -413,6 +454,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.sig_algo = rsa_sa_algo; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -429,6 +471,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.sig_algo = rsa_sa_algo; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; ssl->specs.iv_size = AES_IV_SIZE; @@ -444,6 +487,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = rsa_kea; ssl->specs.hash_size = MD5_DIGEST_SIZE; ssl->specs.pad_size = PAD_MD5; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = HC_128_KEY_SIZE; ssl->specs.block_size = 0; ssl->specs.iv_size = HC_128_IV_SIZE; @@ -459,6 +503,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = rsa_kea; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = HC_128_KEY_SIZE; ssl->specs.block_size = 0; ssl->specs.iv_size = HC_128_IV_SIZE; @@ -474,6 +519,7 @@ int SetCipherSpecs(CYASSL* ssl) ssl->specs.kea = rsa_kea; ssl->specs.hash_size = SHA_DIGEST_SIZE; ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; ssl->specs.key_size = RABBIT_KEY_SIZE; ssl->specs.block_size = 0; ssl->specs.iv_size = RABBIT_IV_SIZE; @@ -482,7 +528,7 @@ int SetCipherSpecs(CYASSL* ssl) #endif default: - CYASSL_MSG("Unsupported cipher suite"); + CYASSL_MSG("Unsupported cipher suite, SetCipherSpecs"); return UNSUPPORTED_SUITE; } /* switch */ } /* if ECC / Normal suites else */ diff --git a/src/ssl.c b/src/ssl.c index b66db6d95..1ff49f4c3 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -996,10 +996,37 @@ int AddCA(CYASSL_CTX* ctx, buffer der, int type) return SSL_BAD_FILE; } ecc_free(&key); - ctx->haveECDSA = 1; + ctx->haveStaticECC = 1; + if (ssl) + ssl->options.haveStaticECC = 1; } #endif /* HAVE_ECC */ } + else if (type == CERT_TYPE) { + int ret; + DecodedCert cert; + + CYASSL_MSG("Checking cert signature type"); + InitDecodedCert(&cert, der.buffer, der.length, ctx->heap); + + if ((ret = DecodeToKey(&cert, 0)) < 0) { + CYASSL_MSG("Decode to key failed"); + return SSL_BAD_FILE; + } + switch (cert.signatureOID) { + case CTC_SHAwECDSA: + case CTC_SHA256wECDSA: + case CTC_SHA384wECDSA: + case CTC_SHA512wECDSA: + CYASSL_MSG("ECDSA cert signature"); + ctx->haveECDSA = 1; + if (ssl) + ssl->options.haveECDSA = 1; + break; + } + + FreeDecodedCert(&cert); + } return SSL_SUCCESS; } @@ -4365,6 +4392,9 @@ int CyaSSL_set_compression(CYASSL* ssl) return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA : return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; + + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA : + return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; default: return "NONE"; } From 97e6a637e6486ea0c09999b9fdb8bd367b7debf9 Mon Sep 17 00:00:00 2001 From: toddouska Date: Thu, 3 May 2012 09:57:17 -0700 Subject: [PATCH 2/6] rest of ECDH suites --- cyassl/internal.h | 19 ++++++- src/internal.c | 131 +++++++++++++++++++++++++++++++++++++++++----- src/keys.c | 119 +++++++++++++++++++++++++++++++++++++++++ src/ssl.c | 26 +++++++-- 4 files changed, 274 insertions(+), 21 deletions(-) diff --git a/cyassl/internal.h b/cyassl/internal.h index 2bfe15346..f1a8b0670 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -170,15 +170,24 @@ void c32to24(word32 in, word24 out); #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA #endif #if !defined(NO_RC4) #define BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA #define BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + + #define BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + #define BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA #endif #if !defined(NO_DES3) #define BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA #define BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + + #define BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + #define BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA #endif #endif @@ -238,8 +247,14 @@ enum { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0x08, /* static ECDH, first byte is 0xC0 (ECC_BYTE) */ + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0x0F, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0x0E, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0x05, - + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0x04, + TLS_ECDH_RSA_WITH_RC4_128_SHA = 0x0C, + TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0x02, + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0D, + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0x03, /* CyaSSL extension - eSTREAM */ TLS_RSA_WITH_HC_128_CBC_MD5 = 0xFB, @@ -550,7 +565,7 @@ typedef struct Suites { CYASSL_LOCAL -void InitSuites(Suites*, ProtocolVersion, byte, byte, byte, byte, int); +void InitSuites(Suites*, ProtocolVersion, byte, byte, byte, byte, byte, int); CYASSL_LOCAL int SetCipherList(Suites*, const char* list); diff --git a/src/internal.c b/src/internal.c index fe349cc04..01a5e83df 100644 --- a/src/internal.c +++ b/src/internal.c @@ -373,14 +373,15 @@ int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method) /* server can turn on by loading key */ #endif #ifdef HAVE_ECC - if (method->side == CLIENT_END) - ctx->haveECDSA = 1; /* always on cliet side */ - /* server can turn on by loading key */ + if (method->side == CLIENT_END) { + ctx->haveECDSA = 1; /* always on cliet side */ + ctx->haveStaticECC = 1; /* server can turn on by loading key */ + } #endif ctx->suites.setSuites = 0; /* user hasn't set yet */ /* remove DH later if server didn't set, add psk later */ InitSuites(&ctx->suites, method->version, TRUE, FALSE, ctx->haveNTRU, - ctx->haveECDSA, method->side); + ctx->haveECDSA, ctx->haveStaticECC, method->side); ctx->verifyPeer = 0; ctx->verifyNone = 0; ctx->failNoCert = 0; @@ -438,16 +439,13 @@ void FreeSSL_Ctx(CYASSL_CTX* ctx) void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, - byte haveNTRU, byte haveECDSA, int side) + byte haveNTRU, byte haveStaticECC, byte haveECDSA, int side) { word16 idx = 0; int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR; int tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR; int haveRSA = 1; - /* TAO temp fix */ - int haveStaticECC = 1; - (void)tls; /* shut up compiler */ (void)haveDH; (void)havePSK; @@ -513,6 +511,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + if (tls && haveECDSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA; + } +#endif + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA if (tls && haveECDSA) { suites->suites[idx++] = ECC_BYTE; @@ -520,6 +525,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + if (tls && haveECDSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_RC4_128_SHA; + } +#endif + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA if (tls && haveECDSA) { suites->suites[idx++] = ECC_BYTE; @@ -527,6 +539,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + if (tls && haveECDSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA; + } +#endif + #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA if (tls && haveRSA) { suites->suites[idx++] = ECC_BYTE; @@ -534,6 +553,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + if (tls && haveRSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA; + } +#endif + #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA if (tls && haveRSA) { suites->suites[idx++] = ECC_BYTE; @@ -541,6 +567,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + if (tls && haveRSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA; + } +#endif + #ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA if (tls && haveRSA) { suites->suites[idx++] = ECC_BYTE; @@ -548,6 +581,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + if (tls && haveRSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_RC4_128_SHA; + } +#endif + #ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA if (tls && haveRSA) { suites->suites[idx++] = ECC_BYTE; @@ -555,6 +595,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, } #endif +#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + if (tls && haveRSA && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA; + } +#endif + #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 if (tls1_2 && haveDH && haveRSA) { suites->suites[idx++] = 0; @@ -854,11 +901,11 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) if (ssl->options.side == SERVER_END) InitSuites(&ssl->suites, ssl->version,ssl->options.haveDH, havePSK, ssl->options.haveNTRU, ssl->options.haveECDSA, - ssl->ctx->method->side); + ssl->options.haveStaticECC, ssl->ctx->method->side); else InitSuites(&ssl->suites, ssl->version, TRUE, havePSK, ssl->options.haveNTRU, ssl->options.haveECDSA, - ssl->ctx->method->side); + ssl->options.haveStaticECC, ssl->ctx->method->side); #ifdef SESSION_CERTS @@ -3559,8 +3606,36 @@ const char* const cipher_names[] = "DHE-RSA-AES256-SHA256", #endif +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + "ECDH-RSA-AES128-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + "ECDH-RSA-AES256-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + "ECDH-ECDSA-AES128-SHA", +#endif + #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - "ECDH-ECDSA-AES256-SHA" + "ECDH-ECDSA-AES256-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + "ECDH-RSA-RC4-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + "ECDH-RSA-DES-CBC3-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + "ECDH-ECDSA-RC4-SHA", +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + "ECDH-ECDSA-DES-CBC3-SHA" #endif }; @@ -3683,8 +3758,36 @@ int cipher_name_idx[] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, #endif +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, +#endif + #ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + TLS_ECDH_RSA_WITH_RC4_128_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + TLS_ECDH_ECDSA_WITH_RC4_128_SHA, +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA #endif }; @@ -5362,7 +5465,7 @@ int SetCipherList(Suites* s, const char* list) InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, havePSK, ssl->options.haveNTRU, ssl->options.haveECDSA, - ssl->ctx->method->side); + ssl->options.haveStaticECC, ssl->ctx->method->side); } /* suite size */ @@ -5492,7 +5595,7 @@ int SetCipherList(Suites* s, const char* list) #endif InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, havePSK, ssl->options.haveNTRU, ssl->options.haveECDSA, - ssl->ctx->method->side); + ssl->options.haveStaticECC, ssl->ctx->method->side); } /* random */ XMEMCPY(ssl->arrays.clientRandom, input + i, RAN_LEN); diff --git a/src/keys.c b/src/keys.c index 917524956..3fb4c8a60 100644 --- a/src/keys.c +++ b/src/keys.c @@ -56,6 +56,23 @@ int SetCipherSpecs(CYASSL* ssl) break; #endif +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + #ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA : ssl->specs.bulk_cipher_algorithm = triple_des; @@ -73,6 +90,23 @@ int SetCipherSpecs(CYASSL* ssl) break; #endif +#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + #ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA case TLS_ECDHE_RSA_WITH_RC4_128_SHA : ssl->specs.bulk_cipher_algorithm = rc4; @@ -90,6 +124,23 @@ int SetCipherSpecs(CYASSL* ssl) break; #endif +#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + case TLS_ECDH_RSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA : ssl->specs.bulk_cipher_algorithm = triple_des; @@ -107,6 +158,23 @@ int SetCipherSpecs(CYASSL* ssl) break; #endif +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : ssl->specs.bulk_cipher_algorithm = rc4; @@ -124,6 +192,23 @@ int SetCipherSpecs(CYASSL* ssl) break; #endif +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA : ssl->specs.bulk_cipher_algorithm = aes; @@ -141,6 +226,23 @@ int SetCipherSpecs(CYASSL* ssl) break; #endif +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA : ssl->specs.bulk_cipher_algorithm = aes; @@ -158,6 +260,23 @@ int SetCipherSpecs(CYASSL* ssl) break; #endif +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA : ssl->specs.bulk_cipher_algorithm = aes; diff --git a/src/ssl.c b/src/ssl.c index 1ff49f4c3..705cd2f60 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -227,7 +227,7 @@ int CyaSSL_SetTmpDH(CYASSL* ssl, const unsigned char* p, int pSz, #endif InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, havePSK, ssl->options.haveNTRU, ssl->options.haveECDSA, - ssl->ctx->method->side); + ssl->options.haveStaticECC, ssl->ctx->method->side); CYASSL_LEAVE("CyaSSL_SetTmpDH", 0); return 0; @@ -1660,7 +1660,7 @@ int CyaSSL_set_cipher_list(CYASSL* ssl, const char* list) InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, havePSK, ssl->options.haveNTRU, ssl->options.haveECDSA, - ssl->ctx->method->side); + ssl->options.haveStaticECC, ssl->ctx->method->side); return SSL_SUCCESS; } @@ -2676,7 +2676,8 @@ int CyaSSL_set_compression(CYASSL* ssl) ssl->options.client_psk_cb = cb; InitSuites(&ssl->suites, ssl->version,TRUE,TRUE, ssl->options.haveNTRU, - ssl->options.haveECDSA, ssl->ctx->method->side); + ssl->options.haveECDSA, ssl->options.haveStaticECC, + ssl->ctx->method->side); } @@ -2697,7 +2698,7 @@ int CyaSSL_set_compression(CYASSL* ssl) InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, TRUE, ssl->options.haveNTRU, ssl->options.haveECDSA, - ssl->ctx->method->side); + ssl->optoins.haveStaticECC, ssl->ctx->method->side); } @@ -2931,7 +2932,7 @@ int CyaSSL_set_compression(CYASSL* ssl) #endif InitSuites(&ssl->suites, ssl->version, ssl->options.haveDH, havePSK, ssl->options.haveNTRU, ssl->options.haveECDSA, - ssl->ctx->method->side); + ssl->options.haveStaticECC, ssl->ctx->method->side); } @@ -4393,8 +4394,23 @@ int CyaSSL_set_compression(CYASSL* ssl) case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA : return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA : + return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA : + return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA : + return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA : return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; + case TLS_ECDH_RSA_WITH_RC4_128_SHA : + return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA : + return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA : + return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA : + return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; + default: return "NONE"; } From 686a7395b1d197addcb74a1ee1ef4124c258c974 Mon Sep 17 00:00:00 2001 From: toddouska Date: Thu, 3 May 2012 10:04:18 -0700 Subject: [PATCH 3/6] fix potential ecc memory leak in ServerKeyExchange --- src/internal.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 01a5e83df..1d9633096 100644 --- a/src/internal.c +++ b/src/internal.c @@ -5147,6 +5147,7 @@ int SetCipherList(Suites* s, const char* list) ret = RsaSSL_Sign(signBuffer, signSz, output + idx, sigSz, &rsaKey, &ssl->rng); FreeRsaKey(&rsaKey); + ecc_free(&dsaKey); if (ret > 0) ret = 0; /* reset on success */ else @@ -5155,9 +5156,10 @@ int SetCipherList(Suites* s, const char* list) else if (ssl->specs.sig_algo == ecc_dsa_sa_algo) { word32 sz = sigSz; - FreeRsaKey(&rsaKey); ret = ecc_sign_hash(&hash[MD5_DIGEST_SIZE], SHA_DIGEST_SIZE, output + idx, &sz, &ssl->rng, &dsaKey); + FreeRsaKey(&rsaKey); + ecc_free(&dsaKey); if (ret < 0) return ret; } } From ccabe829cbe334947005d6e74c3c2ef96cb29ec5 Mon Sep 17 00:00:00 2001 From: toddouska Date: Thu, 3 May 2012 10:38:10 -0700 Subject: [PATCH 4/6] v2.1.3 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 0c8e2c370..1f3e8b5e9 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ # # -AC_INIT([cyassl],[2.1.2],[http://www.yassl.com]) +AC_INIT([cyassl],[2.1.3],[http://www.yassl.com]) AC_CONFIG_AUX_DIR(config) From 37e994f4a2eea976bb69b140b6d27f0f9fb412ac Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 3 May 2012 14:48:45 -0600 Subject: [PATCH 5/6] exclude CyaSSL_connect_cert when using NO_CYASSL_CLIENT --- src/ssl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ssl.c b/src/ssl.c index 705cd2f60..16ceb4583 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -395,6 +395,7 @@ int CyaSSL_CTX_set_group_messages(CYASSL_CTX* ctx) } +#ifndef NO_CYASSL_CLIENT /* connect enough to get peer cert chain */ int CyaSSL_connect_cert(CYASSL* ssl) { @@ -409,6 +410,7 @@ int CyaSSL_connect_cert(CYASSL* ssl) return ret; } +#endif /* trun on handshake group messages for ssl object */ From 4fe81df45c98985cbf2367cefd836a3fcc3a4829 Mon Sep 17 00:00:00 2001 From: toddouska Date: Thu, 3 May 2012 18:07:31 -0700 Subject: [PATCH 6/6] basic extneral cert manager added --- ctaocrypt/src/asn.c | 10 +- cyassl/ctaocrypt/asn.h | 6 +- cyassl/ctaocrypt/types.h | 3 +- cyassl/error.h | 5 +- cyassl/internal.h | 18 +++- cyassl/ssl.h | 9 ++ src/internal.c | 24 +++-- src/ssl.c | 207 +++++++++++++++++++++++++++++++++------ 8 files changed, 225 insertions(+), 57 deletions(-) diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index 4d99584d1..dc74b909f 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -2017,13 +2017,12 @@ static int ConfirmSignature(DecodedCert* cert, const byte* key, word32 keySz, } -int ParseCert(DecodedCert* cert, int type, int verify, - Signer* signers) +int ParseCert(DecodedCert* cert, int type, int verify, void* cm) { int ret; char* ptr; - ret = ParseCertRelative(cert, type, verify, signers); + ret = ParseCertRelative(cert, type, verify, cm); if (ret < 0) return ret; @@ -2144,8 +2143,7 @@ static void IsCa(DecodedCert* cert) #endif -int ParseCertRelative(DecodedCert* cert, int type, int verify, - Signer* signers) +int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) { word32 confirmOID; int ret; @@ -2181,7 +2179,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, return ASN_SIG_OID_E; if (verify && type != CA_TYPE) { - Signer* ca = GetCA(signers, cert->issuerHash); + Signer* ca = GetCA(cm, cert->issuerHash); CYASSL_MSG("About to verify certificate signature"); if (ca) { diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index 148e71ce3..b17bed755 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -262,11 +262,9 @@ struct Signer { CYASSL_TEST_API void InitDecodedCert(DecodedCert*, byte*, word32, void*); CYASSL_TEST_API void FreeDecodedCert(DecodedCert*); -CYASSL_TEST_API int ParseCert(DecodedCert*, int type, int verify, - Signer* signer); +CYASSL_TEST_API int ParseCert(DecodedCert*, int type, int verify, void* cm); -CYASSL_LOCAL int ParseCertRelative(DecodedCert*, int type, int verify, - Signer* signer); +CYASSL_LOCAL int ParseCertRelative(DecodedCert*, int type, int verify,void* cm); CYASSL_LOCAL int DecodeToKey(DecodedCert*, int verify); CYASSL_LOCAL word32 EncodeSignature(byte* out, const byte* digest, word32 digSz, diff --git a/cyassl/ctaocrypt/types.h b/cyassl/ctaocrypt/types.h index 9e1c829bf..441be4105 100644 --- a/cyassl/ctaocrypt/types.h +++ b/cyassl/ctaocrypt/types.h @@ -200,7 +200,8 @@ enum { DYNAMIC_TYPE_SSL = 17, DYNAMIC_TYPE_CTX = 18, DYNAMIC_TYPE_WRITEV = 19, - DYNAMIC_TYPE_OPENSSL = 20 + DYNAMIC_TYPE_OPENSSL = 20, + DYNAMIC_TYPE_CERT_MANAGER = 21 }; /* stack protection */ diff --git a/cyassl/error.h b/cyassl/error.h index f22c56865..70eefcd40 100644 --- a/cyassl/error.h +++ b/cyassl/error.h @@ -91,11 +91,12 @@ enum CyaSSL_ErrorCodes { BAD_MUTEX_ERROR = -256, /* Bad mutex */ NOT_CA_ERROR = -257, /* Not a CA cert error */ BAD_PATH_ERROR = -258, /* Bad path for opendir */ + BAD_CERT_MANAGER_ERROR = -259, /* Bad Cert Manager */ /* add strings to SetErrorString !!!!! */ /* begin negotiation parameter errors */ - UNSUPPORTED_SUITE = -260, /* unsupported cipher suite */ - MATCH_SUITE_ERROR = -261 /* can't match cipher suite */ + UNSUPPORTED_SUITE = -270, /* unsupported cipher suite */ + MATCH_SUITE_ERROR = -271 /* can't match cipher suite */ /* end negotiation parameter errors only 10 for now */ /* add strings to SetErrorString !!!!! */ }; diff --git a/cyassl/internal.h b/cyassl/internal.h index f1a8b0670..79913cb06 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -619,6 +619,15 @@ CYASSL_LOCAL int LockMutex(CyaSSL_Mutex*); CYASSL_LOCAL int UnLockMutex(CyaSSL_Mutex*); +/* CyaSSL Certificate Manager */ +struct CYASSL_CERT_MANAGER { + Signer* caList; /* the CA signer list */ + CyaSSL_Mutex caLock; /* CA list lock */ + CallbackCACache caCacheCallback; /* CA cache addition callback */ + void* heap; /* heap helper */ +}; + + /* CyaSSL context type */ struct CYASSL_CTX { CYASSL_METHOD* method; @@ -630,7 +639,7 @@ struct CYASSL_CTX { buffer privateKey; buffer serverDH_P; buffer serverDH_G; - Signer* caList; /* CYASSL_CTX owns this, SSL will reference */ + CYASSL_CERT_MANAGER* cm; /* our cert manager, ctx owns SSL will use */ Suites suites; void* heap; /* for user memory overrides */ byte verifyPeer; @@ -648,7 +657,6 @@ struct CYASSL_CTX { byte groupMessages; /* group handshake messages before sending */ CallbackIORecv CBIORecv; CallbackIOSend CBIOSend; - CallbackCACache caCacheCallback; /* CA cache addition callback */ VerifyCallback verifyCallback; /* cert verification callback */ word32 timeout; /* session timeout */ #ifdef HAVE_ECC @@ -680,9 +688,9 @@ CYASSL_LOCAL int ProcessOldClientHello(CYASSL* ssl, const byte* input, word32* inOutIdx, word32 inSz, word16 sz); CYASSL_LOCAL -int AddCA(CYASSL_CTX* ctx, buffer der, int force); +int AddCA(CYASSL_CERT_MANAGER* ctx, buffer der, int type, int verify); CYASSL_LOCAL -int AlreadySigner(CYASSL_CTX* ctx, byte* hash); +int AlreadySigner(CYASSL_CERT_MANAGER* cm, byte* hash); /* All cipher suite related info */ typedef struct CipherSpecs { @@ -1257,7 +1265,7 @@ CYASSL_LOCAL int IsAtLeastTLSv1_2(const CYASSL* ssl); CYASSL_LOCAL void ShrinkInputBuffer(CYASSL* ssl, int forcedFree); CYASSL_LOCAL void ShrinkOutputBuffer(CYASSL* ssl); CYASSL_LOCAL int SendHelloVerifyRequest(CYASSL* ssl); -CYASSL_LOCAL Signer* GetCA(Signer* signers, byte* hash); +CYASSL_LOCAL Signer* GetCA(void* cm, byte* hash); CYASSL_LOCAL void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender); #ifndef NO_TLS diff --git a/cyassl/ssl.h b/cyassl/ssl.h index c850aa09b..3b9c8e42f 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -65,6 +65,7 @@ typedef struct CYASSL_X509 CYASSL_X509; typedef struct CYASSL_X509_NAME CYASSL_X509_NAME; typedef struct CYASSL_X509_CHAIN CYASSL_X509_CHAIN; +typedef struct CYASSL_CERT_MANAGER CYASSL_CERT_MANAGER; /* redeclare guard */ #define CYASSL_TYPES_DEFINED @@ -776,6 +777,14 @@ typedef void (*CallbackCACache)(unsigned char* der, int sz, int type); CYASSL_API void CyaSSL_CTX_SetCACb(CYASSL_CTX*, CallbackCACache); +CYASSL_API CYASSL_CERT_MANAGER* CyaSSL_CertManagerNew(void); +CYASSL_API void CyaSSL_CertManagerFree(CYASSL_CERT_MANAGER*); + +CYASSL_API int CyaSSL_CertManagerLoadCA(CYASSL_CERT_MANAGER*, const char* f, + const char* d); +CYASSL_API int CyaSSL_CertManagerVerify(CYASSL_CERT_MANAGER*, const char* f, + int format); + #ifdef CYASSL_CALLBACKS /* used internally by CyaSSL while OpenSSL types aren't */ diff --git a/src/internal.c b/src/internal.c index 1d9633096..adf5bd1ad 100644 --- a/src/internal.c +++ b/src/internal.c @@ -364,9 +364,8 @@ int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method) #endif ctx->partialWrite = 0; ctx->verifyCallback = 0; - ctx->caCacheCallback = 0; - ctx->caList = 0; + ctx->cm = CyaSSL_CertManagerNew(); #ifdef HAVE_NTRU if (method->side == CLIENT_END) ctx->haveNTRU = 1; /* always on cliet side */ @@ -395,6 +394,10 @@ int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method) CYASSL_MSG("Mutex error on CTX init"); return BAD_MUTEX_ERROR; } + if (ctx->cm == NULL) { + CYASSL_MSG("Bad Cert Manager New"); + return BAD_CERT_MANAGER_ERROR; + } return 0; } @@ -409,7 +412,7 @@ void SSL_CtxResourceFree(CYASSL_CTX* ctx) XFREE(ctx->certChain.buffer, ctx->heap, DYNAMIC_TYPE_CERT); XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD); - FreeSigners(ctx->caList, ctx->heap); + CyaSSL_CertManagerFree(ctx->cm); } @@ -858,7 +861,7 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) ssl->options.certOnly = 0; ssl->options.groupMessages = ctx->groupMessages; - /* ctx still owns certificate, certChain, key, dh, and caList buffers */ + /* ctx still owns certificate, certChain, key, dh, and cm */ ssl->buffers.certificate = ctx->certificate; ssl->buffers.certChain = ctx->certChain; ssl->buffers.key = ctx->privateKey; @@ -1613,7 +1616,7 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx) InitDecodedCert(&dCert, myCert.buffer, myCert.length, ssl->heap); ret = ParseCertRelative(&dCert, CERT_TYPE, !ssl->options.verifyNone, - ssl->ctx->caList); + ssl->ctx->cm); if (ret == 0 && dCert.isCA == 0) { CYASSL_MSG("Chain cert is not a CA, not adding as one"); (void)ret; @@ -1622,7 +1625,7 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx) CYASSL_MSG("Chain cert not verified by option, not adding as CA"); (void)ret; } - else if (ret == 0 && !AlreadySigner(ssl->ctx, dCert.subjectHash)) { + else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, dCert.subjectHash)) { buffer add; add.length = myCert.length; add.buffer = (byte*)XMALLOC(myCert.length, ssl->heap, @@ -1633,7 +1636,8 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx) return MEMORY_E; XMEMCPY(add.buffer, myCert.buffer, myCert.length); - ret = AddCA(ssl->ctx, add, CYASSL_CHAIN_CA); + ret = AddCA(ssl->ctx->cm, add, CYASSL_CHAIN_CA, + ssl->ctx->verifyPeer); if (ret == 1) ret = 0; /* SSL_SUCCESS for external */ } else if (ret != 0) { @@ -1662,7 +1666,7 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx) InitDecodedCert(&dCert, myCert.buffer, myCert.length, ssl->heap); ret = ParseCertRelative(&dCert, CERT_TYPE, !ssl->options.verifyNone, - ssl->ctx->caList); + ssl->ctx->cm); if (ret == 0) { CYASSL_MSG("Verified Peer's cert"); fatal = 0; @@ -3482,6 +3486,10 @@ void SetErrorString(int error, char* str) XSTRNCPY(str, "Bad path for opendir error", max); break; + case BAD_CERT_MANAGER_ERROR: + XSTRNCPY(str, "Bad Cert Manager error", max); + break; + default : XSTRNCPY(str, "unknown error number", max); } diff --git a/src/ssl.c b/src/ssl.c index 705cd2f60..182a08548 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -362,6 +362,45 @@ void CyaSSL_ERR_error_string_n(unsigned long e, char* buf, unsigned long len) } +CYASSL_CERT_MANAGER* CyaSSL_CertManagerNew(void) +{ + CYASSL_CERT_MANAGER* cm = NULL; + + CYASSL_ENTER("CyaSSL_CertManagerNew"); + + cm = (CYASSL_CERT_MANAGER*) XMALLOC(sizeof(CYASSL_CERT_MANAGER), 0, + DYNAMIC_TYPE_CERT_MANAGER); + if (cm) { + cm->caList = NULL; + cm->heap = NULL; + cm->caCacheCallback = NULL; + + if (InitMutex(&cm->caLock) != 0) { + CYASSL_MSG("Bad mutex init"); + CyaSSL_CertManagerFree(cm); + return NULL; + } + } + + return cm; +} + + +void CyaSSL_CertManagerFree(CYASSL_CERT_MANAGER* cm) +{ + CYASSL_ENTER("CyaSSL_CertManagerFree"); + + if (cm) { + FreeSigners(cm->caList, NULL); + FreeMutex(&cm->caLock); + XFREE(cm, NULL, DYNAMIC_TYPE_CERT_MANAGER); + } + +} + + + + #ifndef NO_FILESYSTEM void CyaSSL_ERR_print_errors_fp(FILE* fp, int err) @@ -423,17 +462,15 @@ int CyaSSL_set_group_messages(CYASSL* ssl) } -static CyaSSL_Mutex ca_mutex; /* CA signers mutex */ - /* does CA already exist on signer list */ -int AlreadySigner(CYASSL_CTX* ctx, byte* hash) +int AlreadySigner(CYASSL_CERT_MANAGER* cm, byte* hash) { Signer* signers; int ret = 0; - if (LockMutex(&ca_mutex) != 0) + if (LockMutex(&cm->caLock) != 0) return ret; - signers = ctx->caList; + signers = cm->caList; while (signers) { if (XMEMCMP(hash, signers->hash, SHA_DIGEST_SIZE) == 0) { ret = 1; @@ -441,18 +478,25 @@ int AlreadySigner(CYASSL_CTX* ctx, byte* hash) } signers = signers->next; } - UnLockMutex(&ca_mutex); + UnLockMutex(&cm->caLock); return ret; } /* return CA if found, otherwise NULL */ -Signer* GetCA(Signer* signers, byte* hash) +Signer* GetCA(void* vp, byte* hash) { - Signer* ret = 0; + CYASSL_CERT_MANAGER* cm = (CYASSL_CERT_MANAGER*)vp; + Signer* ret = NULL; + Signer* signers; - if (LockMutex(&ca_mutex) != 0) + if (cm == NULL) + return NULL; + + signers = cm->caList; + + if (LockMutex(&cm->caLock) != 0) return ret; while (signers) { if (XMEMCMP(hash, signers->hash, SHA_DIGEST_SIZE) == 0) { @@ -461,7 +505,7 @@ Signer* GetCA(Signer* signers, byte* hash) } signers = signers->next; } - UnLockMutex(&ca_mutex); + UnLockMutex(&cm->caLock); return ret; } @@ -470,28 +514,28 @@ Signer* GetCA(Signer* signers, byte* hash) /* owns der, internal now uses too */ /* type flag ids from user or from chain received during verify don't allow chain ones to be added w/o isCA extension */ -int AddCA(CYASSL_CTX* ctx, buffer der, int type) +int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify) { int ret; DecodedCert cert; Signer* signer = 0; CYASSL_MSG("Adding a CA"); - InitDecodedCert(&cert, der.buffer, der.length, ctx->heap); - ret = ParseCert(&cert, CA_TYPE, ctx->verifyPeer, 0); + InitDecodedCert(&cert, der.buffer, der.length, cm->heap); + ret = ParseCert(&cert, CA_TYPE, verify, cm); CYASSL_MSG(" Parsed new CA"); if (ret == 0 && cert.isCA == 0 && type != CYASSL_USER_CA) { CYASSL_MSG(" Can't add as CA if not actually one"); ret = NOT_CA_ERROR; } - else if (ret == 0 && AlreadySigner(ctx, cert.subjectHash)) { + else if (ret == 0 && AlreadySigner(cm, cert.subjectHash)) { CYASSL_MSG(" Already have this CA, not adding again"); (void)ret; } else if (ret == 0) { /* take over signer parts */ - signer = MakeSigner(ctx->heap); + signer = MakeSigner(cm->heap); if (!signer) ret = MEMORY_ERROR; else { @@ -505,17 +549,17 @@ int AddCA(CYASSL_CTX* ctx, buffer der, int type) cert.publicKey = 0; /* don't free here */ cert.subjectCN = 0; - if (LockMutex(&ca_mutex) == 0) { - signer->next = ctx->caList; - ctx->caList = signer; /* takes ownership */ - UnLockMutex(&ca_mutex); - if (ctx->caCacheCallback) - ctx->caCacheCallback(der.buffer, (int)der.length, type); + if (LockMutex(&cm->caLock) == 0) { + signer->next = cm->caList; + cm->caList = signer; /* takes ownership */ + UnLockMutex(&cm->caLock); + if (cm->caCacheCallback) + cm->caCacheCallback(der.buffer, (int)der.length, type); } else { CYASSL_MSG(" CA Mutex Lock failed"); ret = BAD_MUTEX_ERROR; - FreeSigners(signer, ctx->heap); + FreeSigners(signer, cm->heap); } } } @@ -932,7 +976,8 @@ int AddCA(CYASSL_CTX* ctx, buffer der, int type) #endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ if (type == CA_TYPE) - return AddCA(ctx, der, CYASSL_USER_CA); /* takes der over */ + return AddCA(ctx->cm, der, CYASSL_USER_CA, ctx->verifyPeer); + /* takes der over */ else if (type == CERT_TYPE) { if (ssl) { if (ssl->buffers.weOwnCert && ssl->buffers.certificate.buffer) @@ -1201,6 +1246,105 @@ int CyaSSL_CTX_load_verify_locations(CYASSL_CTX* ctx, const char* file, } +/* Verify the ceritficate, 1 for success, < 0 for error */ +int CyaSSL_CertManagerVerify(CYASSL_CERT_MANAGER* cm, const char* fname, + int format) +{ + int ret = SSL_FATAL_ERROR; + int eccKey = 0; /* not used */ + DecodedCert cert; + + byte staticBuffer[FILE_BUFFER_SIZE]; + byte* myBuffer = staticBuffer; + int dynamic = 0; + long sz = 0; + buffer der; + XFILE* file = XFOPEN(fname, "rb"); + + if (!file) return SSL_BAD_FILE; + XFSEEK(file, 0, XSEEK_END); + sz = XFTELL(file); + XREWIND(file); + + der.buffer = NULL; + + if (sz > (long)sizeof(staticBuffer)) { + CYASSL_MSG("Getting dynamic buffer"); + myBuffer = (byte*) XMALLOC(sz, cm->heap, DYNAMIC_TYPE_FILE); + if (myBuffer == NULL) { + XFCLOSE(file); + return SSL_BAD_FILE; + } + dynamic = 1; + } + + if ( (ret = XFREAD(myBuffer, sz, 1, file)) < 0) + ret = SSL_BAD_FILE; + else { + ret = 0; /* ok */ + if (format == SSL_FILETYPE_PEM) { + EncryptedInfo info; + + info.set = 0; + info.ctx = NULL; + info.consumed = 0; + ret = PemToDer(myBuffer, sz, CERT_TYPE, &der, cm->heap, &info, + &eccKey); + InitDecodedCert(&cert, der.buffer, der.length, cm->heap); + + } + else + InitDecodedCert(&cert, myBuffer, sz, cm->heap); + + if (ret == 0) + ret = ParseCertRelative(&cert, CERT_TYPE, 1, cm); + } + + FreeDecodedCert(&cert); + XFREE(der.buffer, cm->heap, DYNAMIC_TYPE_CERT); + XFCLOSE(file); + if (dynamic) XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); + + if (ret == 0) + return SSL_SUCCESS; + return ret; +} + + +/* like load verify locations, 1 for success, < 0 for error */ +int CyaSSL_CertManagerLoadCA(CYASSL_CERT_MANAGER* cm, const char* file, + const char* path) +{ + int ret = SSL_FATAL_ERROR; + CYASSL_CTX* tmp; + + CYASSL_ENTER("CyaSSL_CertManagerLoadCA"); + + if (cm == NULL) { + CYASSL_MSG("No CertManager error"); + return ret; + } + tmp = CyaSSL_CTX_new(CyaSSLv3_client_method()); + + if (tmp == NULL) { + CYASSL_MSG("CTX new failed"); + return ret; + } + + /* for tmp use */ + CyaSSL_CertManagerFree(tmp->cm); + tmp->cm = cm; + + ret = CyaSSL_CTX_load_verify_locations(tmp, file, path); + + /* don't loose our good one */ + tmp->cm = NULL; + CyaSSL_CTX_free(tmp); + + return ret; +} + + #ifdef CYASSL_DER_LOAD /* Add format parameter to allow DER load of CA files */ @@ -1580,8 +1724,8 @@ void CyaSSL_set_verify(CYASSL* ssl, int mode, VerifyCallback vc) /* store context CA Cache addition callback */ void CyaSSL_CTX_SetCACb(CYASSL_CTX* ctx, CallbackCACache cb) { - if (ctx && cb) - ctx->caCacheCallback = cb; + if (ctx && ctx->cm) + ctx->cm->caCacheCallback = cb; } @@ -2126,6 +2270,7 @@ int CyaSSL_set_cipher_list(CYASSL* ssl, const char* list) /* prevent multiple mutex initializations */ static volatile int initRefCount = 0; +static CyaSSL_Mutex count_mutex; /* init ref count mutex */ int CyaSSL_Init(void) { @@ -2138,13 +2283,13 @@ int CyaSSL_Init(void) if (InitMutex(&session_mutex) != 0) ret = BAD_MUTEX_ERROR; #endif - if (InitMutex(&ca_mutex) != 0) + if (InitMutex(&count_mutex) != 0) ret = BAD_MUTEX_ERROR; } if (ret == 0) { - LockMutex(&ca_mutex); + LockMutex(&count_mutex); initRefCount++; - UnLockMutex(&ca_mutex); + UnLockMutex(&count_mutex); } return ret; @@ -2158,13 +2303,13 @@ int CyaSSL_Cleanup(void) CYASSL_ENTER("CyaSSL_Cleanup"); - LockMutex(&ca_mutex); + LockMutex(&count_mutex); release = initRefCount-- == 1; if (initRefCount < 0) initRefCount = 0; - UnLockMutex(&ca_mutex); + UnLockMutex(&count_mutex); if (!release) return ret; @@ -2173,7 +2318,7 @@ int CyaSSL_Cleanup(void) if (FreeMutex(&session_mutex) != 0) ret = BAD_MUTEX_ERROR; #endif - if (FreeMutex(&ca_mutex) != 0) + if (FreeMutex(&count_mutex) != 0) ret = BAD_MUTEX_ERROR; return ret;