diff options
author | wolfbeast <mcwerewolf@gmail.com> | 2018-12-17 14:12:04 +0100 |
---|---|---|
committer | wolfbeast <mcwerewolf@gmail.com> | 2018-12-17 14:12:04 +0100 |
commit | 51b821b3fdc5a7eab2369cb6a6680598a6264b08 (patch) | |
tree | f3608a518bbb9e31b0a42b9a10742fb11ef5b39b /security/nss/lib/freebl/rsapkcs.c | |
parent | 8e44bbb43789e585fab9fc1ce8becc94b45d566c (diff) | |
parent | 680c3eadb6aaec1f3653636db081a519e0f62ef5 (diff) | |
download | UXP-51b821b3fdc5a7eab2369cb6a6680598a6264b08.tar UXP-51b821b3fdc5a7eab2369cb6a6680598a6264b08.tar.gz UXP-51b821b3fdc5a7eab2369cb6a6680598a6264b08.tar.lz UXP-51b821b3fdc5a7eab2369cb6a6680598a6264b08.tar.xz UXP-51b821b3fdc5a7eab2369cb6a6680598a6264b08.zip |
Merge branch 'master' into Sync-weave
Diffstat (limited to 'security/nss/lib/freebl/rsapkcs.c')
-rw-r--r-- | security/nss/lib/freebl/rsapkcs.c | 68 |
1 files changed, 38 insertions, 30 deletions
diff --git a/security/nss/lib/freebl/rsapkcs.c b/security/nss/lib/freebl/rsapkcs.c index ad18c8b73..875e4e28d 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; } /* |