Blame SOURCES/opencryptoki-3.15.1-1e98001ff63cd7e75d95b4ea0d3d2a69965d8890.patch

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