summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/lowhashtest/Makefile8
-rw-r--r--cmd/lowhashtest/lowhashtest.c90
-rw-r--r--cmd/lowhashtest/manifest.mn3
-rw-r--r--cmd/shlibsign/shlibsign.c885
-rw-r--r--lib/freebl/Makefile3
-rw-r--r--lib/freebl/nsslowhash.c7
-rw-r--r--lib/freebl/shsign.h16
-rw-r--r--lib/freebl/shvfy.c438
-rw-r--r--lib/freebl/stubs.c43
-rw-r--r--lib/freebl/stubs.h1
-rwxr-xr-x[-rw-r--r--]tests/lowhash/lowhash.sh0
11 files changed, 1005 insertions, 489 deletions
diff --git a/cmd/lowhashtest/Makefile b/cmd/lowhashtest/Makefile
index cfac7700a..a9c64c1d5 100644
--- a/cmd/lowhashtest/Makefile
+++ b/cmd/lowhashtest/Makefile
@@ -28,9 +28,6 @@ include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
-include ../platlibs.mk
-
-
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
@@ -50,12 +47,7 @@ EXTRA_LIBS += \
EXTRA_SHARED_LIBS += \
-L$(DIST)/lib \
-L$(NSSUTIL_LIB_DIR) \
- -lnssutil3 \
-lfreebl3 \
- -L$(NSPR_LIB_DIR) \
- -lplc4 \
- -lplds4 \
- -lnspr4 \
$(NULL)
#######################################################################
diff --git a/cmd/lowhashtest/lowhashtest.c b/cmd/lowhashtest/lowhashtest.c
index a711ebd4a..6a980fbbf 100644
--- a/cmd/lowhashtest/lowhashtest.c
+++ b/cmd/lowhashtest/lowhashtest.c
@@ -2,19 +2,85 @@
#include <string.h>
#include <assert.h>
-#include "nspr.h"
-
/* nss headers */
-#include "prtypes.h"
-#include "plgetopt.h"
#include "hasht.h"
#include "nsslowhash.h"
#include "secport.h"
-#include "hasht.h"
-#include "basicutil.h"
static char *progName = NULL;
+/* can't call NSPR or NSSUtil directly, so just include
+ * our own versions of SECU_ functions in basicutil.c.
+ * We need this test program to link without those functions
+ * so we can test that everyting works in a freebl only
+ * environment */
+const char *hex = "0123456789abcdef";
+
+const char printable[257] = {
+ "................" /* 0x */
+ "................" /* 1x */
+ " !\"#$%&'()*+,-./" /* 2x */
+ "0123456789:;<=>?" /* 3x */
+ "@ABCDEFGHIJKLMNO" /* 4x */
+ "PQRSTUVWXYZ[\\]^_" /* 5x */
+ "`abcdefghijklmno" /* 6x */
+ "pqrstuvwxyz{|}~." /* 7x */
+ "................" /* 8x */
+ "................" /* 9x */
+ "................" /* ax */
+ "................" /* bx */
+ "................" /* cx */
+ "................" /* dx */
+ "................" /* ex */
+ "................" /* fx */
+};
+
+static void
+SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len)
+{
+ const unsigned char *cp = (const unsigned char *)vp;
+ char buf[80];
+ char *bp;
+ char *ap;
+
+ fprintf(out, "%s [Len: %d]\n", msg, len);
+ memset(buf, ' ', sizeof buf);
+ bp = buf;
+ ap = buf + 50;
+ while (--len >= 0) {
+ unsigned char ch = *cp++;
+ *bp++ = hex[(ch >> 4) & 0xf];
+ *bp++ = hex[ch & 0xf];
+ *bp++ = ' ';
+ *ap++ = printable[ch];
+ if (ap - buf >= 66) {
+ *ap = 0;
+ fprintf(out, " %s\n", buf);
+ memset(buf, ' ', sizeof buf);
+ bp = buf;
+ ap = buf + 50;
+ }
+ }
+ if (bp > buf) {
+ *ap = 0;
+ fprintf(out, " %s\n", buf);
+ }
+}
+
+/* simple version o print error */
+static void
+SECU_PrintError(const char *prog, const char *string)
+{
+ fprintf(stderr, "%s: %s", prog, string);
+}
+
+/* simple version o print error */
+static void
+SECU_PrintError3(const char *prog, const char *string, const char *string2)
+{
+ fprintf(stderr, "%s: %s %s\n", prog, string, string2);
+}
+
static int
test_long_message(NSSLOWInitContext *initCtx,
HASH_HashType algoType, unsigned int hashLen,
@@ -28,7 +94,7 @@ test_long_message(NSSLOWInitContext *initCtx,
* buffer and call update 1,000 times.
*/
unsigned char buf[1000];
- (void)PORT_Memset(buf, 'a', sizeof(buf));
+ (void)memset(buf, 'a', sizeof(buf));
ctx = NSSLOWHASH_NewContext(initCtx, algoType);
if (ctx == NULL) {
@@ -42,8 +108,8 @@ test_long_message(NSSLOWInitContext *initCtx,
}
NSSLOWHASH_End(ctx, results, &len, hashLen);
- PR_ASSERT(len == hashLen);
- PR_ASSERT(PORT_Memcmp(expected, results, hashLen) == 0);
+ assert(len == hashLen);
+ assert(PORT_Memcmp(expected, results, hashLen) == 0);
if (PORT_Memcmp(expected, results, len) != 0) {
SECU_PrintError(progName, "Hash mismatch\n");
SECU_PrintBuf(stdout, "Expected: ", expected, hashLen);
@@ -140,8 +206,8 @@ testMessageDigest(NSSLOWInitContext *initCtx,
NSSLOWHASH_Begin(ctx);
NSSLOWHASH_Update(ctx, message, PORT_Strlen((const char *)message));
NSSLOWHASH_End(ctx, results, &len, hashLen);
- PR_ASSERT(len == hashLen);
- PR_ASSERT(PORT_Memcmp(expected, results, len) == 0);
+ assert(len == hashLen);
+ assert(PORT_Memcmp(expected, results, len) == 0);
if (PORT_Memcmp(expected, results, len) != 0) {
SECU_PrintError(progName, "Hash mismatch\n");
@@ -425,7 +491,7 @@ main(int argc, char **argv)
} else if (strcmp(argv[1], "SHA512") == 0) {
rv += testSHA512(initCtx);
} else {
- SECU_PrintError(progName, "Unsupported hash type %s\n", argv[0]);
+ SECU_PrintError3(progName, "Unsupported hash type", argv[0]);
Usage();
}
diff --git a/cmd/lowhashtest/manifest.mn b/cmd/lowhashtest/manifest.mn
index 00659ee11..8f438704c 100644
--- a/cmd/lowhashtest/manifest.mn
+++ b/cmd/lowhashtest/manifest.mn
@@ -6,7 +6,7 @@ CORE_DEPTH = ../..
MODULE = nss
-REQUIRES = seccmd dbm softoken
+REQUIRES =
INCLUDES += -I$(CORE_DEPTH)/nss/lib/freebl
@@ -16,4 +16,3 @@ CSRCS = \
lowhashtest.c \
$(NULL)
-USE_STATIC_LIBS = 1
diff --git a/cmd/shlibsign/shlibsign.c b/cmd/shlibsign/shlibsign.c
index ad8f3b84e..5745426ba 100644
--- a/cmd/shlibsign/shlibsign.c
+++ b/cmd/shlibsign/shlibsign.c
@@ -19,6 +19,9 @@
#define USES_LINKS 1
#endif
+#define COMPAT_MAJOR 0x01
+#define COMPAT_MINOR 0x02
+
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
@@ -49,22 +52,74 @@
/* freebl headers */
#include "shsign.h"
-#define NUM_ELEM(array) (sizeof(array) / sizeof(array[0]))
-CK_BBOOL true = CK_TRUE;
-CK_BBOOL false = CK_FALSE;
+/* nss headers for definition of HASH_HashType */
+#include "hasht.h"
+
+CK_BBOOL cktrue = CK_TRUE;
+CK_BBOOL ckfalse = CK_FALSE;
static PRBool verbose = PR_FALSE;
+static PRBool verify = PR_FALSE;
+static PRBool compat = PR_FALSE;
+
+typedef struct HashTableStruct {
+ char *name;
+ CK_MECHANISM_TYPE hash;
+ CK_MECHANISM_TYPE hmac;
+ CK_KEY_TYPE keyType;
+ HASH_HashType hashType;
+ CK_ULONG hashLength;
+} HashTable;
+
+#define CKR_INTERNAL_OUT_FAILURE 0x80111111
+#define CKR_INTERNAL_IN_FAILURE 0x80222222
+#define CKM_SHA1 CKM_SHA_1
+#define CKM_SHA1_HMAC CKM_SHA_1_HMAC
+#define CKK_SHA1_HMAC CKK_SHA_1_HMAC
+#define MKHASH(name, mech) \
+ { \
+ name, CKM_##mech, CKM_##mech##_HMAC, \
+ CKK_##mech##_HMAC, HASH_Alg##mech, mech##_LENGTH \
+ }
+static HashTable hashTable[] = {
+ MKHASH("sha-1", SHA1), MKHASH("sha1", SHA1), MKHASH("sha224", SHA224),
+ MKHASH("sha256", SHA256), MKHASH("sha384", SHA384),
+ MKHASH("sha512", SHA512)
+};
+static size_t hashTableSize = PR_ARRAY_SIZE(hashTable);
+
+const HashTable *
+findHash(const char *hashName)
+{
+ int i;
+
+ for (i = 0; i < hashTableSize; i++) {
+ if (PL_strcasecmp(hashTable[i].name, hashName) == 0) {
+ return &hashTable[i];
+ }
+ }
+ return NULL;
+}
static void
usage(const char *program_name)
{
+ int i;
+ const char *comma = "";
PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
PR_fprintf(debug_out,
"type %s -H for more detail information.\n", program_name);
PR_fprintf(debug_out,
"Usage: %s [-v] [-V] [-o outfile] [-d dbdir] [-f pwfile]\n"
- " [-F] [-p pwd] -[P dbprefix ] "
+ " [-F] [-p pwd] -[P dbprefix ] [-t hash]"
+ " [-D] [-k keysize] [-c]"
"-i shared_library_name\n",
program_name);
+ PR_fprintf(debug_out, "Valid Hashes: ");
+ for (i = 0; i < hashTableSize; i++) {
+ PR_fprintf(debug_out, "%s%s", comma, hashTable[i].name);
+ comma = ", ";
+ }
+ PR_fprintf(debug_out, "\n");
exit(1);
}
@@ -72,10 +127,16 @@ static void
long_usage(const char *program_name)
{
PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
+ int i;
+ const char *comma = "";
PR_fprintf(debug_out, "%s test program usage:\n", program_name);
PR_fprintf(debug_out, "\t-i <infile> shared_library_name to process\n");
PR_fprintf(debug_out, "\t-o <outfile> checksum outfile\n");
PR_fprintf(debug_out, "\t-d <path> database path location\n");
+ PR_fprintf(debug_out, "\t-t <hash> Hash for HMAC/or DSA\n");
+ PR_fprintf(debug_out, "\t-D Sign with DSA rather than HMAC\n");
+ PR_fprintf(debug_out, "\t-k <keysize> size of the DSA key\n");
+ PR_fprintf(debug_out, "\t-c Use compatible versions for old NSS\n");
PR_fprintf(debug_out, "\t-P <prefix> database prefix\n");
PR_fprintf(debug_out, "\t-f <file> password File : echo pw > file \n");
PR_fprintf(debug_out, "\t-F FIPS mode\n");
@@ -90,6 +151,12 @@ long_usage(const char *program_name)
PR_fprintf(debug_out, "\t pre-existing libraries with generated ");
PR_fprintf(debug_out, "checksum files\n");
PR_fprintf(debug_out, "\t and database in FIPS mode \n");
+ PR_fprintf(debug_out, "Valid Hashes: ");
+ for (i = 0; i < hashTableSize; i++) {
+ PR_fprintf(debug_out, "%s%s", comma, hashTable[i].name);
+ comma = ", ";
+ }
+ PR_fprintf(debug_out, "\n");
exit(1);
}
@@ -131,8 +198,7 @@ encodeInt(unsigned char *buf, int val)
}
static PRStatus
-writeItem(PRFileDesc *fd, CK_VOID_PTR pValue,
- CK_ULONG ulValueLen, char *file)
+writeItem(PRFileDesc *fd, CK_VOID_PTR pValue, CK_ULONG ulValueLen)
{
unsigned char buf[4];
int bytesWritten;
@@ -144,12 +210,10 @@ writeItem(PRFileDesc *fd, CK_VOID_PTR pValue,
encodeInt(buf, ulValueLen);
bytesWritten = PR_Write(fd, buf, 4);
if (bytesWritten != 4) {
- lperror(file);
return PR_FAILURE;
}
bytesWritten = PR_Write(fd, pValue, ulValueLen);
if (bytesWritten < 0 || (CK_ULONG)bytesWritten != ulValueLen) {
- lperror(file);
return PR_FAILURE;
}
return PR_SUCCESS;
@@ -701,6 +765,481 @@ getSlotList(CK_FUNCTION_LIST_PTR pFunctionList,
return pSlotList;
}
+CK_RV
+shlibSignDSA(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID slot,
+ CK_SESSION_HANDLE hRwSession, int keySize, PRFileDesc *ifd,
+ PRFileDesc *ofd, const HashTable *hash)
+{
+ CK_MECHANISM digestmech;
+ CK_ULONG digestLen = 0;
+ CK_BYTE digest[HASH_LENGTH_MAX];
+ CK_BYTE sign[64]; /* DSA2 SIGNATURE LENGTH */
+ CK_ULONG signLen = 0;
+ CK_ULONG expectedSigLen = sizeof(sign);
+ CK_MECHANISM signMech = {
+ CKM_DSA, NULL, 0
+ };
+ int bytesRead;
+ int bytesWritten;
+ unsigned char file_buf[512];
+ NSSSignChkHeader header;
+ int count = 0;
+ CK_RV crv = CKR_GENERAL_ERROR;
+ PRStatus rv = PR_SUCCESS;
+ const char *hashName = "sha256"; /* default hash value */
+ int i;
+
+ /*** DSA Key ***/
+ CK_MECHANISM dsaKeyPairGenMech;
+ CK_ATTRIBUTE dsaPubKeyTemplate[5];
+ CK_ATTRIBUTE dsaPrivKeyTemplate[5];
+ CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE;
+ CK_BYTE dsaPubKey[384];
+ CK_ATTRIBUTE dsaPubKeyValue;
+
+ if ((keySize == 0) || (keySize > 1024)) {
+ CK_MECHANISM_INFO mechInfo;
+ crv = pFunctionList->C_GetMechanismInfo(slot,
+ CKM_DSA, &mechInfo);
+ if (crv != CKR_OK) {
+ pk11error("Couldn't get mechanism info for DSA", crv);
+ return crv;
+ }
+
+ if (keySize && (mechInfo.ulMaxKeySize < keySize)) {
+ PR_fprintf(PR_STDERR,
+ "token doesn't support DSA2 (Max key size=%d)\n",
+ mechInfo.ulMaxKeySize);
+ return crv;
+ }
+
+ if ((keySize == 0) && mechInfo.ulMaxKeySize >= 2048) {
+ keySize = 2048;
+ } else {
+ keySize = 1024;
+ }
+ }
+
+ /* DSA key init */
+ if (keySize == 1024) {
+ dsaPubKeyTemplate[0].type = CKA_PRIME;
+ dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR)&prime;
+ dsaPubKeyTemplate[0].ulValueLen = sizeof(prime);
+ dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
+ dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR)&subprime;
+ dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime);
+ dsaPubKeyTemplate[2].type = CKA_BASE;
+ dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR)&base;
+ dsaPubKeyTemplate[2].ulValueLen = sizeof(base);
+ hashName = "sha-1"; /* use sha-1 for old dsa keys */
+ expectedSigLen = 32;
+ } else if (keySize == 2048) {
+ dsaPubKeyTemplate[0].type = CKA_PRIME;
+ dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR)&prime2;
+ dsaPubKeyTemplate[0].ulValueLen = sizeof(prime2);
+ dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
+ dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR)&subprime2;
+ dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime2);
+ dsaPubKeyTemplate[2].type = CKA_BASE;
+ dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR)&base2;
+ dsaPubKeyTemplate[2].ulValueLen = sizeof(base2);
+ digestmech.mechanism = hash ? hash->hash : CKM_SHA256;
+ digestmech.pParameter = NULL;
+ digestmech.ulParameterLen = 0;
+ } else {
+ PR_fprintf(PR_STDERR, "Only keysizes 1024 and 2048 are supported");
+ return CKR_GENERAL_ERROR;
+ }
+ if (hash == NULL) {
+ hash = findHash(hashName);
+ }
+ if (hash == NULL) {
+ PR_fprintf(PR_STDERR,
+ "Internal error, couldn't find hash '%s' in table.\n",
+ hashName);
+ return CKR_GENERAL_ERROR;
+ }
+ digestmech.mechanism = hash->hash;
+ digestmech.pParameter = NULL;
+ digestmech.ulParameterLen = 0;
+ dsaPubKeyTemplate[3].type = CKA_TOKEN;
+ dsaPubKeyTemplate[3].pValue = &ckfalse; /* session object */
+ dsaPubKeyTemplate[3].ulValueLen = sizeof(ckfalse);
+ dsaPubKeyTemplate[4].type = CKA_VERIFY;
+ dsaPubKeyTemplate[4].pValue = &cktrue;
+ dsaPubKeyTemplate[4].ulValueLen = sizeof(cktrue);
+ dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN;
+ dsaKeyPairGenMech.pParameter = NULL;
+ dsaKeyPairGenMech.ulParameterLen = 0;
+ dsaPrivKeyTemplate[0].type = CKA_TOKEN;
+ dsaPrivKeyTemplate[0].pValue = &ckfalse; /* session object */
+ dsaPrivKeyTemplate[0].ulValueLen = sizeof(ckfalse);
+ dsaPrivKeyTemplate[1].type = CKA_PRIVATE;
+ dsaPrivKeyTemplate[1].pValue = &cktrue;
+ dsaPrivKeyTemplate[1].ulValueLen = sizeof(cktrue);
+ dsaPrivKeyTemplate[2].type = CKA_SENSITIVE;
+ dsaPrivKeyTemplate[2].pValue = &cktrue;
+ dsaPrivKeyTemplate[2].ulValueLen = sizeof(cktrue);
+ dsaPrivKeyTemplate[3].type = CKA_SIGN,
+ dsaPrivKeyTemplate[3].pValue = &cktrue;
+ dsaPrivKeyTemplate[3].ulValueLen = sizeof(cktrue);
+ dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE;
+ dsaPrivKeyTemplate[4].pValue = &ckfalse;
+ dsaPrivKeyTemplate[4].ulValueLen = sizeof(ckfalse);
+
+ /* Generate a DSA key pair */
+ logIt("Generate a DSA key pair ... \n");
+ crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech,
+ dsaPubKeyTemplate,
+ PR_ARRAY_SIZE(dsaPubKeyTemplate),
+ dsaPrivKeyTemplate,
+ PR_ARRAY_SIZE(dsaPrivKeyTemplate),
+ &hDSApubKey, &hDSAprivKey);
+ if (crv != CKR_OK) {
+ pk11error("DSA key pair generation failed", crv);
+ return crv;
+ }
+
+ /* compute the digest */
+ memset(digest, 0, sizeof(digest));
+ crv = pFunctionList->C_DigestInit(hRwSession, &digestmech);
+ if (crv != CKR_OK) {
+ pk11error("C_DigestInit failed", crv);
+ return crv;
+ }
+
+ /* Digest the file */
+ while ((bytesRead = PR_Read(ifd, file_buf, sizeof(file_buf))) > 0) {
+ crv = pFunctionList->C_DigestUpdate(hRwSession, (CK_BYTE_PTR)file_buf,
+ bytesRead);
+ if (crv != CKR_OK) {
+ pk11error("C_DigestUpdate failed", crv);
+ return crv;
+ }
+ count += bytesRead;
+ }
+
+ if (bytesRead < 0) {
+ lperror("0 bytes read from input file");
+ return CKR_INTERNAL_IN_FAILURE;
+ }
+
+ digestLen = sizeof(digest);
+ crv = pFunctionList->C_DigestFinal(hRwSession, (CK_BYTE_PTR)digest,
+ &digestLen);
+ if (crv != CKR_OK) {
+ pk11error("C_DigestFinal failed", crv);
+ return crv;
+ }
+
+ if (digestLen != hash->hashLength) {
+ PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu "
+ "it should be %lu \n",
+ digestLen, sizeof(digest));
+ return crv;
+ }
+
+ /* sign the hash */
+ memset(sign, 0, sizeof(sign));
+ /* SignUpdate */
+ crv = pFunctionList->C_SignInit(hRwSession, &signMech, hDSAprivKey);
+ if (crv != CKR_OK) {
+ pk11error("C_SignInit failed", crv);
+ return crv;
+ }
+
+ signLen = sizeof(sign);
+ crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE *)digest, digestLen,
+ sign, &signLen);
+ if (crv != CKR_OK) {
+ pk11error("C_Sign failed", crv);
+ return crv;
+ }
+
+ if (signLen != expectedSigLen) {
+ PR_fprintf(PR_STDERR, "signLen has incorrect length %lu "
+ "it should be %lu \n",
+ signLen, expectedSigLen);
+ return crv;
+ }
+
+ if (verify) {
+ crv = pFunctionList->C_VerifyInit(hRwSession, &signMech, hDSApubKey);
+ if (crv != CKR_OK) {
+ pk11error("C_VerifyInit failed", crv);
+ return crv;
+ }
+ crv = pFunctionList->C_Verify(hRwSession, digest, digestLen,
+ sign, signLen);
+ if (crv != CKR_OK) {
+ pk11error("C_Verify failed", crv);
+ return crv;
+ }
+ }
+
+ if (verbose) {
+ int j;
+ PR_fprintf(PR_STDERR, "Library File Size: %d bytes\n", count);
+ PR_fprintf(PR_STDERR, " hash: %lu bytes\n", digestLen);
+#define STEP 10
+ for (i = 0; i < (int)digestLen; i += STEP) {
+ PR_fprintf(PR_STDERR, " ");
+ for (j = 0; j < STEP && (i + j) < (int)digestLen; j++) {
+ PR_fprintf(PR_STDERR, " %02x", digest[i + j]);
+ }
+ PR_fprintf(PR_STDERR, "\n");
+ }
+ PR_fprintf(PR_STDERR, " signature: %lu bytes\n", signLen);
+ for (i = 0; i < (int)signLen; i += STEP) {
+ PR_fprintf(PR_STDERR, " ");
+ for (j = 0; j < STEP && (i + j) < (int)signLen; j++) {
+ PR_fprintf(PR_STDERR, " %02x", sign[i + j]);
+ }
+ PR_fprintf(PR_STDERR, "\n");
+ }
+ }
+
+ /*
+ * we write the key out in a straight binary format because very
+ * low level libraries need to read an parse this file. Ideally we should
+ * just derEncode the public key (which would be pretty simple, and be
+ * more general), but then we'd need to link the ASN.1 decoder with the
+ * freebl libraries.
+ */
+
+ header.magic1 = NSS_SIGN_CHK_MAGIC1;
+ header.magic2 = NSS_SIGN_CHK_MAGIC2;
+ header.majorVersion = compat ? COMPAT_MAJOR : NSS_SIGN_CHK_MAJOR_VERSION;
+ header.minorVersion = compat ? COMPAT_MINOR : NSS_SIGN_CHK_MINOR_VERSION;
+ encodeInt(header.offset, sizeof(header)); /* offset to data start */
+ encodeInt(header.type, CKK_DSA);
+ bytesWritten = PR_Write(ofd, &header, sizeof(header));
+ if (bytesWritten != sizeof(header)) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+
+ /* get DSA Public KeyValue */
+ memset(dsaPubKey, 0, sizeof(dsaPubKey));
+ dsaPubKeyValue.type = CKA_VALUE;
+ dsaPubKeyValue.pValue = (CK_VOID_PTR)&dsaPubKey;
+ dsaPubKeyValue.ulValueLen = sizeof(dsaPubKey);
+
+ crv = pFunctionList->C_GetAttributeValue(hRwSession, hDSApubKey,
+ &dsaPubKeyValue, 1);
+ if (crv != CKR_OK && crv != CKR_ATTRIBUTE_TYPE_INVALID) {
+ pk11error("C_GetAttributeValue failed", crv);
+ return crv;
+ }
+
+ /* CKA_PRIME */
+ rv = writeItem(ofd, dsaPubKeyTemplate[0].pValue,
+ dsaPubKeyTemplate[0].ulValueLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+ /* CKA_SUBPRIME */
+ rv = writeItem(ofd, dsaPubKeyTemplate[1].pValue,
+ dsaPubKeyTemplate[1].ulValueLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+ /* CKA_BASE */
+ rv = writeItem(ofd, dsaPubKeyTemplate[2].pValue,
+ dsaPubKeyTemplate[2].ulValueLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+ /* DSA Public Key value */
+ rv = writeItem(ofd, dsaPubKeyValue.pValue,
+ dsaPubKeyValue.ulValueLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+ /* DSA SIGNATURE */
+ rv = writeItem(ofd, &sign, signLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+
+ return CKR_OK;
+}
+
+CK_RV
+shlibSignHMAC(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID slot,
+ CK_SESSION_HANDLE hRwSession, int keySize, PRFileDesc *ifd,
+ PRFileDesc *ofd, const HashTable *hash)
+{
+ CK_MECHANISM hmacMech = { 0, NULL, 0 };
+ CK_MECHANISM hmacKeyGenMech = { 0, NULL, 0 };
+ CK_BYTE keyBuf[HASH_LENGTH_MAX];
+ CK_ULONG keyLen = 0;
+ CK_BYTE sign[HASH_LENGTH_MAX];
+ CK_ULONG signLen = 0;
+ int bytesRead;
+ int bytesWritten;
+ unsigned char file_buf[512];
+ NSSSignChkHeader header;
+ int count = 0;
+ CK_RV crv = CKR_GENERAL_ERROR;
+ PRStatus rv = PR_SUCCESS;
+ int i;
+
+ /*** HMAC Key ***/
+ CK_ATTRIBUTE hmacKeyTemplate[7];
+ CK_ATTRIBUTE hmacKeyValue;
+ CK_OBJECT_HANDLE hHMACKey = CK_INVALID_HANDLE;
+
+ if (hash == NULL) {
+ hash = findHash("sha256");
+ }
+ if (hash == NULL) {
+ PR_fprintf(PR_STDERR,
+ "Internal error:Could find sha256 entry in table.\n");
+ }
+
+ hmacKeyTemplate[0].type = CKA_TOKEN;
+ hmacKeyTemplate[0].pValue = &ckfalse; /* session object */
+ hmacKeyTemplate[0].ulValueLen = sizeof(ckfalse);
+ hmacKeyTemplate[1].type = CKA_PRIVATE;
+ hmacKeyTemplate[1].pValue = &cktrue;
+ hmacKeyTemplate[1].ulValueLen = sizeof(cktrue);
+ hmacKeyTemplate[2].type = CKA_SENSITIVE;
+ hmacKeyTemplate[2].pValue = &ckfalse;
+ hmacKeyTemplate[2].ulValueLen = sizeof(cktrue);
+ hmacKeyTemplate[3].type = CKA_SIGN;
+ hmacKeyTemplate[3].pValue = &cktrue;
+ hmacKeyTemplate[3].ulValueLen = sizeof(cktrue);
+ hmacKeyTemplate[4].type = CKA_EXTRACTABLE;
+ hmacKeyTemplate[4].pValue = &ckfalse;
+ hmacKeyTemplate[4].ulValueLen = sizeof(ckfalse);
+ hmacKeyTemplate[5].type = CKA_VALUE_LEN;
+ hmacKeyTemplate[5].pValue = (void *)&hash->hashLength;
+ hmacKeyTemplate[5].ulValueLen = sizeof(hash->hashLength);
+ hmacKeyTemplate[6].type = CKA_KEY_TYPE;
+ hmacKeyTemplate[6].pValue = (void *)&hash->keyType;
+ hmacKeyTemplate[6].ulValueLen = sizeof(hash->keyType);
+ hmacKeyGenMech.mechanism = CKM_GENERIC_SECRET_KEY_GEN;
+ hmacMech.mechanism = hash->hmac;
+
+ /* Generate a DSA key pair */
+ logIt("Generate an HMAC key ... \n");
+ crv = pFunctionList->C_GenerateKey(hRwSession, &hmacKeyGenMech,
+ hmacKeyTemplate,
+ PR_ARRAY_SIZE(hmacKeyTemplate),
+ &hHMACKey);
+ if (crv != CKR_OK) {
+ pk11error("HMAC key generation failed", crv);
+ return crv;
+ }
+
+ /* compute the digest */
+ memset(sign, 0, sizeof(sign));
+ crv = pFunctionList->C_SignInit(hRwSession, &hmacMech, hHMACKey);
+ if (crv != CKR_OK) {
+ pk11error("C_SignInit failed", crv);
+ return crv;
+ }
+
+ /* Digest the file */
+ while ((bytesRead = PR_Read(ifd, file_buf, sizeof(file_buf))) > 0) {
+ crv = pFunctionList->C_SignUpdate(hRwSession, (CK_BYTE_PTR)file_buf,
+ bytesRead);
+ if (crv != CKR_OK) {
+ pk11error("C_SignUpdate failed", crv);
+ return crv;
+ }
+ count += bytesRead;
+ }
+
+ if (bytesRead < 0) {
+ lperror("0 bytes read from input file");
+ return CKR_INTERNAL_IN_FAILURE;
+ }
+
+ signLen = sizeof(sign);
+ crv = pFunctionList->C_SignFinal(hRwSession, (CK_BYTE_PTR)sign,
+ &signLen);
+ if (crv != CKR_OK) {
+ pk11error("C_SignFinal failed", crv);
+ return crv;
+ }
+
+ if (signLen != hash->hashLength) {
+ PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu "
+ "it should be %lu \n",
+ signLen, hash->hashLength);
+ return crv;
+ }
+ /* get HMAC KeyValue */
+ memset(keyBuf, 0, sizeof(keyBuf));
+ hmacKeyValue.type = CKA_VALUE;
+ hmacKeyValue.pValue = (CK_VOID_PTR)&keyBuf;
+ hmacKeyValue.ulValueLen = sizeof(keyBuf);
+
+ crv = pFunctionList->C_GetAttributeValue(hRwSession, hHMACKey,
+ &hmacKeyValue, 1);
+ if (crv != CKR_OK && crv != CKR_ATTRIBUTE_TYPE_INVALID) {
+ pk11error("C_GetAttributeValue failed", crv);
+ return crv;
+ }
+ keyLen = hmacKeyValue.ulValueLen;
+
+ if (verbose) {
+ int j;
+ PR_fprintf(PR_STDERR, "Library File Size: %d bytes\n", count);
+ PR_fprintf(PR_STDERR, " key: %lu bytes\n", keyLen);
+#define STEP 10
+ for (i = 0; i < (int)keyLen; i += STEP) {
+ PR_fprintf(PR_STDERR, " ");
+ for (j = 0; j < STEP && (i + j) < (int)keyLen; j++) {
+ PR_fprintf(PR_STDERR, " %02x", keyBuf[i + j]);
+ }
+ PR_fprintf(PR_STDERR, "\n");
+ }
+ PR_fprintf(PR_STDERR, " signature: %lu bytes\n", signLen);
+ for (i = 0; i < (int)signLen; i += STEP) {
+ PR_fprintf(PR_STDERR, " ");
+ for (j = 0; j < STEP && (i + j) < (int)signLen; j++) {
+ PR_fprintf(PR_STDERR, " %02x", sign[i + j]);
+ }
+ PR_fprintf(PR_STDERR, "\n");
+ }
+ }
+
+ /*
+ * we write the key out in a straight binary format because very
+ * low level libraries need to read an parse this file. Ideally we should
+ * just derEncode the public key (which would be pretty simple, and be
+ * more general), but then we'd need to link the ASN.1 decoder with the
+ * freebl libraries.
+ */
+
+ header.magic1 = NSS_SIGN_CHK_MAGIC1;
+ header.magic2 = NSS_SIGN_CHK_MAGIC2;
+ header.majorVersion = NSS_SIGN_CHK_MAJOR_VERSION;
+ header.minorVersion = NSS_SIGN_CHK_MINOR_VERSION;
+ encodeInt(header.offset, sizeof(header)); /* offset to data start */
+ encodeInt(header.type, NSS_SIGN_CHK_FLAG_HMAC | hash->hashType);
+ bytesWritten = PR_Write(ofd, &header, sizeof(header));
+ if (bytesWritten != sizeof(header)) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+
+ /* HMACKey */
+ rv = writeItem(ofd, keyBuf, keyLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+ /* HMAC SIGNATURE */
+ rv = writeItem(ofd, &sign, signLen);
+ if (rv != PR_SUCCESS) {
+ return CKR_INTERNAL_OUT_FAILURE;
+ }
+
+ return CKR_OK;
+}
+
int
main(int argc, char **argv)
{
@@ -708,19 +1247,15 @@ main(int argc, char **argv)
char *program_name;
char *libname = NULL;
PRLibrary *lib = NULL;
- PRFileDesc *fd;
- PRStatus rv = PR_SUCCESS;
+ PRFileDesc *ifd = NULL;
+ PRFileDesc *ofd = NULL;
const char *input_file = NULL; /* read/create encrypted data from here */
char *output_file = NULL; /* write new encrypted data here */
- int bytesRead;
- int bytesWritten;
- unsigned char file_buf[512];
- int count = 0;
unsigned int keySize = 0;
- int i;
- PRBool verify = PR_FALSE;
static PRBool FIPSMODE = PR_FALSE;
+ static PRBool useDSA = PR_FALSE;
PRBool successful = PR_FALSE;
+ const HashTable *hash = NULL;
#ifdef USES_LINKS
int ret;
@@ -741,29 +1276,10 @@ main(int argc, char **argv)
CK_SESSION_HANDLE hRwSession;
CK_SLOT_ID *pSlotList = NULL;
CK_ULONG slotIndex = 0;
- CK_MECHANISM digestmech;
- CK_ULONG digestLen = 0;
- CK_BYTE digest[32]; /* SHA256_LENGTH */
- CK_BYTE sign[64]; /* DSA SIGNATURE LENGTH */
- CK_ULONG signLen = 0;
- CK_MECHANISM signMech = {
- CKM_DSA, NULL, 0
- };
-
- /*** DSA Key ***/
-
- CK_MECHANISM dsaKeyPairGenMech;
- CK_ATTRIBUTE dsaPubKeyTemplate[5];
- CK_ATTRIBUTE dsaPrivKeyTemplate[5];
- CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE;
- CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE;
-
- CK_BYTE dsaPubKey[384];
- CK_ATTRIBUTE dsaPubKeyValue;
program_name = strrchr(argv[0], '/');
program_name = program_name ? (program_name + 1) : argv[0];
- optstate = PL_CreateOptState(argc, argv, "i:o:f:Fd:hH?k:p:P:vVs:");
+ optstate = PL_CreateOptState(argc, argv, "i:o:f:Fd:hH?k:p:P:vVs:t:Dc");
if (optstate == NULL) {
lperror("PL_CreateOptState failed");
return 1;
@@ -781,6 +1297,14 @@ main(int argc, char **argv)
checkPath(configDir);
break;
+ case 'D':
+ useDSA = PR_TRUE;
+ break;
+
+ case 'c':
+ compat = PR_TRUE;
+ break;
+
case 'i':
if (!optstate->value) {
PL_DestroyOptState(optstate);
@@ -835,6 +1359,18 @@ main(int argc, char **argv)
dbPrefix = PL_strdup(optstate->value);
break;
+ case 't':
+ if (!optstate->value) {
+ PL_DestroyOptState(optstate);
+ usage(program_name);
+ }
+ hash = findHash(optstate->value);
+ if (hash == NULL) {
+ PR_fprintf(PR_STDERR, "Invalid hash '%s'\n",
+ optstate->value);
+ usage(program_name);
+ }
+ break;
case 'v':
verbose = PR_TRUE;
break;
@@ -930,86 +1466,6 @@ main(int argc, char **argv)
goto cleanup;
}
- if ((keySize == 0) || (keySize > 1024)) {
- CK_MECHANISM_INFO mechInfo;
- crv = pFunctionList->C_GetMechanismInfo(pSlotList[slotIndex],
- CKM_DSA, &mechInfo);
- if (crv != CKR_OK) {
- pk11error("Couldn't get mechanism info for DSA", crv);
- goto cleanup;
- }
-
- if (keySize && (mechInfo.ulMaxKeySize < keySize)) {
- PR_fprintf(PR_STDERR,
- "token doesn't support DSA2 (Max key size=%d)\n",
- mechInfo.ulMaxKeySize);
- goto cleanup;
- }
-
- if ((keySize == 0) && mechInfo.ulMaxKeySize >= 2048) {
- keySize = 2048;
- } else {
- keySize = 1024;
- }
- }
-
- /* DSA key init */
- if (keySize == 1024) {
- dsaPubKeyTemplate[0].type = CKA_PRIME;
- dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR)&prime;
- dsaPubKeyTemplate[0].ulValueLen = sizeof(prime);
- dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
- dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR)&subprime;
- dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime);
- dsaPubKeyTemplate[2].type = CKA_BASE;
- dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR)&base;
- dsaPubKeyTemplate[2].ulValueLen = sizeof(base);
- digestmech.mechanism = CKM_SHA_1;
- digestmech.pParameter = NULL;
- digestmech.ulParameterLen = 0;
- } else if (keySize == 2048) {
- dsaPubKeyTemplate[0].type = CKA_PRIME;
- dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR)&prime2;
- dsaPubKeyTemplate[0].ulValueLen = sizeof(prime2);
- dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
- dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR)&subprime2;
- dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime2);
- dsaPubKeyTemplate[2].type = CKA_BASE;
- dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR)&base2;
- dsaPubKeyTemplate[2].ulValueLen = sizeof(base2);
- digestmech.mechanism = CKM_SHA256;
- digestmech.pParameter = NULL;
- digestmech.ulParameterLen = 0;
- } else {
- /* future - generate pqg */
- PR_fprintf(PR_STDERR, "Only keysizes 1024 and 2048 are supported");
- goto cleanup;
- }
- dsaPubKeyTemplate[3].type = CKA_TOKEN;
- dsaPubKeyTemplate[3].pValue = &false; /* session object */
- dsaPubKeyTemplate[3].ulValueLen = sizeof(false);
- dsaPubKeyTemplate[4].type = CKA_VERIFY;
- dsaPubKeyTemplate[4].pValue = &true;
- dsaPubKeyTemplate[4].ulValueLen = sizeof(true);
- dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN;
- dsaKeyPairGenMech.pParameter = NULL;
- dsaKeyPairGenMech.ulParameterLen = 0;
- dsaPrivKeyTemplate[0].type = CKA_TOKEN;
- dsaPrivKeyTemplate[0].pValue = &false; /* session object */
- dsaPrivKeyTemplate[0].ulValueLen = sizeof(false);
- dsaPrivKeyTemplate[1].type = CKA_PRIVATE;
- dsaPrivKeyTemplate[1].pValue = &true;
- dsaPrivKeyTemplate[1].ulValueLen = sizeof(true);
- dsaPrivKeyTemplate[2].type = CKA_SENSITIVE;
- dsaPrivKeyTemplate[2].pValue = &true;
- dsaPrivKeyTemplate[2].ulValueLen = sizeof(true);
- dsaPrivKeyTemplate[3].type = CKA_SIGN,
- dsaPrivKeyTemplate[3].pValue = &true;
- dsaPrivKeyTemplate[3].ulValueLen = sizeof(true);
- dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE;
- dsaPrivKeyTemplate[4].pValue = &false;
- dsaPrivKeyTemplate[4].ulValueLen = sizeof(false);
-
crv = pFunctionList->C_OpenSession(pSlotList[slotIndex],
CKF_RW_SESSION | CKF_SERIAL_SESSION,
NULL, NULL, &hRwSession);
@@ -1041,22 +1497,9 @@ main(int argc, char **argv)
logIt("A password was provided but the password was not used.\n");
}
- /* Generate a DSA key pair */
- logIt("Generate a DSA key pair ... \n");
- crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech,
- dsaPubKeyTemplate,
- NUM_ELEM(dsaPubKeyTemplate),
- dsaPrivKeyTemplate,
- NUM_ELEM(dsaPrivKeyTemplate),
- &hDSApubKey, &hDSAprivKey);
- if (crv != CKR_OK) {
- pk11error("DSA key pair generation failed", crv);
- goto cleanup;
- }
-
/* open the shared library */
- fd = PR_OpenFile(input_file, PR_RDONLY, 0);
- if (fd == NULL) {
+ ifd = PR_OpenFile(input_file, PR_RDONLY, 0);
+ if (ifd == NULL) {
lperror(input_file);
goto cleanup;
}
@@ -1102,179 +1545,42 @@ main(int argc, char **argv)
output_file = mkoutput(input_file);
}
- /* compute the digest */
- memset(digest, 0, sizeof(digest));
- crv = pFunctionList->C_DigestInit(hRwSession, &digestmech);
- if (crv != CKR_OK) {
- pk11error("C_DigestInit failed", crv);
- goto cleanup;
- }
-
- /* Digest the file */
- while ((bytesRead = PR_Read(fd, file_buf, sizeof(file_buf))) > 0) {
- crv = pFunctionList->C_DigestUpdate(hRwSession, (CK_BYTE_PTR)file_buf,
- bytesRead);
- if (crv != CKR_OK) {
- pk11error("C_DigestUpdate failed", crv);
- goto cleanup;
- }
- count += bytesRead;
- }
-
- /* close the input_File */
- PR_Close(fd);
- fd = NULL;
- if (bytesRead < 0) {
- lperror("0 bytes read from input file");
- goto cleanup;
- }
-
- digestLen = sizeof(digest);
- crv = pFunctionList->C_DigestFinal(hRwSession, (CK_BYTE_PTR)digest,
- &digestLen);
- if (crv != CKR_OK) {
- pk11error("C_DigestFinal failed", crv);
- goto cleanup;
- }
-
- if (digestLen != sizeof(digest)) {
- PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu "
- "it should be %lu \n",
- digestLen, sizeof(digest));
- goto cleanup;
- }
-
- /* sign the hash */
- memset(sign, 0, sizeof(sign));
- /* SignUpdate */
- crv = pFunctionList->C_SignInit(hRwSession, &signMech, hDSAprivKey);
- if (crv != CKR_OK) {
- pk11error("C_SignInit failed", crv);
- goto cleanup;
- }
-
- signLen = sizeof(sign);
- crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE *)digest, digestLen,
- sign, &signLen);
- if (crv != CKR_OK) {
- pk11error("C_Sign failed", crv);
- goto cleanup;
- }
-
- if (signLen != sizeof(sign)) {
- PR_fprintf(PR_STDERR, "signLen has incorrect length %lu "
- "it should be %lu \n",
- signLen, sizeof(sign));
- goto cleanup;
- }
-
- if (verify) {
- crv = pFunctionList->C_VerifyInit(hRwSession, &signMech, hDSApubKey);
- if (crv != CKR_OK) {
- pk11error("C_VerifyInit failed", crv);
- goto cleanup;
- }
- crv = pFunctionList->C_Verify(hRwSession, digest, digestLen,
- sign, signLen);
- if (crv != CKR_OK) {
- pk11error("C_Verify failed", crv);
- goto cleanup;
- }
- }
-
if (verbose) {
- int j;
- PR_fprintf(PR_STDERR, "Library File: %s %d bytes\n", input_file, count);
+ PR_fprintf(PR_STDERR, "Library File: %s\n", input_file);
PR_fprintf(PR_STDERR, "Check File: %s\n", output_file);
#ifdef USES_LINKS
if (link_file) {
PR_fprintf(PR_STDERR, "Link: %s\n", link_file);
}
#endif
- PR_fprintf(PR_STDERR, " hash: %lu bytes\n", digestLen);
-#define STEP 10
- for (i = 0; i < (int)digestLen; i += STEP) {
- PR_fprintf(PR_STDERR, " ");
- for (j = 0; j < STEP && (i + j) < (int)digestLen; j++) {
- PR_fprintf(PR_STDERR, " %02x", digest[i + j]);
- }
- PR_fprintf(PR_STDERR, "\n");
- }
- PR_fprintf(PR_STDERR, " signature: %lu bytes\n", signLen);
- for (i = 0; i < (int)signLen; i += STEP) {
- PR_fprintf(PR_STDERR, " ");
- for (j = 0; j < STEP && (i + j) < (int)signLen; j++) {
- PR_fprintf(PR_STDERR, " %02x", sign[i + j]);
- }
- PR_fprintf(PR_STDERR, "\n");
- }
}
/* open the target signature file */
- fd = PR_Open(output_file, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0666);
- if (fd == NULL) {
+ ofd = PR_Open(output_file, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0666);
+ if (ofd == NULL) {
lperror(output_file);
goto cleanup;
}
- /*
- * we write the key out in a straight binary format because very
- * low level libraries need to read an parse this file. Ideally we should
- * just derEncode the public key (which would be pretty simple, and be
- * more general), but then we'd need to link the ASN.1 decoder with the
- * freebl libraries.
- */
-
- file_buf[0] = NSS_SIGN_CHK_MAGIC1;
- file_buf[1] = NSS_SIGN_CHK_MAGIC2;
- file_buf[2] = NSS_SIGN_CHK_MAJOR_VERSION;
- file_buf[3] = NSS_SIGN_CHK_MINOR_VERSION;
- encodeInt(&file_buf[4], 12); /* offset to data start */
- encodeInt(&file_buf[8], CKK_DSA);
- bytesWritten = PR_Write(fd, file_buf, 12);
- if (bytesWritten != 12) {
+ if (useDSA) {
+ crv = shlibSignDSA(pFunctionList, pSlotList[slotIndex], hRwSession,
+ keySize, ifd, ofd, hash);
+ } else {
+ crv = shlibSignHMAC(pFunctionList, pSlotList[slotIndex], hRwSession,
+ keySize, ifd, ofd, hash);
+ }
+ if (crv == CKR_INTERNAL_OUT_FAILURE) {
lperror(output_file);
- goto cleanup;
}
-
- /* get DSA Public KeyValue */
- memset(dsaPubKey, 0, sizeof(dsaPubKey));
- dsaPubKeyValue.type = CKA_VALUE;
- dsaPubKeyValue.pValue = (CK_VOID_PTR)&dsaPubKey;
- dsaPubKeyValue.ulValueLen = sizeof(dsaPubKey);
-
- crv = pFunctionList->C_GetAttributeValue(hRwSession, hDSApubKey,
- &dsaPubKeyValue, 1);
- if (crv != CKR_OK && crv != CKR_ATTRIBUTE_TYPE_INVALID) {
- pk11error("C_GetAttributeValue failed", crv);
- goto cleanup;
+ if (crv == CKR_INTERNAL_IN_FAILURE) {
+ lperror(input_file);
}
- /* CKA_PRIME */
- rv = writeItem(fd, dsaPubKeyTemplate[0].pValue,
- dsaPubKeyTemplate[0].ulValueLen, output_file);
- if (rv != PR_SUCCESS)
- goto cleanup;
- /* CKA_SUBPRIME */
- rv = writeItem(fd, dsaPubKeyTemplate[1].pValue,
- dsaPubKeyTemplate[1].ulValueLen, output_file);
- if (rv != PR_SUCCESS)
- goto cleanup;
- /* CKA_BASE */
- rv = writeItem(fd, dsaPubKeyTemplate[2].pValue,
- dsaPubKeyTemplate[2].ulValueLen, output_file);
- if (rv != PR_SUCCESS)
- goto cleanup;
- /* DSA Public Key value */
- rv = writeItem(fd, dsaPubKeyValue.pValue,
- dsaPubKeyValue.ulValueLen, output_file);
- if (rv != PR_SUCCESS)
- goto cleanup;
- /* DSA SIGNATURE */
- rv = writeItem(fd, &sign, signLen, output_file);
- if (rv != PR_SUCCESS)
- goto cleanup;
- PR_Close(fd);
+ PR_Close(ofd);
+ ofd = NULL;
+ /* close the input_File */
+ PR_Close(ifd);
+ ifd = NULL;
#ifdef USES_LINKS
if (link_file) {
@@ -1286,7 +1592,6 @@ main(int argc, char **argv)
}
}
#endif
-
successful = PR_TRUE;
cleanup:
@@ -1318,6 +1623,12 @@ cleanup:
PL_strfree(link_file);
}
#endif
+ if (ifd) {
+ PR_Close(ifd);
+ }
+ if (ofd) {
+ PR_Close(ofd);
+ }
disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
if (!disableUnload && lib) {
diff --git a/lib/freebl/Makefile b/lib/freebl/Makefile
index 228549ede..a15db872f 100644
--- a/lib/freebl/Makefile
+++ b/lib/freebl/Makefile
@@ -101,6 +101,9 @@ endif
ifdef NSS_NO_INIT_SUPPORT
DEFINES += -DNSS_NO_INIT_SUPPORT
endif
+ifdef NSS_STRICT_INTEGRITY
+ DEFINES += -DNSS_STRICT_INTEGRITY_
+endif
ifdef FREEBL_PRELINK_COMMAND
DEFINES +=-DFREEBL_PRELINK_COMMAND=\"$(FREEBL_PRELINK_COMMAND)\"
diff --git a/lib/freebl/nsslowhash.c b/lib/freebl/nsslowhash.c
index 22f97810f..e950e0865 100644
--- a/lib/freebl/nsslowhash.c
+++ b/lib/freebl/nsslowhash.c
@@ -6,6 +6,7 @@
#include "stubs.h"
#endif
#include "prtypes.h"
+#include "prenv.h"
#include "secerr.h"
#include "blapi.h"
#include "hasht.h"
@@ -30,6 +31,12 @@ nsslow_GetFIPSEnabled(void)
FILE *f;
char d;
size_t size;
+ const char *env;
+
+ env = PR_GetEnvSecure("NSS_FIPS");
+ if (env && (*env == 'y' || *env == 'f' || *env == '1' || *env == 't')) {
+ return 1;
+ }
f = fopen("/proc/sys/crypto/fips_enabled", "r");
if (!f)
diff --git a/lib/freebl/shsign.h b/lib/freebl/shsign.h
index 590c0e6b3..d1a595a39 100644
--- a/lib/freebl/shsign.h
+++ b/lib/freebl/shsign.h
@@ -8,7 +8,19 @@
#define SGN_SUFFIX ".chk"
#define NSS_SIGN_CHK_MAGIC1 0xf1
#define NSS_SIGN_CHK_MAGIC2 0xc5
-#define NSS_SIGN_CHK_MAJOR_VERSION 0x01
-#define NSS_SIGN_CHK_MINOR_VERSION 0x02
+/* new hmac based signatures */
+#define NSS_SIGN_CHK_MAJOR_VERSION 0x02
+#define NSS_SIGN_CHK_MINOR_VERSION 0x01
+#define NSS_SIGN_CHK_TYPE_FLAGS 0xff000000
+#define NSS_SIGN_CHK_FLAG_HMAC 0x80000000
+typedef struct NSSSignChkHeaderStr NSSSignChkHeader;
+struct NSSSignChkHeaderStr {
+ unsigned char magic1;
+ unsigned char magic2;
+ unsigned char majorVersion;
+ unsigned char minorVersion;
+ unsigned char offset[4];
+ unsigned char type[4];
+};
#endif /* _SHSIGN_H_ */
diff --git a/lib/freebl/shvfy.c b/lib/freebl/shvfy.c
index 0428bf6c0..e713f64b0 100644
--- a/lib/freebl/shvfy.c
+++ b/lib/freebl/shvfy.c
@@ -19,6 +19,7 @@
#include "pqg.h"
#include "blapii.h"
#include "secitem.h"
+#include "pkcs11t.h"
#ifndef NSS_FIPS_DISABLED
@@ -321,228 +322,315 @@ BLAPI_SHVerifyFile(const char *shName)
return blapi_SHVerifyFile(shName, PR_FALSE);
}
+#ifndef NSS_STRICT_INTEGRITY
+/* This allows checks with old shlibsign .chk files. If NSS_STRICT_INTEGRITY
+ * is set, we don't accept DSA */
static PRBool
-blapi_SHVerifyFile(const char *shName, PRBool self)
+blapi_SHVerifyDSACheck(PRFileDesc *shFD, const SECHashObject *hashObj,
+ DSAPublicKey *key, const SECItem *signature)
{
- char *checkName = NULL;
- PRFileDesc *checkFD = NULL;
- PRFileDesc *shFD = NULL;
void *hashcx = NULL;
- const SECHashObject *hashObj = NULL;
- SECItem signature = { 0, NULL, 0 };
SECItem hash;
- int bytesRead, offset;
- SECStatus rv;
- DSAPublicKey key;
- int count;
- (void)count; /* Suppress unused var warning (Bug 1738028) */
-#ifdef FREEBL_USE_PRELINK
- int pid = 0;
-#endif
-
- PRBool result = PR_FALSE; /* if anything goes wrong,
- * the signature does not verify */
- unsigned char buf[4096];
+ int bytesRead;
unsigned char hashBuf[HASH_LENGTH_MAX];
+ unsigned char buf[4096];
+ SECStatus rv;
- PORT_Memset(&key, 0, sizeof(key));
+ hash.type = siBuffer;
hash.data = hashBuf;
hash.len = sizeof(hashBuf);
- /* If our integrity check was never ran or failed, fail any other
- * integrity checks to prevent any token going into FIPS mode. */
- if (!self && (BL_FIPSEntryOK(PR_FALSE) != SECSuccess)) {
+ /* hash our library file */
+ hashcx = hashObj->create();
+ if (hashcx == NULL) {
return PR_FALSE;
}
+ hashObj->begin(hashcx);
- if (!shName) {
- goto loser;
+ while ((bytesRead = PR_Read(shFD, buf, sizeof(buf))) > 0) {
+ hashObj->update(hashcx, buf, bytesRead);
}
+ hashObj->end(hashcx, hash.data, &hash.len, hash.len);
+ hashObj->destroy(hashcx, PR_TRUE);
- /* figure out the name of our check file */
- checkName = mkCheckFileName(shName);
- if (!checkName) {
- goto loser;
- }
+ /* verify the hash against the check file */
+ rv = DSA_VerifyDigest(key, signature, &hash);
+ PORT_Memset(hashBuf, 0, sizeof hashBuf);
+ return (rv == SECSuccess) ? PR_TRUE : PR_FALSE;
+}
+#endif
- /* open the check File */
- checkFD = PR_Open(checkName, PR_RDONLY, 0);
- if (checkFD == NULL) {
-#ifdef DEBUG_SHVERIFY
- fprintf(stderr, "Failed to open the check file %s: (%d, %d)\n",
- checkName, (int)PR_GetError(), (int)PR_GetOSError());
-#endif /* DEBUG_SHVERIFY */
- goto loser;
+#ifdef NSS_STRICT_INTEGRITY
+/* don't allow MD2, MD5, SHA1 or SHA224 as your integrity hash */
+static PRBool
+blapi_HashAllowed(SECHashObject *hashObj)
+{
+ switch (hashObj->type) {
+ case HASH_AlgSHA256:
+ case HASH_AlgSHA384:
+ case HASH_AlgSHA512:
+ return PR_TRUE;
+ default:
+ break;
}
+ return PR_FALSE;
+}
+#endif
- /* read and Verify the headerthe header */
- bytesRead = PR_Read(checkFD, buf, 12);
- if (bytesRead != 12) {
- goto loser;
- }
- if ((buf[0] != NSS_SIGN_CHK_MAGIC1) || (buf[1] != NSS_SIGN_CHK_MAGIC2)) {
- goto loser;
- }
- if ((buf[2] != NSS_SIGN_CHK_MAJOR_VERSION) ||
- (buf[3] < NSS_SIGN_CHK_MINOR_VERSION)) {
- goto loser;
- }
-#ifdef notdef
- if (decodeInt(&buf[8]) != CKK_DSA) {
- goto loser;
- }
+static PRBool
+blapi_SHVerifyHMACCheck(PRFileDesc *shFD, const SECHashObject *hashObj,
+ const SECItem *key, const SECItem *signature)
+{
+ HMACContext *hmaccx = NULL;
+ SECItem hash;
+ int bytesRead;
+ unsigned char hashBuf[HASH_LENGTH_MAX];
+ unsigned char buf[4096];
+ SECStatus rv;
+ PRBool result = PR_FALSE;
+
+#ifdef NSS_STRICT_INTEGRITY
+ if (!blapi_HashAllowed(hashObj)) {
+ return PR_FALSE;
#endif
- /* seek past any future header extensions */
- offset = decodeInt(&buf[4]);
- if (PR_Seek(checkFD, offset, PR_SEEK_SET) < 0) {
- goto loser;
- }
+ hash.type = siBuffer;
+ hash.data = hashBuf;
+ hash.len = hashObj->length;
- /* read the key */
- rv = readItem(checkFD, &key.params.prime);
- if (rv != SECSuccess) {
- goto loser;
- }
- rv = readItem(checkFD, &key.params.subPrime);
- if (rv != SECSuccess) {
- goto loser;
- }
- rv = readItem(checkFD, &key.params.base);
- if (rv != SECSuccess) {
- goto loser;
- }
- rv = readItem(checkFD, &key.publicValue);
- if (rv != SECSuccess) {
- goto loser;
- }
- /* read the siganture */
- rv = readItem(checkFD, &signature);
- if (rv != SECSuccess) {
- goto loser;
- }
+ /* create an hmac for the library file */
+ hmaccx = HMAC_Create(hashObj, key->data, key->len, PR_TRUE);
+ if (hmaccx == NULL) {
+ return PR_FALSE;
+ }
+ HMAC_Begin(hmaccx);
+
+ while ((bytesRead = PR_Read(shFD, buf, sizeof(buf))) > 0) {
+ HMAC_Update(hmaccx, buf, bytesRead);
+ }
+ rv = HMAC_Finish(hmaccx, hash.data, &hash.len, hash.len);
- /* done with the check file */
- PR_Close(checkFD);
- checkFD = NULL;
+ HMAC_Destroy(hmaccx, PR_TRUE);
- hashObj = HASH_GetRawHashObject(PQG_GetHashType(&key.params));
- if (hashObj == NULL) {
- goto loser;
+ /* verify the hmac against the check file */
+ if (rv == SECSuccess) {
+ result = SECITEM_ItemsAreEqual(signature, &hash);
+ }
+ PORT_Memset(hashBuf, 0, sizeof hashBuf);
+ return result;
}
+ static PRBool
+ blapi_SHVerifyFile(const char *shName, PRBool self)
+ {
+ char *checkName = NULL;
+ PRFileDesc *checkFD = NULL;
+ PRFileDesc *shFD = NULL;
+ const SECHashObject *hashObj = NULL;
+ SECItem signature = { 0, NULL, 0 };
+ int bytesRead, offset, type;
+ SECStatus rv;
+ SECItem hmacKey = { 0, NULL, 0 };
+#ifdef FREEBL_USE_PRELINK
+ int pid = 0;
+#endif
+ PRBool result = PR_FALSE; /* if anything goes wrong,
+ * the signature does not verify */
+ NSSSignChkHeader header;
+#ifndef NSS_STRICT_INTEGRITY
+ DSAPublicKey key;
+
+ PORT_Memset(&key, 0, sizeof(key));
+#endif
+
+ /* If our integrity check was never ran or failed, fail any other
+ * integrity checks to prevent any token going into FIPS mode. */
+ if (!self && (BL_FIPSEntryOK(PR_FALSE) != SECSuccess)) {
+ return PR_FALSE;
+ }
+
+ if (!shName) {
+ goto loser;
+ }
+
+ /* figure out the name of our check file */
+ checkName = mkCheckFileName(shName);
+ if (!checkName) {
+ goto loser;
+ }
+
+ /* open the check File */
+ checkFD = PR_Open(checkName, PR_RDONLY, 0);
+ if (checkFD == NULL) {
+#ifdef DEBUG_SHVERIFY
+ fprintf(stderr, "Failed to open the check file %s: (%d, %d)\n",
+ checkName, (int)PR_GetError(), (int)PR_GetOSError());
+#endif /* DEBUG_SHVERIFY */
+ goto loser;
+ }
+
+ /* read and Verify the headerthe header */
+ bytesRead = PR_Read(checkFD, &header, sizeof(header));
+ if (bytesRead != sizeof(header)) {
+ goto loser;
+ }
+ if ((header.magic1 != NSS_SIGN_CHK_MAGIC1) ||
+ (header.magic2 != NSS_SIGN_CHK_MAGIC2)) {
+ goto loser;
+ }
+ /* we've bumped the version number so that newly signed .check
+ * files will fail nicely on old version of nss */
+ if (header.majorVersion > NSS_SIGN_CHK_MAJOR_VERSION) {
+ goto loser;
+ }
+ if (header.minorVersion < NSS_SIGN_CHK_MINOR_VERSION) {
+ goto loser;
+ }
+ type = decodeInt(header.type);
+
+ /* seek past any future header extensions */
+ offset = decodeInt(header.offset);
+ if (PR_Seek(checkFD, offset, PR_SEEK_SET) < 0) {
+ goto loser;
+ }
+
+ switch (type) {
+ case CKK_DSA:
+#ifdef NSS_STRICT_INTEGRITY
+ goto loser;
+#else
+ /* accept old dsa check files if NSS_STRICT_INTEGRITY is not set*/
+ /* read the key */
+ rv = readItem(checkFD, &key.params.prime);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ rv = readItem(checkFD, &key.params.subPrime);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ rv = readItem(checkFD, &key.params.base);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ rv = readItem(checkFD, &key.publicValue);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ /* read the signature */
+ rv = readItem(checkFD, &signature);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ hashObj = HASH_GetRawHashObject(PQG_GetHashType(&key.params));
+ break;
+#endif
+ default:
+ if ((type & NSS_SIGN_CHK_TYPE_FLAGS) != NSS_SIGN_CHK_FLAG_HMAC) {
+ goto loser;
+ }
+ /* read the HMAC Key */
+ rv = readItem(checkFD, &hmacKey);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ /* read the siganture */
+ rv = readItem(checkFD, &signature);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ hashObj = HASH_GetRawHashObject(type & ~NSS_SIGN_CHK_TYPE_FLAGS);
+ }
+
+ /* done with the check file */
+ PR_Close(checkFD);
+ checkFD = NULL;
+
+ if (hashObj == NULL) {
+ goto loser;
+ }
+
/* open our library file */
#ifdef FREEBL_USE_PRELINK
- shFD = bl_OpenUnPrelink(shName, &pid);
+ shFD = bl_OpenUnPrelink(shName, &pid);
#else
shFD = PR_Open(shName, PR_RDONLY, 0);
#endif
- if (shFD == NULL) {
+ if (shFD == NULL) {
#ifdef DEBUG_SHVERIFY
- fprintf(stderr, "Failed to open the library file %s: (%d, %d)\n",
- shName, (int)PR_GetError(), (int)PR_GetOSError());
+ fprintf(stderr, "Failed to open the library file %s: (%d, %d)\n",
+ shName, (int)PR_GetError(), (int)PR_GetOSError());
#endif /* DEBUG_SHVERIFY */
- goto loser;
- }
+ goto loser;
+ }
- /* hash our library file with SHA1 */
- hashcx = hashObj->create();
- if (hashcx == NULL) {
- goto loser;
- }
- hashObj->begin(hashcx);
+ switch (type) {
+ case CKK_DSA:
+#ifndef NSS_STRICT_INTEGRITY
+ result = blapi_SHVerifyDSACheck(shFD, hashObj, &key, &signature);
+#endif
+ break;
+ default:
+ if ((type & NSS_SIGN_CHK_TYPE_FLAGS) != NSS_SIGN_CHK_FLAG_HMAC) {
+ break;
+ }
+ result = blapi_SHVerifyHMACCheck(shFD, hashObj, &hmacKey, &signature);
+ break;
+ }
- count = 0;
- while ((bytesRead = PR_Read(shFD, buf, sizeof(buf))) > 0) {
- hashObj->update(hashcx, buf, bytesRead);
- count += bytesRead;
- }
#ifdef FREEBL_USE_PRELINK
- bl_CloseUnPrelink(shFD, pid);
+ bl_CloseUnPrelink(shFD, pid);
#else
PR_Close(shFD);
#endif
- shFD = NULL;
-
- hashObj->end(hashcx, hash.data, &hash.len, hash.len);
+ shFD = NULL;
- /* verify the hash against the check file */
- if (DSA_VerifyDigest(&key, &signature, &hash) == SECSuccess) {
- result = PR_TRUE;
- }
-#ifdef DEBUG_SHVERIFY
- {
- int i, j;
- fprintf(stderr, "File %s: %d bytes\n", shName, count);
- fprintf(stderr, " hash: %d bytes\n", hash.len);
-#define STEP 10
- for (i = 0; i < hash.len; i += STEP) {
- fprintf(stderr, " ");
- for (j = 0; j < STEP && (i + j) < hash.len; j++) {
- fprintf(stderr, " %02x", hash.data[i + j]);
- }
- fprintf(stderr, "\n");
+ loser:
+ PORT_Memset(&header, 0, sizeof header);
+ if (checkName != NULL) {
+ PORT_Free(checkName);
}
- fprintf(stderr, " signature: %d bytes\n", signature.len);
- for (i = 0; i < signature.len; i += STEP) {
- fprintf(stderr, " ");
- for (j = 0; j < STEP && (i + j) < signature.len; j++) {
- fprintf(stderr, " %02x", signature.data[i + j]);
- }
- fprintf(stderr, "\n");
+ if (checkFD != NULL) {
+ PR_Close(checkFD);
}
- fprintf(stderr, "Verified : %s\n", result ? "TRUE" : "FALSE");
- }
-#endif /* DEBUG_SHVERIFY */
-
-loser:
- PORT_Memset(buf, 0, sizeof buf);
- PORT_Memset(hashBuf, 0, sizeof hashBuf);
- if (checkName != NULL) {
- PORT_Free(checkName);
- }
- if (checkFD != NULL) {
- PR_Close(checkFD);
- }
- if (shFD != NULL) {
- PR_Close(shFD);
- }
- if (hashcx != NULL) {
- if (hashObj) {
- hashObj->destroy(hashcx, PR_TRUE);
+ if (shFD != NULL) {
+ PR_Close(shFD);
}
- }
- if (signature.data != NULL) {
- SECITEM_ZfreeItem(&signature, PR_FALSE);
- }
- if (key.params.prime.data != NULL) {
- SECITEM_ZfreeItem(&key.params.prime, PR_FALSE);
- }
- if (key.params.subPrime.data != NULL) {
- SECITEM_ZfreeItem(&key.params.subPrime, PR_FALSE);
- }
- if (key.params.base.data != NULL) {
- SECITEM_ZfreeItem(&key.params.base, PR_FALSE);
- }
- if (key.publicValue.data != NULL) {
- SECITEM_ZfreeItem(&key.publicValue, PR_FALSE);
+ if (hmacKey.data != NULL) {
+ SECITEM_ZfreeItem(&hmacKey, PR_FALSE);
+ }
+ if (signature.data != NULL) {
+ SECITEM_ZfreeItem(&signature, PR_FALSE);
+ }
+#ifndef NSS_STRICT_INTEGRITY
+ if (key.params.prime.data != NULL) {
+ SECITEM_ZfreeItem(&key.params.prime, PR_FALSE);
+ }
+ if (key.params.subPrime.data != NULL) {
+ SECITEM_ZfreeItem(&key.params.subPrime, PR_FALSE);
+ }
+ if (key.params.base.data != NULL) {
+ SECITEM_ZfreeItem(&key.params.base, PR_FALSE);
+ }
+ if (key.publicValue.data != NULL) {
+ SECITEM_ZfreeItem(&key.publicValue, PR_FALSE);
+ }
+#endif
+ return result;
}
- return result;
-}
-
-PRBool
-BLAPI_VerifySelf(const char *name)
-{
- if (name == NULL) {
- /*
+ PRBool
+ BLAPI_VerifySelf(const char *name)
+ {
+ if (name == NULL) {
+ /*
* If name is NULL, freebl is statically linked into softoken.
* softoken will call BLAPI_SHVerify next to verify itself.
*/
- return PR_TRUE;
+ return PR_TRUE;
+ }
+ return blapi_SHVerify(name, (PRFuncPtr)decodeInt, PR_TRUE);
}
- return blapi_SHVerify(name, (PRFuncPtr)decodeInt, PR_TRUE);
-}
#else /* NSS_FIPS_DISABLED */
diff --git a/lib/freebl/stubs.c b/lib/freebl/stubs.c
index 122e5b251..82b5b2e78 100644
--- a/lib/freebl/stubs.c
+++ b/lib/freebl/stubs.c
@@ -170,6 +170,7 @@ STUB_DECLARE(char *, PR_GetEnvSecure, (const char *));
STUB_DECLARE(SECItem *, SECITEM_AllocItem_Util, (PLArenaPool * arena, SECItem *item, unsigned int len));
STUB_DECLARE(SECComparison, SECITEM_CompareItem_Util, (const SECItem *a, const SECItem *b));
+STUB_DECLARE(PRBool, SECITEM_ItemsAreEqual_Util, (const SECItem *a, const SECItem *b));
STUB_DECLARE(SECStatus, SECITEM_CopyItem_Util, (PLArenaPool * arena, SECItem *to, const SECItem *from));
STUB_DECLARE(void, SECITEM_FreeItem_Util, (SECItem * zap, PRBool freeit));
STUB_DECLARE(void, SECITEM_ZfreeItem_Util, (SECItem * zap, PRBool freeit));
@@ -573,8 +574,11 @@ extern char *
PR_GetEnvSecure_stub(const char *var)
{
STUB_SAFE_CALL1(PR_GetEnvSecure, var);
- abort();
- return NULL;
+#ifdef __USE_GNU
+ return secure_getenv(var);
+#else
+ return getenv(var);
+#endif
}
extern void
@@ -622,6 +626,30 @@ SECITEM_CompareItem_stub(const SECItem *a, const SECItem *b)
return SECEqual;
}
+extern PRBool
+SECITEM_ItemsAreEqual_stub(const SECItem *a, const SECItem *b)
+{
+ STUB_SAFE_CALL2(SECITEM_ItemsAreEqual_Util, a, b);
+ /* two nulls are equal */
+ if (!a && !b) {
+ return PR_TRUE;
+ }
+ /* only one NULL is not equal */
+ if (!a || !b) {
+ return PR_FALSE;
+ }
+ /* we know both secitems have been set, now make sure the lengths
+ * are equal */
+ if (a->len != b->len) {
+ return PR_FALSE;
+ }
+ /* lengths are equal, safe to verify the data */
+ if (PORT_Memcmp(a->data, b->data, b->len) != 0) {
+ return PR_FALSE;
+ }
+ return PR_TRUE;
+}
+
extern SECStatus
SECITEM_CopyItem_stub(PLArenaPool *arena, SECItem *to, const SECItem *from)
{
@@ -646,7 +674,16 @@ extern void
SECITEM_ZfreeItem_stub(SECItem *zap, PRBool freeit)
{
STUB_SAFE_CALL2(SECITEM_ZfreeItem_Util, zap, freeit);
- abort();
+ if (zap) {
+ if (zap->data) {
+ PORT_Memset(zap->data, 0, zap->len);
+ PORT_Free_stub(zap->data);
+ }
+ PORT_Memset(zap, 0, sizeof(SECItem));
+ if (freeit) {
+ PORT_Free_stub(zap);
+ }
+ }
}
extern int
diff --git a/lib/freebl/stubs.h b/lib/freebl/stubs.h
index e63cf7a5d..e6d9ed03a 100644
--- a/lib/freebl/stubs.h
+++ b/lib/freebl/stubs.h
@@ -35,6 +35,7 @@
#define SECITEM_AllocItem SECITEM_AllocItem_stub
#define SECITEM_CompareItem SECITEM_CompareItem_stub
+#define SECITEM_ItemsAreEqual SECITEM_ItemsAreEqual_stub
#define SECITEM_CopyItem SECITEM_CopyItem_stub
#define SECITEM_FreeItem SECITEM_FreeItem_stub
#define SECITEM_ZfreeItem SECITEM_ZfreeItem_stub
diff --git a/tests/lowhash/lowhash.sh b/tests/lowhash/lowhash.sh
index 6de255be4..6de255be4 100644..100755
--- a/tests/lowhash/lowhash.sh
+++ b/tests/lowhash/lowhash.sh