Skip to content

Commit 6f866d0

Browse files
authored
Merge pull request #594 from keldonin/implement_edwards_wrapping
implement wrapping and unwrapping of Edwards curve-based private keys
2 parents 3c941fb + a37c9b8 commit 6f866d0

File tree

4 files changed

+207
-1
lines changed

4 files changed

+207
-1
lines changed

src/lib/SoftHSM.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6541,7 +6541,9 @@ CK_RV SoftHSM::C_WrapKey
65416541
break;
65426542
#endif
65436543
#ifdef WITH_EDDSA
6544-
// Not yet
6544+
case CKK_EC_EDWARDS:
6545+
alg = AsymAlgo::EDDSA;
6546+
break;
65456547
#endif
65466548
#ifdef WITH_GOST
65476549
case CKK_GOSTR3410:
@@ -6577,6 +6579,11 @@ CK_RV SoftHSM::C_WrapKey
65776579
rv = getECPrivateKey((ECPrivateKey*)privateKey, token, key);
65786580
break;
65796581
#endif
6582+
#ifdef WITH_EDDSA
6583+
case CKK_EC_EDWARDS:
6584+
rv = getEDPrivateKey((EDPrivateKey*)privateKey, token, key);
6585+
break;
6586+
#endif
65806587
#ifdef WITH_GOST
65816588
case CKK_GOSTR3410:
65826589
rv = getGOSTPrivateKey((GOSTPrivateKey*)privateKey, token, key);
@@ -6996,6 +7003,12 @@ CK_RV SoftHSM::C_UnwrapKey
69967003
bOK = bOK && setECPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
69977004
}
69987005
#endif
7006+
#ifdef WITH_EDDSA
7007+
else if (keyType == CKK_EC_EDWARDS)
7008+
{
7009+
bOK = bOK && setEDPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
7010+
}
7011+
#endif
69997012
#ifdef WITH_GOST
70007013
else if (keyType == CKK_GOSTR3410)
70017014
{
@@ -12536,6 +12549,46 @@ bool SoftHSM::setECPrivateKey(OSObject* key, const ByteString &ber, Token* token
1253612549
return bOK;
1253712550
}
1253812551

12552+
bool SoftHSM::setEDPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
12553+
{
12554+
AsymmetricAlgorithm* ecc = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::EDDSA);
12555+
if (ecc == NULL)
12556+
return false;
12557+
PrivateKey* priv = ecc->newPrivateKey();
12558+
if (priv == NULL)
12559+
{
12560+
CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
12561+
return false;
12562+
}
12563+
if (!priv->PKCS8Decode(ber))
12564+
{
12565+
ecc->recyclePrivateKey(priv);
12566+
CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
12567+
return false;
12568+
}
12569+
// EC Private Key Attributes
12570+
ByteString group;
12571+
ByteString value;
12572+
if (isPrivate)
12573+
{
12574+
token->encrypt(((EDPrivateKey*)priv)->getEC(), group);
12575+
token->encrypt(((EDPrivateKey*)priv)->getK(), value);
12576+
}
12577+
else
12578+
{
12579+
group = ((EDPrivateKey*)priv)->getEC();
12580+
value = ((EDPrivateKey*)priv)->getK();
12581+
}
12582+
bool bOK = true;
12583+
bOK = bOK && key->setAttribute(CKA_EC_PARAMS, group);
12584+
bOK = bOK && key->setAttribute(CKA_VALUE, value);
12585+
12586+
ecc->recyclePrivateKey(priv);
12587+
CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
12588+
12589+
return bOK;
12590+
}
12591+
1253912592
bool SoftHSM::setGOSTPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
1254012593
{
1254112594
AsymmetricAlgorithm* gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);

src/lib/SoftHSM.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ class SoftHSM
442442
bool setDSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const;
443443
bool setDHPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const;
444444
bool setECPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const;
445+
bool setEDPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const;
445446
bool setGOSTPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const;
446447

447448

src/lib/test/SymmetricAlgorithmTests.cpp

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,48 @@ CK_RV SymmetricAlgorithmTests::generateRsaPrivateKey(CK_SESSION_HANDLE hSession,
392392
return rv;
393393
}
394394

