From 6235e2ed8e85d094c2aa3a913c97ad92de64e2f7 Mon Sep 17 00:00:00 2001 From: Bhaskar Sarma <61213083+bhaskar-apple@users.noreply.github.com> Date: Tue, 21 Apr 2020 18:29:58 -0700 Subject: [PATCH] Need implementation of an openSSL based ECDSA signing using NIST P256v1 (#421) * Need implementation of an openSSL based ECDSA signing using NIST P256v1 #255 * Restyled by clang-format * Fix crypto test in Travis CI * PR Feedback. Add a new test to test signing using SHA256 * PR Feedback - use SHA256. Limit to P56v1 curve. change API to let caller pass in the signature buffer * Update min signature buffer size * Update msg signature buffer length. * Update msg signature buffer length. * Delete unused method * Update comments * Rename kMinimum_ECDSA_Signature_Buffer_Length to kMax_ECDSA_Signature_Length * Update API comments Co-authored-by: Bhaskar Sarma Co-authored-by: Restyled.io --- .gitignore | 1 + .vscode/launch.json | 2 +- .vscode/tasks.json | 17 +- src/crypto/CHIPCryptoPAL.h | 33 ++++ src/crypto/CHIPCryptoPALOpenSSL.cpp | 251 +++++++++++++++++++++++++ src/crypto/tests/CHIPCryptoPALTest.cpp | 198 +++++++++++++++++-- 6 files changed, 484 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index dc9525b66f0ed5..31b6d8d20ff6f0 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ config.log config.status configure src/include/BuildConfig.h.in +src/include/BuildConfig.h.in~ # Repos stuff .repos-warning-stamp diff --git a/.vscode/launch.json b/.vscode/launch.json index 7aab2993d2165b..d58a5a1e1a84cc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -55,7 +55,7 @@ "environment": [], "externalConsole": false, "MIMode": "gdb", - "preLaunchTask": "Build & Run Crypto Tests", + "preLaunchTask": "Build openSSL crypto Tests", "setupCommands": [ { "description": "Enable pretty-printing for gdb", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 6c624292ee17be..95dcc4a35c055a 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -122,7 +122,18 @@ "command": "make -C examples/lock-app/nrf5", "group": "none", "dependsOn": "Clean Tree", - "problemMatcher": ["$gcc"] - } - ] + "problemMatcher": [ + "$gcc" + ] + }, + { + "label": "Build openSSL crypto Tests", + "type": "shell", + "command": " make -C build/default/src/crypto/ && make -C build/default/src/crypto/tests/ TestOpenSSLCrypto", + "group": "none", + "problemMatcher": [ + "$gcc" + ] + }, + ], } diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index 9bae19162ff852..9433b4184945c6 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -29,6 +29,8 @@ namespace chip { namespace Crypto { +const size_t kMax_ECDSA_Signature_Length = 72; + /** * @brief A function that implements 256-bit AES-CCM encryption * @param plaintext Plaintext to encrypt @@ -91,6 +93,37 @@ CHIP_ERROR HKDF_SHA256(const unsigned char * secret, const size_t secret_length, **/ CHIP_ERROR DRBG_get_bytes(unsigned char * out_buffer, const size_t out_length); +/** + * @brief A function to sign a msg using ECDSA + * @param msg Message that needs to be signed + * @param msg_length Length of message + * @param private_key Key to use to sign the message. Private keys are ASN.1 DER encoded as padded big-endian field elements as + *described in SEC 1: Elliptic Curve Cryptography [https://www.secg.org/sec1-v2.pdf] + * @param private_key_length Length of private key + * @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s), represented + *as ASN.1 DER integers, plus the ASN.1 sequence Header + * @param out_signature_length Length of out buffer + * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise + **/ +CHIP_ERROR ECDSA_sign_msg(const unsigned char * msg, const size_t msg_length, const unsigned char * private_key, + const size_t private_key_length, unsigned char * out_signature, size_t & out_signature_length); + +/** + * @brief A function to sign a msg using ECDSA + * @param msg Message that needs to be signed + * @param msg_length Length of message + * @param public_key Key to use to verify the message signature. Public keys are ASN.1 DER encoded as uncompressed points as + *described in SEC 1: Elliptic Curve Cryptography [https://www.secg.org/sec1-v2.pdf] + * @param private_key_length Length of public key + * @param signature Signature to use for verification. The signature consists of: 2 EC elements (r and s), represented as ASN.1 DER + *integers, plus the ASN.1 sequence Header + * @param signature_length Length of signature + * @return Returns a CHIP_NO_ERROR on successful verification, a CHIP_ERROR otherwise + **/ +CHIP_ERROR ECDSA_validate_msg_signature(const unsigned char * msg, const size_t msg_length, const unsigned char * public_key, + const size_t public_key_length, const unsigned char * signature, + const size_t signature_length); } // namespace Crypto } // namespace chip + #endif diff --git a/src/crypto/CHIPCryptoPALOpenSSL.cpp b/src/crypto/CHIPCryptoPALOpenSSL.cpp index 46f84609ba1345..3757f8707b4f6d 100644 --- a/src/crypto/CHIPCryptoPALOpenSSL.cpp +++ b/src/crypto/CHIPCryptoPALOpenSSL.cpp @@ -24,14 +24,42 @@ #include #include +#include #include #include #include +#include #include #include #define kKeyLengthInBits 256 +enum class DigestType +{ + SHA256 +}; + +enum class ECName +{ + P256v1 +}; + +using namespace chip::Crypto; + +static int _nidForCurve(ECName name) +{ + switch (name) + { + case ECName::P256v1: + return EC_curve_nist2nid("P-256"); + break; + + default: + return NID_undef; + break; + } +} + static bool _isValidTagLength(size_t tag_length) { if (tag_length == 8 || tag_length == 12 || tag_length == 16) @@ -41,6 +69,36 @@ static bool _isValidTagLength(size_t tag_length) return false; } +static void _logSSLError() +{ + int ssl_err_code = ERR_get_error(); + while (ssl_err_code != 0) + { + const char * err_str_lib = ERR_lib_error_string(ssl_err_code); + const char * err_str_routine = ERR_func_error_string(ssl_err_code); + const char * err_str_reason = ERR_reason_error_string(ssl_err_code); + if (err_str_lib) + { + printf("\nssl err %s %s %s\n", err_str_lib, err_str_routine, err_str_reason); + } + ssl_err_code = ERR_get_error(); + } +} + +static const EVP_MD * _digestForType(DigestType digestType) +{ + switch (digestType) + { + case DigestType::SHA256: + return EVP_sha256(); + break; + + default: + return NULL; + break; + } +} + CHIP_ERROR chip::Crypto::AES_CCM_256_encrypt(const unsigned char * plaintext, size_t plaintext_length, const unsigned char * aad, size_t aad_length, const unsigned char * key, const unsigned char * iv, size_t iv_length, unsigned char * ciphertext, unsigned char * tag, size_t tag_length) @@ -251,3 +309,196 @@ CHIP_ERROR chip::Crypto::DRBG_get_bytes(unsigned char * out_buffer, const size_t exit: return error; } + +CHIP_ERROR chip::Crypto::ECDSA_sign_msg(const unsigned char * msg, const size_t msg_length, const unsigned char * private_key, + const size_t private_key_length, unsigned char * out_signature, + size_t & out_signature_length) +{ + ERR_clear_error(); + static_assert(kMax_ECDSA_Signature_Length >= 72, "ECDSA signature buffer length is too short"); + + CHIP_ERROR error = CHIP_NO_ERROR; + int result = 0; + EVP_MD_CTX * context = NULL; + int nid = NID_undef; + EC_KEY * ec_key = NULL; + EVP_PKEY * signing_key = NULL; + char * _hexKey = NULL; + BIGNUM * pvt_key = NULL; + const EVP_MD * md = NULL; + ECName curve_name = ECName::P256v1; + DigestType digest = DigestType::SHA256; + size_t out_length = 0; + + VerifyOrExit(msg != NULL, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(msg_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + nid = _nidForCurve(curve_name); + VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(private_key != NULL, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(private_key_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(out_signature != NULL, error = CHIP_ERROR_INVALID_ARGUMENT); + md = _digestForType(digest); + VerifyOrExit(md != NULL, error = CHIP_ERROR_INVALID_ARGUMENT); + + ec_key = EC_KEY_new_by_curve_name(nid); + VerifyOrExit(ec_key != NULL, error = CHIP_ERROR_INTERNAL); + + pvt_key = BN_bin2bn(private_key, private_key_length, pvt_key); + VerifyOrExit(pvt_key != NULL, error = CHIP_ERROR_INTERNAL); + + result = EC_KEY_set_private_key(ec_key, pvt_key); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + + signing_key = EVP_PKEY_new(); + VerifyOrExit(signing_key != NULL, error = CHIP_ERROR_INTERNAL); + + result = EVP_PKEY_set1_EC_KEY(signing_key, ec_key); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + + context = EVP_MD_CTX_create(); + VerifyOrExit(context != NULL, error = CHIP_ERROR_INTERNAL); + + result = EVP_DigestSignInit(context, NULL, md, NULL, signing_key); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + + result = EVP_DigestSignUpdate(context, msg, msg_length); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + + // Call the EVP_DigestSignFinal with a NULL param to get length of the signature. + + result = EVP_DigestSignFinal(context, NULL, &out_length); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(out_signature_length >= out_length, error = CHIP_ERROR_INVALID_ARGUMENT); + + result = EVP_DigestSignFinal(context, out_signature, &out_length); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + // This should not happen due to the check above. But check this nonetheless + VerifyOrExit(out_signature_length >= out_length, error = CHIP_ERROR_INTERNAL); + out_signature_length = out_length; + +exit: + if (ec_key != NULL) + { + EC_KEY_free(ec_key); + ec_key = NULL; + } + + if (context != NULL) + { + EVP_MD_CTX_destroy(context); + context = NULL; + } + if (signing_key != NULL) + { + EVP_PKEY_free(signing_key); + signing_key = NULL; + } + + if (error != CHIP_NO_ERROR) + { + _logSSLError(); + } + + if (_hexKey != NULL) + { + free(_hexKey); + } + + return error; +} + +CHIP_ERROR chip::Crypto::ECDSA_validate_msg_signature(const unsigned char * msg, const size_t msg_length, + const unsigned char * public_key, const size_t public_key_length, + const unsigned char * signature, const size_t signature_length) +{ + ERR_clear_error(); + CHIP_ERROR error = CHIP_ERROR_INTERNAL; + int nid = NID_undef; + const EVP_MD * md = NULL; + EC_KEY * ec_key = NULL; + EVP_PKEY * verification_key = NULL; + EC_POINT * key_point = NULL; + EC_GROUP * ec_group = NULL; + int result = 0; + EVP_MD_CTX * md_context = NULL; + ECName curve_name = ECName::P256v1; + DigestType digest = DigestType::SHA256; + + VerifyOrExit(msg != NULL, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(msg_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + nid = _nidForCurve(curve_name); + VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(public_key != NULL, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(public_key_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(signature != NULL, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrExit(signature_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + + md = _digestForType(digest); + VerifyOrExit(md != NULL, error = CHIP_ERROR_INVALID_ARGUMENT); + + ec_group = EC_GROUP_new_by_curve_name(nid); + VerifyOrExit(ec_group != NULL, error = CHIP_ERROR_INTERNAL); + + key_point = EC_POINT_new(ec_group); + VerifyOrExit(key_point != NULL, error = CHIP_ERROR_INTERNAL); + + result = EC_POINT_oct2point(ec_group, key_point, public_key, public_key_length, NULL); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + + ec_key = EC_KEY_new_by_curve_name(nid); + VerifyOrExit(ec_key != NULL, error = CHIP_ERROR_INTERNAL); + + result = EC_KEY_set_public_key(ec_key, key_point); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + + result = EC_KEY_check_key(ec_key); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + + verification_key = EVP_PKEY_new(); + VerifyOrExit(verification_key != NULL, error = CHIP_ERROR_INTERNAL); + + result = EVP_PKEY_set1_EC_KEY(verification_key, ec_key); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + + md_context = EVP_MD_CTX_create(); + VerifyOrExit(md_context != NULL, error = CHIP_ERROR_INTERNAL); + + result = EVP_DigestVerifyInit(md_context, NULL, md, NULL, verification_key); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + + result = EVP_DigestVerifyUpdate(md_context, msg, msg_length); + VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL); + + result = EVP_DigestVerifyFinal(md_context, signature, signature_length); + VerifyOrExit(result == 1, error = CHIP_ERROR_INVALID_SIGNATURE); + error = CHIP_NO_ERROR; + +exit: + _logSSLError(); + if (ec_group != NULL) + { + EC_GROUP_free(ec_group); + ec_group = NULL; + } + if (key_point != NULL) + { + EC_POINT_clear_free(key_point); + key_point = NULL; + } + if (md_context) + { + EVP_MD_CTX_destroy(md_context); + md_context = NULL; + } + if (ec_key != NULL) + { + EC_KEY_free(ec_key); + ec_key = NULL; + } + if (verification_key != NULL) + { + EVP_PKEY_free(verification_key); + verification_key = NULL; + } + return error; +} diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index 1f7d5c424c3037..60544358875f92 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -23,7 +23,9 @@ #include #include #include +#include +using namespace chip; using namespace chip::Crypto; static void TestAES_CCM_256EncryptTestVectors(nlTestSuite * inSuite, void * inContext) @@ -297,24 +299,192 @@ static void TestDRBG_Output(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, memcmp(out_buf, orig_buf, sizeof(out_buf)) != 0); } +static void TestECDSA_Signing_SHA256(nlTestSuite * inSuite, void * inContext) +{ + const char * msg = "Hello World!"; + size_t msg_length = strlen((const char *) msg); + + unsigned char hex_private_key[] = { 0xc6, 0x1a, 0x2f, 0x89, 0x36, 0x67, 0x2b, 0x26, 0x12, 0x47, 0x4f, + 0x11, 0x0e, 0x34, 0x15, 0x81, 0x81, 0x12, 0xfc, 0x36, 0xeb, 0x65, + 0x61, 0x07, 0xaa, 0x63, 0xe8, 0xc5, 0x22, 0xac, 0x52, 0xa1 }; + + unsigned char hex_public_key[] = { 0x04, 0xe2, 0x07, 0x64, 0xff, 0x6f, 0x6a, 0x91, 0xd9, 0xc2, 0xc3, 0x0a, 0xc4, + 0x3c, 0x56, 0x4b, 0x42, 0x8a, 0xf3, 0xb4, 0x49, 0x29, 0x39, 0x95, 0xa2, 0xf7, + 0x02, 0x8c, 0xa5, 0xce, 0xf3, 0xc9, 0xca, 0x24, 0xc5, 0xd4, 0x5c, 0x60, 0x79, + 0x48, 0x30, 0x3c, 0x53, 0x86, 0xd9, 0x23, 0xe6, 0x61, 0x1f, 0x5a, 0x3d, 0xdf, + 0x9f, 0xdc, 0x35, 0xea, 0xd0, 0xde, 0x16, 0x7e, 0x64, 0xde, 0x7f, 0x3c, 0xa6 }; + + unsigned char signature[kMax_ECDSA_Signature_Length]; + size_t signature_length = sizeof(signature); + CHIP_ERROR signing_error = ECDSA_sign_msg((const unsigned char *) msg, msg_length, hex_private_key, sizeof(hex_private_key), + signature, signature_length); + NL_TEST_ASSERT(inSuite, signing_error == CHIP_NO_ERROR); + + CHIP_ERROR validation_error = ECDSA_validate_msg_signature((const unsigned char *) msg, msg_length, hex_public_key, + sizeof(hex_public_key), signature, signature_length); + NL_TEST_ASSERT(inSuite, validation_error == CHIP_NO_ERROR); +} + +static void TestECDSA_ValidationFailsDifferentMessage(nlTestSuite * inSuite, void * inContext) +{ + const char * msg = "Hello World!"; + size_t msg_length = strlen((const char *) msg); + + unsigned char hex_private_key[] = { 0xc6, 0x1a, 0x2f, 0x89, 0x36, 0x67, 0x2b, 0x26, 0x12, 0x47, 0x4f, + 0x11, 0x0e, 0x34, 0x15, 0x81, 0x81, 0x12, 0xfc, 0x36, 0xeb, 0x65, + 0x61, 0x07, 0xaa, 0x63, 0xe8, 0xc5, 0x22, 0xac, 0x52, 0xa1 }; + + unsigned char hex_public_key[] = { 0x04, 0xe2, 0x07, 0x64, 0xff, 0x6f, 0x6a, 0x91, 0xd9, 0xc2, 0xc3, 0x0a, 0xc4, + 0x3c, 0x56, 0x4b, 0x42, 0x8a, 0xf3, 0xb4, 0x49, 0x29, 0x39, 0x95, 0xa2, 0xf7, + 0x02, 0x8c, 0xa5, 0xce, 0xf3, 0xc9, 0xca, 0x24, 0xc5, 0xd4, 0x5c, 0x60, 0x79, + 0x48, 0x30, 0x3c, 0x53, 0x86, 0xd9, 0x23, 0xe6, 0x61, 0x1f, 0x5a, 0x3d, 0xdf, + 0x9f, 0xdc, 0x35, 0xea, 0xd0, 0xde, 0x16, 0x7e, 0x64, 0xde, 0x7f, 0x3c, 0xa6 }; + + unsigned char signature[kMax_ECDSA_Signature_Length]; + size_t signature_length = sizeof(signature); + CHIP_ERROR signing_error = ECDSA_sign_msg((const unsigned char *) msg, msg_length, hex_private_key, sizeof(hex_private_key), + signature, signature_length); + NL_TEST_ASSERT(inSuite, signing_error == CHIP_NO_ERROR); + + const char * diff_msg = "NOT Hello World!"; + size_t diff_msg_length = strlen((const char *) msg); + CHIP_ERROR validation_error = ECDSA_validate_msg_signature((const unsigned char *) diff_msg, diff_msg_length, hex_public_key, + sizeof(hex_public_key), signature, signature_length); + NL_TEST_ASSERT(inSuite, validation_error != CHIP_NO_ERROR); +} + +static void TestECDSA_ValidationFailIncorrectSignature(nlTestSuite * inSuite, void * inContext) +{ + const char * msg = "Hello World!"; + size_t msg_length = strlen((const char *) msg); + + unsigned char hex_private_key[] = { 0xc6, 0x1a, 0x2f, 0x89, 0x36, 0x67, 0x2b, 0x26, 0x12, 0x47, 0x4f, + 0x11, 0x0e, 0x34, 0x15, 0x81, 0x81, 0x12, 0xfc, 0x36, 0xeb, 0x65, + 0x61, 0x07, 0xaa, 0x63, 0xe8, 0xc5, 0x22, 0xac, 0x52, 0xa1 }; + + unsigned char hex_public_key[] = { 0x04, 0xe2, 0x07, 0x64, 0xff, 0x6f, 0x6a, 0x91, 0xd9, 0xc2, 0xc3, 0x0a, 0xc4, + 0x3c, 0x56, 0x4b, 0x42, 0x8a, 0xf3, 0xb4, 0x49, 0x29, 0x39, 0x95, 0xa2, 0xf7, + 0x02, 0x8c, 0xa5, 0xce, 0xf3, 0xc9, 0xca, 0x24, 0xc5, 0xd4, 0x5c, 0x60, 0x79, + 0x48, 0x30, 0x3c, 0x53, 0x86, 0xd9, 0x23, 0xe6, 0x61, 0x1f, 0x5a, 0x3d, 0xdf, + 0x9f, 0xdc, 0x35, 0xea, 0xd0, 0xde, 0x16, 0x7e, 0x64, 0xde, 0x7f, 0x3c, 0xa6 }; + + unsigned char signature[kMax_ECDSA_Signature_Length]; + size_t signature_length = sizeof(signature); + CHIP_ERROR signing_error = ECDSA_sign_msg((const unsigned char *) msg, msg_length, hex_private_key, sizeof(hex_private_key), + signature, signature_length); + NL_TEST_ASSERT(inSuite, signing_error == CHIP_NO_ERROR); + signature[0] = ~signature[0]; // Flipping bits should invalidate the signature. + + CHIP_ERROR validation_error = ECDSA_validate_msg_signature((const unsigned char *) msg, msg_length, hex_public_key, + sizeof(hex_public_key), signature, signature_length); + NL_TEST_ASSERT(inSuite, validation_error == CHIP_ERROR_INVALID_SIGNATURE); +} + +static void TestECDSA_SigningInvalidParams(nlTestSuite * inSuite, void * inContext) +{ + const unsigned char * msg = (unsigned char *) "Hello World!"; + size_t msg_length = strlen((const char *) msg); + unsigned char hex_private_key[] = { 0xc6, 0x1a, 0x2f, 0x89, 0x36, 0x67, 0x2b, 0x26, 0x12, 0x47, 0x4f, + 0x11, 0x0e, 0x34, 0x15, 0x81, 0x81, 0x12, 0xfc, 0x36, 0xeb, 0x65, + 0x61, 0x07, 0xaa, 0x63, 0xe8, 0xc5, 0x22, 0xac, 0x52, 0xa1 }; + + unsigned char signature[kMax_ECDSA_Signature_Length]; + size_t signature_length = sizeof(signature); + CHIP_ERROR signing_error = + ECDSA_sign_msg(NULL, msg_length, hex_private_key, sizeof(hex_private_key), signature, signature_length); + NL_TEST_ASSERT(inSuite, signing_error == CHIP_ERROR_INVALID_ARGUMENT); + signing_error = CHIP_NO_ERROR; + + signing_error = ECDSA_sign_msg(msg, 0, hex_private_key, sizeof(hex_private_key), signature, signature_length); + NL_TEST_ASSERT(inSuite, signing_error == CHIP_ERROR_INVALID_ARGUMENT); + signing_error = CHIP_NO_ERROR; + + signing_error = ECDSA_sign_msg(msg, msg_length, NULL, sizeof(hex_private_key), signature, signature_length); + NL_TEST_ASSERT(inSuite, signing_error == CHIP_ERROR_INVALID_ARGUMENT); + signing_error = CHIP_NO_ERROR; + + signing_error = ECDSA_sign_msg(msg, msg_length, hex_private_key, 0, signature, signature_length); + NL_TEST_ASSERT(inSuite, signing_error == CHIP_ERROR_INVALID_ARGUMENT); + signing_error = CHIP_NO_ERROR; + + signing_error = ECDSA_sign_msg(msg, msg_length, hex_private_key, sizeof(hex_private_key), NULL, signature_length); + NL_TEST_ASSERT(inSuite, signing_error == CHIP_ERROR_INVALID_ARGUMENT); + signing_error = CHIP_NO_ERROR; +} + +static void TestECDSA_ValidationInvalidParam(nlTestSuite * inSuite, void * inContext) +{ + const char * msg = "Hello World!"; + size_t msg_length = strlen((const char *) msg); + + unsigned char hex_private_key[] = { 0xc6, 0x1a, 0x2f, 0x89, 0x36, 0x67, 0x2b, 0x26, 0x12, 0x47, 0x4f, + 0x11, 0x0e, 0x34, 0x15, 0x81, 0x81, 0x12, 0xfc, 0x36, 0xeb, 0x65, + 0x61, 0x07, 0xaa, 0x63, 0xe8, 0xc5, 0x22, 0xac, 0x52, 0xa1 }; + + unsigned char hex_public_key[] = { 0x04, 0xe2, 0x07, 0x64, 0xff, 0x6f, 0x6a, 0x91, 0xd9, 0xc2, 0xc3, 0x0a, 0xc4, + 0x3c, 0x56, 0x4b, 0x42, 0x8a, 0xf3, 0xb4, 0x49, 0x29, 0x39, 0x95, 0xa2, 0xf7, + 0x02, 0x8c, 0xa5, 0xce, 0xf3, 0xc9, 0xca, 0x24, 0xc5, 0xd4, 0x5c, 0x60, 0x79, + 0x48, 0x30, 0x3c, 0x53, 0x86, 0xd9, 0x23, 0xe6, 0x61, 0x1f, 0x5a, 0x3d, 0xdf, + 0x9f, 0xdc, 0x35, 0xea, 0xd0, 0xde, 0x16, 0x7e, 0x64, 0xde, 0x7f, 0x3c, 0xa6 }; + + unsigned char signature[kMax_ECDSA_Signature_Length]; + size_t signature_length = sizeof(signature); + CHIP_ERROR signing_error = ECDSA_sign_msg((const unsigned char *) msg, msg_length, hex_private_key, sizeof(hex_private_key), + signature, signature_length); + NL_TEST_ASSERT(inSuite, signing_error == CHIP_NO_ERROR); + + CHIP_ERROR validation_error = + ECDSA_validate_msg_signature(NULL, msg_length, hex_public_key, sizeof(hex_public_key), signature, signature_length); + NL_TEST_ASSERT(inSuite, validation_error == CHIP_ERROR_INVALID_ARGUMENT); + validation_error = CHIP_NO_ERROR; + + validation_error = ECDSA_validate_msg_signature((const unsigned char *) msg, 0, hex_public_key, sizeof(hex_public_key), + signature, signature_length); + NL_TEST_ASSERT(inSuite, validation_error == CHIP_ERROR_INVALID_ARGUMENT); + validation_error = CHIP_NO_ERROR; + + validation_error = + ECDSA_validate_msg_signature((const unsigned char *) msg, msg_length, hex_public_key, 0, signature, signature_length); + NL_TEST_ASSERT(inSuite, validation_error == CHIP_ERROR_INVALID_ARGUMENT); + validation_error = CHIP_NO_ERROR; + + validation_error = ECDSA_validate_msg_signature((const unsigned char *) msg, msg_length, hex_public_key, sizeof(hex_public_key), + NULL, signature_length); + NL_TEST_ASSERT(inSuite, validation_error == CHIP_ERROR_INVALID_ARGUMENT); + validation_error = CHIP_NO_ERROR; + + validation_error = + ECDSA_validate_msg_signature((const unsigned char *) msg, msg_length, hex_public_key, sizeof(hex_public_key), signature, 0); + NL_TEST_ASSERT(inSuite, validation_error == CHIP_ERROR_INVALID_ARGUMENT); + validation_error = CHIP_NO_ERROR; +} + /** * Test Suite. It lists all the test functions. */ -static const nlTest sTests[] = { NL_TEST_DEF("Test encrypting test vectors", TestAES_CCM_256EncryptTestVectors), - NL_TEST_DEF("Test decrypting test vectors", TestAES_CCM_256DecryptTestVectors), - NL_TEST_DEF("Test encrypting invalid plain text", TestAES_CCM_256EncryptInvalidPlainText), - NL_TEST_DEF("Test encrypting using nil key", TestAES_CCM_256EncryptNilKey), - NL_TEST_DEF("Test encrypting using invalid IV", TestAES_CCM_256EncryptInvalidIVLen), - NL_TEST_DEF("Test encrypting using invalid tag", TestAES_CCM_256EncryptInvalidTagLen), - NL_TEST_DEF("Test decrypting invalid ct", TestAES_CCM_256DecryptInvalidCipherText), - NL_TEST_DEF("Test decrypting invalid key", TestAES_CCM_256DecryptInvalidKey), - NL_TEST_DEF("Test decrypting invalid IV", TestAES_CCM_256DecryptInvalidIVLen), - NL_TEST_DEF("Test decrypting invalid vectors", TestAES_CCM_256DecryptInvalidTestVectors), - NL_TEST_DEF("Test HKDF SHA 256", TestHKDF_SHA256), - NL_TEST_DEF("Test DRBG invalid inputs", TestDRBG_InvalidInputs), - NL_TEST_DEF("Test DRBG output", TestDRBG_Output), - NL_TEST_SENTINEL() }; +static const nlTest sTests[] = { + NL_TEST_DEF("Test encrypting test vectors", TestAES_CCM_256EncryptTestVectors), + NL_TEST_DEF("Test decrypting test vectors", TestAES_CCM_256DecryptTestVectors), + NL_TEST_DEF("Test encrypting invalid plain text", TestAES_CCM_256EncryptInvalidPlainText), + NL_TEST_DEF("Test encrypting using nil key", TestAES_CCM_256EncryptNilKey), + NL_TEST_DEF("Test encrypting using invalid IV", TestAES_CCM_256EncryptInvalidIVLen), + NL_TEST_DEF("Test encrypting using invalid tag", TestAES_CCM_256EncryptInvalidTagLen), + NL_TEST_DEF("Test decrypting invalid ct", TestAES_CCM_256DecryptInvalidCipherText), + NL_TEST_DEF("Test decrypting invalid key", TestAES_CCM_256DecryptInvalidKey), + NL_TEST_DEF("Test decrypting invalid IV", TestAES_CCM_256DecryptInvalidIVLen), + NL_TEST_DEF("Test decrypting invalid vectors", TestAES_CCM_256DecryptInvalidTestVectors), + NL_TEST_DEF("Test HKDF SHA 256", TestHKDF_SHA256), + NL_TEST_DEF("Test DRBG invalid inputs", TestDRBG_InvalidInputs), + NL_TEST_DEF("Test DRBG output", TestDRBG_Output), + NL_TEST_DEF("Test ECDSA signing and validation using SHA256", TestECDSA_Signing_SHA256), + NL_TEST_DEF("Test ECDSA signature validation fail - Different msg", TestECDSA_ValidationFailsDifferentMessage), + NL_TEST_DEF("Test ECDSA signature validation fail - Different signature", TestECDSA_ValidationFailIncorrectSignature), + NL_TEST_DEF("Test ECDSA sign msg invalid parameters", TestECDSA_SigningInvalidParams), + NL_TEST_DEF("Test ECDSA signature validation invalid parameters", TestECDSA_ValidationInvalidParam), + + NL_TEST_SENTINEL() +}; int main(void) {