summaryrefslogtreecommitdiff
path: root/lib/freebl/shvfy.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/freebl/shvfy.c')
-rw-r--r--lib/freebl/shvfy.c438
1 files changed, 263 insertions, 175 deletions
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 */