From 9e4dcef12946b4b4b609e02ede18252521451cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Skalski?= Date: Tue, 9 Nov 2021 11:45:57 +0100 Subject: [PATCH] add support for ECDH key derivation Add support for CKM_ECDH1_DERIVE mechanism - add definitions of required structures, And `C_DeriveKey()` function support Note: All DH mechanisms shall be aded (not only ECDH1) --- PyKCS11/__init__.py | 56 +++++++++++++++++++++++++++++++++++++++++++++ src/opensc/pkcs11.h | 16 +++++++++++++ src/pkcs11lib.cpp | 28 +++++++++++++++++++++++ src/pkcs11lib.h | 7 ++++++ src/pykcs11.i | 38 +++++++++++++++++++++++++++--- 5 files changed, 142 insertions(+), 3 deletions(-) diff --git a/PyKCS11/__init__.py b/PyKCS11/__init__.py index 44974d8..87feb96 100644 --- a/PyKCS11/__init__.py +++ b/PyKCS11/__init__.py @@ -31,6 +31,7 @@ CKA = {} CKC = {} +CKD = {} CKF = {} CKG = {} CKH = {} @@ -46,6 +47,7 @@ for x in PyKCS11.LowLevel.__dict__.keys(): if x[:4] == 'CKA_' \ or x[:4] == 'CKC_' \ + or x[:4] == 'CKD_' \ or x[:4] == 'CKF_' \ or x[:4] == 'CKG_' \ or x[:4] == 'CKH_' \ @@ -827,6 +829,38 @@ def __init__(self, mecha, hashAlg, mgf, sLen): def to_native(self): return self._mech +class ECDH1_DERIVE_Mechanism(object): + """CKM_ECDH1_DERIVE key derivation mechanism""" + + def __init__(self, kdf, sharedData, publicData): + """ + :param kdf: Key derivation function + :param sharedData: additional shared data + :param publicData: Other party public key (encoded uncompressed or concatenated x and y coordinates) + """ + self._param = PyKCS11.LowLevel.CK_ECDH1_DERIVE_PARAMS() + + self._param.kdf = kdf + + if sharedData: + self._shared_data = ckbytelist(sharedData) + self._param.pSharedData = self._shared_data + self._param.ulSharedDataLen = len(self._shared_data) + else: + self._source_shared_data = None + + self._public_data = ckbytelist(publicData) + self._param.pPublicData = self._public_data + self._param.ulPublicDataLen = len(self._public_data) + + self._mech = PyKCS11.LowLevel.CK_MECHANISM() + self._mech.mechanism = CKM_ECDH1_DERIVE + self._mech.pParameter = self._param + self._mech.ulParameterLen = PyKCS11.LowLevel.CK_ECDH1_DERIVE_PARAMS_LENGTH + + def to_native(self): + return self._mech + class DigestSession(object): def __init__(self, lib, session, mecha): @@ -1255,6 +1289,28 @@ def unwrapKey(self, unwrappingKey, wrappedKey, template, raise PyKCS11Error(rv) return handle + def deriveKey(self, baseKey, template, mecha): + """ + C_DeriveKey + + :param baseKey: the base key handle + :type baseKey: integer + :param template: template for the unwrapped key + :param mecha: the decrypt mechanism to be used (use + `ECDH1_DERIVE_Mechanism(...)` for `CKM_ECDH1_DERIVE`) + :type mecha: :class:`Mechanism` + :return: the unwrapped key object + :rtype: integer + + """ + m = mecha.to_native() + handle = PyKCS11.LowLevel.CK_OBJECT_HANDLE() + attrs = self._template2ckattrlist(template) + rv = self.lib.C_DeriveKey(self.session, m, baseKey, attrs, handle) + if rv != CKR_OK: + raise PyKCS11Error(rv) + return handle + def isNum(self, type): """ is the type a numerical value? diff --git a/src/opensc/pkcs11.h b/src/opensc/pkcs11.h index a60d885..96899a9 100644 --- a/src/opensc/pkcs11.h +++ b/src/opensc/pkcs11.h @@ -166,6 +166,8 @@ extern "C" { #define source_data pSourceData #define source_data_len ulSourceDataLen +#define ck_ecdh1_derive_params CK_ECDH1_DERIVE_PARAMS + #define ck_rv_t CK_RV #define ck_notify_t CK_NOTIFY @@ -682,6 +684,11 @@ typedef unsigned long ck_mechanism_type_t; #define CKG_MGF1_SHA384 (0x00000003) #define CKG_MGF1_SHA512 (0x00000004) +#define CKD_NULL (0x00000001) +#define CKD_SHA1_KDF (0x00000002) +#define CKD_SHA1_KDF_ASN1 (0x00000003) +#define CKD_SHA1_KDF_CONCATENATE (0x00000004) + struct ck_mechanism { @@ -722,6 +729,15 @@ struct ck_gcm_params { unsigned long ulTagBits; } ; +struct ck_ecdh1_derive_params { + unsigned long kdf; + unsigned long ulSharedDataLen; + void * pSharedData; + unsigned long ulPublicDataLen; + void * pPublicData; +} ; + + #define CKF_HW (1 << 0) #define CKF_ENCRYPT (1 << 8) #define CKF_DECRYPT (1 << 9) diff --git a/src/pkcs11lib.cpp b/src/pkcs11lib.cpp index 86dd8ee..7bddb7d 100644 --- a/src/pkcs11lib.cpp +++ b/src/pkcs11lib.cpp @@ -920,6 +920,34 @@ CK_RV CPKCS11Lib::C_UnwrapKey( return rv; } + +CK_RV CPKCS11Lib::C_DeriveKey( + CK_SESSION_HANDLE hSession, + CK_MECHANISM *pMechanism, + CK_OBJECT_HANDLE hBaseKey, + vector Template, + CK_OBJECT_HANDLE & outKey) +{ + CPKCS11LIB_PROLOGUE(C_DeriveKey); + CK_OBJECT_HANDLE hKey = static_cast(outKey); + + CK_ULONG ulAttributeCount = 0; + CK_ATTRIBUTE* pTemplate = AttrVector2Template(Template, ulAttributeCount); + + rv = m_pFunc->C_DeriveKey(hSession, + pMechanism, + hBaseKey, + pTemplate, + ulAttributeCount, + &hKey); + + if (pTemplate) + DestroyTemplate(pTemplate, ulAttributeCount); + outKey = static_cast(hKey); + CPKCS11LIB_EPILOGUE; + return rv; +} + CK_RV CPKCS11Lib::C_SeedRandom( CK_SESSION_HANDLE hSession, vector Seed) diff --git a/src/pkcs11lib.h b/src/pkcs11lib.h index 2c53679..4738b3b 100644 --- a/src/pkcs11lib.h +++ b/src/pkcs11lib.h @@ -266,6 +266,13 @@ class CPKCS11Lib vector Template, CK_OBJECT_HANDLE & outhKey); + CK_RV C_DeriveKey( + CK_SESSION_HANDLE hSession, + CK_MECHANISM *pMechanism, + CK_OBJECT_HANDLE hBaseKey, + vector Template, + CK_OBJECT_HANDLE & outkey); + CK_RV C_SeedRandom( CK_SESSION_HANDLE hSession, vector Seed); diff --git a/src/pykcs11.i b/src/pykcs11.i index b753e32..1888341 100644 --- a/src/pykcs11.i +++ b/src/pykcs11.i @@ -251,7 +251,10 @@ typedef struct CK_DATE{ if (!SWIG_IsOK(res2)) { res2 = SWIG_ConvertPtr($input, &arg2, $descriptor(CK_GCM_PARAMS*), 0); if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "unsupported CK_MECHANISM Parameter type."); + res2 = SWIG_ConvertPtr($input, &arg2, $descriptor(CK_ECDH1_DERIVE_PARAMS*), 0); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "unsupported CK_MECHANISM Parameter type."); + } } } } @@ -295,8 +298,8 @@ typedef struct CK_GCM_PARAMS { %constant int CK_GCM_PARAMS_LENGTH = sizeof(CK_GCM_PARAMS); -%typemap(in) void*; -%typemap(in) void* = char*; +//%typemap(in) void*; +//%typemap(in) void* = char*; typedef struct CK_RSA_PKCS_OAEP_PARAMS { unsigned long hashAlg; @@ -345,6 +348,35 @@ typedef struct CK_RSA_PKCS_PSS_PARAMS { %constant int CK_RSA_PKCS_PSS_PARAMS_LENGTH = sizeof(CK_RSA_PKCS_PSS_PARAMS); +//%typemap(in) void*; +//%typemap(in) void* = char*; + +typedef struct CK_ECDH1_DERIVE_PARAMS { + unsigned long kdf; + unsigned long ulSharedDataLen; + void* pSharedData; + unsigned long ulPublicDataLen; + void* pPublicData; +} CK_ECDH1_DERIVE_PARAMS; + +%extend CK_ECDH1_DERIVE_PARAMS +{ + CK_ECDH1_DERIVE_PARAMS() + { + CK_ECDH1_DERIVE_PARAMS *p = new CK_ECDH1_DERIVE_PARAMS(); + p->kdf = CKD_NULL; + p->pSharedData = NULL; + p->ulSharedDataLen = 0; + p->pPublicData = NULL; + p->ulPublicDataLen = 0; + + return p; + } +}; + +%constant int CK_ECDH1_DERIVE_PARAMS_LENGTH = sizeof(CK_ECDH1_DERIVE_PARAMS); + + typedef struct CK_MECHANISM_INFO { %immutable; unsigned long ulMinKeySize;