395+
#ifdef WITH_EDDSA
396+
CK_RV SymmetricAlgorithmTests::generateEDPrivateKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey, EDCurveParam &curveparam)
397+
{
398+
CK_MECHANISM mechanism = { CKM_EC_EDWARDS_KEY_PAIR_GEN, NULL_PTR, 0 };
399+
CK_BYTE subject[] = { 0x12, 0x34 }; // dummy
400+
CK_BYTE id[] = { 123 } ; // dummy
401+
CK_BBOOL bTrue = CK_TRUE;
402+
CK_BBOOL bFalse = CK_FALSE;
403+
CK_ATTRIBUTE pubAttribs[] = {
404+
{ CKA_TOKEN, &bToken, sizeof(bToken) },
405+
{ CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
406+
{ CKA_SUBJECT, &subject[0], sizeof(subject) },
407+
{ CKA_ID, &id[0], sizeof(id) },
408+
{ CKA_VERIFY, &bTrue, sizeof(bTrue) },
409+
{ CKA_EC_PARAMS, const_cast<CK_BYTE *>(curveparam.data()), curveparam.size() }
410+
};
411+
CK_ATTRIBUTE privAttribs[] = {
412+
{ CKA_TOKEN, &bToken, sizeof(bToken) },
413+
{ CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
414+
{ CKA_SUBJECT, &subject[0], sizeof(subject) },
415+
{ CKA_ID, &id[0], sizeof(id) },
416+
{ CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
417+
{ CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
418+
{ CKA_SIGN, &bTrue, sizeof(bTrue) },
419+
};
420+
421+
CK_OBJECT_HANDLE hPub = CK_INVALID_HANDLE;
422+
hKey = CK_INVALID_HANDLE;
423+
CK_RV rv;
424+
rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
425+
pubAttribs, sizeof(pubAttribs)/sizeof(CK_ATTRIBUTE),
426+
privAttribs, sizeof(privAttribs)/sizeof(CK_ATTRIBUTE),
427+
&hPub, &hKey) );
428+
if (hPub != CK_INVALID_HANDLE)
429+
{
430+
CRYPTOKI_F_PTR( C_DestroyObject(hSession, hPub) );
431+
}
432+
return rv;
433+
}
434+
435+
#endif
436+
395437
#ifdef WITH_GOST
396438
CK_RV SymmetricAlgorithmTests::generateGostPrivateKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
397439
{
@@ -696,6 +738,102 @@ void SymmetricAlgorithmTests::aesWrapUnwrapGost(CK_MECHANISM_TYPE mechanismType,
696738
}
697739
#endif
698740

741+
#ifdef WITH_EDDSA
742+
void SymmetricAlgorithmTests::aesWrapUnwrapED(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
743+
{
744+
CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
745+
CK_BBOOL bFalse = CK_FALSE;
746+
CK_BBOOL bTrue = CK_TRUE;
747+
748+
std::map<std::string, EDCurveParam > curves {
749+
{ "ED25519", {0x06, 0x03, 0x2b, 0x65, 0x70} },
750+
{ "ED448", {0x06, 0x03, 0x2b, 0x65, 0x71} }
751+
};
752+
753+
for(auto &curve : curves) {
754+
const auto curvename = "Curve name: " + curve.first;
755+
756+
CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
757+
CK_RV rv = generateEDPrivateKey(hSession, CK_TRUE, CK_TRUE, hPrk, curve.second);
758+
CPPUNIT_ASSERT_MESSAGE(curvename, rv == CKR_OK);
759+
CPPUNIT_ASSERT_MESSAGE(curvename, hPrk != CK_INVALID_HANDLE);
760+
761+
CK_OBJECT_CLASS privateClass = CKO_PRIVATE_KEY;
762+
CK_KEY_TYPE keyType = CKK_EC_EDWARDS;
763+
CK_BYTE_PTR prkAttrPtr = NULL_PTR;
764+
CK_ULONG prkAttrLen = 0UL;
765+
CK_ATTRIBUTE prkAttribs[] = {
766+
{ CKA_CLASS, &privateClass, sizeof(privateClass) },
767+
{ CKA_KEY_TYPE, &keyType, sizeof(keyType) },
768+
{ CKA_VALUE, NULL_PTR, 0UL }
769+
};
770+
771+
rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPrk, prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE)) );
772+
CPPUNIT_ASSERT_MESSAGE(curvename, rv == CKR_OK);
773+
774+
CPPUNIT_ASSERT_MESSAGE(curvename, prkAttribs[0].ulValueLen == sizeof(CK_OBJECT_CLASS));
775+
CPPUNIT_ASSERT_MESSAGE(curvename, *(CK_OBJECT_CLASS*)prkAttribs[0].pValue == CKO_PRIVATE_KEY);
776+
CPPUNIT_ASSERT_MESSAGE(curvename, prkAttribs[1].ulValueLen == sizeof(CK_KEY_TYPE));
777+
CPPUNIT_ASSERT_MESSAGE(curvename, *(CK_KEY_TYPE*)prkAttribs[1].pValue == CKK_EC_EDWARDS);
778+
779+
prkAttrLen = prkAttribs[2].ulValueLen;
780+
prkAttrPtr = (CK_BYTE_PTR) malloc(2 * prkAttrLen);
781+
CPPUNIT_ASSERT_MESSAGE(curvename, prkAttrPtr != NULL_PTR);
782+
prkAttribs[2].pValue = prkAttrPtr;
783+
prkAttribs[2].ulValueLen = prkAttrLen;
784+
785+
rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPrk, prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE)) );
786+
CPPUNIT_ASSERT_MESSAGE(curvename, rv == CKR_OK);
787+
CPPUNIT_ASSERT_MESSAGE(curvename, prkAttribs[2].ulValueLen == prkAttrLen);
788+
789+
CK_BYTE_PTR wrappedPtr = NULL_PTR;
790+
CK_ULONG wrappedLen = 0UL;
791+
rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hPrk, wrappedPtr, &wrappedLen) );
792+
CPPUNIT_ASSERT_MESSAGE(curvename, rv == CKR_OK);
793+
wrappedPtr = (CK_BYTE_PTR) malloc(wrappedLen);
794+
CPPUNIT_ASSERT_MESSAGE(curvename, wrappedPtr != NULL_PTR);
795+
rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hPrk, wrappedPtr, &wrappedLen) );
796+
CPPUNIT_ASSERT_MESSAGE(curvename, rv == CKR_OK);
797+
798+
rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hPrk) );
799+
CPPUNIT_ASSERT_MESSAGE(curvename, rv == CKR_OK);
800+
801+
CK_ATTRIBUTE nPrkAttribs[] = {
802+
{ CKA_CLASS, &privateClass, sizeof(privateClass) },
803+
{ CKA_KEY_TYPE, &keyType, sizeof(keyType) },
804+
{ CKA_TOKEN, &bFalse, sizeof(bFalse) },
805+
{ CKA_PRIVATE, &bTrue, sizeof(bTrue) },
806+
{ CKA_DECRYPT, &bTrue, sizeof(bTrue) },
807+
{ CKA_SIGN, &bFalse,sizeof(bFalse) },
808+
{ CKA_UNWRAP, &bTrue, sizeof(bTrue) },
809+
{ CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
810+
{ CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) }
811+
};
812+
813+
hPrk = CK_INVALID_HANDLE;
814+
rv = CRYPTOKI_F_PTR( C_UnwrapKey(hSession, &mechanism, hKey, wrappedPtr, wrappedLen, nPrkAttribs, sizeof(nPrkAttribs)/sizeof(CK_ATTRIBUTE), &hPrk) );
815+
CPPUNIT_ASSERT_MESSAGE(curvename, rv == CKR_OK);
816+
CPPUNIT_ASSERT_MESSAGE(curvename, hPrk != CK_INVALID_HANDLE);
817+
818+
prkAttribs[2].pValue = prkAttrPtr + prkAttrLen;
819+
rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPrk, prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE)) );
820+
CPPUNIT_ASSERT_MESSAGE(curvename, rv == CKR_OK);
821+
822+
CPPUNIT_ASSERT_MESSAGE(curvename, prkAttribs[0].ulValueLen == sizeof(CK_OBJECT_CLASS));
823+
CPPUNIT_ASSERT_MESSAGE(curvename, *(CK_OBJECT_CLASS*)prkAttribs[0].pValue == CKO_PRIVATE_KEY);
824+
CPPUNIT_ASSERT_MESSAGE(curvename, prkAttribs[1].ulValueLen == sizeof(CK_KEY_TYPE));
825+
CPPUNIT_ASSERT_MESSAGE(curvename, *(CK_KEY_TYPE*)prkAttribs[1].pValue == CKK_EC_EDWARDS);
826+
CPPUNIT_ASSERT_MESSAGE(curvename, prkAttribs[2].ulValueLen == prkAttrLen);
827+
CPPUNIT_ASSERT_MESSAGE(curvename, memcmp(prkAttrPtr, prkAttrPtr + prkAttrLen, prkAttrLen) == 0);
828+
829+
free(wrappedPtr);
830+
free(prkAttrPtr);
831+
rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hPrk) );
832+
CPPUNIT_ASSERT_MESSAGE(curvename, rv == CKR_OK);
833+
}
834+
}
835+
#endif
836+
699837
void SymmetricAlgorithmTests::testAesEncryptDecrypt()
700838
{
701839
CK_RV rv;
@@ -792,6 +930,9 @@ void SymmetricAlgorithmTests::testAesWrapUnwrap()
792930
#ifdef WITH_GOST
793931
aesWrapUnwrapGost(CKM_AES_KEY_WRAP_PAD, hSession, hKey);
794932
#endif
933+
#ifdef WITH_EDDSA
934+
aesWrapUnwrapED(CKM_AES_KEY_WRAP_PAD, hSession, hKey);
935+
#endif
795936
#endif
796937
}
797938

src/lib/test/SymmetricAlgorithmTests.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#ifndef _SOFTHSM_V2_SYMENCRYPTDECRYPTTESTS_H
3434
#define _SOFTHSM_V2_SYMENCRYPTDECRYPTTESTS_H
3535

36+
#include <array>
3637
#include "TestsBase.h"
3738
#include <cppunit/extensions/HelperMacros.h>
3839

@@ -85,6 +86,16 @@ class SymmetricAlgorithmTests : public TestsBase
8586
void aesWrapUnwrapGost(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey);
8687
CK_RV generateGostPrivateKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
8788
#endif
89+
#ifdef WITH_EDDSA
90+
using EDCurveParam = const std::array<CK_BYTE, 5>;
91+
void aesWrapUnwrapED(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey);
92+
CK_RV generateEDPrivateKey(CK_SESSION_HANDLE hSession,
93+
CK_BBOOL bToken,
94+
CK_BBOOL bPrivate,
95+
CK_OBJECT_HANDLE &hKey,
96+
EDCurveParam &curveparam);
97+
#endif
98+
8899
};
89100

90101
#endif // !_SOFTHSM_V2_SYMENCRYPTDECRYPTTESTS_H

0 commit comments

Comments
 (0)