Bug 839141 - Upgrade Mozilla to NSS 3.14.3, starting with Beta1, r=ekr

This commit is contained in:
Kai Engert 2013-02-10 01:11:00 +01:00
parent c4c4dbc220
commit 0ec2973ab8
37 changed files with 1964 additions and 413 deletions

View File

@ -1 +1 @@
NSS_3_14_2_RTM
NSS_3_14_3_BETA1

View File

@ -1 +1 @@
NSS_3_14_2_RTM
NSS_3_14_3_BETA1

View File

@ -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);

View File

@ -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) );

View File

@ -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 */);
}

View File

@ -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

View File

@ -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 *

View File

@ -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);
}

View File

@ -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;

View File

@ -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 \

View File

@ -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)
{

View File

@ -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
},
};

View File

@ -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)

View File

@ -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.
*

View File

@ -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

View File

@ -1021,3 +1021,9 @@ CERT_CreateOCSPSingleResponseRevoked;
;+ local:
;+ *;
;+};
;+NSS_3.14.3 { # NSS 3.14.3 release
;+ global:
PK11_SignWithSymKey;
;+ local:
;+ *;
;+};

View File

@ -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
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
*/
#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

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -267,9 +267,3 @@ NSSSMIME_GetVersion;
;+ local:
;+ *;
;+};
;+NSS_3.14.3 { # NSS 3.14.3 release
;+ global:
SEC_PKCS7VerifyDetachedSignatureAtTime;
;+ local:
;+ *;
;+};

View File

@ -47,6 +47,7 @@ CSRCS = \
rsawrapr.c \
sdb.c \
sftkdb.c \
sftkhmac.c \
sftkpars.c \
sftkpwd.c \
softkver.c \

View File

@ -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]);

View File

@ -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;

View File

@ -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)
*/

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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);
}

View File

@ -25,11 +25,11 @@
* The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
*/
#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_ */

View File

@ -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

View File

@ -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;

View File

@ -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*) &params;
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, &param, &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);

View File

@ -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 {

View File

@ -19,12 +19,12 @@
* The format of the version string should be
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
*/
#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

View File

@ -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
*

View File

@ -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