make pkcs#1 decode functions constant-time
as proposed in RFC 3447 only one error return code is used when there are errors while decoding the pkcs#1 format. also, all steps are executed and only the "output" is skipped if something went wrong. Sorry this could break backwards compatibility, since there's no more BUFFER_OVERFLOW messaging. Former error-handling code could also be affected because now there's only OK as return code in cases where "res" is also set to '1'.
This commit is contained in:
parent
e57c92fd23
commit
1e9e98aa0d
@ -28,7 +28,7 @@
|
|||||||
@param out [out] Destination of decoding
|
@param out [out] Destination of decoding
|
||||||
@param outlen [in/out] The max size and resulting size of the decoding
|
@param outlen [in/out] The max size and resulting size of the decoding
|
||||||
@param res [out] Result of decoding, 1==valid, 0==invalid
|
@param res [out] Result of decoding, 1==valid, 0==invalid
|
||||||
@return CRYPT_OK if successful (even if invalid)
|
@return CRYPT_OK if successful
|
||||||
*/
|
*/
|
||||||
int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
|
int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
|
||||||
const unsigned char *lparam, unsigned long lparamlen,
|
const unsigned char *lparam, unsigned long lparamlen,
|
||||||
@ -38,7 +38,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
|
|||||||
{
|
{
|
||||||
unsigned char *DB, *seed, *mask;
|
unsigned char *DB, *seed, *mask;
|
||||||
unsigned long hLen, x, y, modulus_len;
|
unsigned long hLen, x, y, modulus_len;
|
||||||
int err;
|
int err, ret;
|
||||||
|
|
||||||
LTC_ARGCHK(msg != NULL);
|
LTC_ARGCHK(msg != NULL);
|
||||||
LTC_ARGCHK(out != NULL);
|
LTC_ARGCHK(out != NULL);
|
||||||
@ -85,10 +85,12 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
err = CRYPT_OK;
|
||||||
|
ret = CRYPT_OK;
|
||||||
|
|
||||||
/* must have leading 0x00 byte */
|
/* must have leading 0x00 byte */
|
||||||
if (msg[0] != 0x00) {
|
if (msg[0] != 0x00) {
|
||||||
err = CRYPT_OK;
|
ret = CRYPT_INVALID_PACKET;
|
||||||
goto LBL_ERR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now read the masked seed */
|
/* now read the masked seed */
|
||||||
@ -137,8 +139,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
|
|||||||
|
|
||||||
/* compare the lhash'es */
|
/* compare the lhash'es */
|
||||||
if (mem_neq(seed, DB, hLen) != 0) {
|
if (mem_neq(seed, DB, hLen) != 0) {
|
||||||
err = CRYPT_OK;
|
ret = CRYPT_INVALID_PACKET;
|
||||||
goto LBL_ERR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now zeroes before a 0x01 */
|
/* now zeroes before a 0x01 */
|
||||||
@ -146,28 +147,27 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen,
|
|||||||
/* step... */
|
/* step... */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* error out if wasn't 0x01 */
|
/* error if wasn't 0x01 */
|
||||||
if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) {
|
if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) {
|
||||||
err = CRYPT_INVALID_PACKET;
|
ret = CRYPT_INVALID_PACKET;
|
||||||
goto LBL_ERR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rest is the message (and skip 0x01) */
|
/* rest is the message (and skip 0x01) */
|
||||||
if ((modulus_len - hLen - 1 - ++x) > *outlen) {
|
if ((modulus_len - hLen - 1 - ++x) > *outlen) {
|
||||||
*outlen = modulus_len - hLen - 1 - x;
|
ret = CRYPT_INVALID_PACKET;
|
||||||
err = CRYPT_BUFFER_OVERFLOW;
|
|
||||||
goto LBL_ERR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy message */
|
if (ret == CRYPT_OK) {
|
||||||
*outlen = modulus_len - hLen - 1 - x;
|
/* copy message */
|
||||||
XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x);
|
*outlen = modulus_len - hLen - 1 - x;
|
||||||
x += modulus_len - hLen - 1;
|
XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x);
|
||||||
|
x += modulus_len - hLen - 1;
|
||||||
|
|
||||||
/* valid packet */
|
/* valid packet */
|
||||||
*res = 1;
|
*res = 1;
|
||||||
|
}
|
||||||
|
err = ret;
|
||||||
|
|
||||||
err = CRYPT_OK;
|
|
||||||
LBL_ERR:
|
LBL_ERR:
|
||||||
#ifdef LTC_CLEAN_STACK
|
#ifdef LTC_CLEAN_STACK
|
||||||
zeromem(DB, modulus_len);
|
zeromem(DB, modulus_len);
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
* @param outlen [in/out] The max size and resulting size of the decoding
|
* @param outlen [in/out] The max size and resulting size of the decoding
|
||||||
* @param is_valid [out] Boolean whether the padding was valid
|
* @param is_valid [out] Boolean whether the padding was valid
|
||||||
*
|
*
|
||||||
* @return CRYPT_OK if successful (even if invalid)
|
* @return CRYPT_OK if successful
|
||||||
*/
|
*/
|
||||||
int pkcs_1_v1_5_decode(const unsigned char *msg,
|
int pkcs_1_v1_5_decode(const unsigned char *msg,
|
||||||
unsigned long msglen,
|
unsigned long msglen,
|
||||||
@ -51,11 +51,12 @@ int pkcs_1_v1_5_decode(const unsigned char *msg,
|
|||||||
return CRYPT_PK_INVALID_SIZE;
|
return CRYPT_PK_INVALID_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = CRYPT_OK;
|
||||||
|
|
||||||
/* separate encoded message */
|
/* separate encoded message */
|
||||||
|
|
||||||
if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) {
|
if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) {
|
||||||
result = CRYPT_INVALID_PACKET;
|
result = CRYPT_INVALID_PACKET;
|
||||||
goto bail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block_type == LTC_PKCS_1_EME) {
|
if (block_type == LTC_PKCS_1_EME) {
|
||||||
@ -69,7 +70,6 @@ int pkcs_1_v1_5_decode(const unsigned char *msg,
|
|||||||
/* There was no octet with hexadecimal value 0x00 to separate ps from m.
|
/* There was no octet with hexadecimal value 0x00 to separate ps from m.
|
||||||
*/
|
*/
|
||||||
result = CRYPT_INVALID_PACKET;
|
result = CRYPT_INVALID_PACKET;
|
||||||
goto bail;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 2; i < modulus_len - 1; i++) {
|
for (i = 2; i < modulus_len - 1; i++) {
|
||||||
@ -80,7 +80,6 @@ int pkcs_1_v1_5_decode(const unsigned char *msg,
|
|||||||
if (msg[i] != 0) {
|
if (msg[i] != 0) {
|
||||||
/* There was no octet with hexadecimal value 0x00 to separate ps from m. */
|
/* There was no octet with hexadecimal value 0x00 to separate ps from m. */
|
||||||
result = CRYPT_INVALID_PACKET;
|
result = CRYPT_INVALID_PACKET;
|
||||||
goto bail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ps_len = i - 2;
|
ps_len = i - 2;
|
||||||
@ -91,22 +90,20 @@ int pkcs_1_v1_5_decode(const unsigned char *msg,
|
|||||||
/* The length of ps is less than 8 octets.
|
/* The length of ps is less than 8 octets.
|
||||||
*/
|
*/
|
||||||
result = CRYPT_INVALID_PACKET;
|
result = CRYPT_INVALID_PACKET;
|
||||||
goto bail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*outlen < (msglen - (2 + ps_len + 1))) {
|
if (*outlen < (msglen - (2 + ps_len + 1))) {
|
||||||
*outlen = msglen - (2 + ps_len + 1);
|
result = CRYPT_INVALID_PACKET;
|
||||||
result = CRYPT_BUFFER_OVERFLOW;
|
|
||||||
goto bail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*outlen = (msglen - (2 + ps_len + 1));
|
if (result == CRYPT_OK) {
|
||||||
XMEMCPY(out, &msg[2 + ps_len + 1], *outlen);
|
*outlen = (msglen - (2 + ps_len + 1));
|
||||||
|
XMEMCPY(out, &msg[2 + ps_len + 1], *outlen);
|
||||||
|
|
||||||
|
/* valid packet */
|
||||||
|
*is_valid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* valid packet */
|
|
||||||
*is_valid = 1;
|
|
||||||
result = CRYPT_OK;
|
|
||||||
bail:
|
|
||||||
return result;
|
return result;
|
||||||
} /* pkcs_1_v1_5_decode */
|
} /* pkcs_1_v1_5_decode */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user