EdDSA support added for openssl (#82)
* Add EDDSA for OpenSSL
* No support for EdDSA in MBEDTLS
* Install OpenSSL v1.1.1f in order to get EdDSA support in OpenSSL
diff --git a/.ci/build-openssl.sh b/.ci/build-openssl.sh
new file mode 100644
index 0000000..e483f77
--- /dev/null
+++ b/.ci/build-openssl.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+set -eux
+
+download_openssl () {
+ if [[ ! -f "download-cache/openssl-${OPENSSL_VERSION}.tar.gz" ]]; then
+ wget -P download-cache/ \
+ "https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz"
+ fi
+}
+
+build_openssl () {
+ if [[ "$(cat ${OPENSSL_INSTALL_DIR}/.openssl-version)" != "${OPENSSL_VERSION}" ]]; then
+ tar zxf "download-cache/openssl-${OPENSSL_VERSION}.tar.gz"
+ cd "openssl-${OPENSSL_VERSION}/"
+ ./config shared no-deprecated --prefix="${OPENSSL_INSTALL_DIR}" --openssldir="${OPENSSL_INSTALL_DIR}" -DPURIFY
+ make -j $(nproc || sysctl -n hw.ncpu || echo 4) all
+ make install_sw
+ echo "${OPENSSL_VERSION}" > "${OPENSSL_INSTALL_DIR}/.openssl-version"
+ fi
+}
+
+
+download_openssl
+build_openssl
diff --git a/.travis.yml b/.travis.yml
index a146184..9a3b1d5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,22 +3,24 @@
- clang
- gcc
sudo: false
-before_install:
- - pip install cpp-coveralls --user
- - export LD_LIBRARY_PATH=$PWD/build/dist/lib:$LD_LIBRARY_PATH
env:
- - USE_CONTEXT=ON
- COVERALLS="-DCOSE_C_COVERALLS_SEND=ON"
- - USE_CONTEXT=OFF
- COVERALLS="-DCOSE_C_COVERALLS_SEND=ON"
- - USE_CONTEXT=OFF USE_EMBEDTLS=ON
- COVERALLS="-DCOSE_C_COVERALLS_SEND=ON"
- - CMAKE_OPTIONS="-DCOSE_C_INCLUDE_ENCRYPT=ON -DCOSE_C_INCLUDE_encrypt0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF"
- - CMAKE_OPTIONS="-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_encrypt0=ON -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF"
- - CMAKE_OPTIONS="-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_encrypt0=OFF -DCOSE_C_INCLUDE_MAC0=ON -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF"
- - CMAKE_OPTIONS="-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_encrypt0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=ON -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF"
- - CMAKE_OPTIONS="-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_encrypt0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=ON -DCOSE_C_INCLUDE_SIGN1=OFF"
- - CMAKE_OPTIONS="-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_encrypt0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=ON"
+ global:
+ - OPENSSL_VERSION="1.1.1f"
+ OPENSSL_INSTALL_DIR="${HOME}/opt"
+ jobs:
+ - USE_CONTEXT=ON
+ COVERALLS="-DCOSE_C_COVERALLS_SEND=ON"
+ - USE_CONTEXT=OFF
+ COVERALLS="-DCOSE_C_COVERALLS_SEND=ON"
+ - USE_CONTEXT=OFF USE_EMBEDTLS=ON
+ COVERALLS="-DCOSE_C_COVERALLS_SEND=ON"
+ - CMAKE_OPTIONS="-DCOSE_C_INCLUDE_ENCRYPT=ON -DCOSE_C_INCLUDE_encrypt0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF"
+ - CMAKE_OPTIONS="-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_encrypt0=ON -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF"
+ - CMAKE_OPTIONS="-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_encrypt0=OFF -DCOSE_C_INCLUDE_MAC0=ON -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF"
+ - CMAKE_OPTIONS="-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_encrypt0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=ON -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=OFF"
+ - CMAKE_OPTIONS="-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_encrypt0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=ON -DCOSE_C_INCLUDE_SIGN1=OFF"
+ - CMAKE_OPTIONS="-DCOSE_C_INCLUDE_ENCRYPT=OFF -DCOSE_C_INCLUDE_encrypt0=OFF -DCOSE_C_INCLUDE_MAC0=OFF -DCOSE_C_INCLUDE_MAC=OFF -DCOSE_C_INCLUDE_SIGN=OFF -DCOSE_C_INCLUDE_SIGN1=ON"
+
matrix:
exclude:
- compiler: clang
@@ -31,12 +33,19 @@
- llvm-toolchain-precise-3.8
- george-edison55-precise-backports
packages:
- - libssl-dev
-# - libssl1.1.0
+ # - libssl-dev
+ # - libssl1.1
- cmake
- cmake-data
+
+before_install:
+ - pip install cpp-coveralls --user
+ - export LD_LIBRARY_PATH=$PWD/build/dist/lib:$LD_LIBRARY_PATH
+ - bash .ci/build-openssl.sh > build-deps.log 2>&1 || (cat build-deps.log && exit 1)
+
script:
# - apt-get install libssl1.1.0
+ - export OPENSSL_ROOT_DIR=${OPENSSL_INSTALL_DIR}
- cmake --version
- git clone --depth 1 git://github.com/cose-wg/Examples Examples
- mkdir build
diff --git a/include/cose/cose.h b/include/cose/cose.h
index 8b197d4..d767c85 100644
--- a/include/cose/cose.h
+++ b/include/cose/cose.h
@@ -132,6 +132,8 @@
COSE_Algorithm_Direct = -6,
+ COSE_Algorithm_EdDSA = - 8,
+
COSE_Algorithm_Direct_HKDF_HMAC_SHA_256 = -10,
COSE_Algorithm_Direct_HKDF_HMAC_SHA_512 = -11,
COSE_Algorithm_Direct_HKDF_AES_128 = -12,
@@ -177,6 +179,7 @@
} COSE_Header;
typedef enum {
+ COSE_Key_Type_OKP = 1,
COSE_Key_Type_EC2 = 2,
COSE_Key_Type_OCTET = 4,
COSE_Key_Type = 1,
@@ -184,9 +187,20 @@
COSE_Parameter_KID = 4,
COSE_Key_EC2_Curve=-1,
COSE_Key_EC2_X = -2,
- COSE_Key_EC2_Y = -3
+ COSE_Key_EC2_Y = -3,
+ COSE_Key_OPK_Curve = -1,
+ COSE_Key_OPK_X = -2,
} COSE_Constants;
+typedef enum {
+ COSE_Curve_P256 = 1,
+ COSE_Curve_P384 = 2,
+ COSE_Curve_P521 = 3,
+ COSE_Curve_X25519 = 4,
+ COSE_Curve_X448 = 5,
+ COSE_Curve_Ed25519 = 6,
+ COSE_Curve_Ed448 = 7,
+} COSE_Curves;
/*
* messages dealing with the Enveloped message type
diff --git a/include/cose/cose_configure.h b/include/cose/cose_configure.h
index 978c36e..dfabc96 100644
--- a/include/cose/cose_configure.h
+++ b/include/cose/cose_configure.h
@@ -13,6 +13,7 @@
#error Only Define One Crypto Package
#endif
#elif !defined(USE_OPEN_SSL)
+#include <openssl/opensslv.h>
#define USE_OPEN_SSL
#endif
@@ -131,7 +132,16 @@
#define USE_ECDSA_SHA_256
#define USE_ECDSA_SHA_384
#define USE_ECDSA_SHA_512
-
+#if !defined(USE_MBED_TLS)
+// MBEDTLS currently supports ECDH for X25519 but not EdDSA
+#if OPENSSL_VERSION_NUMBER > 0x10100000L
+// Requires OPEN SSL 1.1.1 to build
+#define USE_EDDSA
+#else
+#pragma message("OPENSSL VERSION IS ")
+#pragma message(OPENSSL_VERISON_NUMBER)
+#endif
+#endif // !defined (USE_MBED_TLS)
//#define USE_COUNTER_SIGNATURES
diff --git a/src/Sign1.c b/src/Sign1.c
index ae9c405..93364b8 100644
--- a/src/Sign1.c
+++ b/src/Sign1.c
@@ -369,6 +369,13 @@
f = ECDSA_Sign(&pSigner->m_message, INDEX_SIGNATURE+1, pKey, 512, pbToSign, cbToSign, perr);
break;
#endif
+
+#ifdef USE_EDDSA
+ case COSE_Algorithm_EdDSA:
+ f = EdDSA_Sign(&pSigner->m_message, INDEX_SIGNATURE + 1, pKey, pbToSign, cbToSign, perr);
+ break;
+#endif
+
default:
FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
}
@@ -429,6 +436,12 @@
break;
#endif
+#ifdef USE_EDDSA
+ case COSE_Algorithm_EdDSA:
+ if (!EdDSA_Verify(&pSign->m_message, INDEX_SIGNATURE + 1, pKey, pbToSign, cbToSign, perr)) goto errorReturn;
+ break;
+#endif
+
default:
FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
break;
diff --git a/src/SignerInfo.c b/src/SignerInfo.c
index 33b01d9..82e3a24 100644
--- a/src/SignerInfo.c
+++ b/src/SignerInfo.c
@@ -179,7 +179,6 @@
cn_cbor * cnAlgorithm = NULL;
size_t cbToSign;
byte * pbToSign = NULL;
- bool f;
int alg;
bool fRet = false;
@@ -222,6 +221,12 @@
break;
#endif
+#ifdef USE_EDDSA
+ case COSE_Algorithm_EdDSA:
+ if (!EdDSA_Sign(&pSigner->m_message, INDEX_SIGNATURE, pSigner->m_pkey, pbToSign, cbToSign, perr)) goto errorReturn;
+ break;
+#endif
+
default:
FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
}
@@ -334,6 +339,12 @@
break;
#endif
+#ifdef USE_EDDSA
+ case COSE_Algorithm_EdDSA:
+ if (!EdDSA_Verify(&pSigner->m_message, INDEX_SIGNATURE, pSigner->m_pkey, pbToBeSigned, cbToBeSigned, perr)) goto errorReturn;
+ break;
+#endif
+
default:
FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
break;
diff --git a/src/crypto.h b/src/crypto.h
index 2caebf1..9afb3d6 100644
--- a/src/crypto.h
+++ b/src/crypto.h
@@ -67,6 +67,9 @@
bool ECDH_ComputeSecret(COSE * pReciient, cn_cbor ** ppKeyMe, const cn_cbor * pKeyYou, byte ** ppbSecret, size_t * pcbSecret, CBOR_CONTEXT_COMMA cose_errback *perr);
+bool EdDSA_Sign(COSE* pSigner, int index, const cn_cbor* pKey, const byte* rgbToSign, size_t cbToSign, cose_errback* perr);
+bool EdDSA_Verify(COSE* pSigner, int index, const cn_cbor* pKey, const byte* rgbToSign, size_t cbToSign, cose_errback* perr);
+
/**
* Generate random bytes in a buffer
*
diff --git a/src/openssl.c b/src/openssl.c
index 2ace55c..229ba29 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -1118,6 +1118,137 @@
return true;
}
+
+#ifdef USE_EDDSA
+bool EdDSA_Sign(COSE* pSigner, int index, const cn_cbor* pKeyIn, const byte* rgbToSign, size_t cbToSign, cose_errback* perr)
+{
+#ifdef USE_CBOR_CONTEXT
+ cn_cbor_context* context = &pSigner->m_allocContext;
+#endif
+ cn_cbor* p;
+ cn_cbor_errback cbor_error;
+ EVP_PKEY_CTX* keyCtx = NULL;
+ EVP_MD_CTX* mdCtx = NULL;
+ EVP_PKEY* pkey = NULL;
+ byte* pbSig = NULL;
+ int cbSig;
+
+ p = cn_cbor_mapget_int(pKeyIn, COSE_Key_OPK_Curve);
+ if (p == NULL) {
+ errorReturn:
+ if (mdCtx != NULL) EVP_MD_CTX_free(mdCtx);
+ if (keyCtx != NULL) EVP_PKEY_CTX_free(keyCtx);
+ if (pkey != NULL) EVP_PKEY_free(pkey);
+ if (pbSig != NULL) COSE_FREE(pbSig, context);
+ return false;
+ }
+
+ int type;
+
+ switch (p->v.uint) {
+ case COSE_Curve_Ed25519:
+ type = EVP_PKEY_ED25519;
+ cbSig = 32 * 2;
+ break;
+
+ case COSE_Curve_Ed448:
+ type = EVP_PKEY_ED448;
+ cbSig = 64 * 2;
+ break;
+
+ default:
+ FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+ }
+
+ p = cn_cbor_mapget_int(pKeyIn, COSE_Key_EC_d);
+ CHECK_CONDITION(p != NULL, COSE_ERR_INVALID_PARAMETER);
+
+ pkey = EVP_PKEY_new_raw_private_key(type, NULL, p->v.bytes, p->length);
+ CHECK_CONDITION(pkey != NULL, COSE_ERR_CRYPTO_FAIL);
+
+ keyCtx = EVP_PKEY_CTX_new_id(type, NULL);
+ CHECK_CONDITION(keyCtx != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+ mdCtx = EVP_MD_CTX_new();
+ CHECK_CONDITION(mdCtx != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+ CHECK_CONDITION(EVP_DigestSignInit(mdCtx, &keyCtx, NULL, NULL, pkey) == 1, COSE_ERR_CRYPTO_FAIL);
+ keyCtx = NULL;
+
+ pbSig = COSE_CALLOC(cbSig, 1, context);
+ CHECK_CONDITION(pbSig != NULL, COSE_ERR_OUT_OF_MEMORY);
+
+ size_t cb2 = cbSig;
+ CHECK_CONDITION(EVP_DigestSign(mdCtx, pbSig, &cb2, rgbToSign, cbToSign) == 1, COSE_ERR_CRYPTO_FAIL);
+
+ p = cn_cbor_data_create(pbSig, (int)cb2, CBOR_CONTEXT_PARAM_COMMA & cbor_error);
+ CHECK_CONDITION(p != NULL, COSE_ERR_OUT_OF_MEMORY);
+ pbSig = NULL;
+
+ CHECK_CONDITION(_COSE_array_replace(pSigner, p, index, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR);
+
+ if (mdCtx != NULL) EVP_MD_CTX_free(mdCtx);
+ if (keyCtx != NULL) EVP_PKEY_CTX_free(keyCtx);
+ if (pkey != NULL) EVP_PKEY_free(pkey);
+ if (pbSig != NULL) COSE_FREE(pbSig, context);
+
+ return true;
+}
+
+bool EdDSA_Verify(COSE* pSigner, int index, const cn_cbor* pKey, const byte* rgbToSign, size_t cbToSign, cose_errback* perr)
+{
+#ifdef USE_CBOR_CONTEXT
+ cn_cbor_context* context = &pSigner->m_allocContext;
+#endif
+ cn_cbor* p = NULL;
+ cn_cbor* pSig;
+ EVP_PKEY* pkey = NULL;
+
+ p = cn_cbor_mapget_int(pKey, COSE_Key_OPK_Curve);
+ if (p == NULL) {
+ errorReturn:
+ if (pkey != NULL) EVP_PKEY_free(pkey);
+ return false;
+ }
+
+ int type;
+
+ switch (p->v.uint) {
+ case COSE_Curve_Ed25519:
+ type = EVP_PKEY_ED25519;
+ break;
+
+ case COSE_Curve_Ed448:
+ type = EVP_PKEY_ED448;
+ break;
+
+ default:
+ FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+ }
+
+ p = cn_cbor_mapget_int(pKey, COSE_Key_OPK_X);
+ CHECK_CONDITION(p != NULL, COSE_ERR_INVALID_PARAMETER);
+
+ pkey = EVP_PKEY_new_raw_public_key(type, NULL, p->v.bytes, p->length);
+ CHECK_CONDITION(pkey != NULL, COSE_ERR_CBOR);
+
+ pSig = _COSE_arrayget_int(pSigner, index);
+ CHECK_CONDITION(pSig != NULL, COSE_ERR_INVALID_PARAMETER);
+
+ EVP_MD_CTX* pmdCtx = EVP_MD_CTX_new();
+ EVP_PKEY_CTX* keyCtx = EVP_PKEY_CTX_new_id(type, NULL);
+
+ CHECK_CONDITION(EVP_DigestVerifyInit(pmdCtx, &keyCtx, NULL, NULL, pkey) == 1, COSE_ERR_CRYPTO_FAIL);
+
+ CHECK_CONDITION(EVP_DigestVerify(pmdCtx, pSig->v.bytes, pSig->length, rgbToSign, cbToSign) == 1, COSE_ERR_CRYPTO_FAIL);
+
+ if (pmdCtx != NULL) EVP_MD_CTX_free(pmdCtx);
+ if (pkey != NULL) EVP_PKEY_free(pkey);
+
+ return true;
+}
+#endif
+
bool AES_KW_Decrypt(COSE_Enveloped * pcose, const byte * pbKeyIn, size_t cbitKey, const byte * pbCipherText, size_t cbCipherText, byte * pbKeyOut, int * pcbKeyOut, cose_errback * perr)
{
byte rgbOut[512 / 8];
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index d8b48cc..b95743f 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -57,6 +57,10 @@
NAME ecdsa
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND cose_test --dir Examples/ecdsa-examples)
+add_test(
+ NAME eddsa
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMAND cose_test --dir Examples/eddsa-examples)
add_test(
NAME hmac
@@ -150,3 +154,11 @@
NAME Memory-sign
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND cose_test --memory Examples/ecdsa-examples/ecdsa-01.json)
+add_test(
+ NAME Memory-sign0-eddsa
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMAND cose_test --memory Examples/eddsa-examples/eddsa-sig-01.json)
+add_test(
+ NAME Memory-sign-eddsa
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMAND cose_test --memory Examples/eddsa-examples/eddsa-01.json)
diff --git a/test/json.c b/test/json.c
index e7931d0..9a99ecd 100644
--- a/test/json.c
+++ b/test/json.c
@@ -249,3 +249,37 @@
void base64_cleanup() {
free(decoding_table);
}
+
+unsigned char* hex_decode(const char* data,
+ size_t input_length,
+ size_t* output_length) {
+
+ if (input_length % 2 != 0) {
+ return NULL;
+ }
+
+ *output_length = input_length / 2;
+
+ unsigned char* decoded_data = malloc(*output_length);
+ if (decoded_data == NULL) {
+ return NULL;
+ }
+
+ for (unsigned int i = 0, j = 0; i < input_length; i++) {
+ int c;
+
+ if ('0' <= data[i] && data[i] <= '9') c = data[i] - '0';
+ else if ('A' <= data[i] && data[i] <= 'F') c = data[i] - 'A' + 10;
+ else if ('a' <= data[i] && data[i] <= 'f') c = data[i] - 'a' + 10;
+ else return NULL;
+
+ if ((i & 0x1) == 0) {
+ decoded_data[j] = ((unsigned char) c << 4);
+ }
+ else {
+ decoded_data[j++] |= (unsigned char)c;
+ }
+ }
+
+ return decoded_data;
+}
diff --git a/test/json.h b/test/json.h
index 4dbabf3..4e2d60f 100644
--- a/test/json.h
+++ b/test/json.h
@@ -3,3 +3,4 @@
extern const cn_cbor * ParseJson(const char * fileName);
extern unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length);
+extern unsigned char* hex_decode(const char* data, size_t input_length, size_t* output_length);
diff --git a/test/test.c b/test/test.c
index 209af1b..bc110f1 100644
--- a/test/test.c
+++ b/test/test.c
@@ -33,7 +33,7 @@
int i;
} NameMap;
-NameMap RgAlgorithmNames[47] = {
+NameMap RgAlgorithmNames[48] = {
{"HS256", COSE_Algorithm_HMAC_256_256},
{"HS256/64", COSE_Algorithm_HMAC_256_64},
{"HS384", COSE_Algorithm_HMAC_384_384},
@@ -81,13 +81,18 @@
{ "ECDH-SS-A128KW", COSE_Algorithm_ECDH_SS_A128KW },
{ "ECDH-SS-A192KW", COSE_Algorithm_ECDH_SS_A192KW },
{ "ECDH-SS-A256KW", COSE_Algorithm_ECDH_SS_A256KW },
+ { "EdDSA", COSE_Algorithm_EdDSA},
};
-NameMap RgCurveNames[3] = {
+NameMap RgCurveNames[7] = {
{"P-256", 1},
{"P-384", 2},
- {"P-521", 3}
+ {"P-521", 3},
+ {"X25519", 4},
+ {"X448", 5},
+ {"Ed25519", 6},
+ {"Ed448", 7}
};
int MapName(const cn_cbor * p, NameMap * rgMap, unsigned int cMap)
@@ -259,6 +264,9 @@
#ifdef USE_HMAC_512_512
case COSE_Algorithm_HMAC_512_512:
#endif
+#ifdef USE_EDDSA
+ case COSE_Algorithm_EdDSA:
+#endif
case COSE_Algorithm_Direct:
case -999: // Unsupported algorithm for testing.
return true;
@@ -300,20 +308,24 @@
#define OPERATION_BASE64 1
#define OPERATION_IGNORE 2
#define OPERATION_STRING 3
+#define OPERATION_HEX 4
struct {
char * szKey;
int kty;
int operation;
int keyNew;
-} RgStringKeys[7] = {
+} RgStringKeys[10] = {
{ "kty", 0, OPERATION_IGNORE, COSE_Key_Type},
{ "kid", 0, OPERATION_NONE, COSE_Key_ID},
{ "crv", 2, OPERATION_STRING, COSE_Key_EC2_Curve},
{ "x", 2, OPERATION_BASE64, COSE_Key_EC2_X},
{ "y", 2, OPERATION_BASE64, COSE_Key_EC2_Y},
{ "d", 2, OPERATION_BASE64, -4},
- { "k", 4, OPERATION_BASE64, -1}
+ { "k", 4, OPERATION_BASE64, -1},
+ { "crv", COSE_Key_Type_OKP, OPERATION_STRING, COSE_Key_OPK_Curve},
+ { "x_hex", COSE_Key_Type_OKP, OPERATION_HEX, COSE_Key_OPK_X},
+ { "d_hex", COSE_Key_Type_OKP, OPERATION_HEX, -4}
};
bool SetAttributes(HCOSE hHandle, const cn_cbor * pAttributes, int which, int msgType, bool fPublicKey)
@@ -563,6 +575,7 @@
}
else if (pKty->length == 3) {
if (strncmp(pKty->v.str, "oct", 3) == 0) kty = 4;
+ else if (strncmp(pKty->v.str, "OKP", 3) == 0) kty = COSE_Key_Type_OKP;
else return NULL;
}
else return NULL;
@@ -575,7 +588,7 @@
pValue = pKey->next;
if (pKey->type == CN_CBOR_TEXT) {
- for (i = 0; i < 7; i++) {
+ for (i = 0; i < sizeof(RgStringKeys)/sizeof(RgStringKeys[0]); i++) {
if ((pKey->length == strlen(RgStringKeys[i].szKey)) &&
(strncmp(pKey->v.str, RgStringKeys[i].szKey, strlen(RgStringKeys[i].szKey)) == 0) &&
((RgStringKeys[i].kty == 0) || (RgStringKeys[i].kty == kty))) {
@@ -600,6 +613,14 @@
if (p == NULL) return NULL;
if (!cn_cbor_mapput_int(pKeyOut, RgStringKeys[i].keyNew, p, CBOR_CONTEXT_PARAM_COMMA NULL)) return NULL;
break;
+
+ case OPERATION_HEX:
+ if ((strcmp(pKey->v.str, "d_hex") == 0) && fPublicKey) continue;
+ pb = hex_decode(pValue->v.str, pValue->length, &cb);
+ p = cn_cbor_data_create(pb, (int)cb, CBOR_CONTEXT_PARAM_COMMA NULL);
+ if (p == NULL) return NULL;
+ if (!cn_cbor_mapput_int(pKeyOut, RgStringKeys[i].keyNew, p, CBOR_CONTEXT_PARAM_COMMA NULL)) return NULL;
+ break;
}
i = 99;
}
@@ -695,9 +716,7 @@
bool fValidateDone = false;
bool fBuildDone = false;
- for (iFail = 0; !fValidateDone || !fBuildDone; iFail++) {
- context = CreateContext(iFail);
-
+ for (iFail = 0; (!fValidateDone || !fBuildDone) && (iFail < 3); iFail++) {
if (cn_cbor_mapget_string(pInput, "mac") != NULL) {
#if INCLUDE_MAC
if (!fValidateDone) {
@@ -705,6 +724,7 @@
CFails = 0;
ValidateMAC(pControl);
if (CFails == 0) fValidateDone = true;
+ FreeContext(context);
}
if (!fBuildDone) {
@@ -712,6 +732,7 @@
CFails = 0;
BuildMacMessage(pControl);
if (CFails == 0) fBuildDone = true;
+ FreeContext(context);
}
#else
fValidateDone = true;
@@ -725,6 +746,7 @@
CFails = 0;
ValidateMac0(pControl);
if (CFails == 0) fValidateDone = true;
+ FreeContext(context);
}
if (!fBuildDone) {
@@ -732,6 +754,7 @@
CFails = 0;
BuildMac0Message(pControl);
if (CFails == 0) fBuildDone = true;
+ FreeContext(context);
}
#else
fValidateDone = true;
@@ -745,6 +768,7 @@
CFails = 0;
ValidateEncrypt(pControl);
if (CFails == 0) fValidateDone = true;
+ FreeContext(context);
}
if (!fBuildDone) {
@@ -752,6 +776,7 @@
CFails = 0;
BuildEncryptMessage(pControl);
if (CFails == 0) fBuildDone = true;
+ FreeContext(context);
}
#else
fValidateDone = true;
@@ -765,6 +790,7 @@
CFails = 0;
ValidateEnveloped(pControl);
if (CFails == 0) fValidateDone = true;
+ FreeContext(context);
}
if (!fBuildDone) {
@@ -772,6 +798,7 @@
CFails = 0;
BuildEnvelopedMessage(pControl);
if (CFails == 0) fBuildDone = true;
+ FreeContext(context);
}
#else
fValidateDone = true;
@@ -785,6 +812,7 @@
CFails = 0;
ValidateSigned(pControl);
if (CFails == 0) fValidateDone = true;
+ FreeContext(context);
}
if (!fBuildDone) {
@@ -792,6 +820,7 @@
CFails = 0;
BuildSignedMessage(pControl);
if (CFails == 0) fBuildDone = true;
+ FreeContext(context);
}
#else
fValidateDone = true;
@@ -805,6 +834,7 @@
CFails = 0;
ValidateSign1(pControl);
if (CFails == 0) fValidateDone = true;
+ FreeContext(context);
}
if (!fBuildDone) {
@@ -812,6 +842,7 @@
CFails = 0;
BuildSign1Message(pControl);
if (CFails == 0) fBuildDone = true;
+ FreeContext(context);
}
#else
fValidateDone = true;