From 0ec2973ab860e644b8032d487ad0d0879aac12c9 Mon Sep 17 00:00:00 2001 From: Kai Engert Date: Sun, 10 Feb 2013 01:11:00 +0100 Subject: [PATCH] Bug 839141 - Upgrade Mozilla to NSS 3.14.3, starting with Beta1, r=ekr --- security/nss/TAG-INFO | 2 +- security/nss/TAG-INFO-CKBI | 2 +- security/nss/lib/freebl/blapi.h | 34 +- security/nss/lib/freebl/ecl/ecp_aff.c | 7 +- security/nss/lib/freebl/hmacct.c | 336 +++++++++++++ security/nss/lib/freebl/hmacct.h | 38 ++ security/nss/lib/freebl/ldvector.c | 10 +- security/nss/lib/freebl/loader.c | 50 +- security/nss/lib/freebl/loader.h | 34 +- security/nss/lib/freebl/manifest.mn | 2 + security/nss/lib/freebl/md5.c | 29 +- security/nss/lib/freebl/rawhash.c | 30 +- security/nss/lib/freebl/sha512.c | 77 ++- security/nss/lib/freebl/sha_fast.c | 21 +- security/nss/lib/freebl/sha_fast.h | 12 +- security/nss/lib/nss/nss.def | 6 + security/nss/lib/nss/nss.h | 8 +- security/nss/lib/pk11wrap/pk11obj.c | 45 ++ security/nss/lib/pk11wrap/pk11pub.h | 2 + security/nss/lib/pkcs7/p7decode.c | 41 +- security/nss/lib/pkcs7/secpkcs7.h | 17 - security/nss/lib/smime/smime.def | 6 - security/nss/lib/softoken/manifest.mn | 1 + security/nss/lib/softoken/pkcs11.c | 5 +- security/nss/lib/softoken/pkcs11c.c | 160 ++++++- security/nss/lib/softoken/pkcs11i.h | 37 ++ security/nss/lib/softoken/rsawrapr.c | 664 +++++++++++++++++--------- security/nss/lib/softoken/sdb.c | 5 + security/nss/lib/softoken/sftkhmac.c | 192 ++++++++ security/nss/lib/softoken/softkver.h | 6 +- security/nss/lib/softoken/softoken.h | 18 +- security/nss/lib/softoken/softoknt.h | 5 +- security/nss/lib/ssl/ssl3con.c | 445 ++++++++++++++--- security/nss/lib/util/hasht.h | 3 +- security/nss/lib/util/nssutil.h | 6 +- security/nss/lib/util/pkcs11n.h | 19 +- security/nss/tests/ssl/ssl.sh | 2 +- 37 files changed, 1964 insertions(+), 413 deletions(-) create mode 100644 security/nss/lib/freebl/hmacct.c create mode 100644 security/nss/lib/freebl/hmacct.h create mode 100644 security/nss/lib/softoken/sftkhmac.c diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO index b9d80352c563..c1f02756231e 100644 --- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1 +1 @@ -NSS_3_14_2_RTM +NSS_3_14_3_BETA1 diff --git a/security/nss/TAG-INFO-CKBI b/security/nss/TAG-INFO-CKBI index b9d80352c563..c1f02756231e 100644 --- a/security/nss/TAG-INFO-CKBI +++ b/security/nss/TAG-INFO-CKBI @@ -1 +1 @@ -NSS_3_14_2_RTM +NSS_3_14_3_BETA1 diff --git a/security/nss/lib/freebl/blapi.h b/security/nss/lib/freebl/blapi.h index fd3190511718..44b4c63956f3 100644 --- a/security/nss/lib/freebl/blapi.h +++ b/security/nss/lib/freebl/blapi.h @@ -4,7 +4,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: blapi.h,v 1.49 2012/10/11 00:10:26 rrelyea%redhat.com Exp $ */ +/* $Id: blapi.h,v 1.50 2013/02/05 18:10:42 wtc%google.com Exp $ */ #ifndef _BLAPI_H_ #define _BLAPI_H_ @@ -874,6 +874,18 @@ extern void MD5_Update(MD5Context *cx, extern void MD5_End(MD5Context *cx, unsigned char *digest, unsigned int *digestLen, unsigned int maxDigestLen); +/* +** Export the raw state of the MD5 hash without appending the standard padding +** and length bytes. Produce the digested results in "digest" +** "cx" the context +** "digest" where the 16 bytes of digest data are stored +** "digestLen" where the digest length (16) is stored (optional) +** "maxDigestLen" the maximum amount of data that can ever be +** stored in "digest" +*/ +extern void MD5_EndRaw(MD5Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen); + /* * Return the the size of a buffer needed to flatten the MD5 Context into * "cx" the context @@ -1030,6 +1042,18 @@ extern void SHA1_Update(SHA1Context *cx, const unsigned char *input, extern void SHA1_End(SHA1Context *cx, unsigned char *digest, unsigned int *digestLen, unsigned int maxDigestLen); +/* +** Export the current state of the SHA-1 hash without appending the standard +** padding and length. Produce the digested results in "digest" +** "cx" the context +** "digest" where the 16 bytes of digest data are stored +** "digestLen" where the digest length (20) is stored (optional) +** "maxDigestLen" the maximum amount of data that can ever be +** stored in "digest" +*/ +extern void SHA1_EndRaw(SHA1Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen); + /* ** trace the intermediate state info of the SHA1 hash. */ @@ -1068,6 +1092,8 @@ extern void SHA224_Update(SHA224Context *cx, const unsigned char *input, unsigned int inputLen); extern void SHA224_End(SHA224Context *cx, unsigned char *digest, unsigned int *digestLen, unsigned int maxDigestLen); +extern void SHA224_EndRaw(SHA224Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen); extern SECStatus SHA224_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length); extern SECStatus SHA224_Hash(unsigned char *dest, const char *src); @@ -1086,6 +1112,8 @@ extern void SHA256_Update(SHA256Context *cx, const unsigned char *input, unsigned int inputLen); extern void SHA256_End(SHA256Context *cx, unsigned char *digest, unsigned int *digestLen, unsigned int maxDigestLen); +extern void SHA256_EndRaw(SHA256Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen); extern SECStatus SHA256_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length); extern SECStatus SHA256_Hash(unsigned char *dest, const char *src); @@ -1102,6 +1130,8 @@ extern void SHA512_DestroyContext(SHA512Context *cx, PRBool freeit); extern void SHA512_Begin(SHA512Context *cx); extern void SHA512_Update(SHA512Context *cx, const unsigned char *input, unsigned int inputLen); +extern void SHA512_EndRaw(SHA512Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen); extern void SHA512_End(SHA512Context *cx, unsigned char *digest, unsigned int *digestLen, unsigned int maxDigestLen); extern SECStatus SHA512_HashBuf(unsigned char *dest, const unsigned char *src, @@ -1122,6 +1152,8 @@ extern void SHA384_Update(SHA384Context *cx, const unsigned char *input, unsigned int inputLen); extern void SHA384_End(SHA384Context *cx, unsigned char *digest, unsigned int *digestLen, unsigned int maxDigestLen); +extern void SHA384_EndRaw(SHA384Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen); extern SECStatus SHA384_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length); extern SECStatus SHA384_Hash(unsigned char *dest, const char *src); diff --git a/security/nss/lib/freebl/ecl/ecp_aff.c b/security/nss/lib/freebl/ecl/ecp_aff.c index 5ed84e028879..92e860448ae5 100644 --- a/security/nss/lib/freebl/ecl/ecp_aff.c +++ b/security/nss/lib/freebl/ecl/ecp_aff.c @@ -285,11 +285,10 @@ ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group) } /* left-hand side: y^2 */ MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) ); - /* right-hand side: x^3 + a*x + b */ + /* right-hand side: x^3 + a*x + b = (x^2 + a)*x + b by Horner's rule */ MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) ); - MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) ); - MP_CHECKOK( group->meth->field_mul(&group->curvea, &pxt, &tmp, group->meth) ); - MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) ); + MP_CHECKOK( group->meth->field_add(&tmp, &group->curvea, &tmp, group->meth) ); + MP_CHECKOK( group->meth->field_mul(&tmp, &pxt, &accr, group->meth) ); MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) ); /* check LHS - RHS == 0 */ MP_CHECKOK( group->meth->field_sub(&accl, &accr, &accr, group->meth) ); diff --git a/security/nss/lib/freebl/hmacct.c b/security/nss/lib/freebl/hmacct.c new file mode 100644 index 000000000000..0c3ba41dec10 --- /dev/null +++ b/security/nss/lib/freebl/hmacct.c @@ -0,0 +1,336 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifdef FREEBL_NO_DEPEND +#include "stubs.h" +#endif + +#include "secport.h" +#include "hasht.h" +#include "blapit.h" +#include "hmacct.h" +#include "secerr.h" + +/* MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's length + * field. (SHA-384/512 have 128-bit length.) */ +#define MAX_HASH_BIT_COUNT_BYTES 16 + +/* Some utility functions are needed: + * + * These macros return the given value with the MSB copied to all the other + * bits. They use the fact that an arithmetic shift shifts-in the sign bit. + * However, this is not ensured by the C standard so you may need to replace + * them with something else on odd CPUs. + * + * Note: the argument to these macros must be an unsigned int. + * */ +#define DUPLICATE_MSB_TO_ALL(x) ( (unsigned int)( (int)(x) >> (sizeof(int)*8-1) ) ) +#define DUPLICATE_MSB_TO_ALL_8(x) ( (unsigned char)(DUPLICATE_MSB_TO_ALL(x)) ) + +/* constantTimeGE returns 0xff if a>=b and 0x00 otherwise, where a, b < + * MAX_UINT/2. */ +static unsigned char +constantTimeGE(unsigned int a, unsigned int b) +{ + a -= b; + return DUPLICATE_MSB_TO_ALL(~a); +} + +/* constantTimeEQ8 returns 0xff if a==b and 0x00 otherwise. */ +static unsigned char +constantTimeEQ8(unsigned char a, unsigned char b) +{ + unsigned int c = a ^ b; + c--; + return DUPLICATE_MSB_TO_ALL_8(c); +} + +/* MAC performs a constant time SSLv3/TLS MAC of |dataLen| bytes of |data|, + * where |dataLen| includes both the authenticated bytes and the MAC tag from + * the sender. |dataLen| must be >= the length of the MAC tag. + * + * |dataTotalLen| is >= |dataLen| and also accounts for any padding bytes + * that may follow the sender's MAC. (Only a single block of padding may + * follow in SSLv3, or up to 255 bytes in TLS.) + * + * Since the results of decryption are secret information (otherwise a + * padding-oracle is created), this function is constant-time with respect to + * |dataLen|. + * + * |header| contains either the 13-byte TLS header (containing the sequence + * number, record type etc), or it contains the SSLv3 header with the SSLv3 + * padding bytes etc. */ +static SECStatus +MAC(unsigned char *mdOut, + unsigned int *mdOutLen, + unsigned int mdOutMax, + const SECHashObject *hashObj, + const unsigned char *macSecret, + unsigned int macSecretLen, + const unsigned char *header, + unsigned int headerLen, + const unsigned char *data, + unsigned int dataLen, + unsigned int dataTotalLen, + unsigned char isSSLv3) +{ + void *mdState = hashObj->create(); + const unsigned int mdSize = hashObj->length; + const unsigned int mdBlockSize = hashObj->blocklength; + /* mdLengthSize is the number of bytes in the length field that terminates + * the hash. + * + * This assumes that hash functions with a 64 byte block size use a 64-bit + * length, and otherwise they use a 128-bit length. This is true of {MD5, + * SHA*} (which are all of the hash functions specified for use with TLS + * today). */ + const unsigned int mdLengthSize = mdBlockSize == 64 ? 8 : 16; + + const unsigned int sslv3PadLen = hashObj->type == HASH_AlgMD5 ? 48 : 40; + + /* varianceBlocks is the number of blocks of the hash that we have to + * calculate in constant time because they could be altered by the + * padding value. + * + * In SSLv3, the padding must be minimal so the end of the plaintext + * varies by, at most, 15+20 = 35 bytes. (We conservatively assume that + * the MAC size varies from 0..20 bytes.) In case the 9 bytes of hash + * termination (0x80 + 64-bit length) don't fit in the final block, we + * say that the final two blocks can vary based on the padding. + * + * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not + * required to be minimal. Therefore we say that the final six blocks + * can vary based on the padding. + * + * Later in the function, if the message is short and there obviously + * cannot be this many blocks then varianceBlocks can be reduced. */ + unsigned int varianceBlocks = isSSLv3 ? 2 : 6; + /* From now on we're dealing with the MAC, which conceptually has 13 + * bytes of `header' before the start of the data (TLS) or 71/75 bytes + * (SSLv3) */ + const unsigned int len = dataTotalLen + headerLen; + /* maxMACBytes contains the maximum bytes of bytes in the MAC, including + * |header|, assuming that there's no padding. */ + const unsigned int maxMACBytes = len - mdSize - 1; + /* numBlocks is the maximum number of hash blocks. */ + const unsigned int numBlocks = + (maxMACBytes + 1 + mdLengthSize + mdBlockSize - 1) / mdBlockSize; + /* macEndOffset is the index just past the end of the data to be + * MACed. */ + const unsigned int macEndOffset = dataLen + headerLen - mdSize; + /* c is the index of the 0x80 byte in the final hash block that + * contains application data. */ + const unsigned int c = macEndOffset % mdBlockSize; + /* indexA is the hash block number that contains the 0x80 terminating + * value. */ + const unsigned int indexA = macEndOffset / mdBlockSize; + /* indexB is the hash block number that contains the 64-bit hash + * length, in bits. */ + const unsigned int indexB = (macEndOffset + mdLengthSize) / mdBlockSize; + /* bits is the hash-length in bits. It includes the additional hash + * block for the masked HMAC key, or whole of |header| in the case of + * SSLv3. */ + unsigned int bits; + /* In order to calculate the MAC in constant time we have to handle + * the final blocks specially because the padding value could cause the + * end to appear somewhere in the final |varianceBlocks| blocks and we + * can't leak where. However, |numStartingBlocks| worth of data can + * be hashed right away because no padding value can affect whether + * they are plaintext. */ + unsigned int numStartingBlocks = 0; + /* k is the starting byte offset into the conceptual header||data where + * we start processing. */ + unsigned int k = 0; + unsigned char lengthBytes[MAX_HASH_BIT_COUNT_BYTES]; + /* hmacPad is the masked HMAC key. */ + unsigned char hmacPad[HASH_BLOCK_LENGTH_MAX]; + unsigned char firstBlock[HASH_BLOCK_LENGTH_MAX]; + unsigned char macOut[HASH_LENGTH_MAX]; + unsigned i, j; + + /* For SSLv3, if we're going to have any starting blocks then we need + * at least two because the header is larger than a single block. */ + if (numBlocks > varianceBlocks + (isSSLv3 ? 1 : 0)) { + numStartingBlocks = numBlocks - varianceBlocks; + k = mdBlockSize*numStartingBlocks; + } + + bits = 8*macEndOffset; + hashObj->begin(mdState); + if (!isSSLv3) { + /* Compute the initial HMAC block. For SSLv3, the padding and + * secret bytes are included in |header| because they take more + * than a single block. */ + bits += 8*mdBlockSize; + memset(hmacPad, 0, mdBlockSize); + PORT_Assert(macSecretLen <= sizeof(hmacPad)); + memcpy(hmacPad, macSecret, macSecretLen); + for (i = 0; i < mdBlockSize; i++) + hmacPad[i] ^= 0x36; + hashObj->update(mdState, hmacPad, mdBlockSize); + } + + j = 0; + memset(lengthBytes, 0, sizeof(lengthBytes)); + if (mdLengthSize == 16) { + j = 8; + } + if (hashObj->type == HASH_AlgMD5) { + /* MD5 appends a little-endian length. */ + for (i = 0; i < 4; i++) { + lengthBytes[i+j] = bits >> (8*i); + } + } else { + /* All other TLS hash functions use a big-endian length. */ + for (i = 0; i < 4; i++) { + lengthBytes[4+i+j] = bits >> (8*(3-i)); + } + } + + if (k > 0) { + if (isSSLv3) { + /* The SSLv3 header is larger than a single block. + * overhang is the number of bytes beyond a single + * block that the header consumes: either 7 bytes + * (SHA1) or 11 bytes (MD5). */ + const unsigned int overhang = headerLen-mdBlockSize; + hashObj->update(mdState, header, mdBlockSize); + memcpy(firstBlock, header + mdBlockSize, overhang); + memcpy(firstBlock + overhang, data, mdBlockSize-overhang); + hashObj->update(mdState, firstBlock, mdBlockSize); + for (i = 1; i < k/mdBlockSize - 1; i++) { + hashObj->update(mdState, data + mdBlockSize*i - overhang, + mdBlockSize); + } + } else { + /* k is a multiple of mdBlockSize. */ + memcpy(firstBlock, header, 13); + memcpy(firstBlock+13, data, mdBlockSize-13); + hashObj->update(mdState, firstBlock, mdBlockSize); + for (i = 1; i < k/mdBlockSize; i++) { + hashObj->update(mdState, data + mdBlockSize*i - 13, + mdBlockSize); + } + } + } + + memset(macOut, 0, sizeof(macOut)); + + /* We now process the final hash blocks. For each block, we construct + * it in constant time. If i == indexA then we'll include the 0x80 + * bytes and zero pad etc. For each block we selectively copy it, in + * constant time, to |macOut|. */ + for (i = numStartingBlocks; i <= numStartingBlocks+varianceBlocks; i++) { + unsigned char block[HASH_BLOCK_LENGTH_MAX]; + unsigned char isBlockA = constantTimeEQ8(i, indexA); + unsigned char isBlockB = constantTimeEQ8(i, indexB); + for (j = 0; j < mdBlockSize; j++) { + unsigned char isPastC = isBlockA & constantTimeGE(j, c); + unsigned char isPastCPlus1 = isBlockA & constantTimeGE(j, c+1); + unsigned char b = 0; + if (k < headerLen) { + b = header[k]; + } else if (k < dataTotalLen + headerLen) { + b = data[k-headerLen]; + } + k++; + + /* If this is the block containing the end of the + * application data, and we are at the offset for the + * 0x80 value, then overwrite b with 0x80. */ + b = (b&~isPastC) | (0x80&isPastC); + /* If this the the block containing the end of the + * application data and we're past the 0x80 value then + * just write zero. */ + b = b&~isPastCPlus1; + /* If this is indexB (the final block), but not + * indexA (the end of the data), then the 64-bit + * length didn't fit into indexA and we're having to + * add an extra block of zeros. */ + b &= ~isBlockB | isBlockA; + + /* The final bytes of one of the blocks contains the length. */ + if (j >= mdBlockSize - mdLengthSize) { + /* If this is indexB, write a length byte. */ + b = (b&~isBlockB) | + (isBlockB&lengthBytes[j-(mdBlockSize-mdLengthSize)]); + } + block[j] = b; + } + + hashObj->update(mdState, block, mdBlockSize); + hashObj->end_raw(mdState, block, NULL, mdSize); + /* If this is indexB, copy the hash value to |macOut|. */ + for (j = 0; j < mdSize; j++) { + macOut[j] |= block[j]&isBlockB; + } + } + + hashObj->begin(mdState); + + if (isSSLv3) { + /* We repurpose |hmacPad| to contain the SSLv3 pad2 block. */ + for (i = 0; i < sslv3PadLen; i++) + hmacPad[i] = 0x5c; + + hashObj->update(mdState, macSecret, macSecretLen); + hashObj->update(mdState, hmacPad, sslv3PadLen); + hashObj->update(mdState, macOut, mdSize); + } else { + /* Complete the HMAC in the standard manner. */ + for (i = 0; i < mdBlockSize; i++) + hmacPad[i] ^= 0x6a; + + hashObj->update(mdState, hmacPad, mdBlockSize); + hashObj->update(mdState, macOut, mdSize); + } + + hashObj->end(mdState, mdOut, mdOutLen, mdOutMax); + hashObj->destroy(mdState, PR_TRUE); + + return SECSuccess; +} + +SECStatus +HMAC_ConstantTime( + unsigned char *result, + unsigned int *resultLen, + unsigned int maxResultLen, + const SECHashObject *hashObj, + const unsigned char *secret, + unsigned int secretLen, + const unsigned char *header, + unsigned int headerLen, + const unsigned char *body, + unsigned int bodyLen, + unsigned int bodyTotalLen) +{ + if (hashObj->end_raw == NULL) + return SECFailure; + return MAC(result, resultLen, maxResultLen, hashObj, secret, secretLen, + header, headerLen, body, bodyLen, bodyTotalLen, + 0 /* not SSLv3 */); +} + +SECStatus +SSLv3_MAC_ConstantTime( + unsigned char *result, + unsigned int *resultLen, + unsigned int maxResultLen, + const SECHashObject *hashObj, + const unsigned char *secret, + unsigned int secretLen, + const unsigned char *header, + unsigned int headerLen, + const unsigned char *body, + unsigned int bodyLen, + unsigned int bodyTotalLen) +{ + if (hashObj->end_raw == NULL) + return SECFailure; + return MAC(result, resultLen, maxResultLen, hashObj, secret, secretLen, + header, headerLen, body, bodyLen, bodyTotalLen, + 1 /* SSLv3 */); +} + diff --git a/security/nss/lib/freebl/hmacct.h b/security/nss/lib/freebl/hmacct.h new file mode 100644 index 000000000000..8b0e91c8a26e --- /dev/null +++ b/security/nss/lib/freebl/hmacct.h @@ -0,0 +1,38 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef _ALGHMACCT_H_ +#define _ALGHMACCT_H_ + +SEC_BEGIN_PROTOS + +extern SECStatus HMAC_ConstantTime( + unsigned char *result, + unsigned int *resultLen, + unsigned int maxResultLen, + const SECHashObject *hashObj, + const unsigned char *secret, + unsigned int secretLen, + const unsigned char *header, + unsigned int headerLen, + const unsigned char *body, + unsigned int bodyLen, + unsigned int bodyTotalLen); + +extern SECStatus SSLv3_MAC_ConstantTime( + unsigned char *result, + unsigned int *resultLen, + unsigned int maxResultLen, + const SECHashObject *hashObj, + const unsigned char *secret, + unsigned int secretLen, + const unsigned char *header, + unsigned int headerLen, + const unsigned char *body, + unsigned int bodyLen, + unsigned int bodyTotalLen); + +SEC_END_PROTOS + +#endif diff --git a/security/nss/lib/freebl/ldvector.c b/security/nss/lib/freebl/ldvector.c index a7e83a258a4f..0f252c66f92b 100644 --- a/security/nss/lib/freebl/ldvector.c +++ b/security/nss/lib/freebl/ldvector.c @@ -4,7 +4,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: ldvector.c,v 1.32 2012/06/28 17:55:05 rrelyea%redhat.com Exp $ */ +/* $Id: ldvector.c,v 1.33 2013/02/05 18:10:42 wtc%google.com Exp $ */ #ifdef FREEBL_NO_DEPEND extern int FREEBL_InitStubs(void); @@ -12,6 +12,7 @@ extern int FREEBL_InitStubs(void); #include "loader.h" #include "alghmac.h" +#include "hmacct.h" static const struct FREEBLVectorStr vector = @@ -258,9 +259,14 @@ static const struct FREEBLVectorStr vector = /* End of Version 3.013 */ PQG_ParamGenV2, - PRNGTEST_RunHealthTests + PRNGTEST_RunHealthTests, /* End of Version 3.014 */ + + HMAC_ConstantTime, + SSLv3_MAC_ConstantTime + + /* End of Version 3.015 */ }; const FREEBLVector * diff --git a/security/nss/lib/freebl/loader.c b/security/nss/lib/freebl/loader.c index 4f274e49b3da..391f09b6f28b 100644 --- a/security/nss/lib/freebl/loader.c +++ b/security/nss/lib/freebl/loader.c @@ -4,7 +4,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: loader.c,v 1.58 2012/12/13 22:47:15 wtc%google.com Exp $ */ +/* $Id: loader.c,v 1.60 2013/02/06 22:20:22 wtc%google.com Exp $ */ #include "loader.h" #include "prmem.h" @@ -1858,3 +1858,51 @@ PRNGTEST_RunHealthTests(void) return SECFailure; return vector->p_PRNGTEST_RunHealthTests(); } + +SECStatus +SSLv3_MAC_ConstantTime( + unsigned char *result, + unsigned int *resultLen, + unsigned int maxResultLen, + const SECHashObject *hashObj, + const unsigned char *secret, + unsigned int secretLen, + const unsigned char *header, + unsigned int headerLen, + const unsigned char *body, + unsigned int bodyLen, + unsigned int bodyTotalLen) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return SECFailure; + return (vector->p_SSLv3_MAC_ConstantTime)( + result, resultLen, maxResultLen, + hashObj, + secret, secretLen, + header, headerLen, + body, bodyLen, bodyTotalLen); +} + +SECStatus +HMAC_ConstantTime( + unsigned char *result, + unsigned int *resultLen, + unsigned int maxResultLen, + const SECHashObject *hashObj, + const unsigned char *secret, + unsigned int secretLen, + const unsigned char *header, + unsigned int headerLen, + const unsigned char *body, + unsigned int bodyLen, + unsigned int bodyTotalLen) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return SECFailure; + return (vector->p_HMAC_ConstantTime)( + result, resultLen, maxResultLen, + hashObj, + secret, secretLen, + header, headerLen, + body, bodyLen, bodyTotalLen); +} diff --git a/security/nss/lib/freebl/loader.h b/security/nss/lib/freebl/loader.h index dccd9517ed84..ec64d9975eae 100644 --- a/security/nss/lib/freebl/loader.h +++ b/security/nss/lib/freebl/loader.h @@ -4,14 +4,14 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: loader.h,v 1.38 2012/06/28 17:55:05 rrelyea%redhat.com Exp $ */ +/* $Id: loader.h,v 1.39 2013/02/05 18:10:42 wtc%google.com Exp $ */ #ifndef _LOADER_H_ #define _LOADER_H_ 1 #include "blapi.h" -#define FREEBL_VERSION 0x030E +#define FREEBL_VERSION 0x030F struct FREEBLVectorStr { @@ -569,7 +569,35 @@ struct FREEBLVectorStr { SECStatus (*p_PRNGTEST_RunHealthTests)(void); /* Version 3.014 came to here */ -}; + + SECStatus (* p_HMAC_ConstantTime)( + unsigned char *result, + unsigned int *resultLen, + unsigned int maxResultLen, + const SECHashObject *hashObj, + const unsigned char *secret, + unsigned int secretLen, + const unsigned char *header, + unsigned int headerLen, + const unsigned char *body, + unsigned int bodyLen, + unsigned int bodyTotalLen); + + SECStatus (* p_SSLv3_MAC_ConstantTime)( + unsigned char *result, + unsigned int *resultLen, + unsigned int maxResultLen, + const SECHashObject *hashObj, + const unsigned char *secret, + unsigned int secretLen, + const unsigned char *header, + unsigned int headerLen, + const unsigned char *body, + unsigned int bodyLen, + unsigned int bodyTotalLen); + + /* Version 3.015 came to here */ + }; typedef struct FREEBLVectorStr FREEBLVector; diff --git a/security/nss/lib/freebl/manifest.mn b/security/nss/lib/freebl/manifest.mn index ea29a8eaa2d4..f7f98c15bcfa 100644 --- a/security/nss/lib/freebl/manifest.mn +++ b/security/nss/lib/freebl/manifest.mn @@ -56,6 +56,7 @@ EXPORTS = \ PRIVATE_EXPORTS = \ alghmac.h \ blapi.h \ + hmacct.h \ secmpi.h \ secrng.h \ ec.h \ @@ -102,6 +103,7 @@ CSRCS = \ cts.c \ ctr.c \ gcm.c \ + hmacct.c \ rijndael.c \ aeskeywrap.c \ camellia.c \ diff --git a/security/nss/lib/freebl/md5.c b/security/nss/lib/freebl/md5.c index 705a85735f07..2929a633dfa9 100644 --- a/security/nss/lib/freebl/md5.c +++ b/security/nss/lib/freebl/md5.c @@ -523,7 +523,8 @@ MD5_End(MD5Context *cx, unsigned char *digest, md5_compress(cx, cx->u.w); /* Copy the resulting values out of the chain variables into return buf. */ - *digestLen = MD5_HASH_LEN; + if (digestLen) + *digestLen = MD5_HASH_LEN; #ifndef IS_LITTLE_ENDIAN cx->cv[0] = lendian(cx->cv[0]); cx->cv[1] = lendian(cx->cv[1]); @@ -533,6 +534,32 @@ MD5_End(MD5Context *cx, unsigned char *digest, memcpy(digest, cx->cv, MD5_HASH_LEN); } +void +MD5_EndRaw(MD5Context *cx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen) +{ +#ifndef IS_LITTLE_ENDIAN + PRUint32 tmp; +#endif + PRUint32 cv[4]; + + if (maxDigestLen < MD5_HASH_LEN) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return; + } + + memcpy(cv, cx->cv, sizeof(cv)); +#ifndef IS_LITTLE_ENDIAN + cv[0] = lendian(cv[0]); + cv[1] = lendian(cv[1]); + cv[2] = lendian(cv[2]); + cv[3] = lendian(cv[3]); +#endif + memcpy(digest, cv, MD5_HASH_LEN); + if (digestLen) + *digestLen = MD5_HASH_LEN; +} + unsigned int MD5_FlattenSize(MD5Context *cx) { diff --git a/security/nss/lib/freebl/rawhash.c b/security/nss/lib/freebl/rawhash.c index 253b0fe73af0..7962b1fff432 100644 --- a/security/nss/lib/freebl/rawhash.c +++ b/security/nss/lib/freebl/rawhash.c @@ -58,7 +58,9 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) null_hash_end, 0, - HASH_AlgNULL + HASH_AlgNULL, + (void (*)(void *, unsigned char *, unsigned int *, + unsigned int)) null_hash_end }, { MD2_LENGTH, (void * (*)(void)) MD2_NewContext, @@ -68,7 +70,8 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, const unsigned char *, unsigned int)) MD2_Update, (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) MD2_End, MD2_BLOCK_LENGTH, - HASH_AlgMD2 + HASH_AlgMD2, + NULL /* end_raw */ }, { MD5_LENGTH, (void * (*)(void)) MD5_NewContext, @@ -78,7 +81,8 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, const unsigned char *, unsigned int)) MD5_Update, (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) MD5_End, MD5_BLOCK_LENGTH, - HASH_AlgMD5 + HASH_AlgMD5, + (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) MD5_EndRaw }, { SHA1_LENGTH, (void * (*)(void)) SHA1_NewContext, @@ -88,7 +92,9 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, const unsigned char *, unsigned int)) SHA1_Update, (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA1_End, SHA1_BLOCK_LENGTH, - HASH_AlgSHA1 + HASH_AlgSHA1, + (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) + SHA1_EndRaw }, { SHA256_LENGTH, (void * (*)(void)) SHA256_NewContext, @@ -99,7 +105,9 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA256_End, SHA256_BLOCK_LENGTH, - HASH_AlgSHA256 + HASH_AlgSHA256, + (void (*)(void *, unsigned char *, unsigned int *, + unsigned int)) SHA256_EndRaw }, { SHA384_LENGTH, (void * (*)(void)) SHA384_NewContext, @@ -110,7 +118,9 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA384_End, SHA384_BLOCK_LENGTH, - HASH_AlgSHA384 + HASH_AlgSHA384, + (void (*)(void *, unsigned char *, unsigned int *, + unsigned int)) SHA384_EndRaw }, { SHA512_LENGTH, (void * (*)(void)) SHA512_NewContext, @@ -121,7 +131,9 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA512_End, SHA512_BLOCK_LENGTH, - HASH_AlgSHA512 + HASH_AlgSHA512, + (void (*)(void *, unsigned char *, unsigned int *, + unsigned int)) SHA512_EndRaw }, { SHA224_LENGTH, (void * (*)(void)) SHA224_NewContext, @@ -132,7 +144,9 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA224_End, SHA224_BLOCK_LENGTH, - HASH_AlgSHA224 + HASH_AlgSHA224, + (void (*)(void *, unsigned char *, unsigned int *, + unsigned int)) SHA224_EndRaw }, }; diff --git a/security/nss/lib/freebl/sha512.c b/security/nss/lib/freebl/sha512.c index 5515fb2d4e8e..ac65aa5da0eb 100644 --- a/security/nss/lib/freebl/sha512.c +++ b/security/nss/lib/freebl/sha512.c @@ -4,7 +4,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: sha512.c,v 1.21 2012/07/27 20:00:39 wtc%google.com Exp $ */ +/* $Id: sha512.c,v 1.23 2013/02/06 00:41:13 wtc%google.com Exp $ */ #ifdef FREEBL_NO_DEPEND #include "stubs.h" @@ -462,6 +462,35 @@ SHA256_End(SHA256Context *ctx, unsigned char *digest, *digestLen = padLen; } +void +SHA256_EndRaw(SHA256Context *ctx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen) +{ + PRUint32 h[8]; + unsigned int len; +#ifdef SWAP4MASK + PRUint32 t1; +#endif + + memcpy(h, ctx->h, sizeof(h)); + +#if defined(IS_LITTLE_ENDIAN) + BYTESWAP4(h[0]); + BYTESWAP4(h[1]); + BYTESWAP4(h[2]); + BYTESWAP4(h[3]); + BYTESWAP4(h[4]); + BYTESWAP4(h[5]); + BYTESWAP4(h[6]); + BYTESWAP4(h[7]); +#endif + + len = PR_MIN(SHA256_LENGTH, maxDigestLen); + memcpy(digest, h, len); + if (digestLen) + *digestLen = len; +} + SECStatus SHA256_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length) @@ -556,6 +585,14 @@ SHA224_End(SHA256Context *ctx, unsigned char *digest, SHA256_End(ctx, digest, digestLen, maxLen); } +void +SHA224_EndRaw(SHA256Context *ctx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen) +{ + unsigned int maxLen = SHA_MIN(maxDigestLen, SHA224_LENGTH); + SHA256_EndRaw(ctx, digest, digestLen, maxLen); +} + SECStatus SHA224_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length) @@ -1228,6 +1265,36 @@ SHA512_End(SHA512Context *ctx, unsigned char *digest, *digestLen = padLen; } +void +SHA512_EndRaw(SHA512Context *ctx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen) +{ +#if defined(HAVE_LONG_LONG) + PRUint64 t1; +#else + PRUint32 t1; +#endif + PRUint64 h[8]; + unsigned int len; + + memcpy(h, ctx->h, sizeof(h)); + +#if defined(IS_LITTLE_ENDIAN) + BYTESWAP8(h[0]); + BYTESWAP8(h[1]); + BYTESWAP8(h[2]); + BYTESWAP8(h[3]); + BYTESWAP8(h[4]); + BYTESWAP8(h[5]); + BYTESWAP8(h[6]); + BYTESWAP8(h[7]); +#endif + len = PR_MIN(SHA512_LENGTH, maxDigestLen); + memcpy(digest, h, len); + if (digestLen) + *digestLen = len; +} + SECStatus SHA512_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length) @@ -1336,6 +1403,14 @@ SHA384_End(SHA384Context *ctx, unsigned char *digest, SHA512_End(ctx, digest, digestLen, maxLen); } +void +SHA384_EndRaw(SHA384Context *ctx, unsigned char *digest, + unsigned int *digestLen, unsigned int maxDigestLen) +{ + unsigned int maxLen = SHA_MIN(maxDigestLen, SHA384_LENGTH); + SHA512_EndRaw(ctx, digest, digestLen, maxLen); +} + SECStatus SHA384_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length) diff --git a/security/nss/lib/freebl/sha_fast.c b/security/nss/lib/freebl/sha_fast.c index cc7895c4b52a..4db53fe15b27 100644 --- a/security/nss/lib/freebl/sha_fast.c +++ b/security/nss/lib/freebl/sha_fast.c @@ -148,6 +148,7 @@ SHA1_End(SHA1Context *ctx, unsigned char *hashout, { register PRUint64 size; register PRUint32 lenB; + PRUint32 tmpbuf[5]; static const unsigned char bulk_pad[64] = { 0x80,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -174,12 +175,28 @@ SHA1_End(SHA1Context *ctx, unsigned char *hashout, * Output hash */ SHA_STORE_RESULT; - *pDigestLen = SHA1_LENGTH; + if (pDigestLen) { + *pDigestLen = SHA1_LENGTH; + } +#undef tmp +} +void +SHA1_EndRaw(SHA1Context *ctx, unsigned char *hashout, + unsigned int *pDigestLen, unsigned int maxDigestLen) +{ +#if defined(SHA_NEED_TMP_VARIABLE) + register PRUint32 tmp; +#endif + PRUint32 tmpbuf[5]; + PORT_Assert (maxDigestLen >= SHA1_LENGTH); + + SHA_STORE_RESULT; + if (pDigestLen) + *pDigestLen = SHA1_LENGTH; } #undef B -#undef tmp /* * SHA: Compression function, unrolled. * diff --git a/security/nss/lib/freebl/sha_fast.h b/security/nss/lib/freebl/sha_fast.h index fb490b0563be..9d47aba42ea9 100644 --- a/security/nss/lib/freebl/sha_fast.h +++ b/security/nss/lib/freebl/sha_fast.h @@ -147,12 +147,12 @@ static __inline__ PRUint32 swap4b(PRUint32 value) SHA_STORE(3); \ SHA_STORE(4); \ } else { \ - ctx->u.w[0] = SHA_HTONL(ctx->H[0]); \ - ctx->u.w[1] = SHA_HTONL(ctx->H[1]); \ - ctx->u.w[2] = SHA_HTONL(ctx->H[2]); \ - ctx->u.w[3] = SHA_HTONL(ctx->H[3]); \ - ctx->u.w[4] = SHA_HTONL(ctx->H[4]); \ - memcpy(hashout, ctx->u.w, SHA1_LENGTH); \ + tmpbuf[0] = SHA_HTONL(ctx->H[0]); \ + tmpbuf[1] = SHA_HTONL(ctx->H[1]); \ + tmpbuf[2] = SHA_HTONL(ctx->H[2]); \ + tmpbuf[3] = SHA_HTONL(ctx->H[3]); \ + tmpbuf[4] = SHA_HTONL(ctx->H[4]); \ + memcpy(hashout, tmpbuf, SHA1_LENGTH); \ } #else diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index aecd928703c5..31a6163966d7 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -1021,3 +1021,9 @@ CERT_CreateOCSPSingleResponseRevoked; ;+ local: ;+ *; ;+}; +;+NSS_3.14.3 { # NSS 3.14.3 release +;+ global: +PK11_SignWithSymKey; +;+ local: +;+ *; +;+}; diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h index 332b03d24ec1..8ab65b918e75 100644 --- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -4,7 +4,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: nss.h,v 1.102 2013/01/31 22:47:08 kaie%kuix.de Exp $ */ +/* $Id: nss.h,v 1.103 2013/01/31 22:59:44 kaie%kuix.de Exp $ */ #ifndef __nss_h_ #define __nss_h_ @@ -34,12 +34,12 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define NSS_VERSION "3.14.2.0" _NSS_ECC_STRING _NSS_CUSTOMIZED +#define NSS_VERSION "3.14.3.0" _NSS_ECC_STRING _NSS_CUSTOMIZED " Beta" #define NSS_VMAJOR 3 #define NSS_VMINOR 14 -#define NSS_VPATCH 2 +#define NSS_VPATCH 3 #define NSS_VBUILD 0 -#define NSS_BETA PR_FALSE +#define NSS_BETA PR_TRUE #ifndef RC_INVOKED diff --git a/security/nss/lib/pk11wrap/pk11obj.c b/security/nss/lib/pk11wrap/pk11obj.c index be701d2174e0..4fa5dde98994 100644 --- a/security/nss/lib/pk11wrap/pk11obj.c +++ b/security/nss/lib/pk11wrap/pk11obj.c @@ -777,6 +777,51 @@ PK11_Sign(SECKEYPrivateKey *key, SECItem *sig, const SECItem *hash) return SECSuccess; } +/* + * sign data with a MAC key. + */ +SECStatus +PK11_SignWithSymKey(PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism, + SECItem *param, SECItem *sig, const SECItem *data) +{ + PK11SlotInfo *slot = symKey->slot; + CK_MECHANISM mech = {0, NULL, 0 }; + PRBool owner = PR_TRUE; + CK_SESSION_HANDLE session; + PRBool haslock = PR_FALSE; + CK_ULONG len; + CK_RV crv; + + mech.mechanism = mechanism; + if (param) { + mech.pParameter = param->data; + mech.ulParameterLen = param->len; + } + + session = pk11_GetNewSession(slot,&owner); + haslock = (!owner || !(slot->isThreadSafe)); + if (haslock) PK11_EnterSlotMonitor(slot); + crv = PK11_GETTAB(slot)->C_SignInit(session,&mech,symKey->objectID); + if (crv != CKR_OK) { + if (haslock) PK11_ExitSlotMonitor(slot); + pk11_CloseSession(slot,session,owner); + PORT_SetError( PK11_MapError(crv) ); + return SECFailure; + } + + len = sig->len; + crv = PK11_GETTAB(slot)->C_Sign(session,data->data, + data->len, sig->data, &len); + if (haslock) PK11_ExitSlotMonitor(slot); + pk11_CloseSession(slot,session,owner); + sig->len = len; + if (crv != CKR_OK) { + PORT_SetError( PK11_MapError(crv) ); + return SECFailure; + } + return SECSuccess; +} + /* * Now SSL 2.0 uses raw RSA stuff. These next to functions *must* use * RSA keys, or they'll fail. We do the checks up front. If anyone comes diff --git a/security/nss/lib/pk11wrap/pk11pub.h b/security/nss/lib/pk11wrap/pk11pub.h index 314ccba4091a..f15d6da81764 100644 --- a/security/nss/lib/pk11wrap/pk11pub.h +++ b/security/nss/lib/pk11wrap/pk11pub.h @@ -660,6 +660,8 @@ int PK11_SignatureLen(SECKEYPrivateKey *key); PK11SlotInfo * PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key); SECStatus PK11_Sign(SECKEYPrivateKey *key, SECItem *sig, const SECItem *hash); +SECStatus PK11_SignWithSymKey(PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism, + SECItem *param, SECItem *sig, const SECItem *data); SECStatus PK11_VerifyRecover(SECKEYPublicKey *key, const SECItem *sig, SECItem *dsig, void * wincx); SECStatus PK11_Verify(SECKEYPublicKey *key, const SECItem *sig, diff --git a/security/nss/lib/pkcs7/p7decode.c b/security/nss/lib/pkcs7/p7decode.c index dc3339a9ad85..d0d02d75e8c5 100644 --- a/security/nss/lib/pkcs7/p7decode.c +++ b/security/nss/lib/pkcs7/p7decode.c @@ -1281,8 +1281,7 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, SECCertUsage certusage, const SECItem *detached_digest, HASH_HashType digest_type, - PRBool keepcerts, - PRTime atTime) + PRBool keepcerts) { SECAlgorithmID **digestalgs, *bulkid; const SECItem *digest; @@ -1300,8 +1299,7 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, SECItem *content_type; PK11SymKey *sigkey; SECItem *encoded_stime; - PRTime stime; - PRTime verificationTime; + int64 stime; SECStatus rv; /* @@ -1438,10 +1436,8 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, * in a time (and for non-S/MIME callers to pass in nothing, or * maybe make them pass in the current time, always?). */ - verificationTime = atTime ? atTime - : (encoded_stime ? stime : PR_Now()); if (CERT_VerifyCert (certdb, cert, PR_TRUE, certusage, - verificationTime, + encoded_stime != NULL ? stime : PR_Now(), cinfo->pwfn_arg, NULL) != SECSuccess) { /* @@ -1761,7 +1757,7 @@ SEC_PKCS7VerifySignature(SEC_PKCS7ContentInfo *cinfo, PRBool keepcerts) { return sec_pkcs7_verify_signature (cinfo, certusage, - NULL, HASH_AlgNULL, keepcerts, 0); + NULL, HASH_AlgNULL, keepcerts); } /* @@ -1783,34 +1779,9 @@ SEC_PKCS7VerifyDetachedSignature(SEC_PKCS7ContentInfo *cinfo, { return sec_pkcs7_verify_signature (cinfo, certusage, detached_digest, digest_type, - keepcerts, 0); + keepcerts); } -/* - * SEC_PKCS7VerifyDetachedSignatureAtTime - * Look at a PKCS7 contentInfo and check if the signature matches - * a passed-in digest (calculated, supposedly, from detached contents). - * The verification checks that the signing cert is valid and trusted - * for the purpose specified by "certusage" at time "atTime" - * if "atTime" is non-zero, or at the current time (as returned by - * PR_Now) otherwise. - */ -PRBool -SEC_PKCS7VerifyDetachedSignatureAtTime(SEC_PKCS7ContentInfo *cinfo, - SECCertUsage certusage, - const SECItem *detached_digest, - HASH_HashType digest_type, - PRBool keepcerts, - PRTime atTime) -{ - if (!atTime) { - atTime = PR_Now(); - } - - return sec_pkcs7_verify_signature (cinfo, certusage, - detached_digest, digest_type, - keepcerts, atTime); -} /* * Return the asked-for portion of the name of the signer of a PKCS7 @@ -1873,7 +1844,7 @@ sec_pkcs7_get_signer_cert_info(SEC_PKCS7ContentInfo *cinfo, int selector) * some valid usage to pass in. */ (void) sec_pkcs7_verify_signature (cinfo, certUsageEmailSigner, - NULL, HASH_AlgNULL, PR_FALSE, 0); + NULL, HASH_AlgNULL, PR_FALSE); signercert = signerinfos[0]->cert; if (signercert == NULL) return NULL; diff --git a/security/nss/lib/pkcs7/secpkcs7.h b/security/nss/lib/pkcs7/secpkcs7.h index d1dd7b935015..a50f5aedd8bb 100644 --- a/security/nss/lib/pkcs7/secpkcs7.h +++ b/security/nss/lib/pkcs7/secpkcs7.h @@ -133,23 +133,6 @@ extern PRBool SEC_PKCS7VerifyDetachedSignature(SEC_PKCS7ContentInfo *cinfo, HASH_HashType digest_type, PRBool keepcerts); - -/* - * SEC_PKCS7VerifyDetachedSignatureAtTime - * Look at a PKCS7 contentInfo and check if the signature matches - * a passed-in digest (calculated, supposedly, from detached contents). - * The verification checks that the signing cert is valid and trusted - * for the purpose specified by "certusage" at time "atTime" - * if "atTime" is non-zero, or at the current time (as returned by - * PR_Now) otherwise. - */ -extern PRBool SEC_PKCS7VerifyDetachedSignatureAtTime(SEC_PKCS7ContentInfo *cinfo, - SECCertUsage certusage, - const SECItem *detached_digest, - HASH_HashType digest_type, - PRBool keepcerts, - PRTime atTime); - /* * SEC_PKCS7GetSignerCommonName, SEC_PKCS7GetSignerEmailAddress * The passed-in contentInfo is espected to be Signed, and these diff --git a/security/nss/lib/smime/smime.def b/security/nss/lib/smime/smime.def index 8d4279df8900..623eaa460878 100644 --- a/security/nss/lib/smime/smime.def +++ b/security/nss/lib/smime/smime.def @@ -267,9 +267,3 @@ NSSSMIME_GetVersion; ;+ local: ;+ *; ;+}; -;+NSS_3.14.3 { # NSS 3.14.3 release -;+ global: -SEC_PKCS7VerifyDetachedSignatureAtTime; -;+ local: -;+ *; -;+}; diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn index eefbb19fc4e3..e36bf60759ce 100644 --- a/security/nss/lib/softoken/manifest.mn +++ b/security/nss/lib/softoken/manifest.mn @@ -47,6 +47,7 @@ CSRCS = \ rsawrapr.c \ sdb.c \ sftkdb.c \ + sftkhmac.c \ sftkpars.c \ sftkpwd.c \ softkver.c \ diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index 226b9c60ba55..f91d15a3d872 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -488,7 +488,10 @@ static const struct mechanismList mechanisms[] = { {CKM_NSS_JPAKE_FINAL_SHA1, {0, 0, CKF_DERIVE}, PR_TRUE}, {CKM_NSS_JPAKE_FINAL_SHA256, {0, 0, CKF_DERIVE}, PR_TRUE}, {CKM_NSS_JPAKE_FINAL_SHA384, {0, 0, CKF_DERIVE}, PR_TRUE}, - {CKM_NSS_JPAKE_FINAL_SHA512, {0, 0, CKF_DERIVE}, PR_TRUE} + {CKM_NSS_JPAKE_FINAL_SHA512, {0, 0, CKF_DERIVE}, PR_TRUE}, + /* -------------------- Constant Time TLS MACs ----------------------- */ + {CKM_NSS_HMAC_CONSTANT_TIME, {0, 0, CKF_DIGEST}, PR_TRUE}, + {CKM_NSS_SSL3_MAC_CONSTANT_TIME, {0, 0, CKF_DIGEST}, PR_TRUE} }; static const CK_ULONG mechanismCount = sizeof(mechanisms)/sizeof(mechanisms[0]); diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index ee38d8d21e4b..4c2ccaa7e815 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -457,6 +457,24 @@ sftk_aes_mode(CK_MECHANISM_TYPE mechanism) return -1; } +static SECStatus +sftk_EncryptOAEP(SFTKOAEPEncryptInfo *info, unsigned char *output, + unsigned int *outputLen, unsigned int maxLen, + unsigned char *input, unsigned int inputLen) +{ + return RSA_EncryptOAEP(info->params, info->key, output, outputLen, + maxLen, input, inputLen); +} + +static SECStatus +sftk_DecryptOAEP(SFTKOAEPDecryptInfo *info, unsigned char *output, + unsigned int *outputLen, unsigned int maxLen, + unsigned char *input, unsigned int inputLen) +{ + return RSA_DecryptOAEP(info->params, info->key, output, outputLen, + maxLen, input, inputLen); +} + /** NSC_CryptInit initializes an encryption/Decryption operation. * * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey. @@ -513,6 +531,7 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, if (isEncrypt) { NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key,CKK_RSA,&crv); if (pubKey == NULL) { + crv = CKR_KEY_HANDLE_INVALID; break; } context->maxLen = nsslowkey_PublicModulusLen(pubKey); @@ -523,6 +542,7 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, } else { NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key,CKK_RSA,&crv); if (privKey == NULL) { + crv = CKR_KEY_HANDLE_INVALID; break; } context->maxLen = nsslowkey_PrivateModulusLen(privKey); @@ -533,6 +553,55 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, } context->destroy = sftk_Null; break; +/* XXX: Disabled until unit tests land. + case CKM_RSA_PKCS_OAEP: + if (key_type != CKK_RSA) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + context->multi = PR_FALSE; + context->rsa = PR_TRUE; + if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS)) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + /\* XXX: Need Parameter validation here *\/ + if (isEncrypt) { + SFTKOAEPEncryptInfo *info = PORT_New(SFTKOAEPEncryptInfo); + if (info == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + info->params = pMechanism->pParameter; + info->key = sftk_GetPubKey(key, CKK_RSA, &crv); + if (info->key == NULL) { + PORT_Free(info); + crv = CKR_KEY_HANDLE_INVALID; + break; + } + context->update = (SFTKCipher) sftk_EncryptOAEP; + context->maxLen = nsslowkey_PublicModulusLen(info->key); + context->cipherInfo = info; + } else { + SFTKOAEPDecryptInfo *info = PORT_New(SFTKOAEPDecryptInfo); + if (info == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + info->params = pMechanism->pParameter; + info->key = sftk_GetPrivKey(key, CKK_RSA, &crv); + if (info->key == NULL) { + PORT_Free(info); + crv = CKR_KEY_HANDLE_INVALID; + break; + } + context->update = (SFTKCipher) sftk_DecryptOAEP; + context->maxLen = nsslowkey_PrivateModulusLen(info->key); + context->cipherInfo = info; + } + context->destroy = (SFTKDestroy) sftk_Space; + break; +*/ case CKM_RC2_CBC_PAD: context->doPad = PR_TRUE; /* fall thru */ @@ -1460,17 +1529,25 @@ DOSUB(SHA256) DOSUB(SHA384) DOSUB(SHA512) -/* - * HMAC General copies only a portion of the result. This update routine likes - * the final HMAC output with the signature. - */ static SECStatus -sftk_HMACCopy(CK_ULONG *copyLen,unsigned char *sig,unsigned int *sigLen, - unsigned int maxLen,unsigned char *hash, unsigned int hashLen) +sftk_SignCopy( + CK_ULONG *copyLen, + void *out, unsigned int *outLength, + unsigned int maxLength, + const unsigned char *hashResult, + unsigned int hashResultLength) { - if (maxLen < *copyLen) return SECFailure; - PORT_Memcpy(sig,hash,*copyLen); - *sigLen = *copyLen; + unsigned int toCopy = *copyLen; + if (toCopy > maxLength) { + toCopy = maxLength; + } + if (toCopy > hashResultLength) { + toCopy = hashResultLength; + } + memcpy(out, hashResult, toCopy); + if (outLength) { + *outLength = toCopy; + } return SECSuccess; } @@ -1519,14 +1596,14 @@ sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash, context->end = (SFTKEnd) HMAC_Finish; context->hashdestroy = (SFTKDestroy) HMAC_Destroy; - intpointer = (CK_ULONG *) PORT_Alloc(sizeof(CK_ULONG)); + intpointer = PORT_New(CK_ULONG); if (intpointer == NULL) { return CKR_HOST_MEMORY; } *intpointer = mac_size; - context->cipherInfo = (void *) intpointer; + context->cipherInfo = intpointer; context->destroy = (SFTKDestroy) sftk_Space; - context->update = (SFTKCipher) sftk_HMACCopy; + context->update = (SFTKCipher) sftk_SignCopy; context->verify = (SFTKVerify) sftk_HMACCmp; context->maxLen = hashObj->length; HMAC_Begin(HMACcontext); @@ -2172,6 +2249,65 @@ finish_rsa: case CKM_TLS_PRF_GENERAL: crv = sftk_TLSPRFInit(context, key, key_type); break; + + case CKM_NSS_HMAC_CONSTANT_TIME: { + sftk_MACConstantTimeCtx *ctx = + sftk_HMACConstantTime_New(pMechanism,key); + CK_ULONG *intpointer; + + if (ctx == NULL) { + crv = CKR_ARGUMENTS_BAD; + break; + } + intpointer = PORT_New(CK_ULONG); + if (intpointer == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + *intpointer = ctx->hash->length; + + context->cipherInfo = intpointer; + context->hashInfo = ctx; + context->currentMech = pMechanism->mechanism; + context->hashUpdate = sftk_HMACConstantTime_Update; + context->hashdestroy = sftk_MACConstantTime_DestroyContext; + context->end = sftk_MACConstantTime_EndHash; + context->update = sftk_SignCopy; + context->destroy = sftk_Space; + context->maxLen = 64; + context->multi = PR_TRUE; + break; + } + + case CKM_NSS_SSL3_MAC_CONSTANT_TIME: { + sftk_MACConstantTimeCtx *ctx = + sftk_SSLv3MACConstantTime_New(pMechanism,key); + CK_ULONG *intpointer; + + if (ctx == NULL) { + crv = CKR_ARGUMENTS_BAD; + break; + } + intpointer = PORT_New(CK_ULONG); + if (intpointer == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + *intpointer = ctx->hash->length; + + context->cipherInfo = intpointer; + context->hashInfo = ctx; + context->currentMech = pMechanism->mechanism; + context->hashUpdate = sftk_SSLv3MACConstantTime_Update; + context->hashdestroy = sftk_MACConstantTime_DestroyContext; + context->end = sftk_MACConstantTime_EndHash; + context->update = sftk_SignCopy; + context->destroy = sftk_Space; + context->maxLen = 64; + context->multi = PR_TRUE; + break; + } + default: crv = CKR_MECHANISM_INVALID; break; diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h index 7f468400678a..904a0621ae1e 100644 --- a/security/nss/lib/softoken/pkcs11i.h +++ b/security/nss/lib/softoken/pkcs11i.h @@ -101,6 +101,8 @@ typedef struct SFTKSessionContextStr SFTKSessionContext; typedef struct SFTKSearchResultsStr SFTKSearchResults; typedef struct SFTKHashVerifyInfoStr SFTKHashVerifyInfo; typedef struct SFTKHashSignInfoStr SFTKHashSignInfo; +typedef struct SFTKOAEPEncryptInfoStr SFTKOAEPEncryptInfo; +typedef struct SFTKOAEPDecryptInfoStr SFTKOAEPDecryptInfo; typedef struct SFTKSSLMACInfoStr SFTKSSLMACInfo; typedef struct SFTKItemTemplateStr SFTKItemTemplate; @@ -372,6 +374,19 @@ struct SFTKHashSignInfoStr { NSSLOWKEYPrivateKey *key; }; +/** + * Contexts for RSA-OAEP + */ +struct SFTKOAEPEncryptInfoStr { + CK_RSA_PKCS_OAEP_PARAMS *params; + NSSLOWKEYPublicKey *key; +}; + +struct SFTKOAEPDecryptInfoStr { + CK_RSA_PKCS_OAEP_PARAMS *params; + NSSLOWKEYPrivateKey *key; +}; + /* context for the Final SSLMAC message */ struct SFTKSSLMACInfoStr { void *hashContext; @@ -693,6 +708,28 @@ CK_RV jpake_Final(HASH_HashType hashType, const CK_NSS_JPAKEFinalParams * params, SFTKObject * sourceKey, SFTKObject * key); +/* Constant time MAC functions (hmacct.c) */ + +struct sftk_MACConstantTimeCtxStr { + const SECHashObject *hash; + unsigned char mac[64]; + unsigned char secret[64]; + unsigned int headerLength; + unsigned int secretLength; + unsigned int totalLength; + unsigned char header[75]; +}; +typedef struct sftk_MACConstantTimeCtxStr sftk_MACConstantTimeCtx; +sftk_MACConstantTimeCtx* sftk_HMACConstantTime_New( + CK_MECHANISM_PTR mech, SFTKObject *key); +sftk_MACConstantTimeCtx* sftk_SSLv3MACConstantTime_New( + CK_MECHANISM_PTR mech, SFTKObject *key); +void sftk_HMACConstantTime_Update(void *pctx, void *data, unsigned int len); +void sftk_SSLv3MACConstantTime_Update(void *pctx, void *data, unsigned int len); +void sftk_MACConstantTime_EndHash( + void *pctx, void *out, unsigned int *outLength, unsigned int maxLength); +void sftk_MACConstantTime_DestroyContext(void *pctx, PRBool); + /**************************************** * implement TLS Pseudo Random Function (PRF) */ diff --git a/security/nss/lib/softoken/rsawrapr.c b/security/nss/lib/softoken/rsawrapr.c index 15cf22d8e37e..cf4490f7e770 100644 --- a/security/nss/lib/softoken/rsawrapr.c +++ b/security/nss/lib/softoken/rsawrapr.c @@ -5,7 +5,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: rsawrapr.c,v 1.21 2012/06/26 22:27:31 rrelyea%redhat.com Exp $ */ +/* $Id: rsawrapr.c,v 1.22 2013/02/05 02:19:52 ryan.sleevi%gmail.com Exp $ */ #include "blapi.h" #include "softoken.h" @@ -19,137 +19,42 @@ #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 - -#define FLAT_BUFSIZE 512 /* bytes to hold flattened SHA1Context. */ - /* Needed for RSA-PSS functions */ static const unsigned char eightZeros[] = { 0, 0, 0, 0, 0, 0, 0, 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 = PORT_Alloc(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) - PORT_Free(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); } /* @@ -265,97 +170,6 @@ rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType, PORT_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) { - sftk_fatalError = PR_TRUE; - PORT_Free (block); - return NULL; - } - bp += OAEP_SALT_LEN; - - /* - * Pad1 - */ - PORT_Memset (bp, OAEP_PAD_OCTET, OAEP_PAD_LEN); - bp += OAEP_PAD_LEN; - - /* - * Data - */ - PORT_Memcpy (bp, data->data, data->len); - bp += data->len; - - /* - * Pad2 - */ - if (bp < (block + modulusLen)) { - rv = RNG_GenerateGlobalRandomBytes(bp, block - bp + modulusLen); - if (rv != SECSuccess) { - sftk_fatalError = PR_TRUE; - PORT_Free (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) { - PORT_Free (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) { - PORT_Free (block); - return NULL; - } - - break; - default: PORT_Assert (0); PORT_Free (block); @@ -403,26 +217,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 @@ -958,6 +752,266 @@ MGF1(HASH_HashType hashAlg, unsigned char *mask, unsigned int maskLen, return SECSuccess; } +/* + * Decodes an EME-OAEP encoded block, validating the encoding in constant + * time. + * Described in RFC 3447, section 7.1.2. + * input contains the encoded block, after decryption. + * label is the optional value L that was associated with the message. + * On success, the original message and message length will be stored in + * output and outputLen. + */ +static SECStatus +eme_oaep_decode(unsigned char *output, unsigned int *outputLen, + unsigned int maxOutputLen, + const unsigned char *input, unsigned int inputLen, + HASH_HashType hashAlg, HASH_HashType maskHashAlg, + const unsigned char *label, unsigned int labelLen) +{ + const SECHashObject *hash; + void *hashContext; + SECStatus rv = SECFailure; + unsigned char labelHash[HASH_LENGTH_MAX]; + unsigned int i, maskLen, paddingOffset; + unsigned char *mask = NULL, *tmpOutput = NULL; + unsigned char isGood, foundPaddingEnd; + + hash = HASH_GetRawHashObject(hashAlg); + + /* 1.c */ + if (inputLen < (hash->length * 2) + 2) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + return SECFailure; + } + + /* Step 3.a - Generate lHash */ + hashContext = (*hash->create)(); + if (hashContext == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + (*hash->begin)(hashContext); + if (labelLen > 0) + (*hash->update)(hashContext, label, labelLen); + (*hash->end)(hashContext, labelHash, &i, sizeof(labelHash)); + (*hash->destroy)(hashContext, PR_TRUE); + + tmpOutput = (unsigned char*)PORT_Alloc(inputLen); + if (tmpOutput == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto done; + } + + maskLen = inputLen - hash->length - 1; + mask = (unsigned char*)PORT_Alloc(maskLen); + if (mask == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + goto done; + } + + PORT_Memcpy(tmpOutput, input, inputLen); + + /* 3.c - Generate seedMask */ + MGF1(maskHashAlg, mask, hash->length, &tmpOutput[1 + hash->length], + inputLen - hash->length - 1); + /* 3.d - Unmask seed */ + for (i = 0; i < hash->length; ++i) + tmpOutput[1 + i] ^= mask[i]; + + /* 3.e - Generate dbMask */ + MGF1(maskHashAlg, mask, maskLen, &tmpOutput[1], hash->length); + /* 3.f - Unmask DB */ + for (i = 0; i < maskLen; ++i) + tmpOutput[1 + hash->length + i] ^= mask[i]; + + /* 3.g - Compare Y, lHash, and PS in constant time + * Warning: This code is timing dependent and must not disclose which of + * these were invalid. + */ + paddingOffset = 0; + isGood = 1; + foundPaddingEnd = 0; + + /* Compare Y */ + isGood &= constantTimeEQ8(0x00, tmpOutput[0]); + + /* Compare lHash and lHash' */ + isGood &= constantTimeCompare(&labelHash[0], + &tmpOutput[1 + hash->length], + hash->length); + + /* Compare that the padding is zero or more zero octets, followed by a + * 0x01 octet */ + for (i = 1 + (hash->length * 2); i < inputLen; ++i) { + unsigned char isZero = constantTimeEQ8(0x00, tmpOutput[i]); + unsigned char isOne = constantTimeEQ8(0x01, tmpOutput[i]); + /* non-constant time equivalent: + * if (tmpOutput[i] == 0x01 && !foundPaddingEnd) + * paddingOffset = i; + */ + paddingOffset = constantTimeCondition(isOne & ~foundPaddingEnd, i, + paddingOffset); + /* non-constant time equivalent: + * if (tmpOutput[i] == 0x01) + * foundPaddingEnd = true; + * + * Note: This may yield false positives, as it will be set whenever + * a 0x01 byte is encountered. If there was bad padding (eg: + * 0x03 0x02 0x01), foundPaddingEnd will still be set to true, and + * paddingOffset will still be set to 2. + */ + foundPaddingEnd = constantTimeCondition(isOne, 1, foundPaddingEnd); + /* non-constant time equivalent: + * if (tmpOutput[i] != 0x00 && tmpOutput[i] != 0x01 && + * !foundPaddingEnd) { + * isGood = false; + * } + * + * Note: This may yield false positives, as a message (and padding) + * that is entirely zeros will result in isGood still being true. Thus + * it's necessary to check foundPaddingEnd is positive below. + */ + isGood = constantTimeCondition(~foundPaddingEnd & ~isZero, 0, isGood); + } + + /* While both isGood and foundPaddingEnd may have false positives, they + * cannot BOTH have false positives. If both are not true, then an invalid + * message was received. Note, this comparison must still be done in constant + * time so as not to leak either condition. + */ + if (!(isGood & foundPaddingEnd)) { + PORT_SetError(SEC_ERROR_BAD_DATA); + goto done; + } + + /* End timing dependent code */ + + ++paddingOffset; /* Skip the 0x01 following the end of PS */ + + *outputLen = inputLen - paddingOffset; + if (*outputLen > maxOutputLen) { + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + goto done; + } + + if (*outputLen) + PORT_Memcpy(output, &tmpOutput[paddingOffset], *outputLen); + rv = SECSuccess; + +done: + if (mask) + PORT_ZFree(mask, maskLen); + if (tmpOutput) + PORT_ZFree(tmpOutput, inputLen); + return rv; +} + +/* + * Generate an EME-OAEP encoded block for encryption + * Described in RFC 3447, section 7.1.1 + * We use input instead of M for the message to be encrypted + * label is the optional value L to be associated with the message. + */ +static SECStatus +eme_oaep_encode(unsigned char *em, unsigned int emLen, + const unsigned char *input, unsigned int inputLen, + HASH_HashType hashAlg, HASH_HashType maskHashAlg, + const unsigned char *label, unsigned int labelLen) +{ + const SECHashObject *hash; + void *hashContext; + SECStatus rv; + unsigned char *mask; + unsigned int reservedLen, dbMaskLen, i; + + hash = HASH_GetRawHashObject(hashAlg); + + /* Step 1.b */ + reservedLen = (2 * hash->length) + 2; + if (emLen < reservedLen || inputLen > (emLen - reservedLen)) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + return SECFailure; + } + + /* + * From RFC 3447, Section 7.1 + * +----------+---------+-------+ + * DB = | lHash | PS | M | + * +----------+---------+-------+ + * | + * +----------+ V + * | seed |--> MGF ---> xor + * +----------+ | + * | | + * +--+ V | + * |00| xor <----- MGF <-----| + * +--+ | | + * | | | + * V V V + * +--+----------+----------------------------+ + * EM = |00|maskedSeed| maskedDB | + * +--+----------+----------------------------+ + * + * We use mask to hold the result of the MGF functions, and all other + * values are generated in their final resting place. + */ + *em = 0x00; + + /* Step 2.a - Generate lHash */ + hashContext = (*hash->create)(); + if (hashContext == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + (*hash->begin)(hashContext); + if (labelLen > 0) + (*hash->update)(hashContext, label, labelLen); + (*hash->end)(hashContext, &em[1 + hash->length], &i, hash->length); + (*hash->destroy)(hashContext, PR_TRUE); + + /* Step 2.b - Generate PS */ + if (emLen - reservedLen - inputLen > 0) { + PORT_Memset(em + 1 + (hash->length * 2), 0x00, + emLen - reservedLen - inputLen); + } + + /* Step 2.c. - Generate DB + * DB = lHash || PS || 0x01 || M + * Note that PS and lHash have already been placed into em at their + * appropriate offsets. This just copies M into place + */ + em[emLen - inputLen - 1] = 0x01; + if (inputLen) + PORT_Memcpy(em + emLen - inputLen, input, inputLen); + + /* Step 2.d - Generate seed */ + rv = RNG_GenerateGlobalRandomBytes(em + 1, hash->length); + if (rv != SECSuccess) { + return rv; + } + + /* Step 2.e - Generate dbMask*/ + dbMaskLen = emLen - hash->length - 1; + mask = (unsigned char*)PORT_Alloc(dbMaskLen); + if (mask == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + MGF1(maskHashAlg, mask, dbMaskLen, em + 1, hash->length); + /* Step 2.f - Compute maskedDB*/ + for (i = 0; i < dbMaskLen; ++i) + em[1 + hash->length + i] ^= mask[i]; + + /* Step 2.g - Generate seedMask */ + MGF1(maskHashAlg, mask, hash->length, &em[1 + hash->length], dbMaskLen); + /* Step 2.h - Compute maskedSeed */ + for (i = 0; i < hash->length; ++i) + em[1 + i] ^= mask[i]; + + PORT_ZFree(mask, dbMaskLen); + return SECSuccess; +} + /* * Encode a RSA-PSS signature. * Described in RFC 3447, section 9.1.1. @@ -1008,7 +1062,7 @@ emsa_pss_encode(unsigned char *em, unsigned int emLen, (*hash->destroy)(hash_context, PR_TRUE); /* Step 7 + 8 */ - memset(em, 0, dbMaskLen - sLen - 1); + PORT_Memset(em, 0, dbMaskLen - sLen - 1); em[dbMaskLen - sLen - 1] = 0x01; /* Step 9 */ @@ -1251,3 +1305,145 @@ done: PORT_Free(pss_encoded); return rv; } + +/* MGF1 is the only supported MGF. */ +SECStatus +RSA_EncryptOAEP(CK_RSA_PKCS_OAEP_PARAMS *oaepParams, + NSSLOWKEYPublicKey *key, + unsigned char *output, unsigned int *outputLen, + unsigned int maxOutputLen, + const unsigned char *input, unsigned int inputLen) +{ + SECStatus rv = SECFailure; + unsigned int modulusLen = nsslowkey_PublicModulusLen(key); + unsigned char *oaepEncoded = NULL; + unsigned char *sourceData = NULL; + unsigned int sourceDataLen = 0; + + HASH_HashType hashAlg; + HASH_HashType maskHashAlg; + + if (maxOutputLen < modulusLen) { + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + return SECFailure; + } + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); + if (key->keyType != NSSLOWKEYRSAKey) { + PORT_SetError(SEC_ERROR_INVALID_KEY); + return SECFailure; + } + + hashAlg = GetHashTypeFromMechanism(oaepParams->hashAlg); + maskHashAlg = GetHashTypeFromMechanism(oaepParams->mgf); + if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + return SECFailure; + } + + /* The PKCS#11 source parameter is the "source" of the label parameter. + * The only defined source is explicitly specified, in which case, the + * label is an optional byte string in pSourceData. If ulSourceDataLen is + * zero, then pSourceData MUST be NULL - otherwise, it must be non-NULL. + */ + if (oaepParams->source != CKZ_DATA_SPECIFIED) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + return SECFailure; + } + sourceData = (unsigned char*)oaepParams->pSourceData; + sourceDataLen = oaepParams->ulSourceDataLen; + if ((sourceDataLen == 0 && sourceData != NULL) || + (sourceDataLen > 0 && sourceData == NULL)) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + return SECFailure; + } + + oaepEncoded = (unsigned char *)PORT_Alloc(modulusLen); + if (oaepEncoded == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + rv = eme_oaep_encode(oaepEncoded, modulusLen, input, inputLen, + hashAlg, maskHashAlg, sourceData, sourceDataLen); + if (rv != SECSuccess) + goto done; + + rv = RSA_PublicKeyOp(&key->u.rsa, output, oaepEncoded); + if (rv != SECSuccess) + goto done; + *outputLen = modulusLen; + +done: + PORT_Free(oaepEncoded); + return rv; +} + +/* MGF1 is the only supported MGF. */ +SECStatus +RSA_DecryptOAEP(CK_RSA_PKCS_OAEP_PARAMS *oaepParams, + NSSLOWKEYPrivateKey *key, + unsigned char *output, unsigned int *outputLen, + unsigned int maxOutputLen, + const unsigned char *input, unsigned int inputLen) +{ + SECStatus rv = SECFailure; + unsigned int modulusLen = nsslowkey_PrivateModulusLen(key); + unsigned char *oaepEncoded = NULL; + unsigned char *sourceData = NULL; + unsigned int sourceDataLen = 0; + + HASH_HashType hashAlg = GetHashTypeFromMechanism(oaepParams->hashAlg); + HASH_HashType maskHashAlg = GetHashTypeFromMechanism(oaepParams->mgf); + + if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + return SECFailure; + } + + if (inputLen != modulusLen) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + return SECFailure; + } + PORT_Assert(key->keyType == NSSLOWKEYRSAKey); + if (key->keyType != NSSLOWKEYRSAKey) { + PORT_SetError(SEC_ERROR_INVALID_KEY); + return SECFailure; + } + + /* The PKCS#11 source parameter is the "source" of the label parameter. + * The only defined source is explicitly specified, in which case, the + * label is an optional byte string in pSourceData. If ulSourceDataLen is + * zero, then pSourceData MUST be NULL - otherwise, it must be non-NULL. + */ + if (oaepParams->source != CKZ_DATA_SPECIFIED) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + return SECFailure; + } + sourceData = (unsigned char*)oaepParams->pSourceData; + sourceDataLen = oaepParams->ulSourceDataLen; + if ((sourceDataLen == 0 && sourceData != NULL) || + (sourceDataLen > 0 && sourceData == NULL)) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + return SECFailure; + } + + oaepEncoded = (unsigned char *)PORT_Alloc(modulusLen); + if (oaepEncoded == NULL) { + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + + rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, oaepEncoded, input); + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + goto done; + } + + rv = eme_oaep_decode(output, outputLen, maxOutputLen, oaepEncoded, + modulusLen, hashAlg, maskHashAlg, sourceData, + sourceDataLen); + +done: + if (oaepEncoded) + PORT_ZFree(oaepEncoded, modulusLen); + return rv; +} diff --git a/security/nss/lib/softoken/sdb.c b/security/nss/lib/softoken/sdb.c index 0d25953ddd95..e93c662befe6 100644 --- a/security/nss/lib/softoken/sdb.c +++ b/security/nss/lib/softoken/sdb.c @@ -254,6 +254,11 @@ sdb_getFallbackTempDir(void) #error "sdb_getFallbackTempDir not implemented" #endif +#ifndef SQLITE_FCNTL_TEMPFILENAME +/* SQLITE_FCNTL_TEMPFILENAME was added in SQLite 3.7.15 */ +#define SQLITE_FCNTL_TEMPFILENAME 16 +#endif + static char * sdb_getTempDir(sqlite3 *sqlDB) { diff --git a/security/nss/lib/softoken/sftkhmac.c b/security/nss/lib/softoken/sftkhmac.c new file mode 100644 index 000000000000..3b55a0572c98 --- /dev/null +++ b/security/nss/lib/softoken/sftkhmac.c @@ -0,0 +1,192 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "seccomon.h" +#include "secerr.h" +#include "blapi.h" +#include "pkcs11i.h" +#include "softoken.h" +#include "hmacct.h" + +/* MACMechanismToHash converts a PKCS#11 MAC mechanism into a freebl hash + * type. */ +static HASH_HashType +MACMechanismToHash(CK_MECHANISM_TYPE mech) +{ + switch (mech) { + case CKM_MD5_HMAC: + case CKM_SSL3_MD5_MAC: + return HASH_AlgMD5; + case CKM_SHA_1_HMAC: + case CKM_SSL3_SHA1_MAC: + return HASH_AlgSHA1; + case CKM_SHA224_HMAC: + return HASH_AlgSHA224; + case CKM_SHA256_HMAC: + return HASH_AlgSHA256; + case CKM_SHA384_HMAC: + return HASH_AlgSHA384; + case CKM_SHA512_HMAC: + return HASH_AlgSHA512; + } + return HASH_AlgNULL; +} + +static sftk_MACConstantTimeCtx * +SetupMAC(CK_MECHANISM_PTR mech, SFTKObject *key) +{ + CK_NSS_MAC_CONSTANT_TIME_PARAMS *params = + (CK_NSS_MAC_CONSTANT_TIME_PARAMS *) mech->pParameter; + sftk_MACConstantTimeCtx *ctx; + HASH_HashType alg; + SFTKAttribute *keyval; + unsigned char secret[sizeof(ctx->secret)]; + unsigned int secretLength; + + if (mech->ulParameterLen != sizeof(CK_NSS_MAC_CONSTANT_TIME_PARAMS)) { + return NULL; + } + + alg = MACMechanismToHash(params->macAlg); + if (alg == HASH_AlgNULL) { + return NULL; + } + + keyval = sftk_FindAttribute(key,CKA_VALUE); + if (keyval == NULL) { + return NULL; + } + secretLength = keyval->attrib.ulValueLen; + if (secretLength > sizeof(secret)) { + sftk_FreeAttribute(keyval); + return NULL; + } + memcpy(secret, keyval->attrib.pValue, secretLength); + sftk_FreeAttribute(keyval); + + ctx = PORT_Alloc(sizeof(sftk_MACConstantTimeCtx)); + if (!ctx) { + return NULL; + } + + memcpy(ctx->secret, secret, secretLength); + ctx->secretLength = secretLength; + ctx->hash = HASH_GetRawHashObject(alg); + ctx->totalLength = params->ulBodyTotalLen; + + return ctx; +} + +sftk_MACConstantTimeCtx * +sftk_HMACConstantTime_New(CK_MECHANISM_PTR mech, SFTKObject *key) +{ + CK_NSS_MAC_CONSTANT_TIME_PARAMS *params = + (CK_NSS_MAC_CONSTANT_TIME_PARAMS *) mech->pParameter; + sftk_MACConstantTimeCtx *ctx; + + if (params->ulHeaderLen > sizeof(ctx->header)) { + return NULL; + } + ctx = SetupMAC(mech, key); + if (!ctx) { + return NULL; + } + + ctx->headerLength = params->ulHeaderLen; + memcpy(ctx->header, params->pHeader, params->ulHeaderLen); + return ctx; +} + +sftk_MACConstantTimeCtx * +sftk_SSLv3MACConstantTime_New(CK_MECHANISM_PTR mech, SFTKObject *key) +{ + CK_NSS_MAC_CONSTANT_TIME_PARAMS *params = + (CK_NSS_MAC_CONSTANT_TIME_PARAMS *) mech->pParameter; + unsigned int padLength = 40, j; + sftk_MACConstantTimeCtx *ctx; + + if (params->macAlg != CKM_SSL3_MD5_MAC && + params->macAlg != CKM_SSL3_SHA1_MAC) { + return NULL; + } + ctx = SetupMAC(mech, key); + if (!ctx) { + return NULL; + } + + if (params->macAlg == CKM_SSL3_MD5_MAC) { + padLength = 48; + } + + ctx->headerLength = + ctx->secretLength + + padLength + + params->ulHeaderLen; + + if (ctx->headerLength > sizeof(ctx->header)) { + goto loser; + } + + j = 0; + memcpy(&ctx->header[j], ctx->secret, ctx->secretLength); + j += ctx->secretLength; + memset(&ctx->header[j], 0x36, padLength); + j += padLength; + memcpy(&ctx->header[j], params->pHeader, params->ulHeaderLen); + + return ctx; + +loser: + PORT_Free(ctx); + return NULL; +} + +void +sftk_HMACConstantTime_Update(void *pctx, void *data, unsigned int len) +{ + sftk_MACConstantTimeCtx *ctx = (sftk_MACConstantTimeCtx *) pctx; + SECStatus rv = HMAC_ConstantTime( + ctx->mac, NULL, sizeof(ctx->mac), + ctx->hash, + ctx->secret, ctx->secretLength, + ctx->header, ctx->headerLength, + data, len, + ctx->totalLength); + PORT_Assert(rv == SECSuccess); +} + +void +sftk_SSLv3MACConstantTime_Update(void *pctx, void *data, unsigned int len) +{ + sftk_MACConstantTimeCtx *ctx = (sftk_MACConstantTimeCtx *) pctx; + SECStatus rv = SSLv3_MAC_ConstantTime( + ctx->mac, NULL, sizeof(ctx->mac), + ctx->hash, + ctx->secret, ctx->secretLength, + ctx->header, ctx->headerLength, + data, len, + ctx->totalLength); + PORT_Assert(rv == SECSuccess); +} + +void +sftk_MACConstantTime_EndHash(void *pctx, void *out, unsigned int *outLength, + unsigned int maxLength) +{ + const sftk_MACConstantTimeCtx *ctx = (sftk_MACConstantTimeCtx *) pctx; + unsigned int toCopy = ctx->hash->length; + if (toCopy > maxLength) { + toCopy = maxLength; + } + memcpy(out, ctx->mac, toCopy); + if (outLength) { + *outLength = toCopy; + } +} + +void +sftk_MACConstantTime_DestroyContext(void *pctx, PRBool free) +{ + PORT_Free(pctx); +} diff --git a/security/nss/lib/softoken/softkver.h b/security/nss/lib/softoken/softkver.h index 7b24c33b4e32..ce9b764f7e52 100644 --- a/security/nss/lib/softoken/softkver.h +++ b/security/nss/lib/softoken/softkver.h @@ -25,11 +25,11 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define SOFTOKEN_VERSION "3.14.2.0" SOFTOKEN_ECC_STRING +#define SOFTOKEN_VERSION "3.14.3.0" SOFTOKEN_ECC_STRING " Beta" #define SOFTOKEN_VMAJOR 3 #define SOFTOKEN_VMINOR 14 -#define SOFTOKEN_VPATCH 2 +#define SOFTOKEN_VPATCH 3 #define SOFTOKEN_VBUILD 0 -#define SOFTOKEN_BETA PR_FALSE +#define SOFTOKEN_BETA PR_TRUE #endif /* _SOFTKVER_H_ */ diff --git a/security/nss/lib/softoken/softoken.h b/security/nss/lib/softoken/softoken.h index 8a4e497da7b0..7bafdd0a30e1 100644 --- a/security/nss/lib/softoken/softoken.h +++ b/security/nss/lib/softoken/softoken.h @@ -4,7 +4,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: softoken.h,v 1.28 2012/04/25 14:50:10 gerv%gerv.net Exp $ */ +/* $Id: softoken.h,v 1.29 2013/02/05 02:19:52 ryan.sleevi%gmail.com Exp $ */ #ifndef _SOFTOKEN_H_ #define _SOFTOKEN_H_ @@ -14,7 +14,7 @@ #include "softoknt.h" #include "secoidt.h" -#include "pkcs11t.h" /* CK_RV Required for sftk_fipsPowerUpSelfTest(). */ +#include "pkcs11t.h" SEC_BEGIN_PROTOS @@ -94,6 +94,20 @@ SECStatus RSA_DecryptBlock(NSSLOWKEYPrivateKey *key, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen, unsigned char *input, unsigned int inputLen); +extern +SECStatus RSA_EncryptOAEP(CK_RSA_PKCS_OAEP_PARAMS *oaepParams, + NSSLOWKEYPublicKey *key, + unsigned char *output, unsigned int *outputLen, + unsigned int maxOutputLen, + const unsigned char *input, unsigned int inputLen); + +extern +SECStatus RSA_DecryptOAEP(CK_RSA_PKCS_OAEP_PARAMS *oaepParams, + NSSLOWKEYPrivateKey *key, + unsigned char *output, unsigned int *outputLen, + unsigned int maxOutputLen, + const unsigned char *input, unsigned int inputLen); + /* * added to make pkcs #11 happy * RAW is RSA_X_509 diff --git a/security/nss/lib/softoken/softoknt.h b/security/nss/lib/softoken/softoknt.h index e3a9b09456ef..d1a282b7eb43 100644 --- a/security/nss/lib/softoken/softoknt.h +++ b/security/nss/lib/softoken/softoknt.h @@ -4,7 +4,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: softoknt.h,v 1.7 2012/04/25 14:50:10 gerv%gerv.net Exp $ */ +/* $Id: softoknt.h,v 1.8 2013/02/05 02:19:52 ryan.sleevi%gmail.com Exp $ */ #ifndef _SOFTOKNT_H_ #define _SOFTOKNT_H_ @@ -20,9 +20,6 @@ typedef enum { RSA_BlockPrivate0 = 0, /* unused, really */ RSA_BlockPrivate = 1, /* pad for a private-key operation */ RSA_BlockPublic = 2, /* pad for a public-key operation */ - RSA_BlockOAEP = 3, /* use OAEP padding */ - /* XXX is this only for a public-key - operation? If so, add "Public" */ RSA_BlockRaw = 4, /* simply justify the block appropriately */ RSA_BlockTotal } RSA_BlockType; diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index e8040231eb69..bc630137b9a7 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -5,7 +5,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: ssl3con.c,v 1.197 2013/01/18 19:31:42 bsmith%mozilla.com Exp $ */ +/* $Id: ssl3con.c,v 1.201 2013/02/07 01:29:19 wtc%google.com Exp $ */ /* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */ @@ -1844,7 +1844,6 @@ static const unsigned char mac_pad_2 [60] = { }; /* Called from: ssl3_SendRecord() -** ssl3_HandleRecord() ** Caller must already hold the SpecReadLock. (wish we could assert that!) */ static SECStatus @@ -2026,6 +2025,128 @@ ssl3_ComputeRecordMAC( return rv; } +/* Called from: ssl3_HandleRecord() + * Caller must already hold the SpecReadLock. (wish we could assert that!) + * + * On entry: + * originalLen >= inputLen >= MAC size +*/ +static SECStatus +ssl3_ComputeRecordMACConstantTime( + ssl3CipherSpec * spec, + PRBool useServerMacKey, + PRBool isDTLS, + SSL3ContentType type, + SSL3ProtocolVersion version, + SSL3SequenceNumber seq_num, + const SSL3Opaque * input, + int inputLen, + int originalLen, + unsigned char * outbuf, + unsigned int * outLen) +{ + CK_MECHANISM_TYPE macType; + CK_NSS_MAC_CONSTANT_TIME_PARAMS params; + SECItem param, inputItem, outputItem; + SECStatus rv; + unsigned char header[13]; + PK11SymKey * key; + int recordLength; + + PORT_Assert(inputLen >= spec->mac_size); + PORT_Assert(originalLen >= inputLen); + + if (spec->bypassCiphers) { + /* This function doesn't support PKCS#11 bypass. We fallback on the + * non-constant time version. */ + goto fallback; + } + + if (spec->mac_def->mac == mac_null) { + *outLen = 0; + return SECSuccess; + } + + header[0] = (unsigned char)(seq_num.high >> 24); + header[1] = (unsigned char)(seq_num.high >> 16); + header[2] = (unsigned char)(seq_num.high >> 8); + header[3] = (unsigned char)(seq_num.high >> 0); + header[4] = (unsigned char)(seq_num.low >> 24); + header[5] = (unsigned char)(seq_num.low >> 16); + header[6] = (unsigned char)(seq_num.low >> 8); + header[7] = (unsigned char)(seq_num.low >> 0); + header[8] = type; + + macType = CKM_NSS_HMAC_CONSTANT_TIME; + recordLength = inputLen - spec->mac_size; + if (spec->version <= SSL_LIBRARY_VERSION_3_0) { + macType = CKM_NSS_SSL3_MAC_CONSTANT_TIME; + header[9] = recordLength >> 8; + header[10] = recordLength; + params.ulHeaderLen = 11; + } else { + if (isDTLS) { + SSL3ProtocolVersion dtls_version; + + dtls_version = dtls_TLSVersionToDTLSVersion(version); + header[9] = dtls_version >> 8; + header[10] = dtls_version; + } else { + header[9] = version >> 8; + header[10] = version; + } + header[11] = recordLength >> 8; + header[12] = recordLength; + params.ulHeaderLen = 13; + } + + params.macAlg = spec->mac_def->mmech; + params.ulBodyTotalLen = originalLen; + params.pHeader = header; + + param.data = (unsigned char*) ¶ms; + param.len = sizeof(params); + param.type = 0; + + inputItem.data = (unsigned char *) input; + inputItem.len = inputLen; + inputItem.type = 0; + + outputItem.data = outbuf; + outputItem.len = *outLen; + outputItem.type = 0; + + key = spec->server.write_mac_key; + if (!useServerMacKey) { + key = spec->client.write_mac_key; + } + + rv = PK11_SignWithSymKey(key, macType, ¶m, &outputItem, &inputItem); + if (rv != SECSuccess) { + if (PORT_GetError() == SEC_ERROR_INVALID_ALGORITHM) { + goto fallback; + } + + *outLen = 0; + rv = SECFailure; + ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); + return rv; + } + + PORT_Assert(outputItem.len == (unsigned)spec->mac_size); + *outLen = outputItem.len; + + return rv; + +fallback: + /* ssl3_ComputeRecordMAC expects the MAC to have been removed from the + * length already. */ + inputLen -= spec->mac_size; + return ssl3_ComputeRecordMAC(spec, useServerMacKey, isDTLS, type, + version, seq_num, input, inputLen, + outbuf, outLen); +} + static PRBool ssl3_ClientAuthTokenPresent(sslSessionID *sid) { PK11SlotInfo *slot = NULL; @@ -9534,6 +9655,186 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) return SECSuccess; } +/* These macros return the given value with the MSB copied to all the other + * bits. They use the fact that arithmetic shift shifts-in the sign bit. + * However, this is not ensured by the C standard so you may need to replace + * them with something else for odd compilers. */ +#define DUPLICATE_MSB_TO_ALL(x) ( (unsigned)( (int)(x) >> (sizeof(int)*8-1) ) ) +#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x))) + +/* SECStatusToMask returns, in constant time, a mask value of all ones if + * rv == SECSuccess. Otherwise it returns zero. */ +static unsigned int +SECStatusToMask(SECStatus rv) +{ + unsigned int good; + /* rv ^ SECSuccess is zero iff rv == SECSuccess. Subtracting one results + * in the MSB being set to one iff it was zero before. */ + good = rv ^ SECSuccess; + good--; + return DUPLICATE_MSB_TO_ALL(good); +} + +/* ssl_ConstantTimeGE returns 0xff if a>=b and 0x00 otherwise. */ +static unsigned char +ssl_ConstantTimeGE(unsigned int a, unsigned int b) +{ + a -= b; + return DUPLICATE_MSB_TO_ALL(~a); +} + +/* ssl_ConstantTimeEQ8 returns 0xff if a==b and 0x00 otherwise. */ +static unsigned char +ssl_ConstantTimeEQ8(unsigned char a, unsigned char b) +{ + unsigned int c = a ^ b; + c--; + return DUPLICATE_MSB_TO_ALL_8(c); +} + +static SECStatus +ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext, + unsigned int blockSize, + unsigned int macSize) +{ + unsigned int paddingLength, good, t; + const unsigned int overhead = 1 /* padding length byte */ + macSize; + + /* These lengths are all public so we can test them in non-constant + * time. */ + if (overhead > plaintext->len) { + return SECFailure; + } + + paddingLength = plaintext->buf[plaintext->len-1]; + /* SSLv3 padding bytes are random and cannot be checked. */ + t = plaintext->len; + t -= paddingLength+overhead; + /* If len >= padding_length+overhead then the MSB of t is zero. */ + good = DUPLICATE_MSB_TO_ALL(~t); + /* SSLv3 requires that the padding is minimal. */ + t = blockSize - (paddingLength+1); + good &= DUPLICATE_MSB_TO_ALL(~t); + plaintext->len -= good & (paddingLength+1); + return (good & SECSuccess) | (~good & SECFailure); +} + +static SECStatus +ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize) +{ + unsigned int paddingLength, good, t, toCheck, i; + const unsigned int overhead = 1 /* padding length byte */ + macSize; + + /* These lengths are all public so we can test them in non-constant + * time. */ + if (overhead > plaintext->len) { + return SECFailure; + } + + paddingLength = plaintext->buf[plaintext->len-1]; + t = plaintext->len; + t -= paddingLength+overhead; + /* If len >= paddingLength+overhead then the MSB of t is zero. */ + good = DUPLICATE_MSB_TO_ALL(~t); + + /* The padding consists of a length byte at the end of the record and then + * that many bytes of padding, all with the same value as the length byte. + * Thus, with the length byte included, there are paddingLength+1 bytes of + * padding. + * + * We can't check just |paddingLength+1| bytes because that leaks + * decrypted information. Therefore we always have to check the maximum + * amount of padding possible. (Again, the length of the record is + * public information so we can use it.) */ + toCheck = 255; /* maximum amount of padding. */ + if (toCheck > plaintext->len-1) { + toCheck = plaintext->len-1; + } + + for (i = 0; i < toCheck; i++) { + unsigned int t = paddingLength - i; + /* If i <= paddingLength then the MSB of t is zero and mask is + * 0xff. Otherwise, mask is 0. */ + unsigned char mask = DUPLICATE_MSB_TO_ALL(~t); + unsigned char b = plaintext->buf[plaintext->len-1-i]; + /* The final |paddingLength+1| bytes should all have the value + * |paddingLength|. Therefore the XOR should be zero. */ + good &= ~(mask&(paddingLength ^ b)); + } + + /* If any of the final |paddingLength+1| bytes had the wrong value, + * one or more of the lower eight bits of |good| will be cleared. We + * AND the bottom 8 bits together and duplicate the result to all the + * bits. */ + good &= good >> 4; + good &= good >> 2; + good &= good >> 1; + good <<= sizeof(good)*8-1; + good = DUPLICATE_MSB_TO_ALL(good); + + plaintext->len -= good & (paddingLength+1); + return (good & SECSuccess) | (~good & SECFailure); +} + +/* On entry: + * originalLength >= macSize + * macSize <= MAX_MAC_LENGTH + * plaintext->len >= macSize + */ +static void +ssl_CBCExtractMAC(sslBuffer *plaintext, + unsigned int originalLength, + SSL3Opaque* out, + unsigned int macSize) +{ + unsigned char rotatedMac[MAX_MAC_LENGTH]; + /* macEnd is the index of |plaintext->buf| just after the end of the + * MAC. */ + unsigned macEnd = plaintext->len; + unsigned macStart = macEnd - macSize; + /* scanStart contains the number of bytes that we can ignore because + * the MAC's position can only vary by 255 bytes. */ + unsigned scanStart = 0; + unsigned i, j, divSpoiler; + unsigned char rotateOffset; + + if (originalLength > macSize + 255 + 1) + scanStart = originalLength - (macSize + 255 + 1); + + /* divSpoiler contains a multiple of macSize that is used to cause the + * modulo operation to be constant time. Without this, the time varies + * based on the amount of padding when running on Intel chips at least. + * + * The aim of right-shifting macSize is so that the compiler doesn't + * figure out that it can remove divSpoiler as that would require it + * to prove that macSize is always even, which I hope is beyond it. */ + divSpoiler = macSize >> 1; + divSpoiler <<= (sizeof(divSpoiler)-1)*8; + rotateOffset = (divSpoiler + macStart - scanStart) % macSize; + + memset(rotatedMac, 0, macSize); + for (i = scanStart; i < originalLength;) { + for (j = 0; j < macSize && i < originalLength; i++, j++) { + unsigned char macStarted = ssl_ConstantTimeGE(i, macStart); + unsigned char macEnded = ssl_ConstantTimeGE(i, macEnd); + unsigned char b = 0; + b = plaintext->buf[i]; + rotatedMac[j] |= b & macStarted & ~macEnded; + } + } + + /* Now rotate the MAC. If we knew that the MAC fit into a CPU cache line + * we could line-align |rotatedMac| and rotate in place. */ + memset(out, 0, macSize); + for (i = 0; i < macSize; i++) { + unsigned char offset = + (divSpoiler + macSize - rotateOffset + i) % macSize; + for (j = 0; j < macSize; j++) { + out[j] |= rotatedMac[i] & ssl_ConstantTimeEQ8(j, offset); + } + } +} + /* if cText is non-null, then decipher, check MAC, and decompress the * SSL record from cText->buf (typically gs->inbuf) * into databuf (typically gs->buf), and any previous contents of databuf @@ -9563,15 +9864,18 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) ssl3CipherSpec * crSpec; SECStatus rv; unsigned int hashBytes = MAX_MAC_LENGTH + 1; - unsigned int padding_length; PRBool isTLS; - PRBool padIsBad = PR_FALSE; SSL3ContentType rType; SSL3Opaque hash[MAX_MAC_LENGTH]; + SSL3Opaque givenHashBuf[MAX_MAC_LENGTH]; + SSL3Opaque *givenHash; sslBuffer *plaintext; sslBuffer temp_buf; PRUint64 dtls_seq_num; unsigned int ivLen = 0; + unsigned int originalLen = 0; + unsigned int good; + unsigned int minLength; PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); @@ -9639,6 +9943,30 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) } } + good = (unsigned)-1; + minLength = crSpec->mac_size; + if (cipher_def->type == type_block) { + /* CBC records have a padding length byte at the end. */ + minLength++; + if (crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { + /* With >= TLS 1.1, CBC records have an explicit IV. */ + minLength += cipher_def->iv_size; + } + } + + /* We can perform this test in variable time because the record's total + * length and the ciphersuite are both public knowledge. */ + if (cText->buf->len < minLength) { + SSL_DBG(("%d: SSL3[%d]: HandleRecord, record too small.", + SSL_GETPID(), ss->fd)); + /* must not hold spec lock when calling SSL3_SendAlert. */ + ssl_ReleaseSpecReadLock(ss); + SSL3_SendAlert(ss, alert_fatal, bad_record_mac); + /* always log mac error, in case attacker can read server logs. */ + PORT_SetError(SSL_ERROR_BAD_MAC_READ); + return SECFailure; + } + if (cipher_def->type == type_block && crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { /* Consume the per-record explicit IV. RFC 4346 Section 6.2.3.2 states @@ -9656,16 +9984,6 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } - if (ivLen > cText->buf->len) { - SSL_DBG(("%d: SSL3[%d]: HandleRecord, IV length check failed", - SSL_GETPID(), ss->fd)); - /* must not hold spec lock when calling SSL3_SendAlert. */ - ssl_ReleaseSpecReadLock(ss); - SSL3_SendAlert(ss, alert_fatal, bad_record_mac); - /* always log mac error, in case attacker can read server logs. */ - PORT_SetError(SSL_ERROR_BAD_MAC_READ); - return SECFailure; - } PRINT_BUF(80, (ss, "IV (ciphertext):", cText->buf->buf, ivLen)); @@ -9676,12 +9994,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) rv = crSpec->decode(crSpec->decodeContext, iv, &decoded, sizeof(iv), cText->buf->buf, ivLen); - if (rv != SECSuccess) { - /* All decryption failures must be treated like a bad record - * MAC; see RFC 5246 (TLS 1.2). - */ - padIsBad = PR_TRUE; - } + good &= SECStatusToMask(rv); } /* If we will be decompressing the buffer we need to decrypt somewhere @@ -9723,54 +10036,70 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) rv = crSpec->decode( crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len, plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen); + good &= SECStatusToMask(rv); PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len)); - if (rv != SECSuccess) { - /* All decryption failures must be treated like a bad record - * MAC; see RFC 5246 (TLS 1.2). - */ - padIsBad = PR_TRUE; - } + + originalLen = plaintext->len; /* If it's a block cipher, check and strip the padding. */ - if (cipher_def->type == type_block && !padIsBad) { - PRUint8 * pPaddingLen = plaintext->buf + plaintext->len - 1; - padding_length = *pPaddingLen; - /* TLS permits padding to exceed the block size, up to 255 bytes. */ - if (padding_length + 1 + crSpec->mac_size > plaintext->len) - padIsBad = PR_TRUE; - else { - plaintext->len -= padding_length + 1; - /* In TLS all padding bytes must be equal to the padding length. */ - if (isTLS) { - PRUint8 *p; - for (p = pPaddingLen - padding_length; p < pPaddingLen; ++p) { - padIsBad |= *p ^ padding_length; - } - } - } - } + if (cipher_def->type == type_block) { + const unsigned int blockSize = cipher_def->iv_size; + const unsigned int macSize = crSpec->mac_size; - /* Remove the MAC. */ - if (plaintext->len >= crSpec->mac_size) - plaintext->len -= crSpec->mac_size; - else - padIsBad = PR_TRUE; /* really macIsBad */ + if (crSpec->version <= SSL_LIBRARY_VERSION_3_0) { + good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding( + plaintext, blockSize, macSize)); + } else { + good &= SECStatusToMask(ssl_RemoveTLSCBCPadding( + plaintext, macSize)); + } + } /* compute the MAC */ rType = cText->type; - rv = ssl3_ComputeRecordMAC( crSpec, (PRBool)(!ss->sec.isServer), - IS_DTLS(ss), rType, cText->version, - IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, - plaintext->buf, plaintext->len, hash, &hashBytes); - if (rv != SECSuccess) { - padIsBad = PR_TRUE; /* really macIsBad */ + if (cipher_def->type == type_block) { + rv = ssl3_ComputeRecordMACConstantTime( + crSpec, (PRBool)(!ss->sec.isServer), + IS_DTLS(ss), rType, cText->version, + IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, + plaintext->buf, plaintext->len, originalLen, + hash, &hashBytes); + + ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf, + crSpec->mac_size); + givenHash = givenHashBuf; + + /* plaintext->len will always have enough space to remove the MAC + * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust + * plaintext->len if the result has enough space for the MAC and we + * tested the unadjusted size against minLength, above. */ + plaintext->len -= crSpec->mac_size; + } else { + /* This is safe because we checked the minLength above. */ + plaintext->len -= crSpec->mac_size; + + rv = ssl3_ComputeRecordMAC( + crSpec, (PRBool)(!ss->sec.isServer), + IS_DTLS(ss), rType, cText->version, + IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, + plaintext->buf, plaintext->len, + hash, &hashBytes); + + /* We can read the MAC directly from the record because its location is + * public when a stream cipher is used. */ + givenHash = plaintext->buf + plaintext->len; } - /* Check the MAC */ - if (hashBytes != (unsigned)crSpec->mac_size || padIsBad || - NSS_SecureMemcmp(plaintext->buf + plaintext->len, hash, - crSpec->mac_size) != 0) { + good &= SECStatusToMask(rv); + + if (hashBytes != (unsigned)crSpec->mac_size || + NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) { + /* We're allowed to leak whether or not the MAC check was correct */ + good = 0; + } + + if (good == 0) { /* must not hold spec lock when calling SSL3_SendAlert. */ ssl_ReleaseSpecReadLock(ss); diff --git a/security/nss/lib/util/hasht.h b/security/nss/lib/util/hasht.h index aa6c227d0998..6942464ed798 100644 --- a/security/nss/lib/util/hasht.h +++ b/security/nss/lib/util/hasht.h @@ -1,7 +1,7 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: hasht.h,v 1.10 2012/06/26 22:27:33 rrelyea%redhat.com Exp $ */ +/* $Id: hasht.h,v 1.11 2013/02/05 18:10:46 wtc%google.com Exp $ */ #ifndef _HASHT_H_ #define _HASHT_H_ @@ -51,6 +51,7 @@ struct SECHashObjectStr { void (*end)(void *, unsigned char *, unsigned int *, unsigned int); unsigned int blocklength; /* hash input block size (in bytes) */ HASH_HashType type; + void (*end_raw)(void *, unsigned char *, unsigned int *, unsigned int); }; struct HASHContextStr { diff --git a/security/nss/lib/util/nssutil.h b/security/nss/lib/util/nssutil.h index cf098d6e56bf..1fda7c8fde21 100644 --- a/security/nss/lib/util/nssutil.h +++ b/security/nss/lib/util/nssutil.h @@ -19,12 +19,12 @@ * The format of the version string should be * ".[.[.]][ ]" */ -#define NSSUTIL_VERSION "3.14.2.0" +#define NSSUTIL_VERSION "3.14.3.0 Beta" #define NSSUTIL_VMAJOR 3 #define NSSUTIL_VMINOR 14 -#define NSSUTIL_VPATCH 2 +#define NSSUTIL_VPATCH 3 #define NSSUTIL_VBUILD 0 -#define NSSUTIL_BETA PR_FALSE +#define NSSUTIL_BETA PR_TRUE SEC_BEGIN_PROTOS diff --git a/security/nss/lib/util/pkcs11n.h b/security/nss/lib/util/pkcs11n.h index b5c169630587..6e6194602ee0 100644 --- a/security/nss/lib/util/pkcs11n.h +++ b/security/nss/lib/util/pkcs11n.h @@ -6,7 +6,7 @@ #define _PKCS11N_H_ #ifdef DEBUG -static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.28 $ $Date: 2012/04/25 14:50:16 $"; +static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.31 $ $Date: 2013/02/07 01:29:19 $"; #endif /* DEBUG */ /* @@ -195,6 +195,9 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.28 $ #define CKM_NSS_JPAKE_FINAL_SHA384 (CKM_NSS + 17) #define CKM_NSS_JPAKE_FINAL_SHA512 (CKM_NSS + 18) +#define CKM_NSS_HMAC_CONSTANT_TIME (CKM_NSS + 19) +#define CKM_NSS_SSL3_MAC_CONSTANT_TIME (CKM_NSS + 20) + /* * HISTORICAL: * Do not attempt to use these. They are only used by NETSCAPE's internal @@ -240,6 +243,20 @@ typedef struct CK_NSS_JPAKEFinalParams { CK_NSS_JPAKEPublicValue B; /* in */ } CK_NSS_JPAKEFinalParams; +/* NOTE: the softoken's implementation of CKM_NSS_HMAC_CONSTANT_TIME and + * CKM_NSS_SSL3_MAC_CONSTANT_TIME requires that the sum of ulBodyTotalLen + * and ulHeaderLen be much smaller than 2^32 / 8 bytes because it uses an + * unsigned int variable to represent the length in bits. This should not + * be a problem because the SSL/TLS protocol limits the size of an SSL + * record to something considerably less than 2^32 bytes. + */ +typedef struct CK_NSS_MAC_CONSTANT_TIME_PARAMS { + CK_MECHANISM_TYPE macAlg; /* in */ + CK_ULONG ulBodyTotalLen; /* in */ + CK_BYTE * pHeader; /* in */ + CK_ULONG ulHeaderLen; /* in */ +} CK_NSS_MAC_CONSTANT_TIME_PARAMS; + /* * NSS-defined return values * diff --git a/security/nss/tests/ssl/ssl.sh b/security/nss/tests/ssl/ssl.sh index 5ae5712e8967..4fe39e522dfe 100755 --- a/security/nss/tests/ssl/ssl.sh +++ b/security/nss/tests/ssl/ssl.sh @@ -299,7 +299,7 @@ ssl_cov() elif [ "`echo $ectype | cut -b 1`" != "#" ] ; then echo "$SCRIPTNAME: running $testname ----------------------------" VMAX="ssl3" - if [ "$testmax" = "TLS" ]; then + if [ "$testmax" = "TLS10" ]; then VMAX="tls1.0" fi if [ "$testmax" = "TLS11" ]; then