Группа :: Разработка/Прочее
Пакет: libpkcs11-helper
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: libpkcs11-helper-1.25.1-gost-derive.patch
Скачать
Скачать
include/pkcs11-helper-1.0/pkcs11.h | 49 ++++++
include/pkcs11-helper-1.0/pkcs11h-core.h | 2 +
lib/_pkcs11h-util.h | 12 ++
lib/pkcs11h-certificate.c | 267 ++++++++++++++++++++++++++-----
lib/pkcs11h-util.c | 25 +++
5 files changed, 317 insertions(+), 38 deletions(-)
diff --git a/include/pkcs11-helper-1.0/pkcs11.h b/include/pkcs11-helper-1.0/pkcs11.h
index 2e6a1e3..9a7162c 100644
--- a/include/pkcs11-helper-1.0/pkcs11.h
+++ b/include/pkcs11-helper-1.0/pkcs11.h
@@ -329,6 +329,9 @@ typedef unsigned long ck_hw_feature_type_t;
#define CKH_VENDOR_DEFINED ((unsigned long) (1 << 31))
+#define NSSCK_VENDOR_PKCS11_RU_TEAM 0xD4321000 /* 0x80000000 | 0x54321000 */
+#define CK_VENDOR_PKCS11_RU_TEAM_TC26 NSSCK_VENDOR_PKCS11_RU_TEAM
+
typedef unsigned long ck_key_type_t;
#define CKK_RSA (0)
@@ -356,6 +359,11 @@ typedef unsigned long ck_key_type_t;
#define CKK_AES (0x1f)
#define CKK_BLOWFISH (0x20)
#define CKK_TWOFISH (0x21)
+#define CKK_GOSTR3410 (0x30UL)
+#define CKK_GOSTR3411 (0x31UL)
+#define CKK_GOST28147 (0x32UL)
+#define CKK_GOSTR3410_256 CKK_GOSTR3410
+#define CKK_GOSTR3410_512 (CK_VENDOR_PKCS11_RU_TEAM_TC26 | 0x003)
#define CKK_VENDOR_DEFINED ((unsigned long) (1 << 31))
@@ -669,6 +677,21 @@ typedef unsigned long ck_mechanism_type_t;
#define CKM_AES_MAC (0x1083)
#define CKM_AES_MAC_GENERAL (0x1084)
#define CKM_AES_CBC_PAD (0x1085)
+/* GOST */
+#define CKM_GOSTR3410_KEY_PAIR_GEN 0x00001200
+#define CKM_GOSTR3410 0x00001201
+#define CKM_GOSTR3410_WITH_GOSTR3411 0x00001202
+#define CKM_GOSTR3410_KEY_WRAP 0x00001203
+#define CKM_GOSTR3410_DERIVE 0x00001204
+#define CKM_GOSTR3411 0x00001210
+#define CKM_GOSTR3411_HMAC 0x00001211
+#define CKM_GOST28147_KEY_GEN 0x00001220
+#define CKM_GOST28147_ECB 0x00001221
+#define CKM_GOST28147 0x00001222
+#define CKM_GOST28147_MAC 0x00001223
+#define CKM_GOST28147_KEY_WRAP 0x00001224
+#define CKM_GOSTR3410_12_DERIVE (CK_VENDOR_PKCS11_RU_TEAM_TC26 | 0x007)
+/* Other */
#define CKM_DSA_PARAMETER_GEN (0x2000)
#define CKM_DH_PKCS_PARAMETER_GEN (0x2001)
#define CKM_X9_42_DH_PARAMETER_GEN (0x2002)
@@ -1354,4 +1377,30 @@ typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR;
}
#endif
+/* Flags and structures for Key derivation */
+#define CKD_NULL 0x00000001
+#define CKD_SHA1_KDF 0x00000002
+#define CKD_SHA1_KDF_ASN1 0x00000003
+#define CKD_SHA1_KDF_CONCATENATE 0x00000004
+#define CKD_SHA224_KDF 0x00000005
+#define CKD_SHA256_KDF 0x00000006
+#define CKD_SHA384_KDF 0x00000007
+#define CKD_SHA512_KDF 0x00000008
+
+typedef struct CK_ECDH1_DERIVE_PARAMS {
+ unsigned long kdf;
+ unsigned long ulSharedDataLen;
+ unsigned char * pSharedData;
+ unsigned long ulPublicDataLen;
+ unsigned char * pPublicData;
+} CK_ECDH1_DERIVE_PARAMS;
+
+typedef struct CK_GOSTR3410_DERIVE_PARAMS {
+ CK_ULONG kdf;
+ CK_BYTE *pPublicData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE *pUKM;
+ CK_ULONG ulUKMLen;
+} CK_GOSTR3410_DERIVE_PARAMS;
+
#endif /* PKCS11_H */
diff --git a/include/pkcs11-helper-1.0/pkcs11h-core.h b/include/pkcs11-helper-1.0/pkcs11h-core.h
index 90632f5..6873e39 100644
--- a/include/pkcs11-helper-1.0/pkcs11h-core.h
+++ b/include/pkcs11-helper-1.0/pkcs11h-core.h
@@ -153,6 +153,8 @@ extern "C" {
#define PKCS11H_PRIVATEMODE_MASK_DECRYPT (1<<2)
/** Force unwrap. */
#define PKCS11H_PRIVATEMODE_MASK_UNWRAP (1<<3)
+/** Force derive. */
+#define PKCS11H_PRIVATEMODE_MASK_DERIVE (1<<4)
/** @} */
/**
diff --git a/lib/_pkcs11h-util.h b/lib/_pkcs11h-util.h
index e9237af..5e98594 100644
--- a/lib/_pkcs11h-util.h
+++ b/lib/_pkcs11h-util.h
@@ -92,5 +92,17 @@ _pkcs11h_util_unescapeString (
IN size_t * const max
);
+void
+_pkcs11h_util_flip_buf (
+ IN OUT CK_BYTE_PTR buf,
+ IN CK_ULONG len
+);
+
+void
+_pkcs11h_util_put_lsb32 (
+ OUT CK_BYTE_PTR buf,
+ IN CK_ULONG val
+);
+
#endif
diff --git a/lib/pkcs11h-certificate.c b/lib/pkcs11h-certificate.c
index 92a3c45..67b26fd 100644
--- a/lib/pkcs11h-certificate.c
+++ b/lib/pkcs11h-certificate.c
@@ -60,12 +60,14 @@
#include "_pkcs11h-session.h"
#include "_pkcs11h-token.h"
#include "_pkcs11h-certificate.h"
+#include "_pkcs11h-util.h"
enum __pkcs11h_private_op_e {
__pkcs11h_private_op_sign=0,
__pkcs11h_private_op_sign_recover,
__pkcs11h_private_op_decrypt,
- __pkcs11h_private_op_unwrap
+ __pkcs11h_private_op_unwrap,
+ __pkcs11h_private_op_derive
};
static
@@ -476,7 +478,8 @@ __pkcs11h_certificate_getKeyAttributes (
{CKA_SIGN, NULL, 0},
{CKA_SIGN_RECOVER, NULL, 0},
{CKA_DECRYPT, NULL, 0},
- {CKA_UNWRAP, NULL, 0}
+ {CKA_UNWRAP, NULL, 0},
+ {CKA_DERIVE, NULL, 0}
};
/*
@@ -502,6 +505,7 @@ __pkcs11h_certificate_getKeyAttributes (
CK_BBOOL *key_attrs_sign_recover;
CK_BBOOL *key_attrs_decrypt;
CK_BBOOL *key_attrs_unwrap;
+ CK_BBOOL *key_attrs_derive;
if (
(rv = _pkcs11h_session_getObjectAttributes (
@@ -518,6 +522,7 @@ __pkcs11h_certificate_getKeyAttributes (
key_attrs_sign_recover = (CK_BBOOL *)key_attrs[1].pValue;
key_attrs_decrypt = (CK_BBOOL *)key_attrs[2].pValue;
key_attrs_unwrap = (CK_BBOOL *)key_attrs[3].pValue;
+ key_attrs_derive = (CK_BBOOL *)key_attrs[4].pValue;
if (key_attrs_sign != NULL && *key_attrs_sign != CK_FALSE) {
certificate->mask_private_mode |= PKCS11H_PRIVATEMODE_MASK_SIGN;
@@ -531,6 +536,9 @@ __pkcs11h_certificate_getKeyAttributes (
if (key_attrs_unwrap != NULL && *key_attrs_unwrap != CK_FALSE) {
certificate->mask_private_mode |= PKCS11H_PRIVATEMODE_MASK_UNWRAP;
}
+ if (key_attrs_derive != NULL && *key_attrs_derive != CK_FALSE) {
+ certificate->mask_private_mode |= PKCS11H_PRIVATEMODE_MASK_DERIVE;
+ }
if (certificate->mask_private_mode == 0) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto retry;
@@ -790,20 +798,26 @@ __pkcs11h_certificate_doPrivateOperation (
mech_type, NULL, 0
};
-/* CK_BBOOL wrap_attrs_false = CK_FALSE; */
- CK_BBOOL wrap_attrs_true = CK_TRUE;
+ CK_BBOOL result_attrs_false = CK_FALSE;
+ CK_BBOOL result_attrs_true = CK_TRUE;
CK_OBJECT_CLASS class = CKO_SECRET_KEY;
CK_KEY_TYPE keytype = CKK_GENERIC_SECRET;
- CK_ATTRIBUTE wrap_attrs[] = {
+ CK_ATTRIBUTE result_attrs[] = {
{CKA_CLASS, &class, sizeof (class)},
{CKA_KEY_TYPE, &keytype, sizeof (keytype)},
- {CKA_EXTRACTABLE, &wrap_attrs_true, sizeof (wrap_attrs_true)}
-/* OpenSC fail! {CKA_TOKEN, &wrap_attrs_false, sizeof (wrap_attrs_false)} */
+ {CKA_EXTRACTABLE, &result_attrs_true, sizeof (result_attrs_true)},
+ {CKA_TOKEN, &result_attrs_false, sizeof (result_attrs_false)},
+ {CKA_MODIFIABLE, &result_attrs_true, sizeof (result_attrs_true)},
+ {CKA_PRIVATE, &result_attrs_false, sizeof (result_attrs_false)},
+ {CKA_SENSITIVE, &result_attrs_false, sizeof (result_attrs_false)}
};
- CK_ATTRIBUTE wrap_value[] = {
+ CK_ATTRIBUTE result_value[] = {
{CKA_VALUE, target, 0}
};
- CK_OBJECT_HANDLE wrap_key = _PKCS11H_INVALID_OBJECT_HANDLE;
+ CK_OBJECT_HANDLE result_key = _PKCS11H_INVALID_OBJECT_HANDLE;
+
+ CK_ECDH1_DERIVE_PARAMS ecdh_params;
+ CK_GOSTR3410_DERIVE_PARAMS gost3410_derive_params;
CK_RV rv = CKR_FUNCTION_FAILED;
PKCS11H_BOOL login_retry = FALSE;
@@ -876,9 +890,91 @@ __pkcs11h_certificate_doPrivateOperation (
certificate->key_handle,
(CK_BYTE_PTR)source,
source_size,
- wrap_attrs,
- sizeof (wrap_attrs) / sizeof (CK_ATTRIBUTE),
- &wrap_key
+ result_attrs,
+ sizeof (result_attrs) / sizeof (CK_ATTRIBUTE),
+ &result_key
+ );
+ break;
+ case __pkcs11h_private_op_derive:
+ switch (mech_type) {
+ case CKM_GOSTR3410_DERIVE:
+ memset (&gost3410_derive_params, 0,
+ sizeof (gost3410_derive_params));
+ gost3410_derive_params.kdf = CKD_NULL;
+ gost3410_derive_params.ulPublicDataLen = 64;
+ gost3410_derive_params.pPublicData = (CK_BYTE_PTR) source;
+ gost3410_derive_params.ulUKMLen = source_size - 64;
+ gost3410_derive_params.pUKM = (CK_BYTE_PTR) (source + 64);
+ mech.pParameter = &gost3410_derive_params;
+ mech.ulParameterLen = sizeof (gost3410_derive_params);
+ keytype = CKK_GOST28147;
+ break;
+ case CKM_GOSTR3410_12_DERIVE: {
+ CK_KEY_TYPE pkey_type;
+ CK_ATTRIBUTE _attrs[] = {
+ {CKA_KEY_TYPE, &pkey_type, sizeof (pkey_type)}
+ };
+ rv = certificate->session->provider->f->
+ C_GetAttributeValue (
+ certificate->session->session_handle,
+ certificate->key_handle,
+ _attrs,
+ sizeof (_attrs) / sizeof (CK_ATTRIBUTE)
+ );
+ if (rv != CKR_OK)
+ goto retry;
+
+ unsigned int key_len;
+ switch (pkey_type) {
+ case CKK_GOSTR3410_256:
+ key_len = 64;
+ break;
+ case CKK_GOSTR3410_512:
+ key_len = 128;
+ break;
+ default:
+ rv = CKR_KEY_TYPE_INCONSISTENT;
+ goto cleanup;
+ }
+
+ /* Maximum supported UKM length is 32 bytes */
+ if (source_size - key_len > 32) {
+ rv = CKR_ARGUMENTS_BAD;
+ goto cleanup;
+ }
+
+ CK_BYTE gost3410_12_derive_params[8 + 128 + 4 + 32];
+ _pkcs11h_util_put_lsb32 (gost3410_12_derive_params, CKD_NULL);
+ _pkcs11h_util_put_lsb32 (gost3410_12_derive_params + 4, key_len);
+ memcpy (gost3410_12_derive_params + 8, source, key_len);
+ _pkcs11h_util_put_lsb32 (gost3410_12_derive_params + 8 + key_len,
+ source_size - key_len);
+ memcpy (gost3410_12_derive_params + 8 + key_len + 4,
+ source + key_len, source_size - key_len);
+
+ mech.pParameter = &gost3410_12_derive_params;
+ mech.ulParameterLen = 8 + key_len + 4 + source_size - key_len;
+ keytype = CKK_GOST28147;
+ }
+ break;
+ default:
+ memset (&ecdh_params, 0, sizeof (ecdh_params));
+ ecdh_params.kdf = CKD_NULL;
+ ecdh_params.ulPublicDataLen = source_size;
+ ecdh_params.pPublicData = (CK_BYTE_PTR) source;
+ // TODO: Split the source on public / shared.
+ ecdh_params.ulSharedDataLen = 0;
+ ecdh_params.pSharedData = NULL;
+ mech.pParameter = &ecdh_params;
+ mech.ulParameterLen = sizeof (ecdh_params);
+ }
+ rv = certificate->session->provider->f->C_DeriveKey (
+ certificate->session->session_handle,
+ &mech,
+ certificate->key_handle,
+ result_attrs,
+ sizeof (result_attrs) / sizeof (CK_ATTRIBUTE),
+ &result_key
);
break;
default:
@@ -933,16 +1029,17 @@ __pkcs11h_certificate_doPrivateOperation (
);
break;
case __pkcs11h_private_op_unwrap:
- wrap_value[0].ulValueLen = size;
-
+ case __pkcs11h_private_op_derive:
+ result_value[0].ulValueLen = size;
+
rv = certificate->session->provider->f->C_GetAttributeValue (
certificate->session->session_handle,
- wrap_key,
- wrap_value,
- sizeof (wrap_value) / sizeof (CK_ATTRIBUTE)
+ result_key,
+ result_value,
+ sizeof (result_value) / sizeof (CK_ATTRIBUTE)
);
- size = wrap_value[0].ulValueLen;
+ size = result_value[0].ulValueLen;
break;
default:
rv = CKR_ARGUMENTS_BAD;
@@ -960,7 +1057,10 @@ __pkcs11h_certificate_doPrivateOperation (
rv
);
- if (rv == CKR_BUFFER_TOO_SMALL && op != __pkcs11h_private_op_unwrap) {
+ if (rv == CKR_BUFFER_TOO_SMALL &&
+ op != __pkcs11h_private_op_unwrap &&
+ op != __pkcs11h_private_op_derive)
+ {
certificate->operation_active = TRUE;
}
@@ -971,7 +1071,9 @@ __pkcs11h_certificate_doPrivateOperation (
}
else {
if (rv == CKR_OK) {
- if (op != __pkcs11h_private_op_unwrap) {
+ if (op != __pkcs11h_private_op_unwrap &&
+ op != __pkcs11h_private_op_derive)
+ {
certificate->operation_active = TRUE;
}
}
@@ -985,12 +1087,12 @@ __pkcs11h_certificate_doPrivateOperation (
retry:
- if (wrap_key != _PKCS11H_INVALID_OBJECT_HANDLE) {
+ if (result_key != _PKCS11H_INVALID_OBJECT_HANDLE) {
certificate->session->provider->f->C_DestroyObject (
certificate->session->session_handle,
- wrap_key
+ result_key
);
- wrap_key = _PKCS11H_INVALID_OBJECT_HANDLE;
+ result_key = _PKCS11H_INVALID_OBJECT_HANDLE;
}
if (!op_succeed) {
@@ -1545,6 +1647,68 @@ cleanup:
}
CK_RV
+pkcs11h_certificate_derive (
+ IN const pkcs11h_certificate_t certificate,
+ IN const CK_MECHANISM_TYPE mech_type,
+ IN const unsigned char * const source,
+ IN const size_t source_size,
+ OUT unsigned char * const target,
+ IN OUT size_t * const p_target_size
+) {
+ CK_RV rv = CKR_FUNCTION_FAILED;
+
+ _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
+ _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
+ _PKCS11H_ASSERT (certificate!=NULL);
+ _PKCS11H_ASSERT (source!=NULL);
+ /*_PKCS11H_ASSERT (target); NOT NEEDED*/
+ _PKCS11H_ASSERT (p_target_size!=NULL);
+
+ _PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_derive entry certificate=%p, mech_type=%ld, source=%p, source_size="P_Z", target=%p, *p_target_size="P_Z"",
+ (void *)certificate,
+ mech_type,
+ source,
+ source_size,
+ target,
+ target != NULL ? *p_target_size : 0
+ );
+
+ if (target == NULL) {
+ *p_target_size = 0;
+ }
+
+ if (
+ (rv = __pkcs11h_certificate_doPrivateOperation (
+ certificate,
+ __pkcs11h_private_op_derive,
+ mech_type,
+ source,
+ source_size,
+ target,
+ p_target_size
+ )) != CKR_OK
+ ) {
+ goto cleanup;
+ }
+
+ rv = CKR_OK;
+
+cleanup:
+
+ _PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_derive return rv=%lu-'%s', *p_target_size="P_Z"",
+ rv,
+ pkcs11h_getMessage (rv),
+ *p_target_size
+ );
+
+ return rv;
+}
+
+CK_RV
pkcs11h_certificate_signAny (
IN const pkcs11h_certificate_t certificate,
IN const CK_MECHANISM_TYPE mech_type,
@@ -1585,6 +1749,8 @@ pkcs11h_certificate_signAny (
}
}
+ rv = CKR_FUNCTION_FAILED;
+
if (
!acked &&
(certificate->mask_private_mode & PKCS11H_PRIVATEMODE_MASK_SIGN) != 0
@@ -1639,15 +1805,12 @@ pkcs11h_certificate_signAny (
}
}
- if (!acked) {
+cleanup:
+
+ if (!acked && (rv == CKR_OK)) {
rv = CKR_FUNCTION_FAILED;
- goto cleanup;
}
- rv = CKR_OK;
-
-cleanup:
-
_PKCS11H_DEBUG (
PKCS11H_LOG_DEBUG2,
"PKCS#11: pkcs11h_certificate_signAny return rv=%lu-'%s', *p_target_size="P_Z"",
@@ -1699,19 +1862,21 @@ pkcs11h_certificate_decryptAny (
}
}
+ rv = CKR_FUNCTION_FAILED;
+
if (
!acked &&
(certificate->mask_private_mode & PKCS11H_PRIVATEMODE_MASK_DECRYPT) != 0
) {
switch (
- pkcs11h_certificate_decrypt (
+ (rv = pkcs11h_certificate_decrypt (
certificate,
mech_type,
source,
source_size,
target,
p_target_size
- )
+ ))
) {
case CKR_OK:
acked = TRUE;
@@ -1731,14 +1896,14 @@ pkcs11h_certificate_decryptAny (
(certificate->mask_private_mode & PKCS11H_PRIVATEMODE_MASK_UNWRAP) != 0
) {
switch (
- pkcs11h_certificate_unwrap (
+ (rv = pkcs11h_certificate_unwrap (
certificate,
mech_type,
source,
source_size,
target,
p_target_size
- )
+ ))
) {
case CKR_OK:
acked = TRUE;
@@ -1753,15 +1918,41 @@ pkcs11h_certificate_decryptAny (
}
}
- if (!acked) {
- rv = CKR_FUNCTION_FAILED;
- goto cleanup;
+ /* Make key derivation to be the case of decryption in accoudance
+ * with decrypt_raw() function in the ECC part of Libgcrypt. */
+ if (
+ !acked &&
+ (certificate->mask_private_mode & PKCS11H_PRIVATEMODE_MASK_DERIVE) != 0
+ ) {
+ switch (
+ (rv = pkcs11h_certificate_derive (
+ certificate,
+ mech_type,
+ source,
+ source_size,
+ target,
+ p_target_size
+ ))
+ ) {
+ case CKR_OK:
+ acked = TRUE;
+ break;
+ case CKR_FUNCTION_NOT_SUPPORTED:
+ case CKR_KEY_FUNCTION_NOT_PERMITTED:
+ case CKR_KEY_TYPE_INCONSISTENT:
+ certificate->mask_private_mode &= ~PKCS11H_PRIVATEMODE_MASK_DERIVE;
+ break;
+ default:
+ goto cleanup;
+ }
}
- rv = CKR_OK;
-
cleanup:
+ if (!acked && (rv == CKR_OK)) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+
_PKCS11H_DEBUG (
PKCS11H_LOG_DEBUG2,
"PKCS#11: pkcs11h_certificate_decryptAny return rv=%lu-'%s', *p_target_size="P_Z"",
diff --git a/lib/pkcs11h-util.c b/lib/pkcs11h-util.c
index 7325db4..8d2a512 100644
--- a/lib/pkcs11h-util.c
+++ b/lib/pkcs11h-util.c
@@ -51,6 +51,9 @@
#include "common.h"
#include "_pkcs11h-util.h"
+// For byte order
+#include <arpa/inet.h>
+
void
_pkcs11h_util_fixupFixedString (
OUT char * const target, /* MUST BE >= length+1 */
@@ -287,3 +290,25 @@ cleanup:
return rv;
}
+void
+_pkcs11h_util_flip_buf (
+ IN OUT CK_BYTE_PTR buf,
+ IN CK_ULONG len
+) {
+ CK_ULONG tmp, i;
+
+ for (i = 0; i < len/2; i++) {
+ tmp = buf[i];
+ buf[i] = buf[len - 1 -i];
+ buf[len - 1 - i] = tmp;
+ }
+}
+
+void
+_pkcs11h_util_put_lsb32 (
+ OUT CK_BYTE_PTR buf,
+ IN CK_ULONG val
+) {
+ *((uint32_t *) buf) = htonl ((uint32_t) val);
+ _pkcs11h_util_flip_buf (buf, 4);
+}