diff --git a/include/cose/cose.h b/include/cose/cose.h index 647b1b7d..0cc424cf 100644 --- a/include/cose/cose.h +++ b/include/cose/cose.h @@ -2,10 +2,14 @@ #include #include + #include "cose/cose_configure.h" #ifdef COSE_C_USE_OPENSSL #include #endif +#ifdef COSE_C_USE_MBEDTLS +#include +#endif #ifdef __cplusplus extern "C" { @@ -218,6 +222,10 @@ typedef enum { * Functions dealing with keys */ +const int COSE_KEY_FL_OWN = 0x1; // Cede ownership of the key to the libraray + // Only neede for MBEDTLS as OpenSSL does reference counts + + HCOSE_KEY COSE_KEY_FromCbor(cn_cbor* pcborKey, CBOR_CONTEXT_COMMA cose_errback* perror); bool COSE_KEY_Free(HCOSE_KEY h); @@ -226,6 +234,12 @@ HCOSE_KEY COSE_KEY_FromEVP(EVP_PKEY* opensslKey, cn_cbor* pcborKey, CBOR_CONTEXT_COMMA cose_errback* perror); #endif +#ifdef COSE_C_USE_MBEDTLS +HCOSE_KEY COSE_KEY_FromMbedKeypair(mbedtls_ecp_keypair *, + cn_cbor * pcborKey, + int flags, + CBOR_CONTEXT_COMMA cose_errback* perror); +#endif /* * messages dealing with the Enveloped message type diff --git a/src/CoseKey.cpp b/src/CoseKey.cpp index 717af124..236c05eb 100644 --- a/src/CoseKey.cpp +++ b/src/CoseKey.cpp @@ -136,3 +136,37 @@ HCOSE_KEY COSE_KEY_FromEVP(EVP_PKEY *opensslKey, return (HCOSE_KEY)pkey; } #endif + +#ifdef COSE_C_USE_MBEDTLS +HCOSE_KEY COSE_KEY_FromMbedKeypair(mbedtls_ecp_keypair * mbedtls_keypair, + cn_cbor *pcborKey, + int flags, + CBOR_CONTEXT_COMMA cose_errback *perror) +{ + COSE_KEY *pkey = nullptr; + + pkey = (COSE_KEY *)COSE_CALLOC(1, sizeof(COSE_KEY), context); + + if (pkey == nullptr) { + perror->err = COSE_ERR_OUT_OF_MEMORY; + return nullptr; + } + +#ifdef USE_CBOR_CONTEXT + if (context != nullptr) { + pkey->m_allocContext = *context; + } +#endif + + pkey->m_refCount = 1; + pkey->m_cborKey = pcborKey; + pkey->m_mbedtls_keypair = mbedtls_keypair; + pkey->m_flags = flags; + + pkey->m_nextKey = KeysRoot; + KeysRoot = pkey; + + return (HCOSE_KEY)pkey; +} + +#endif diff --git a/src/cose_int.h b/src/cose_int.h index 5209cc99..88d99075 100644 --- a/src/cose_int.h +++ b/src/cose_int.h @@ -6,6 +6,10 @@ #include #ifdef COSE_C_USE_OPENSSL #include +#include +#endif +#ifdef COSE_C_USE_MBEDTLS +#include #endif // These definitions are here because they aren't required for the public @@ -26,7 +30,7 @@ typedef struct CounterSign1 COSE_CounterSign1; typedef struct _COSE_KEY { int m_refCount; cn_cbor *m_cborKey; - int flags; + int m_flags; struct _COSE_KEY *m_nextKey; #ifdef USE_CBOR_CONTEXT cn_cbor_context m_allocContext; @@ -34,6 +38,9 @@ typedef struct _COSE_KEY { #ifdef COSE_C_USE_OPENSSL EVP_PKEY *m_opensslKey; #endif +#ifdef COSE_C_USE_MBEDTLS + mbedtls_ecp_keypair * m_mbedtls_keypair; +#endif } COSE_KEY; typedef struct _COSE { @@ -468,3 +475,14 @@ enum { COSE_Int_Alg_AES_CBC_MAC_256_64 = -22 }; #define COSE_CounterSign_object 1000 #define COSE_CounterSign1_object 1001 + + +#if defined(COSE_C_USE_OPENSSL) && (OPENSSL_VERSION_NUMBER > 0x10100000L) +EC_KEY *ECKey_From(COSE_KEY *pKey, int *cbGroup, cose_errback *perr); +#endif + +#ifdef COSE_C_USE_MBEDTLS +mbedtls_ecp_keypair * ECKey_From(COSE_KEY *pKey, + mbedtls_ecp_keypair *keypair, + cose_errback *perr); +#endif diff --git a/src/mbedtls.cpp b/src/mbedtls.cpp index 4294e869..56261929 100644 --- a/src/mbedtls.cpp +++ b/src/mbedtls.cpp @@ -666,10 +666,14 @@ bool HMAC_Validate(COSE_MacMessage *pcose, #define COSE_Key_EC_Y -3 #define COSE_Key_EC_d -4 -bool ECKey_From(COSE_KEY *pKey, +mbedtls_ecp_keypair * ECKey_From(COSE_KEY *pKey, mbedtls_ecp_keypair *keypair, cose_errback *perr) { + if (pKey->m_mbedtls_keypair != nullptr) { + return pKey->m_mbedtls_keypair; + } + byte rgbKey[MBEDTLS_ECP_MAX_PT_LEN]; int cbKey = 0; int cbGroup = 0; @@ -755,10 +759,10 @@ bool ECKey_From(COSE_KEY *pKey, mbedtls_mpi_read_binary(&keypair->d, p->v.bytes, p->length) == 0, COSE_ERR_CRYPTO_FAIL); } - return true; + return keypair; errorReturn: - return false; + return nullptr; } bool ECDSA_Sign(COSE *pSigner, @@ -777,6 +781,7 @@ bool ECDSA_Sign(COSE *pSigner, mbedtls_md_type_t mdType; const mbedtls_md_info_t *pmdInfo; mbedtls_ecp_keypair keypair; + mbedtls_ecp_keypair *useKey = nullptr; mbedtls_mpi r; mbedtls_mpi s; #ifdef USE_CBOR_CONTEXT @@ -789,11 +794,12 @@ bool ECDSA_Sign(COSE *pSigner, mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); - if (!ECKey_From(pKey, &keypair, perr)) { + useKey = ECKey_From(pKey, &keypair, perr); + if (useKey == nullptr) { goto errorReturn; } - CHECK_CONDITION(keypair.d.n != 0, COSE_ERR_INVALID_PARAMETER); + CHECK_CONDITION(useKey->d.n != 0, COSE_ERR_INVALID_PARAMETER); switch (cbitDigest) { case 256: @@ -816,11 +822,11 @@ bool ECDSA_Sign(COSE *pSigner, CHECK_CONDITION(mbedtls_md(pmdInfo, rgbToSign, cbToSign, rgbDigest) == 0, COSE_ERR_INVALID_PARAMETER); - CHECK_CONDITION(mbedtls_ecdsa_sign_det(&keypair.grp, &r, &s, &keypair.d, + CHECK_CONDITION(mbedtls_ecdsa_sign_det(&useKey->grp, &r, &s, &useKey->d, rgbDigest, mbedtls_md_get_size(pmdInfo), mdType) == 0, COSE_ERR_CRYPTO_FAIL); - cbR = (keypair.grp.nbits + 7) / 8; + cbR = (useKey->grp.nbits + 7) / 8; pbSig = (byte *)COSE_CALLOC(cbR, 2, context); CHECK_CONDITION(pbSig != nullptr, COSE_ERR_OUT_OF_MEMORY); @@ -863,6 +869,7 @@ bool ECDSA_Verify(COSE *pSigner, cose_errback *perr) { mbedtls_ecp_keypair keypair; + mbedtls_ecp_keypair* useKey = nullptr; mbedtls_mpi r; mbedtls_mpi s; mbedtls_md_type_t mdType; @@ -875,7 +882,8 @@ bool ECDSA_Verify(COSE *pSigner, mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); - if (!ECKey_From(pKey, &keypair, perr)) { + useKey = ECKey_From(pKey, &keypair, perr); + if (useKey == nullptr) { goto errorReturn; } @@ -911,8 +919,8 @@ bool ECDSA_Verify(COSE *pSigner, mbedtls_mpi_read_binary( &s, pSig->v.bytes + pSig->length / 2, pSig->length / 2) == 0, COSE_ERR_OUT_OF_MEMORY); - CHECK_CONDITION(mbedtls_ecdsa_verify(&keypair.grp, rgbDigest, - mbedtls_md_get_size(pmdInfo), &keypair.Q, &r, &s) == 0, + CHECK_CONDITION(mbedtls_ecdsa_verify(&useKey->grp, rgbDigest, + mbedtls_md_get_size(pmdInfo), &useKey->Q, &r, &s) == 0, COSE_ERR_CRYPTO_FAIL); result = true; diff --git a/src/openssl.cpp b/src/openssl.cpp index b9e54e0b..f376fb4b 100644 --- a/src/openssl.cpp +++ b/src/openssl.cpp @@ -1084,6 +1084,7 @@ bool HMAC_Validate(COSE_MacMessage *pcose, #define COSE_Key_EC_Y -3 #define COSE_Key_EC_d -4 + EC_KEY *ECKey_From(COSE_KEY *pKey, int *cbGroup, cose_errback *perr) { EC_KEY *pNewKey = nullptr; @@ -1099,6 +1100,24 @@ EC_KEY *ECKey_From(COSE_KEY *pKey, int *cbGroup, cose_errback *perr) if (pKey->m_opensslKey != nullptr) { EC_KEY *pKeyNew = EVP_PKEY_get1_EC_KEY(pKey->m_opensslKey); CHECK_CONDITION(pKeyNew != nullptr, COSE_ERR_INVALID_PARAMETER); + int gid = EC_GROUP_get_curve_name(EC_KEY_get0_group(pKeyNew)); + switch (gid) { + case NID_X9_62_prime256v1: + *cbGroup = 256 / 8; + break; + + case NID_secp384r1: + *cbGroup = 384 / 8; + break; + + case NID_secp521r1: + *cbGroup = (521 + 7) / 8; + break; + + default: + FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); + } + return pKeyNew; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index aded8c88..85b893bc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -65,6 +65,10 @@ add_test( NAME ecdsa WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cose_test --dir Examples/ecdsa-examples) +add_test( + NAME ecdsa-native + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND cose_test --dir Examples/ecdsa-examples --keyFormat=native) add_test( NAME eddsa WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} diff --git a/test/test.cpp b/test/test.cpp index 9998be65..f5150182 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -21,7 +21,14 @@ #include "json.h" #include "test.h" + +#ifdef COSE_C_USE_OPENSSL +#include +#endif + #ifdef COSE_C_USE_MBEDTLS +#include +#include "mbedtls/ecdsa.h" #include "mbedtls/entropy.h" #endif @@ -30,6 +37,7 @@ cn_cbor_context* context; #endif int CFails = 0; +int KeyFormat = 1; typedef struct _NameMap { const char* sz; @@ -849,18 +857,119 @@ cn_cbor* BuildCborKey(const cn_cbor* pKeyIn, bool fPublicKey) HCOSE_KEY BuildKey(const cn_cbor* pKeyIn, bool fPublicKey) { + cose_errback coseError; cn_cbor* pKeyOut = BuildCborKey(pKeyIn, fPublicKey); if (pKeyOut == nullptr) { return nullptr; } - cose_errback coseError; - HCOSE_KEY key = + Safe_HCOSE_KEY key = COSE_KEY_FromCbor(pKeyOut, CBOR_CONTEXT_PARAM_COMMA & coseError); if (key == nullptr) { CN_CBOR_FREE(pKeyOut, context); } - return key; + if (KeyFormat == 1) { + return key.Release(); + } + + cn_cbor* keyType = cn_cbor_mapget_int(pKeyOut, COSE_Key_Type); + if (keyType == nullptr) { + return nullptr; + } + +#ifdef COSE_C_USE_OPENSSL + EVP_PKEY* opensslKey = EVP_PKEY_new(); +#endif +#ifdef COSE_C_USE_MBEDTLS + mbedtls_ecp_keypair* keypair = nullptr; +#endif + + switch (keyType->v.uint) { + case COSE_Key_Type_EC2: +#if defined(COSE_C_USE_OPENSSL) && (OPENSSL_VERSION_NUMBER > 0x10100000L) + { + int cbR = 0; + EC_KEY* ecKey = + ECKey_From((COSE_KEY*)(HCOSE_KEY)key, &cbR, &coseError); + if (ecKey == nullptr) { + return nullptr; + } + + if (EVP_PKEY_set1_EC_KEY(opensslKey, ecKey) == 0) { + EC_KEY_free(ecKey); + return nullptr; + } + EC_KEY_free(ecKey); + } +#endif +#ifdef COSE_C_USE_MBEDTLS + { + keypair = + static_cast(COSE_CALLOC(sizeof(*keypair), 1, context) + ); + if (keypair == nullptr) { + return nullptr; + } + mbedtls_ecp_keypair_init(keypair); + if (!ECKey_From((COSE_KEY *) (HCOSE_KEY) key, keypair, &coseError)) { + mbedtls_ecp_keypair_free(keypair); + COSE_FREE(keypair, context); + return nullptr; + } + } +#endif + break; + + case COSE_Key_Type_OKP: +#ifdef COSE_C_USE_OPENSSL + +#endif + break; + + default: + break; + } + +#if defined(COSE_C_USE_OPENSSL) && (OPENSSL_VERSION_NUMBER > 0x10100000L) + + if (opensslKey == nullptr) { + return key.Release(); + } + else { + HCOSE_KEY key2 = + COSE_KEY_FromEVP(opensslKey, KeyFormat == 2 ? nullptr : pKeyOut, + CBOR_CONTEXT_PARAM_COMMA & coseError); + if (key2 == nullptr) { + EVP_PKEY_free(opensslKey); + } + else if (KeyFormat == 3) { + // M00BUG - figure out how to get it back. Might be a dup + // CN_CBOR_FREE(pKeyOut, context); + } + return key2; + } +#endif +#ifdef COSE_C_USE_MBEDTLS + if (keypair == nullptr) { + return key.Release(); + } + else { + HCOSE_KEY k2 = COSE_KEY_FromMbedKeypair(keypair, + KeyFormat == 2 ? nullptr : pKeyOut, COSE_KEY_FL_OWN, + CBOR_CONTEXT_PARAM_COMMA & coseError); + if (k2 == nullptr) { + mbedtls_ecp_keypair_free(keypair); + COSE_FREE(keypair, context); + } + else if (KeyFormat == 3) { + // see note above + // CN_CBOR_FREE(pKeyOut, context); + } + return k2; + } +#endif + + return nullptr; } bool Test_cn_cbor_array_replace() @@ -1418,6 +1527,7 @@ void RunTestsInDirectory(const char* szDir) } #endif // _MSCVER + int main(int argc, char** argv) { int i; @@ -1438,6 +1548,21 @@ int main(int argc, char** argv) else if (strcmp(argv[i], "--memory") == 0) { fMemory = true; } + else if (strcmp(argv[i], "--keyFormat=native") == 0) { + KeyFormat = 2; +#if defined(COSE_C_USE_OPENSSL) && (OPENSSL_VERSION_NUMBER < 0x10100000L) +#pragma message("OPENSSL VERSION does not support native key ") + + fprintf(stderr, + "Native key formats not supported for OpenSSL version " + "{%x}\n", + OPENSSL_VERSION_NUMBER); + exit(0); +#endif + } + else if (strcmp(argv[i], "--keyFormat=both") == 0) { + KeyFormat = 3; + } } else { szWhere = argv[i]; diff --git a/test/test.h b/test/test.h index a9a42038..36808ebb 100644 --- a/test/test.h +++ b/test/test.h @@ -148,7 +148,6 @@ int IsAlgorithmSupported(const cn_cbor* alg); handleName Release() \ { \ handleName h2 = h; \ - freeFunction(h); \ h = NULL; \ return h2; \ } \