964621438a
This update involves a bunch of fixes on our side: Update the Gentoo patch to 3.14.1 from http://bit.ly/ZG8OK5 and drop the older one from http://bit.ly/15mN0X1 (for 3.12.5). While checking the old patch from Gentoo, I discovered, that the patch added in revision 06c543b11dfeb708963c6a63bf7f1ed79c5367b2 wasn't the original one in the Gentoo repository. Instead of doing the same again, we now patch up our specific modifications using sed within the postPatch hook. In addition to that, we now have another patch from RedHat/Fedora which syncs the NSS PEM support repository with the latest upstream changes. Patch is coming from the SRPM at http://koji.fedoraproject.org/koji/rpminfo?rpmID=3772072 and I just stripped the "0001-" prefix from the filename. Signed-off-by: aszlig <aszlig@redmoonstudios.org>
407 lines
12 KiB
Diff
407 lines
12 KiB
Diff
From d6dbecfea317a468be12423595e584f43d84d8ec Mon Sep 17 00:00:00 2001
|
|
From: Elio Maldonado <emaldona@redhat.com>
|
|
Date: Sat, 9 Feb 2013 17:11:00 -0500
|
|
Subject: [PATCH] Sync up with upstream softokn changes
|
|
|
|
- Disable RSA OEP case in FormatBlock, RSA_OAEP support is experimental and in a state of flux
|
|
- Numerous change upstream due to the work for TLS/DTLS 'Lucky 13' vulnerability CVE-2013-0169
|
|
- It now compiles with the NSS_3_14_3_BETA1 source
|
|
---
|
|
mozilla/security/nss/lib/ckfw/pem/rsawrapr.c | 338 +++++++-------------------
|
|
1 files changed, 82 insertions(+), 256 deletions(-)
|
|
|
|
diff --git a/mozilla/security/nss/lib/ckfw/pem/rsawrapr.c b/mozilla/security/nss/lib/ckfw/pem/rsawrapr.c
|
|
index 5ac4f39..3780d30 100644
|
|
--- a/mozilla/security/nss/lib/ckfw/pem/rsawrapr.c
|
|
+++ b/mozilla/security/nss/lib/ckfw/pem/rsawrapr.c
|
|
@@ -46,6 +46,7 @@
|
|
#include "sechash.h"
|
|
#include "base.h"
|
|
|
|
+#include "lowkeyi.h"
|
|
#include "secerr.h"
|
|
|
|
#define RSA_BLOCK_MIN_PAD_LEN 8
|
|
@@ -54,9 +55,8 @@
|
|
#define RSA_BLOCK_PRIVATE_PAD_OCTET 0xff
|
|
#define RSA_BLOCK_AFTER_PAD_OCTET 0x00
|
|
|
|
-#define OAEP_SALT_LEN 8
|
|
-#define OAEP_PAD_LEN 8
|
|
-#define OAEP_PAD_OCTET 0x00
|
|
+/* Needed for RSA-PSS functions */
|
|
+static const unsigned char eightZeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
|
|
#define FLAT_BUFSIZE 512 /* bytes to hold flattened SHA1Context. */
|
|
|
|
@@ -78,127 +78,39 @@ pem_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
|
|
return 0;
|
|
}
|
|
|
|
-static SHA1Context *SHA1_CloneContext(SHA1Context * original)
|
|
-{
|
|
- SHA1Context *clone = NULL;
|
|
- unsigned char *pBuf;
|
|
- int sha1ContextSize = SHA1_FlattenSize(original);
|
|
- SECStatus frv;
|
|
- unsigned char buf[FLAT_BUFSIZE];
|
|
-
|
|
- PORT_Assert(sizeof buf >= sha1ContextSize);
|
|
- if (sizeof buf >= sha1ContextSize) {
|
|
- pBuf = buf;
|
|
- } else {
|
|
- pBuf = nss_ZAlloc(NULL, sha1ContextSize);
|
|
- if (!pBuf)
|
|
- goto done;
|
|
- }
|
|
-
|
|
- frv = SHA1_Flatten(original, pBuf);
|
|
- if (frv == SECSuccess) {
|
|
- clone = SHA1_Resurrect(pBuf, NULL);
|
|
- memset(pBuf, 0, sha1ContextSize);
|
|
- }
|
|
- done:
|
|
- if (pBuf != buf)
|
|
- nss_ZFreeIf(pBuf);
|
|
- return clone;
|
|
+/* Constant time comparison of a single byte.
|
|
+ * Returns 1 iff a == b, otherwise returns 0.
|
|
+ * Note: For ranges of bytes, use constantTimeCompare.
|
|
+ */
|
|
+static unsigned char constantTimeEQ8(unsigned char a, unsigned char b) {
|
|
+ unsigned char c = ~(a - b | b - a);
|
|
+ c >>= 7;
|
|
+ return c;
|
|
}
|
|
|
|
-/*
|
|
- * Modify data by XORing it with a special hash of salt.
|
|
+/* Constant time comparison of a range of bytes.
|
|
+ * Returns 1 iff len bytes of a are identical to len bytes of b, otherwise
|
|
+ * returns 0.
|
|
*/
|
|
-static SECStatus
|
|
-oaep_xor_with_h1(unsigned char *data, unsigned int datalen,
|
|
- unsigned char *salt, unsigned int saltlen)
|
|
-{
|
|
- SHA1Context *sha1cx;
|
|
- unsigned char *dp, *dataend;
|
|
- unsigned char end_octet;
|
|
-
|
|
- sha1cx = SHA1_NewContext();
|
|
- if (sha1cx == NULL) {
|
|
- return SECFailure;
|
|
- }
|
|
-
|
|
- /*
|
|
- * Get a hash of salt started; we will use it several times,
|
|
- * adding in a different end octet (x00, x01, x02, ...).
|
|
- */
|
|
- SHA1_Begin(sha1cx);
|
|
- SHA1_Update(sha1cx, salt, saltlen);
|
|
- end_octet = 0;
|
|
-
|
|
- dp = data;
|
|
- dataend = data + datalen;
|
|
-
|
|
- while (dp < dataend) {
|
|
- SHA1Context *sha1cx_h1;
|
|
- unsigned int sha1len, sha1off;
|
|
- unsigned char sha1[SHA1_LENGTH];
|
|
-
|
|
- /*
|
|
- * Create hash of (salt || end_octet)
|
|
- */
|
|
- sha1cx_h1 = SHA1_CloneContext(sha1cx);
|
|
- SHA1_Update(sha1cx_h1, &end_octet, 1);
|
|
- SHA1_End(sha1cx_h1, sha1, &sha1len, sizeof(sha1));
|
|
- SHA1_DestroyContext(sha1cx_h1, PR_TRUE);
|
|
- PORT_Assert(sha1len == SHA1_LENGTH);
|
|
-
|
|
- /*
|
|
- * XOR that hash with the data.
|
|
- * When we have fewer than SHA1_LENGTH octets of data
|
|
- * left to xor, use just the low-order ones of the hash.
|
|
- */
|
|
- sha1off = 0;
|
|
- if ((dataend - dp) < SHA1_LENGTH)
|
|
- sha1off = SHA1_LENGTH - (dataend - dp);
|
|
- while (sha1off < SHA1_LENGTH)
|
|
- *dp++ ^= sha1[sha1off++];
|
|
-
|
|
- /*
|
|
- * Bump for next hash chunk.
|
|
- */
|
|
- end_octet++;
|
|
- }
|
|
-
|
|
- SHA1_DestroyContext(sha1cx, PR_TRUE);
|
|
- return SECSuccess;
|
|
+static unsigned char constantTimeCompare(const unsigned char *a,
|
|
+ const unsigned char *b,
|
|
+ unsigned int len) {
|
|
+ unsigned char tmp = 0;
|
|
+ unsigned int i;
|
|
+ for (i = 0; i < len; ++i, ++a, ++b)
|
|
+ tmp |= *a ^ *b;
|
|
+ return constantTimeEQ8(0x00, tmp);
|
|
}
|
|
|
|
-/*
|
|
- * Modify salt by XORing it with a special hash of data.
|
|
+/* Constant time conditional.
|
|
+ * Returns a if c is 1, or b if c is 0. The result is undefined if c is
|
|
+ * not 0 or 1.
|
|
*/
|
|
-static SECStatus
|
|
-oaep_xor_with_h2(unsigned char *salt, unsigned int saltlen,
|
|
- unsigned char *data, unsigned int datalen)
|
|
+static unsigned int constantTimeCondition(unsigned int c,
|
|
+ unsigned int a,
|
|
+ unsigned int b)
|
|
{
|
|
- unsigned char sha1[SHA1_LENGTH];
|
|
- unsigned char *psalt, *psha1, *saltend;
|
|
- SECStatus rv;
|
|
-
|
|
- /*
|
|
- * Create a hash of data.
|
|
- */
|
|
- rv = SHA1_HashBuf(sha1, data, datalen);
|
|
- if (rv != SECSuccess) {
|
|
- return rv;
|
|
- }
|
|
-
|
|
- /*
|
|
- * XOR the low-order octets of that hash with salt.
|
|
- */
|
|
- PORT_Assert(saltlen <= SHA1_LENGTH);
|
|
- saltend = salt + saltlen;
|
|
- psalt = salt;
|
|
- psha1 = sha1 + SHA1_LENGTH - saltlen;
|
|
- while (psalt < saltend) {
|
|
- *psalt++ ^= *psha1++;
|
|
- }
|
|
-
|
|
- return SECSuccess;
|
|
+ return (~(c - 1) & a) | ((c - 1) & b);
|
|
}
|
|
|
|
/*
|
|
@@ -212,7 +124,7 @@ static unsigned char *rsa_FormatOneBlock(unsigned modulusLen,
|
|
unsigned char *block;
|
|
unsigned char *bp;
|
|
int padLen;
|
|
- int i;
|
|
+ int i, j;
|
|
SECStatus rv;
|
|
|
|
block = (unsigned char *) nss_ZAlloc(NULL, modulusLen);
|
|
@@ -260,124 +172,58 @@ static unsigned char *rsa_FormatOneBlock(unsigned modulusLen,
|
|
*/
|
|
case RSA_BlockPublic:
|
|
|
|
- /*
|
|
- * 0x00 || BT || Pad || 0x00 || ActualData
|
|
- * 1 1 padLen 1 data->len
|
|
- * Pad is all non-zero random bytes.
|
|
- */
|
|
- padLen = modulusLen - data->len - 3;
|
|
- PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
|
|
- if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
|
|
- nss_ZFreeIf(block);
|
|
- return NULL;
|
|
- }
|
|
- for (i = 0; i < padLen; i++) {
|
|
- /* Pad with non-zero random data. */
|
|
- do {
|
|
- rv = RNG_GenerateGlobalRandomBytes(bp + i, 1);
|
|
- } while (rv == SECSuccess
|
|
- && bp[i] == RSA_BLOCK_AFTER_PAD_OCTET);
|
|
- if (rv != SECSuccess) {
|
|
- nss_ZFreeIf(block);
|
|
- return NULL;
|
|
- }
|
|
- }
|
|
- bp += padLen;
|
|
- *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
|
|
- nsslibc_memcpy(bp, data->data, data->len);
|
|
-
|
|
- break;
|
|
-
|
|
- /*
|
|
- * Blocks intended for public-key operation, using
|
|
- * Optimal Asymmetric Encryption Padding (OAEP).
|
|
- */
|
|
- case RSA_BlockOAEP:
|
|
- /*
|
|
- * 0x00 || BT || Modified2(Salt) || Modified1(PaddedData)
|
|
- * 1 1 OAEP_SALT_LEN OAEP_PAD_LEN + data->len [+ N]
|
|
- *
|
|
- * where:
|
|
- * PaddedData is "Pad1 || ActualData [|| Pad2]"
|
|
- * Salt is random data.
|
|
- * Pad1 is all zeros.
|
|
- * Pad2, if present, is random data.
|
|
- * (The "modified" fields are all the same length as the original
|
|
- * unmodified values; they are just xor'd with other values.)
|
|
- *
|
|
- * Modified1 is an XOR of PaddedData with a special octet
|
|
- * string constructed of iterated hashing of Salt (see below).
|
|
- * Modified2 is an XOR of Salt with the low-order octets of
|
|
- * the hash of Modified1 (see farther below ;-).
|
|
- *
|
|
- * Whew!
|
|
- */
|
|
-
|
|
-
|
|
- /*
|
|
- * Salt
|
|
- */
|
|
- rv = RNG_GenerateGlobalRandomBytes(bp, OAEP_SALT_LEN);
|
|
- if (rv != SECSuccess) {
|
|
- nss_ZFreeIf(block);
|
|
- return NULL;
|
|
- }
|
|
- bp += OAEP_SALT_LEN;
|
|
-
|
|
- /*
|
|
- * Pad1
|
|
- */
|
|
- nsslibc_memset(bp, OAEP_PAD_OCTET, OAEP_PAD_LEN);
|
|
- bp += OAEP_PAD_LEN;
|
|
-
|
|
- /*
|
|
- * Data
|
|
- */
|
|
- nsslibc_memcpy(bp, data->data, data->len);
|
|
- bp += data->len;
|
|
-
|
|
- /*
|
|
- * Pad2
|
|
- */
|
|
- if (bp < (block + modulusLen)) {
|
|
- rv = RNG_GenerateGlobalRandomBytes(bp,
|
|
- block - bp + modulusLen);
|
|
- if (rv != SECSuccess) {
|
|
- nss_ZFreeIf(block);
|
|
- return NULL;
|
|
- }
|
|
- }
|
|
-
|
|
- /*
|
|
- * Now we have the following:
|
|
- * 0x00 || BT || Salt || PaddedData
|
|
- * (From this point on, "Pad1 || Data [|| Pad2]" is treated
|
|
- * as the one entity PaddedData.)
|
|
- *
|
|
- * We need to turn PaddedData into Modified1.
|
|
- */
|
|
- if (oaep_xor_with_h1(block + 2 + OAEP_SALT_LEN,
|
|
- modulusLen - 2 - OAEP_SALT_LEN,
|
|
- block + 2, OAEP_SALT_LEN) != SECSuccess) {
|
|
- nss_ZFreeIf(block);
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- /*
|
|
- * Now we have:
|
|
- * 0x00 || BT || Salt || Modified1(PaddedData)
|
|
- *
|
|
- * The remaining task is to turn Salt into Modified2.
|
|
- */
|
|
- if (oaep_xor_with_h2(block + 2, OAEP_SALT_LEN,
|
|
- block + 2 + OAEP_SALT_LEN,
|
|
- modulusLen - 2 - OAEP_SALT_LEN) !=
|
|
- SECSuccess) {
|
|
- nss_ZFreeIf(block);
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- break;
|
|
+ /*
|
|
+ * 0x00 || BT || Pad || 0x00 || ActualData
|
|
+ * 1 1 padLen 1 data->len
|
|
+ * Pad is all non-zero random bytes.
|
|
+ *
|
|
+ * Build the block left to right.
|
|
+ * Fill the entire block from Pad to the end with random bytes.
|
|
+ * Use the bytes after Pad as a supply of extra random bytes from
|
|
+ * which to find replacements for the zero bytes in Pad.
|
|
+ * If we need more than that, refill the bytes after Pad with
|
|
+ * new random bytes as necessary.
|
|
+ */
|
|
+ padLen = modulusLen - (data->len + 3);
|
|
+ PORT_Assert (padLen >= RSA_BLOCK_MIN_PAD_LEN);
|
|
+ if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
|
|
+ nss_ZFreeIf (block);
|
|
+ return NULL;
|
|
+ }
|
|
+ j = modulusLen - 2;
|
|
+ rv = RNG_GenerateGlobalRandomBytes(bp, j);
|
|
+ if (rv == SECSuccess) {
|
|
+ for (i = 0; i < padLen; ) {
|
|
+ unsigned char repl;
|
|
+ /* Pad with non-zero random data. */
|
|
+ if (bp[i] != RSA_BLOCK_AFTER_PAD_OCTET) {
|
|
+ ++i;
|
|
+ continue;
|
|
+ }
|
|
+ if (j <= padLen) {
|
|
+ rv = RNG_GenerateGlobalRandomBytes(bp + padLen,
|
|
+ modulusLen - (2 + padLen));
|
|
+ if (rv != SECSuccess)
|
|
+ break;
|
|
+ j = modulusLen - 2;
|
|
+ }
|
|
+ do {
|
|
+ repl = bp[--j];
|
|
+ } while (repl == RSA_BLOCK_AFTER_PAD_OCTET && j > padLen);
|
|
+ if (repl != RSA_BLOCK_AFTER_PAD_OCTET) {
|
|
+ bp[i++] = repl;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (rv != SECSuccess) {
|
|
+ /*sftk_fatalError = PR_TRUE;*/
|
|
+ nss_ZFreeIf (block);
|
|
+ return NULL;
|
|
+ }
|
|
+ bp += padLen;
|
|
+ *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
|
|
+ nsslibc_memcpy(bp, data->data, data->len);
|
|
+ break;
|
|
|
|
default:
|
|
PORT_Assert(0);
|
|
@@ -427,26 +273,6 @@ rsa_FormatBlock(SECItem * result, unsigned modulusLen,
|
|
|
|
break;
|
|
|
|
- case RSA_BlockOAEP:
|
|
- /*
|
|
- * 0x00 || BT || M1(Salt) || M2(Pad1||ActualData[||Pad2])
|
|
- *
|
|
- * The "2" below is the first octet + the second octet.
|
|
- * (The other fields do not contain the clear values, but are
|
|
- * the same length as the clear values.)
|
|
- */
|
|
- PORT_Assert(data->len <= (modulusLen - (2 + OAEP_SALT_LEN
|
|
- + OAEP_PAD_LEN)));
|
|
-
|
|
- result->data = rsa_FormatOneBlock(modulusLen, blockType, data);
|
|
- if (result->data == NULL) {
|
|
- result->len = 0;
|
|
- return SECFailure;
|
|
- }
|
|
- result->len = modulusLen;
|
|
-
|
|
- break;
|
|
-
|
|
case RSA_BlockRaw:
|
|
/*
|
|
* Pad || ActualData
|
|
--
|
|
1.7.1
|
|
|