Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Side-channel proofing PKCS#1 1.5 paths (CVE-2023-6258) #308

Merged
merged 1 commit into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 */
Loading