SHA256
1
0
forked from pool/openCryptoki
openCryptoki/ocki-3.15.1-SOFT-Fix-problem-with-C_Get-SetOperationState-and-di.patch
Mark Post 6e14030074 Accepting request 872976 from home:markkp:branches:security
- Added ocki-3.15.1-A-slot-ID-has-nothing-to-do-with-the-number-of-slots.patch
  (bsc#1182120)
  Fix pkcscca migration fails with usr/sb2 is not a valid slot ID
- Added ocki-3.15.1-SOFT-Fix-problem-with-C_Get-SetOperationState-and-di.patch
  (bsc#1182190)
  Fix a segmentation fault of the sess_opstate test on the Soft Token

OBS-URL: https://build.opensuse.org/request/show/872976
OBS-URL: https://build.opensuse.org/package/show/security/openCryptoki?expand=0&rev=116
2021-02-16 21:24:55 +00:00

292 lines
9.2 KiB
Diff

From 1e98001ff63cd7e75d95b4ea0d3d2a69965d8890 Mon Sep 17 00:00:00 2001
From: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Tue, 9 Feb 2021 16:22:51 +0100
Subject: [PATCH] SOFT: Fix problem with C_Get/SetOperationState and digest
contexts
In commit 46829bf986d45262ad45c782c084a3f908f4acb8 the SOFT token was changed
to use OpenSSL's EVP interface for implementing SHA digest. With this change,
the OpenSSL digest context (EVP_MD_CTX) was saved in the DIGEST_CONTEXT's
context field. Since EVP_MD_CTX is opaque, its length is not known, so context_len
was set to 1.
This hinders C_Get/SetOperationState to correctly save and restore the digest
state, since the EVP_MD_CTX is not saved by C_GetOperationState, and
C_SetOperationState also can't restore the digest state, leaving a subsequent
C_DigestUpdate or C_DigestFinal with an invalid EVP_MD_CTX. This most likely
produces a segfault.
Fix this by saving the md_data from within the EVP_MD_CTX after each digest operation,
and restoring md_data on every operation with a fresh initialized EVP_MD_CTX.
Fixes: 46829bf986d45262ad45c782c084a3f908f4acb8
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
usr/lib/soft_stdll/soft_specific.c | 160 +++++++++++++++++++++++------
1 file changed, 127 insertions(+), 33 deletions(-)
diff --git a/usr/lib/soft_stdll/soft_specific.c b/usr/lib/soft_stdll/soft_specific.c
index 0b28daa8..a836efa9 100644
--- a/usr/lib/soft_stdll/soft_specific.c
+++ b/usr/lib/soft_stdll/soft_specific.c
@@ -2926,24 +2926,15 @@ CK_RV token_specific_get_mechanism_info(STDLL_TokData_t *tokdata,
return ock_generic_get_mechanism_info(tokdata, type, pInfo);
}
-CK_RV token_specific_sha_init(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
- CK_MECHANISM *mech)
+#ifdef OLDER_OPENSSL
+#define EVP_MD_meth_get_app_datasize(md) md->ctx_size
+#define EVP_MD_CTX_md_data(ctx) ctx->md_data
+#endif
+
+static const EVP_MD *md_from_mech(CK_MECHANISM *mech)
{
const EVP_MD *md = NULL;
- UNUSED(tokdata);
-
- ctx->context_len = 1; /* Dummy length, size of EVP_MD_CTX is unknown */
-#if OPENSSL_VERSION_NUMBER < 0x10101000L
- ctx->context = (CK_BYTE *)EVP_MD_CTX_create();
-#else
- ctx->context = (CK_BYTE *)EVP_MD_CTX_new();
-#endif
- if (ctx->context == NULL) {
- TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
- return CKR_HOST_MEMORY;
- }
-
switch (mech->mechanism) {
case CKM_SHA_1:
md = EVP_sha1();
@@ -2994,19 +2985,85 @@ CK_RV token_specific_sha_init(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
break;
}
+ return md;
+}
+
+static EVP_MD_CTX *md_ctx_from_context(DIGEST_CONTEXT *ctx)
+{
+ const EVP_MD *md;
+ EVP_MD_CTX *md_ctx;
+
+#if OPENSSL_VERSION_NUMBER < 0x10101000L
+ md_ctx = EVP_MD_CTX_create();
+#else
+ md_ctx = EVP_MD_CTX_new();
+#endif
+ if (md_ctx == NULL)
+ return NULL;
+
+ md = md_from_mech(&ctx->mech);
if (md == NULL ||
- !EVP_DigestInit_ex((EVP_MD_CTX *)ctx->context, md, NULL)) {
+ !EVP_DigestInit_ex(md_ctx, md, NULL)) {
+ TRACE_ERROR("md_from_mech or EVP_DigestInit_ex failed\n");
#if OPENSSL_VERSION_NUMBER < 0x10101000L
- EVP_MD_CTX_destroy((EVP_MD_CTX *)ctx->context);
+ EVP_MD_CTX_destroy(md_ctx);
#else
- EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
+ EVP_MD_CTX_free(md_ctx);
#endif
- ctx->context = NULL;
- ctx->context_len = 0;
+ return NULL;
+ }
- return CKR_FUNCTION_FAILED;
+ if (ctx->context_len == 0) {
+ ctx->context_len = EVP_MD_meth_get_app_datasize(EVP_MD_CTX_md(md_ctx));
+ ctx->context = malloc(ctx->context_len);
+ if (ctx->context == NULL) {
+ TRACE_ERROR("malloc failed\n");
+ #if OPENSSL_VERSION_NUMBER < 0x10101000L
+ EVP_MD_CTX_destroy(md_ctx);
+ #else
+ EVP_MD_CTX_free(md_ctx);
+ #endif
+ ctx->context_len = 0;
+ return NULL;
+ }
+
+ /* Save context data for later use */
+ memcpy(ctx->context, EVP_MD_CTX_md_data(md_ctx), ctx->context_len);
+ } else {
+ if (ctx->context_len !=
+ (CK_ULONG)EVP_MD_meth_get_app_datasize(EVP_MD_CTX_md(md_ctx))) {
+ TRACE_ERROR("context size mismatcht\n");
+ return NULL;
+ }
+ /* restore the MD context data */
+ memcpy(EVP_MD_CTX_md_data(md_ctx), ctx->context, ctx->context_len);
}
+ return md_ctx;
+}
+
+CK_RV token_specific_sha_init(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
+ CK_MECHANISM *mech)
+{
+ EVP_MD_CTX *md_ctx;
+
+ UNUSED(tokdata);
+
+ ctx->mech.ulParameterLen = mech->ulParameterLen;
+ ctx->mech.mechanism = mech->mechanism;
+
+ md_ctx = md_ctx_from_context(ctx);
+ if (md_ctx == NULL) {
+ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
+ return CKR_HOST_MEMORY;
+ }
+
+#if OPENSSL_VERSION_NUMBER < 0x10101000L
+ EVP_MD_CTX_destroy(md_ctx);
+#else
+ EVP_MD_CTX_free(md_ctx);
+#endif
+
return CKR_OK;
}
@@ -3016,6 +3073,7 @@ CK_RV token_specific_sha(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
{
unsigned int len;
CK_RV rc = CKR_OK;
+ EVP_MD_CTX *md_ctx;
UNUSED(tokdata);
@@ -3025,11 +3083,18 @@ CK_RV token_specific_sha(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
if (!in_data || !out_data)
return CKR_ARGUMENTS_BAD;
- if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size((EVP_MD_CTX *)ctx->context))
+ /* Recreate the OpenSSL MD context from the saved context */
+ md_ctx = md_ctx_from_context(ctx);
+ if (md_ctx == NULL) {
+ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
+ return CKR_HOST_MEMORY;
+ }
+
+ if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size(md_ctx))
return CKR_BUFFER_TOO_SMALL;
- if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len) ||
- !EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) {
+ if (!EVP_DigestUpdate(md_ctx, in_data, in_data_len) ||
+ !EVP_DigestFinal(md_ctx, out_data, &len)) {
rc = CKR_FUNCTION_FAILED;
goto out;
}
@@ -3038,10 +3103,11 @@ CK_RV token_specific_sha(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
out:
#if OPENSSL_VERSION_NUMBER < 0x10101000L
- EVP_MD_CTX_destroy((EVP_MD_CTX *)ctx->context);
+ EVP_MD_CTX_destroy(md_ctx);
#else
- EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
+ EVP_MD_CTX_free(md_ctx);
#endif
+ free(ctx->context);
ctx->context = NULL;
ctx->context_len = 0;
@@ -3051,6 +3117,8 @@ out:
CK_RV token_specific_sha_update(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
CK_BYTE *in_data, CK_ULONG in_data_len)
{
+ EVP_MD_CTX *md_ctx;
+
UNUSED(tokdata);
if (!ctx || !ctx->context)
@@ -3059,17 +3127,34 @@ CK_RV token_specific_sha_update(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
if (!in_data)
return CKR_ARGUMENTS_BAD;
- if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len)) {
+ /* Recreate the OpenSSL MD context from the saved context */
+ md_ctx = md_ctx_from_context(ctx);
+ if (md_ctx == NULL) {
+ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
+ return CKR_HOST_MEMORY;
+ }
+
+ if (!EVP_DigestUpdate(md_ctx, in_data, in_data_len)) {
#if OPENSSL_VERSION_NUMBER < 0x10101000L
- EVP_MD_CTX_destroy((EVP_MD_CTX *)ctx->context);
+ EVP_MD_CTX_destroy(md_ctx);
#else
- EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
+ EVP_MD_CTX_free(md_ctx);
#endif
+ free(ctx->context);
ctx->context = NULL;
ctx->context_len = 0;
return CKR_FUNCTION_FAILED;
}
+ /* Save context data for later use */
+ memcpy(ctx->context, EVP_MD_CTX_md_data(md_ctx), ctx->context_len);
+
+#if OPENSSL_VERSION_NUMBER < 0x10101000L
+ EVP_MD_CTX_destroy(md_ctx);
+#else
+ EVP_MD_CTX_free(md_ctx);
+#endif
+
return CKR_OK;
}
@@ -3078,6 +3163,7 @@ CK_RV token_specific_sha_final(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
{
unsigned int len;
CK_RV rc = CKR_OK;
+ EVP_MD_CTX *md_ctx;
UNUSED(tokdata);
@@ -3087,10 +3173,17 @@ CK_RV token_specific_sha_final(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
if (!out_data)
return CKR_ARGUMENTS_BAD;
- if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size((EVP_MD_CTX *)ctx->context))
+ /* Recreate the OpenSSL MD context from the saved context */
+ md_ctx = md_ctx_from_context(ctx);
+ if (md_ctx == NULL) {
+ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
+ return CKR_HOST_MEMORY;
+ }
+
+ if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size(md_ctx))
return CKR_BUFFER_TOO_SMALL;
- if (!EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) {
+ if (!EVP_DigestFinal(md_ctx, out_data, &len)) {
rc = CKR_FUNCTION_FAILED;
goto out;
}
@@ -3098,10 +3191,11 @@ CK_RV token_specific_sha_final(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
out:
#if OPENSSL_VERSION_NUMBER < 0x10101000L
- EVP_MD_CTX_destroy((EVP_MD_CTX *)ctx->context);
+ EVP_MD_CTX_destroy(md_ctx);
#else
- EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
+ EVP_MD_CTX_free(md_ctx);
#endif
+ free(ctx->context);
ctx->context = NULL;
ctx->context_len = 0;
--
2.26.2