File nss-CC-approved_crypto-non-EC.patch of Package mozilla-nss.972
# HG changeset patch
# Parent f616a30eaf119c49568a947ae554fa0e96f76f96
Runtime checks for non-approved algorithms in FIPS mode
diff --git a/lib/freebl/alg2268.c b/lib/freebl/alg2268.c
--- a/lib/freebl/alg2268.c
+++ b/lib/freebl/alg2268.c
@@ -10,16 +10,18 @@
#endif
#include "blapi.h"
#include "secerr.h"
#ifdef XP_UNIX_XXX
#include <stddef.h> /* for ptrdiff_t */
#endif
+#include "fips.h"
+
/*
** RC2 symmetric block cypher
*/
typedef SECStatus (rc2Func)(RC2Context *cx, unsigned char *output,
const unsigned char *input, unsigned int inputLen);
/* forward declarations */
@@ -98,30 +100,33 @@ 0231,0174,0072,0205,0043,0270,0264,0172,
0055,0135,0372,0230,0343,0212,0222,0256,0005,0337,0051,0020,0147,0154,0272,0311,
0323,0000,0346,0317,0341,0236,0250,0054,0143,0026,0001,0077,0130,0342,0211,0251,
0015,0070,0064,0033,0253,0063,0377,0260,0273,0110,0014,0137,0271,0261,0315,0056,
0305,0363,0333,0107,0345,0245,0234,0167,0012,0246,0040,0150,0376,0177,0301,0255
};
RC2Context * RC2_AllocateContext(void)
{
+ IN_FIPS_RETURN(NULL);
return PORT_ZNew(RC2Context);
}
SECStatus
RC2_InitContext(RC2Context *cx, const unsigned char *key, unsigned int len,
const unsigned char *input, int mode, unsigned int efLen8,
unsigned int unused)
{
PRUint8 *L,*L2;
int i;
#if !defined(IS_LITTLE_ENDIAN)
PRUint16 tmpS;
#endif
PRUint8 tmpB;
+ IN_FIPS_RETURN(SECFailure);
+
if (!key || !cx || !len || len > (sizeof cx->B) ||
efLen8 > (sizeof cx->B)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (mode == NSS_RC2) {
/* groovy */
} else if (mode == NSS_RC2_CBC) {
@@ -183,17 +188,21 @@ RC2_InitContext(RC2Context *cx, const un
**
** When mode is set to NSS_RC2_CBC the RC2 cipher is run in "cipher block
** chaining" mode.
*/
RC2Context *
RC2_CreateContext(const unsigned char *key, unsigned int len,
const unsigned char *iv, int mode, unsigned efLen8)
{
- RC2Context *cx = PORT_ZNew(RC2Context);
+ RC2Context *cx;
+
+ IN_FIPS_RETURN(NULL);
+
+ cx = PORT_ZNew(RC2Context);
if (cx) {
SECStatus rv = RC2_InitContext(cx, key, len, iv, mode, efLen8, 0);
if (rv != SECSuccess) {
RC2_DestroyContext(cx, PR_TRUE);
cx = NULL;
}
}
return cx;
@@ -427,17 +436,21 @@ rc2_DecryptCBC(RC2Context *cx, unsigned
** stored in "output"
** "input" the input data
** "inputLen" the amount of input data
*/
SECStatus RC2_Encrypt(RC2Context *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
- SECStatus rv = SECSuccess;
+ SECStatus rv;
+
+ IN_FIPS_RETURN(SECFailure);
+
+ rv = SECSuccess;
if (inputLen) {
if (inputLen % RC2_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
if (maxOutputLen < inputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
@@ -460,17 +473,21 @@ SECStatus RC2_Encrypt(RC2Context *cx, un
** stored in "output"
** "input" the input data
** "inputLen" the amount of input data
*/
SECStatus RC2_Decrypt(RC2Context *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
- SECStatus rv = SECSuccess;
+ SECStatus rv;
+
+ IN_FIPS_RETURN(SECFailure);
+
+ rv = SECSuccess;
if (inputLen) {
if (inputLen % RC2_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
if (maxOutputLen < inputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
diff --git a/lib/freebl/arcfour.c b/lib/freebl/arcfour.c
--- a/lib/freebl/arcfour.c
+++ b/lib/freebl/arcfour.c
@@ -8,16 +8,17 @@
#include "stubs.h"
#endif
#include "prerr.h"
#include "secerr.h"
#include "prtypes.h"
#include "blapi.h"
+#include "fips.h"
/* Architecture-dependent defines */
#if defined(SOLARIS) || defined(HPUX) || defined(NSS_X86) || \
defined(_WIN64)
/* Convert the byte-stream to a word-stream */
#define CONVERT_TO_WORDS
#endif
@@ -104,29 +105,32 @@ static const Stype Kinit[256] = {
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
RC4Context *
RC4_AllocateContext(void)
{
+ IN_FIPS_RETURN(NULL);
return PORT_ZNew(RC4Context);
}
SECStatus
RC4_InitContext(RC4Context *cx, const unsigned char *key, unsigned int len,
const unsigned char * unused1, int unused2,
unsigned int unused3, unsigned int unused4)
{
unsigned int i;
PRUint8 j, tmp;
PRUint8 K[256];
PRUint8 *L;
+ IN_FIPS_RETURN(SECFailure);
+
/* verify the key length. */
PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE);
if (len == 0 || len >= ARCFOUR_STATE_SIZE) {
PORT_SetError(SEC_ERROR_BAD_KEY);
return SECFailure;
}
if (cx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -159,30 +163,35 @@ RC4_InitContext(RC4Context *cx, const un
/*
* Initialize a new generator.
*/
RC4Context *
RC4_CreateContext(const unsigned char *key, int len)
{
- RC4Context *cx = RC4_AllocateContext();
+ RC4Context *cx;
+
+ IN_FIPS_RETURN(NULL);
+
+ cx = RC4_AllocateContext();
if (cx) {
SECStatus rv = RC4_InitContext(cx, key, len, NULL, 0, 0, 0);
if (rv != SECSuccess) {
PORT_ZFree(cx, sizeof(*cx));
cx = NULL;
}
}
return cx;
}
void
RC4_DestroyContext(RC4Context *cx, PRBool freeit)
{
+ IN_FIPS_RETURN();
if (freeit)
PORT_ZFree(cx, sizeof(*cx));
}
#if defined(NSS_BEVAND_ARCFOUR)
extern void ARCFOUR(RC4Context *cx, WORD inputLen,
const unsigned char *input, unsigned char *output);
#else
@@ -523,16 +532,18 @@ rc4_wordconv(RC4Context *cx, unsigned ch
#endif
#endif /* NSS_BEVAND_ARCFOUR */
SECStatus
RC4_Encrypt(RC4Context *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
+ IN_FIPS_RETURN(SECFailure);
+
PORT_Assert(maxOutputLen >= inputLen);
if (maxOutputLen < inputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
#if defined(NSS_BEVAND_ARCFOUR)
ARCFOUR(cx, inputLen, input, output);
*outputLen = inputLen;
@@ -545,16 +556,18 @@ RC4_Encrypt(RC4Context *cx, unsigned cha
return rc4_unrolled(cx, output, outputLen, maxOutputLen, input, inputLen);
#endif
}
SECStatus RC4_Decrypt(RC4Context *cx, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
+ IN_FIPS_RETURN(SECFailure);
+
PORT_Assert(maxOutputLen >= inputLen);
if (maxOutputLen < inputLen) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
/* decrypt and encrypt are same operation. */
#if defined(NSS_BEVAND_ARCFOUR)
ARCFOUR(cx, inputLen, input, output);
diff --git a/lib/freebl/fips.c b/lib/freebl/fips.c
--- a/lib/freebl/fips.c
+++ b/lib/freebl/fips.c
@@ -62,8 +62,37 @@ FIPS_rngDev(void)
case 1:
return RNG_DEV_FIPS1;
default:
fatal("Fatal error: internal error at %s:%u"
, __FILE__, __LINE__);
}
}
+/* either returns the input or aborts if in FIPS and the algorithm is not
+ * approved */
+PRBool
+FIPS_hashAlgApproved(HASH_HashType hashAlg)
+{
+ PRBool rv = PR_FALSE;
+
+ switch (hashAlg) {
+ case HASH_AlgNULL:
+ case HASH_AlgSHA1:
+ case HASH_AlgSHA256:
+ case HASH_AlgSHA384:
+ case HASH_AlgSHA512:
+ case HASH_AlgSHA224:
+ rv = PR_TRUE;
+ break;
+ default:
+ /*
+ fatal("Fatal error: non-approved hash algorithm (id %i)"
+ "requested while running in FIPS mode"
+ , hashAlg);
+ */
+ if (!FIPS_mode())
+ rv = PR_TRUE;
+ break;
+ }
+ return rv;
+}
+
diff --git a/lib/freebl/fips.h b/lib/freebl/fips.h
--- a/lib/freebl/fips.h
+++ b/lib/freebl/fips.h
@@ -3,13 +3,25 @@
*
* 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 FIPS_H
#define FIPS_H
+#include "hasht.h"
+#include "secerr.h"
+
+#define IN_FIPS_RETURN(rv) \
+ do { \
+ if (FIPS_mode()) { \
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); \
+ return rv; \
+ } \
+ } while (0)
+
int FIPS_mode(void);
char* FIPS_rngDev(void);
+PRBool FIPS_hashAlgApproved(HASH_HashType hashAlg);
#endif
diff --git a/lib/freebl/md2.c b/lib/freebl/md2.c
--- a/lib/freebl/md2.c
+++ b/lib/freebl/md2.c
@@ -8,16 +8,18 @@
#include "prerr.h"
#include "secerr.h"
#include "prtypes.h"
#include "blapi.h"
+#include "fips.h"
+
#define MD2_DIGEST_LEN 16
#define MD2_BUFSIZE 16
#define MD2_X_SIZE 48 /* The X array, [CV | INPUT | TMP VARS] */
#define MD2_CV 0 /* index into X for chaining variables */
#define MD2_INPUT 16 /* index into X for input */
#define MD2_TMPVARS 32 /* index into X for temporary variables */
#define MD2_CHECKSUM_SIZE 16
@@ -61,31 +63,34 @@ static const PRUint8 MD2S[256] = {
0061, 0104, 0120, 0264, 0217, 0355, 0037, 0032,
0333, 0231, 0215, 0063, 0237, 0021, 0203, 0024
};
SECStatus
MD2_Hash(unsigned char *dest, const char *src)
{
unsigned int len;
+
+ IN_FIPS_RETURN(SECFailure);
MD2Context *cx = MD2_NewContext();
if (!cx) {
PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
return SECFailure;
}
MD2_Begin(cx);
MD2_Update(cx, (const unsigned char *)src, PORT_Strlen(src));
MD2_End(cx, dest, &len, MD2_DIGEST_LEN);
MD2_DestroyContext(cx, PR_TRUE);
return SECSuccess;
}
MD2Context *
MD2_NewContext(void)
{
+ IN_FIPS_RETURN(NULL);
MD2Context *cx = (MD2Context *)PORT_ZAlloc(sizeof(MD2Context));
if (cx == NULL) {
PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
return NULL;
}
return cx;
}
@@ -94,16 +99,17 @@ MD2_DestroyContext(MD2Context *cx, PRBoo
{
if (freeit)
PORT_ZFree(cx, sizeof(*cx));
}
void
MD2_Begin(MD2Context *cx)
{
+ IN_FIPS_RETURN();
memset(cx, 0, sizeof(*cx));
cx->unusedBuffer = MD2_BUFSIZE;
}
static void
md2_compress(MD2Context *cx)
{
int j;
@@ -191,16 +197,18 @@ md2_compress(MD2Context *cx)
cx->unusedBuffer = MD2_BUFSIZE;
}
void
MD2_Update(MD2Context *cx, const unsigned char *input, unsigned int inputLen)
{
PRUint32 bytesToConsume;
+ IN_FIPS_RETURN();
+
/* Fill the remaining input buffer. */
if (cx->unusedBuffer != MD2_BUFSIZE) {
bytesToConsume = PR_MIN(inputLen, cx->unusedBuffer);
memcpy(&cx->X[MD2_INPUT + (MD2_BUFSIZE - cx->unusedBuffer)],
input, bytesToConsume);
if (cx->unusedBuffer + bytesToConsume >= MD2_BUFSIZE)
md2_compress(cx);
inputLen -= bytesToConsume;
@@ -221,16 +229,19 @@ MD2_Update(MD2Context *cx, const unsigne
cx->unusedBuffer = MD2_BUFSIZE - inputLen;
}
void
MD2_End(MD2Context *cx, unsigned char *digest,
unsigned int *digestLen, unsigned int maxDigestLen)
{
PRUint8 padStart;
+
+ IN_FIPS_RETURN();
+
if (maxDigestLen < MD2_BUFSIZE) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return;
}
padStart = MD2_BUFSIZE - cx->unusedBuffer;
memset(&cx->X[MD2_INPUT + padStart], cx->unusedBuffer,
cx->unusedBuffer);
md2_compress(cx);
diff --git a/lib/freebl/md5.c b/lib/freebl/md5.c
--- a/lib/freebl/md5.c
+++ b/lib/freebl/md5.c
@@ -9,16 +9,18 @@
#include "prerr.h"
#include "secerr.h"
#include "prtypes.h"
#include "prlong.h"
#include "blapi.h"
+#include "fips.h"
+
#define MD5_HASH_LEN 16
#define MD5_BUFFER_SIZE 64
#define MD5_END_BUFFER (MD5_BUFFER_SIZE - 8)
#define CV0_1 0x67452301
#define CV0_2 0xefcdab89
#define CV0_3 0x98badcfe
#define CV0_4 0x10325476
@@ -189,56 +191,64 @@ struct MD5ContextStr {
} u;
};
#define inBuf u.b
SECStatus
MD5_Hash(unsigned char *dest, const char *src)
{
+ IN_FIPS_RETURN(SECFailure);
return MD5_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src));
}
SECStatus
MD5_HashBuf(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
{
unsigned int len;
MD5Context cx;
+ IN_FIPS_RETURN(SECFailure);
+
MD5_Begin(&cx);
MD5_Update(&cx, src, src_length);
MD5_End(&cx, dest, &len, MD5_HASH_LEN);
memset(&cx, 0, sizeof cx);
return SECSuccess;
}
MD5Context *
MD5_NewContext(void)
{
+ IN_FIPS_RETURN(NULL);
+
/* no need to ZAlloc, MD5_Begin will init the context */
MD5Context *cx = (MD5Context *)PORT_Alloc(sizeof(MD5Context));
if (cx == NULL) {
PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
return NULL;
}
return cx;
}
void
MD5_DestroyContext(MD5Context *cx, PRBool freeit)
{
- memset(cx, 0, sizeof *cx);
+ if (cx)
+ memset(cx, 0, sizeof *cx);
if (freeit) {
PORT_Free(cx);
}
}
void
MD5_Begin(MD5Context *cx)
{
+ IN_FIPS_RETURN();
+
cx->lsbInput = 0;
cx->msbInput = 0;
/* memset(cx->inBuf, 0, sizeof(cx->inBuf)); */
cx->cv[0] = CV0_1;
cx->cv[1] = CV0_2;
cx->cv[2] = CV0_3;
cx->cv[3] = CV0_4;
}
@@ -417,16 +427,18 @@ md5_compress(MD5Context *cx, const PRUin
void
MD5_Update(MD5Context *cx, const unsigned char *input, unsigned int inputLen)
{
PRUint32 bytesToConsume;
PRUint32 inBufIndex = cx->lsbInput & 63;
const PRUint32 *wBuf;
+ IN_FIPS_RETURN();
+
/* Add the number of input bytes to the 64-bit input counter. */
addto64(cx->msbInput, cx->lsbInput, inputLen);
if (inBufIndex) {
/* There is already data in the buffer. Fill with input. */
bytesToConsume = PR_MIN(inputLen, MD5_BUFFER_SIZE - inBufIndex);
memcpy(&cx->inBuf[inBufIndex], input, bytesToConsume);
if (inBufIndex + bytesToConsume >= MD5_BUFFER_SIZE) {
/* The buffer is filled. Run the compression function. */
@@ -490,16 +502,18 @@ MD5_End(MD5Context *cx, unsigned char *d
unsigned int *digestLen, unsigned int maxDigestLen)
{
#ifndef IS_LITTLE_ENDIAN
PRUint32 tmp;
#endif
PRUint32 lowInput, highInput;
PRUint32 inBufIndex = cx->lsbInput & 63;
+ IN_FIPS_RETURN();
+
if (maxDigestLen < MD5_HASH_LEN) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return;
}
/* Copy out the length of bits input before padding. */
lowInput = cx->lsbInput;
highInput = (cx->msbInput << 3) | (lowInput >> 29);
@@ -538,16 +552,18 @@ void
MD5_EndRaw(MD5Context *cx, unsigned char *digest,
unsigned int *digestLen, unsigned int maxDigestLen)
{
#ifndef IS_LITTLE_ENDIAN
PRUint32 tmp;
#endif
PRUint32 cv[4];
+ IN_FIPS_RETURN();
+
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]);
diff --git a/lib/freebl/nsslowhash.c b/lib/freebl/nsslowhash.c
--- a/lib/freebl/nsslowhash.c
+++ b/lib/freebl/nsslowhash.c
@@ -7,16 +7,17 @@
#endif
#include "prtypes.h"
#include "secerr.h"
#include "pkcs11t.h"
#include "blapi.h"
#include "hasht.h"
#include "plhash.h"
#include "nsslowhash.h"
+#include "fips.h"
/* FIPS selftests are implemented in library constructors and abort on failure
* - if anybody gets to call this function it means the tests passed and this
* can be a successful no-op; the integrity selftest that used to be here is
* handled by the freebl constructor as well
*/
CK_RV
freebl_fipsPowerUpSelfTest( void )
@@ -67,16 +68,22 @@ NSSLOW_Reset(NSSLOWInitContext *context)
}
NSSLOWHASHContext *
NSSLOWHASH_NewContext(NSSLOWInitContext *initContext,
HASH_HashType hashType)
{
NSSLOWHASHContext *context;
+ /* return with an error if unapproved hash is requested in FIPS mode */
+ if (!FIPS_hashAlgApproved(hashType)) {
+ PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+ return NULL;
+ }
+
if (initContext != &dummyContext) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return (NULL);
}
context = PORT_ZNew(NSSLOWHASHContext);
if (!context) {
return NULL;
diff --git a/lib/freebl/rawhash.c b/lib/freebl/rawhash.c
--- a/lib/freebl/rawhash.c
+++ b/lib/freebl/rawhash.c
@@ -5,16 +5,17 @@
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif
#include "nspr.h"
#include "hasht.h"
#include "blapi.h" /* below the line */
#include "secerr.h"
+#include "fips.h"
static void *
null_hash_new_context(void)
{
return NULL;
}
static void *
@@ -148,14 +149,15 @@ const SECHashObject SECRawHashObjects[]
(void (*)(void *, unsigned char *, unsigned int *,
unsigned int)) SHA224_EndRaw
},
};
const SECHashObject *
HASH_GetRawHashObject(HASH_HashType hashType)
{
- if (hashType < HASH_AlgNULL || hashType >= HASH_AlgTOTAL) {
+ if (hashType < HASH_AlgNULL || hashType >= HASH_AlgTOTAL
+ || (!FIPS_hashAlgApproved(hashType))) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
return &SECRawHashObjects[hashType];
}
diff --git a/lib/freebl/seed.c b/lib/freebl/seed.c
--- a/lib/freebl/seed.c
+++ b/lib/freebl/seed.c
@@ -12,16 +12,18 @@
#include <stddef.h>
#ifdef WIN32
#include <memory.h>
#endif
#include "seed.h"
#include "secerr.h"
+#include "fips.h"
+
static const seed_word SS[4][256] = {
{
0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0,
0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124,
0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c,
0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360,
0x28082028, 0x04444044, 0x20002020, 0x1d8d919c,
0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314,
@@ -304,16 +306,18 @@ static const seed_word SS[4][256] = {
void SEED_set_key(const unsigned char rawkey[SEED_KEY_LENGTH],
SEED_KEY_SCHEDULE *ks)
{
seed_word K0, K1, K2, K3;
seed_word t0, t1;
+ IN_FIPS_RETURN();
+
char2word(rawkey , K0);
char2word(rawkey+4 , K1);
char2word(rawkey+8 , K2);
char2word(rawkey+12, K3);
t0 = (K0 + K2 - KC0);
t1 = (K1 - K3 + KC0);
KEYUPDATE_TEMP(t0, t1, &ks->data[0]);
@@ -351,16 +355,18 @@ void SEED_set_key(const unsigned char ra
void SEED_encrypt(const unsigned char s[SEED_BLOCK_SIZE],
unsigned char d[SEED_BLOCK_SIZE],
const SEED_KEY_SCHEDULE *ks)
{
seed_word L0, L1, R0, R1;
seed_word t0, t1;
+ IN_FIPS_RETURN();
+
char2word(s, L0);
char2word(s+4, L1);
char2word(s+8, R0);
char2word(s+12, R1);
E_SEED(t0, t1, L0, L1, R0, R1, 0);
E_SEED(t0, t1, R0, R1, L0, L1, 2);
E_SEED(t0, t1, L0, L1, R0, R1, 4);
@@ -386,16 +392,18 @@ void SEED_encrypt(const unsigned char s[
void SEED_decrypt(const unsigned char s[SEED_BLOCK_SIZE],
unsigned char d[SEED_BLOCK_SIZE],
const SEED_KEY_SCHEDULE *ks)
{
seed_word L0, L1, R0, R1;
seed_word t0, t1;
+ IN_FIPS_RETURN();
+
char2word(s, L0);
char2word(s+4, L1);
char2word(s+8, R0);
char2word(s+12, R1);
E_SEED(t0, t1, L0, L1, R0, R1, 30);
E_SEED(t0, t1, R0, R1, L0, L1, 28);
E_SEED(t0, t1, L0, L1, R0, R1, 26);
@@ -434,16 +442,18 @@ void SEED_ecb_encrypt(const unsigned cha
void SEED_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const SEED_KEY_SCHEDULE *ks,
unsigned char ivec[SEED_BLOCK_SIZE], int enc)
{
size_t n;
unsigned char tmp[SEED_BLOCK_SIZE];
const unsigned char *iv = ivec;
+ IN_FIPS_RETURN();
+
if (enc) {
while (len >= SEED_BLOCK_SIZE) {
for (n = 0; n < SEED_BLOCK_SIZE; ++n)
out[n] = in[n] ^ iv[n];
SEED_encrypt(out, out, ks);
iv = out;
len -= SEED_BLOCK_SIZE;
@@ -510,24 +520,27 @@ void SEED_cbc_encrypt(const unsigned cha
memcpy(ivec, tmp, SEED_BLOCK_SIZE);
}
}
}
SEEDContext *
SEED_AllocateContext(void)
{
+ IN_FIPS_RETURN(NULL);
return PORT_ZNew(SEEDContext);
}
SECStatus
SEED_InitContext(SEEDContext *cx, const unsigned char *key,
unsigned int keylen, const unsigned char *iv,
int mode, unsigned int encrypt,unsigned int unused)
{
+ IN_FIPS_RETURN(SECFailure);
+
if (!cx) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
switch (mode) {
case NSS_SEED:
SEED_set_key(key, &cx->ks);
@@ -549,17 +562,21 @@ SEED_InitContext(SEEDContext *cx, const
return SECSuccess;
}
SEEDContext *
SEED_CreateContext(const unsigned char * key, const unsigned char *iv,
int mode, PRBool encrypt)
{
- SEEDContext *cx = PORT_ZNew(SEEDContext);
+ SEEDContext *cx;
+
+ IN_FIPS_RETURN(NULL);
+
+ cx = PORT_ZNew(SEEDContext);
SECStatus rv = SEED_InitContext(cx, key, SEED_KEY_LENGTH, iv, mode,
encrypt, 0);
if (rv != SECSuccess) {
PORT_ZFree(cx, sizeof *cx);
cx = NULL;
}
@@ -577,16 +594,18 @@ SEED_DestroyContext(SEEDContext *cx, PRB
}
}
SECStatus
SEED_Encrypt(SEEDContext *cx, unsigned char *out, unsigned int *outLen,
unsigned int maxOutLen, const unsigned char *in,
unsigned int inLen)
{
+ IN_FIPS_RETURN(SECFailure);
+
if (!cx) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (!cx->encrypt) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
@@ -611,16 +630,18 @@ SEED_Encrypt(SEEDContext *cx, unsigned c
return SECSuccess;
}
SECStatus
SEED_Decrypt(SEEDContext *cx, unsigned char *out, unsigned int *outLen,
unsigned int maxOutLen, const unsigned char *in,
unsigned int inLen)
{
+ IN_FIPS_RETURN(SECFailure);
+
if (!cx) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (cx->encrypt) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
--- a/lib/softoken/pkcs11c.c
+++ b/lib/softoken/pkcs11c.c
@@ -6098,17 +6098,17 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE h
if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
CKK_GENERIC_SECRET)) {
if (att2) sftk_FreeAttribute(att2);
crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
break;
}
sftk_FreeAttribute(att2);
md5 = MD5_NewContext();
- if (md5 == NULL) {
+ if (md5 == NULL && !isTLS) {
crv = CKR_HOST_MEMORY;
break;
}
sha = SHA1_NewContext();
if (sha == NULL) {
PORT_Free(md5);
crv = CKR_HOST_MEMORY;
break;