Native key (#120)
* Forgot to do the formatting.
* Native keys can now be used for ECDSA
No other algoirthms are currently supported and I don't know what the behavior would be. Probably crash as that is what ECDH did on me. (I think.)
* Fix the error from the unuseful error message
* Is that the compile error - bad version of openssl
* If def with the Openssl version #
* Short cut native keys if openssl version not high enough.
* Is this compiling?
* Correct version number check for openssl
* Get the version checking right
diff --git a/include/cose/cose.h b/include/cose/cose.h
index 647b1b7..0cc424c 100644
--- a/include/cose/cose.h
+++ b/include/cose/cose.h
@@ -2,10 +2,14 @@
#include <stdbool.h>
#include <cn-cbor/cn-cbor.h>
+
#include "cose/cose_configure.h"
#ifdef COSE_C_USE_OPENSSL
#include <openssl/evp.h>
#endif
+#ifdef COSE_C_USE_MBEDTLS
+#include <mbedtls/ecp.h>
+#endif
#ifdef __cplusplus
extern "C" {
@@ -218,6 +222,10 @@
* 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 @@
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 717af12..236c05e 100644
--- a/src/CoseKey.cpp
+++ b/src/CoseKey.cpp
@@ -136,3 +136,37 @@
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 5209cc9..88d9907 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -6,6 +6,10 @@
#include <stdbool.h>
#ifdef COSE_C_USE_OPENSSL
#include <openssl/evp.h>
+#include <openssl/ec.h>
+#endif
+#ifdef COSE_C_USE_MBEDTLS
+#include <mbedtls/ecp.h>
#endif
// These definitions are here because they aren't required for the public
@@ -26,7 +30,7 @@
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 @@
#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 @@
#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 4294e86..5626192 100644
--- a/src/mbedtls.cpp
+++ b/src/mbedtls.cpp
@@ -666,10 +666,14 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 b9e54e0..f376fb4 100644
--- a/src/openssl.cpp
+++ b/src/openssl.cpp
@@ -1084,6 +1084,7 @@
#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 @@
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 aded8c8..85b893b 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -66,6 +66,10 @@
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}
COMMAND cose_test --dir Examples/eddsa-examples)
diff --git a/test/test.cpp b/test/test.cpp
index 9998be6..f515018 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 <openssl/ec.h>
+#endif
+
#ifdef COSE_C_USE_MBEDTLS
+#include <mbedtls/ecp.h>
+#include "mbedtls/ecdsa.h"
#include "mbedtls/entropy.h"
#endif
@@ -30,6 +37,7 @@
#endif
int CFails = 0;
+int KeyFormat = 1;
typedef struct _NameMap {
const char* sz;
@@ -849,18 +857,119 @@
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<mbedtls_ecp_keypair*>(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 @@
}
#endif // _MSCVER
+
int main(int argc, char** argv)
{
int i;
@@ -1438,6 +1548,21 @@
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 a9a4203..36808eb 100644
--- a/test/test.h
+++ b/test/test.h
@@ -148,7 +148,6 @@
handleName Release() \
{ \
handleName h2 = h; \
- freeFunction(h); \
h = NULL; \
return h2; \
} \