Commit 01fa621a authored by Simo Sorce's avatar Simo Sorce Committed by Niels Möller

Add variable len pkcs1-sec decoding function

add a side-channel silent pkcs1 decoding function for use in older
APIs.
Signed-off-by: default avatarSimo Sorce <simo@redhat.com>
parent 760dc943
......@@ -53,6 +53,8 @@
((0U - ((uint32_t)(a) ^ (uint32_t)(b))) >> 31)
#define EQUAL(a, b) \
((((uint32_t)(a) ^ (uint32_t)(b)) - 1U) >> 31)
#define GREATER_OR_EQUAL(a, b) \
(1U - (((uint32_t)(a) - (uint32_t)(b)) >> 31))
int
_pkcs1_sec_decrypt (size_t length, uint8_t *message,
......@@ -80,3 +82,68 @@ _pkcs1_sec_decrypt (size_t length, uint8_t *message,
return ok;
}
int
_pkcs1_sec_decrypt_variable(size_t *length, uint8_t *message,
size_t padded_message_length,
const volatile uint8_t *padded_message)
{
volatile int not_found = 1;
volatile int ok;
volatile size_t offset;
size_t buflen, msglen;
size_t shift, i;
/* Check format, padding, message_size */
ok = EQUAL(padded_message[0], 0);
ok &= EQUAL(padded_message[1], 2);
/* length is discovered in a side-channel silent way.
* not_found goes to 0 when the terminator is found.
* offset strts at 3 as it includes the terminator and
* the fomat bytes already */
offset = 3;
for (i = 2; i < padded_message_length; i++)
{
not_found &= NOT_EQUAL(padded_message[i], 0);
offset += not_found;
}
/* check if we ran out of buffer */
ok &= NOT_EQUAL(not_found, 1);
/* padding must be >= 11 (2 format bytes + 8 pad bytes min. + terminator) */
ok &= GREATER_OR_EQUAL(offset, 11);
/* offset can vary between 3 and padded_message_length, due to the loop
* above, therefore msglen can't underflow */
msglen = padded_message_length - offset;
/* we always fill the whole buffer but only up to
* padded_message_length length */
buflen = *length;
if (buflen > padded_message_length) { /* input independent branch */
buflen = padded_message_length;
}
/* if the message length is larger than the buffer we must fail */
ok &= GREATER_OR_EQUAL(buflen, msglen);
/* fill destination buffer fully regardless of outcome. Copies the message
* in a memory access independent way. The destination message buffer will
* be clobbered past the message length. */
shift = padded_message_length - buflen;
cnd_memcpy(ok, message, padded_message + shift, buflen);
offset -= shift;
/* In this loop, the bits of the 'offset' variable are used as shifting
* conditions, starting from the least significant bit. The end result is
* that the buffer is shifted left eaxctly 'offset' bytes. */
for (shift = 1; shift < buflen; shift <<= 1, offset >>= 1)
{
/* 'ok' is both the a least significant bit mask and a condition */
cnd_memcpy(offset & ok, message, message + shift, buflen - shift);
}
/* update length only if we succeeded, otherwise leave unchanged */
*length = (msglen & (-(size_t) ok)) + (*length & ((size_t) ok - 1));
return ok;
}
......@@ -39,6 +39,7 @@
#define _rsa_sec_compute_root_itch _nettle_rsa_sec_compute_root_itch
#define _rsa_sec_compute_root _nettle_rsa_sec_compute_root
#define _pkcs1_sec_decrypt _nettle_pkcs1_sec_decrypt
#define _pkcs1_sec_decrypt_variable _nettle_pkcs1_sec_decrypt_variable
/* side-channel silent root computation */
mp_size_t
......@@ -55,4 +56,9 @@ _pkcs1_sec_decrypt (size_t length, uint8_t *message,
size_t padded_message_length,
const volatile uint8_t *padded_message);
int
_pkcs1_sec_decrypt_variable(size_t *length, uint8_t *message,
size_t padded_message_length,
const volatile uint8_t *padded_message);
#endif /* NETTLE_RSA_INTERNAL_H_INCLUDED */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment