summaryrefslogtreecommitdiff
path: root/security/nss/lib/freebl/rsapkcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/freebl/rsapkcs.c')
-rw-r--r--security/nss/lib/freebl/rsapkcs.c68
1 files changed, 38 insertions, 30 deletions
diff --git a/security/nss/lib/freebl/rsapkcs.c b/security/nss/lib/freebl/rsapkcs.c
index ad18c8b733..875e4e28d3 100644
--- a/security/nss/lib/freebl/rsapkcs.c
+++ b/security/nss/lib/freebl/rsapkcs.c
@@ -938,48 +938,56 @@ RSA_DecryptBlock(RSAPrivateKey *key,
const unsigned char *input,
unsigned int inputLen)
{
- SECStatus rv;
+ PRInt8 rv;
unsigned int modulusLen = rsa_modulusLen(&key->modulus);
unsigned int i;
- unsigned char *buffer;
+ unsigned char *buffer = NULL;
+ unsigned int outLen = 0;
+ unsigned int copyOutLen = modulusLen - 11;
- if (inputLen != modulusLen)
- goto failure;
+ if (inputLen != modulusLen || modulusLen < 10) {
+ return SECFailure;
+ }
- buffer = (unsigned char *)PORT_Alloc(modulusLen + 1);
- if (!buffer)
- goto failure;
+ if (copyOutLen > maxOutputLen) {
+ copyOutLen = maxOutputLen;
+ }
- rv = RSA_PrivateKeyOp(key, buffer, input);
- if (rv != SECSuccess)
- goto loser;
+ // Allocate enough space to decrypt + copyOutLen to allow copying outLen later.
+ buffer = PORT_ZAlloc(modulusLen + 1 + copyOutLen);
+ if (!buffer) {
+ return SECFailure;
+ }
- /* XXX(rsleevi): Constant time */
- if (buffer[0] != RSA_BLOCK_FIRST_OCTET ||
- buffer[1] != (unsigned char)RSA_BlockPublic) {
- goto loser;
+ // rv is 0 if everything is going well and 1 if an error occurs.
+ rv = RSA_PrivateKeyOp(key, buffer, input) != SECSuccess;
+ rv |= (buffer[0] != RSA_BLOCK_FIRST_OCTET) |
+ (buffer[1] != (unsigned char)RSA_BlockPublic);
+
+ // There have to be at least 8 bytes of padding.
+ for (i = 2; i < 10; i++) {
+ rv |= buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET;
}
- *outputLen = 0;
- for (i = 2; i < modulusLen; i++) {
- if (buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET) {
- *outputLen = modulusLen - i - 1;
- break;
- }
+
+ for (i = 10; i < modulusLen; i++) {
+ unsigned int newLen = modulusLen - i - 1;
+ unsigned int c = (buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET) & (outLen == 0);
+ outLen = constantTimeCondition(c, newLen, outLen);
}
- if (*outputLen == 0)
- goto loser;
- if (*outputLen > maxOutputLen)
- goto loser;
+ rv |= outLen == 0;
+ rv |= outLen > maxOutputLen;
- PORT_Memcpy(output, buffer + modulusLen - *outputLen, *outputLen);
+ // Note that output is set even if SECFailure is returned.
+ PORT_Memcpy(output, buffer + modulusLen - outLen, copyOutLen);
+ *outputLen = constantTimeCondition(outLen > maxOutputLen, maxOutputLen,
+ outLen);
PORT_Free(buffer);
- return SECSuccess;
-loser:
- PORT_Free(buffer);
-failure:
- return SECFailure;
+ for (i = 1; i < sizeof(rv) * 8; i <<= 1) {
+ rv |= rv << i;
+ }
+ return (SECStatus)rv;
}
/*