Skip to content

Commit

Permalink
Side-channel proofing PKCS#1 1.5 paths
Browse files Browse the repository at this point in the history
Fixes CVE-2023-6258 (Marvin)

Signed-off-by: Simo Sorce <[email protected]>
  • Loading branch information
simo5 committed Nov 28, 2023
1 parent 6843795 commit 86e7395
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 1 deletion.
16 changes: 15 additions & 1 deletion src/asymmetric_cipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,12 +296,26 @@ static int p11prov_rsaenc_decrypt(void *ctx, unsigned char *out, size_t *outlen,
goto endsess;
}

/* Special handling against PKCS#1 1.5 side channel leaking */
if (mechanism.mechanism == CKM_RSA_PKCS) {
CK_ULONG cond;
ret = side_channel_free_Decrypt(encctx->provctx, sess, (void *)in,
inlen, out, &out_size);
/* the error case need to be handled in a side-channel free way, so
* conditionals need to be constant time. Always setting outlen is
* fine because out_size is initialized to the value of outlen
* and the value should not matter in an error condition anyway */
*outlen = out_size;
cond = constant_equal(ret, CKR_OK);
result = constant_select_int(cond, RET_OSSL_OK, RET_OSSL_ERR);
goto endsess;
}

ret = p11prov_Decrypt(encctx->provctx, sess, (void *)in, inlen, out,
&out_size);
if (ret != CKR_OK) {
goto endsess;
}

*outlen = out_size;
result = RET_OSSL_OK;

Expand Down
19 changes: 19 additions & 0 deletions src/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,3 +450,22 @@ CK_RV p11prov_module_reinit(P11PROV_MODULE *mctx)
/* ------------- LOCKED SECTION */
return ret;
}

/* This is needed to avoid side channels in the PKCS 1.5 decryption case */
CK_RV side_channel_free_Decrypt(P11PROV_CTX *ctx, CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncryptedData,
CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
CK_ULONG_PTR pulDataLen)
{
P11PROV_INTERFACE *intf = p11prov_ctx_get_interface(ctx);
CK_RV ret = CKR_GENERAL_ERROR;
if (!intf) {
P11PROV_raise(ctx, ret, "Can't get module interfaces");
return ret;
}
P11PROV_debug("Calling C_Decrypt");
/* Must not add any conditionals based on return value, so we just return
* straight */
return intf->Decrypt(hSession, pEncryptedData, ulEncryptedDataLen, pData,
pulDataLen);
}
6 changes: 6 additions & 0 deletions src/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,10 @@ CK_RV p11prov_SeedRandom(P11PROV_CTX *ctx, CK_SESSION_HANDLE hSession,
CK_RV p11prov_GenerateRandom(P11PROV_CTX *ctx, CK_SESSION_HANDLE hSession,
CK_BYTE_PTR RandomData, CK_ULONG ulRandomLen);

/* Special side-channel free path against PKCS#1 1.5 side channel leaking */
CK_RV side_channel_free_Decrypt(P11PROV_CTX *ctx, CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pEncryptedData,
CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
CK_ULONG_PTR pulDataLen);

#endif /* _INTERFACE_H */
14 changes: 14 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,18 @@ CK_RV p11prov_mutex_destroy(P11PROV_CTX *provctx, pthread_mutex_t *lock,

void p11prov_force_rwlock_reinit(pthread_rwlock_t *lock);

static inline CK_ULONG constant_equal(CK_ULONG a, CK_ULONG b)
{
return ((a ^ b) - 1U) >> (sizeof(CK_ULONG) * 8 - 1);
}

static inline int constant_select_int(CK_ULONG cond, int a, int b)
{
volatile unsigned int A = (unsigned int)a;
volatile unsigned int B = (unsigned int)b;
volatile unsigned int mask = -(unsigned int)cond;

return (int)((A & mask) | (B & ~mask));
}

#endif /* _UTIL_H */

0 comments on commit 86e7395

Please sign in to comment.