From 45d26876c88b02028e28d070e0b2864d02055bd4 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 5 Dec 2016 11:36:53 -0800 Subject: [PATCH] Moved wolfSSL_GetEccKey logic to internal.c and use only for PK_CALLBACK. Added other ECC key info to the EccSharedSecretCb. Cleanup of the "if (ssl->ctx->EccSharedSecretCb == NULL)" logic to revert indent so changes are minimized. Removed new wolfSSL_GetEccKey API. --- src/internal.c | 366 +++++++++++++++++++++++++++++-------------------- src/ssl.c | 44 ------ wolfssl/ssl.h | 4 +- wolfssl/test.h | 51 +++---- 4 files changed, 249 insertions(+), 216 deletions(-) diff --git a/src/internal.c b/src/internal.c index fde5d6ee6..5e8933532 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2965,6 +2965,62 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, return ret; } +#ifdef HAVE_PK_CALLBACKS + /* Gets ECC key for shared secret callback testing + * Client side: returns peer key + * Server side: returns private key + */ + static int EccGetKey(WOLFSSL* ssl, byte* otherKeyDer, + word32* otherKeySz, word32* otherKeyId) + { + int ret = NO_PEER_KEY; + ecc_key* otherKey = NULL; + + if (ssl == NULL || otherKeyDer == NULL || otherKeySz == NULL) { + return BAD_FUNC_ARG; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->specs.static_ecdh) { + if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent || + !ssl->peerEccDsaKey->dp) { + return NO_PEER_KEY; + } + otherKey = (struct ecc_key*)ssl->peerEccDsaKey; + } + else { + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || + !ssl->peerEccKey->dp) { + return NO_PEER_KEY; + } + otherKey = (struct ecc_key*)ssl->peerEccKey; + } + } + else if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->specs.static_ecdh) { + if (ssl->sigKey == NULL) { + return NO_PRIVATE_KEY; + } + otherKey = (struct ecc_key*)ssl->sigKey; + } + else { + if (!ssl->eccTempKeyPresent) { + return NO_PRIVATE_KEY; + } + otherKey = (struct ecc_key*)ssl->eccTempKey; + } + } + + if (otherKey) { + ret = wc_ecc_export_x963(otherKey, otherKeyDer, otherKeySz); + if (otherKeyId) + *otherKeyId = otherKey->dp->id; + } + + return ret; + } +#endif /* HAVE_PK_CALLBACKS */ + int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen, int side, void* ctx) @@ -2981,8 +3037,15 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->EccSharedSecretCb) { - ret = ssl->ctx->EccSharedSecretCb(ssl, pubKeyDer, pubKeySz, - out, outlen, side, ctx); + byte* otherKeyDer = NULL; + word32 otherKeySz = 0; + word32 otherKeyId = ECC_CURVE_DEF; + + ret = EccGetKey(ssl, otherKeyDer, &otherKeySz, &otherKeyId); + if (ret == 0) { + ret = ssl->ctx->EccSharedSecretCb(ssl, otherKeyDer, otherKeySz, + otherKeyId, pubKeyDer, pubKeySz, out, outlen, side, ctx); + } } else #endif @@ -15452,24 +15515,27 @@ int SendClientKeyExchange(WOLFSSL* ssl) } #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->EccSharedSecretCb == NULL) - #endif - { - /* create private key */ - ssl->sigKey = XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_scke); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, - ssl->devId); - if (ret != 0) { - goto exit_scke; - } - ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, ssl->peerEccKey); + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; } + #endif + + /* create private key */ + ssl->sigKey = XMALLOC(sizeof(ecc_key), + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->sigKey == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); + } + ssl->sigType = DYNAMIC_TYPE_ECC; + + ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_scke; + } + ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, + ssl->peerEccKey); break; #endif /* HAVE_ECC && !NO_PSK */ #ifdef HAVE_NTRU @@ -15482,46 +15548,49 @@ int SendClientKeyExchange(WOLFSSL* ssl) #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { - #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->EccSharedSecretCb == NULL) - #endif - { - ecc_key* peerKey; + ecc_key* peerKey; - if (ssl->specs.static_ecdh) { - /* TODO: EccDsa is really fixed Ecc change naming */ - if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent || - !ssl->peerEccDsaKey->dp) { - ERROR_OUT(NO_PEER_KEY, exit_scke); - } - peerKey = ssl->peerEccDsaKey; - } - else { - if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || - !ssl->peerEccKey->dp) { - ERROR_OUT(NO_PEER_KEY, exit_scke); - } - peerKey = ssl->peerEccKey; - } - if (peerKey == NULL) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + if (ssl->specs.static_ecdh) { + /* TODO: EccDsa is really fixed Ecc change naming */ + if (!ssl->peerEccDsaKey || + !ssl->peerEccDsaKeyPresent || + !ssl->peerEccDsaKey->dp) { ERROR_OUT(NO_PEER_KEY, exit_scke); } - - /* create private key */ - ssl->sigKey = XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_scke); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, - ssl->devId); - if (ret != 0) { - goto exit_scke; - } - ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, peerKey); + peerKey = ssl->peerEccDsaKey; } + else { + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || + !ssl->peerEccKey->dp) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + peerKey = ssl->peerEccKey; + } + if (peerKey == NULL) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + /* create private key */ + ssl->sigKey = XMALLOC(sizeof(ecc_key), + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->sigKey == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); + } + ssl->sigType = DYNAMIC_TYPE_ECC; + + ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_scke; + } + ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, peerKey); break; } #endif /* HAVE_ECC */ @@ -15677,15 +15746,17 @@ int SendClientKeyExchange(WOLFSSL* ssl) *length = MAX_ENCRYPT_SZ; #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->EccSharedSecretCb == NULL) + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } #endif - { - /* Place ECC key in buffer, leaving room for size */ - ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, - output + OPAQUE8_LEN, length); - if (ret != 0) { - ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); - } + + /* Place ECC key in buffer, leaving room for size */ + ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, + output + OPAQUE8_LEN, length); + if (ret != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); } break; } @@ -15708,15 +15779,17 @@ int SendClientKeyExchange(WOLFSSL* ssl) case ecc_diffie_hellman_kea: { #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->EccSharedSecretCb == NULL) + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } #endif - { - /* Place ECC key in buffer, leaving room for size */ - ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, - encSecret + OPAQUE8_LEN, &encSz); - if (ret != 0) { - ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); - } + + /* Place ECC key in buffer, leaving room for size */ + ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, + encSecret + OPAQUE8_LEN, &encSz); + if (ret != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); } break; } @@ -20146,46 +20219,47 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->EccSharedSecretCb == NULL) + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } #endif - { - if (!ssl->specs.static_ecdh && - ssl->eccTempKeyPresent == 0) { - WOLFSSL_MSG("Ecc ephemeral key not made correctly"); - ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); - } - if (ssl->peerEccKey == NULL) { - /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - ERROR_OUT(MEMORY_E, exit_dcke); - } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); - if (ret != 0) { - goto exit_dcke; - } - } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccKey); - ssl->peerEccKeyPresent = 0; - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); - if (ret != 0) { - goto exit_dcke; - } - } - - if (wc_ecc_import_x963_ex(input + idx, length, ssl->peerEccKey, - private_key->dp->id)) { - ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); - } - - ssl->peerEccKeyPresent = 1; + if (!ssl->specs.static_ecdh && + ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG("Ecc ephemeral key not made correctly"); + ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); } + if (ssl->peerEccKey == NULL) { + /* alloc/init on demand */ + ssl->peerEccKey = (ecc_key*)XMALLOC( + sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + ERROR_OUT(MEMORY_E, exit_dcke); + } + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_dcke; + } + } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_dcke; + } + } + + if (wc_ecc_import_x963_ex(input + idx, length, + ssl->peerEccKey, private_key->dp->id)) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + ssl->peerEccKeyPresent = 1; break; } #endif /* HAVE_ECC */ @@ -20287,45 +20361,47 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #ifdef HAVE_PK_CALLBACKS - if (ssl->ctx->EccSharedSecretCb == NULL) - #endif - { - if (ssl->eccTempKeyPresent == 0) { - WOLFSSL_MSG("Ecc ephemeral key not made correctly"); - ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); - } - - if (ssl->peerEccKey == NULL) { - /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - ERROR_OUT(MEMORY_E, exit_dcke); - } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); - if (ret != 0) { - goto exit_dcke; - } - } - else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccKey); - ssl->peerEccKeyPresent = 0; - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); - if (ret != 0) { - goto exit_dcke; - } - } - - if (wc_ecc_import_x963_ex(input + idx, length, - ssl->peerEccKey, ssl->eccTempKey->dp->id)) { - ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); - } - - ssl->peerEccKeyPresent = 1; + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; } + #endif + + if (ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG("Ecc ephemeral key not made correctly"); + ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); + } + + if (ssl->peerEccKey == NULL) { + /* alloc/init on demand */ + ssl->peerEccKey = (ecc_key*)XMALLOC( + sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + ERROR_OUT(MEMORY_E, exit_dcke); + } + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_dcke; + } + } + else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_dcke; + } + } + + if (wc_ecc_import_x963_ex(input + idx, length, + ssl->peerEccKey, ssl->eccTempKey->dp->id)) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + ssl->peerEccKeyPresent = 1; break; } #endif /* HAVE_ECC && !NO_PSK */ diff --git a/src/ssl.c b/src/ssl.c index f82a6cf46..a865bed42 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -959,50 +959,6 @@ int wolfSSL_SetMinEccKey_Sz(WOLFSSL* ssl, short keySz) return SSL_SUCCESS; } -/* Gets ECC key for shared secret callback testing - * Client side: returns peer key - * Server side: returns private key - */ -int wolfSSL_GetEccKey(WOLFSSL* ssl, struct ecc_key** key) -{ - if (ssl == NULL || key == NULL) { - return BAD_FUNC_ARG; - } - - if (ssl->options.side == WOLFSSL_CLIENT_END) { - if (ssl->specs.static_ecdh) { - if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent || - !ssl->peerEccDsaKey->dp) { - return NO_PEER_KEY; - } - *key = (struct ecc_key*)ssl->peerEccDsaKey; - } - else { - if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || - !ssl->peerEccKey->dp) { - return NO_PEER_KEY; - } - *key = (struct ecc_key*)ssl->peerEccKey; - } - } - else if (ssl->options.side == WOLFSSL_SERVER_END) { - if (ssl->specs.static_ecdh) { - if (ssl->sigKey == NULL) { - return NO_PRIVATE_KEY; - } - *key = (struct ecc_key*)ssl->sigKey; - } - else { - if (!ssl->eccTempKeyPresent) { - return NO_PRIVATE_KEY; - } - *key = (struct ecc_key*)ssl->eccTempKey; - } - } - - return 0; -} - #endif /* !NO_RSA */ #ifndef NO_RSA diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index e574697bb..f331ff31b 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1043,8 +1043,6 @@ WOLFSSL_API int wolfSSL_SetMinRsaKey_Sz(WOLFSSL*, short); #ifdef HAVE_ECC WOLFSSL_API int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX*, short); WOLFSSL_API int wolfSSL_SetMinEccKey_Sz(WOLFSSL*, short); -struct ecc_key; -WOLFSSL_API int wolfSSL_GetEccKey(WOLFSSL*, struct ecc_key**); #endif /* NO_RSA */ WOLFSSL_API int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL*, unsigned short); @@ -1344,6 +1342,8 @@ WOLFSSL_API void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl); typedef int (*CallbackEccSharedSecret)(WOLFSSL* ssl, + const unsigned char* otherKeyDer, unsigned int otherKeySz, + unsigned int otherKeyId, unsigned char* pubKeyDer, unsigned int* pubKeySz, unsigned char* out, unsigned int* outlen, int side, void* ctx); /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */ diff --git a/wolfssl/test.h b/wolfssl/test.h index 9eb46cbfd..eb53cae0c 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -1706,51 +1706,51 @@ static INLINE int myEccVerify(WOLFSSL* ssl, const byte* sig, word32 sigSz, } static INLINE int myEccSharedSecret(WOLFSSL* ssl, + const unsigned char* otherKeyDer, unsigned int otherKeySz, + unsigned int otherKeyId, unsigned char* pubKeyDer, unsigned int* pubKeySz, unsigned char* out, unsigned int* outlen, int side, void* ctx) { - int ret; - ecc_key* privKey; - ecc_key* pubKey; - ecc_key tmpKey; + int ret; + ecc_key privKey; + ecc_key pubKey; (void)ssl; (void)ctx; - ret = wc_ecc_init(&tmpKey); + ret = wc_ecc_init(&privKey); if (ret != 0) { return ret; } + ret = wc_ecc_init(&pubKey); + if (ret != 0) { + wc_ecc_free(&privKey); + return ret; + } /* for client: create and export public key */ if (side == WOLFSSL_CLIENT_END) { - WC_RNG rng; + WC_RNG rng; ret = wc_InitRng(&rng); if (ret == 0) { - ret = wolfSSL_GetEccKey(ssl, &pubKey); - if (ret != 0) { - return ret; - } - privKey = &tmpKey; - - ret = wc_ecc_make_key_ex(&rng, 0, privKey, pubKey->dp->id); - if (ret == 0) { - ret = wc_ecc_export_x963(privKey, pubKeyDer, pubKeySz); - } + ret = wc_ecc_import_x963_ex(otherKeyDer, otherKeySz, &pubKey, + otherKeyId); + if (ret == 0) + ret = wc_ecc_make_key_ex(&rng, 0, &privKey, otherKeyId); + if (ret == 0) + ret = wc_ecc_export_x963(&privKey, pubKeyDer, pubKeySz); wc_FreeRng(&rng); } } /* for server: import public key */ else if (side == WOLFSSL_SERVER_END) { - ret = wolfSSL_GetEccKey(ssl, &privKey); - if (ret != 0) { - return ret; - } - pubKey = &tmpKey; - - ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, pubKey, privKey->dp->id); + ret = wc_ecc_import_x963_ex(otherKeyDer, otherKeySz, &privKey, + otherKeyId); + if (ret == 0) + ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, &pubKey, + otherKeyId); } else { ret = -1; @@ -1758,10 +1758,11 @@ static INLINE int myEccSharedSecret(WOLFSSL* ssl, /* generate shared secret and return it */ if (ret == 0) { - ret = wc_ecc_shared_secret(privKey, pubKey, out, outlen); + ret = wc_ecc_shared_secret(&privKey, &pubKey, out, outlen); } - wc_ecc_free(&tmpKey); + wc_ecc_free(&privKey); + wc_ecc_free(&pubKey); return ret; }