Bug 1550889 - land NSS 8082be3a6363 UPGRADE_NSS_RELEASE, r=me

--HG--
extra : rebase_source : 84cb27998d0b4e36d9a7d388e3a8b2a4fc3bb886
This commit is contained in:
J.C. Jones 2019-06-04 19:39:40 +00:00
Родитель d88f3e04a9
Коммит 2f955dea5e
21 изменённых файлов: 999 добавлений и 321 удалений

Просмотреть файл

@ -1 +1 @@
29a48b604602
8082be3a6363

Просмотреть файл

@ -0,0 +1,4 @@
1 Added function:
'function SECStatus PK11_FindRawCertsWithSubject(PK11SlotInfo*, SECItem*, CERTCertificateList**)' {PK11_FindRawCertsWithSubject@@NSS_3.45}

Просмотреть файл

@ -10,3 +10,4 @@
*/
#error "Do not include this header file."

Просмотреть файл

@ -14,6 +14,7 @@
#include "pk11pqg.h"
#include "pk11pub.h"
#include "pkcs11uri.h"
#include "secmod.h"
struct ScopedDelete {
void operator()(CERTCertificate* cert) { CERT_DestroyCertificate(cert); }
@ -47,6 +48,7 @@ struct ScopedDelete {
SEC_PKCS12DecoderFinish(dcx);
}
void operator()(CERTDistNames* names) { CERT_FreeDistNames(names); }
void operator()(SECMODModule* module) { SECMOD_DestroyModule(module); }
};
template <class T>
@ -82,6 +84,7 @@ SCOPED(PK11Context);
SCOPED(PK11GenericObject);
SCOPED(SEC_PKCS12DecoderContext);
SCOPED(CERTDistNames);
SCOPED(SECMODModule);
#undef SCOPED

Просмотреть файл

@ -8,7 +8,21 @@
#define util_h__
#include <cassert>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <sys/stat.h>
#include <vector>
#if defined(_WIN32)
#include <windows.h>
#include <codecvt>
#include <direct.h>
#else
#include <unistd.h>
#endif
#include "nspr.h"
static inline std::vector<uint8_t> hex_string_to_bytes(std::string s) {
std::vector<uint8_t> bytes;
@ -18,4 +32,81 @@ static inline std::vector<uint8_t> hex_string_to_bytes(std::string s) {
return bytes;
}
// Given a prefix, attempts to create a unique directory that the user can do
// work in without impacting other tests. For example, if given the prefix
// "scratch", a directory like "scratch05c17b25" will be created in the current
// working directory (or the location specified by NSS_GTEST_WORKDIR, if
// defined).
// Upon destruction, the implementation will attempt to delete the directory.
// However, no attempt is made to first remove files in the directory - the
// user is responsible for this. If the directory is not empty, deleting it will
// fail.
// Statistically, it is technically possible to fail to create a unique
// directory name, but this is extremely unlikely given the expected workload of
// this implementation.
class ScopedUniqueDirectory {
public:
explicit ScopedUniqueDirectory(const std::string &prefix) {
std::string path;
const char *workingDirectory = PR_GetEnvSecure("NSS_GTEST_WORKDIR");
if (workingDirectory) {
path.assign(workingDirectory);
}
path.append(prefix);
for (int i = 0; i < RETRY_LIMIT; i++) {
std::string pathCopy(path);
// TryMakingDirectory will modify its input. If it fails, we want to throw
// away the modified result.
if (TryMakingDirectory(pathCopy)) {
mPath.assign(pathCopy);
break;
}
}
assert(mPath.length() > 0);
#if defined(_WIN32)
// sqldb always uses UTF-8 regardless of the current system locale.
DWORD len =
MultiByteToWideChar(CP_ACP, 0, mPath.data(), mPath.size(), nullptr, 0);
std::vector<wchar_t> buf(len, L'\0');
MultiByteToWideChar(CP_ACP, 0, mPath.data(), mPath.size(), buf.data(),
buf.size());
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
mUTF8Path = converter.to_bytes(std::wstring(buf.begin(), buf.end()));
#else
mUTF8Path = mPath;
#endif
}
// NB: the directory must be empty upon destruction
~ScopedUniqueDirectory() { assert(rmdir(mPath.c_str()) == 0); }
const std::string &GetPath() { return mPath; }
const std::string &GetUTF8Path() { return mUTF8Path; }
private:
static const int RETRY_LIMIT = 5;
static void GenerateRandomName(/*in/out*/ std::string &prefix) {
std::stringstream ss;
ss << prefix;
// RAND_MAX is at least 32767.
ss << std::setfill('0') << std::setw(4) << std::hex << rand() << rand();
// This will overwrite the value of prefix. This is a little inefficient,
// but at least it makes the code simple.
ss >> prefix;
}
static bool TryMakingDirectory(/*in/out*/ std::string &prefix) {
GenerateRandomName(prefix);
#if defined(_WIN32)
return _mkdir(prefix.c_str()) == 0;
#else
return mkdir(prefix.c_str(), 0777) == 0;
#endif
}
std::string mPath;
std::string mUTF8Path;
};
#endif // util_h__

Просмотреть файл

@ -7,6 +7,7 @@ DEPTH = ../..
MODULE = nss
CPPSRCS = \
pk11_aes_gcm_unittest.cc \
pk11_aeskeywrap_unittest.cc \
pk11_cbc_unittest.cc \
pk11_chacha20poly1305_unittest.cc \
@ -14,6 +15,7 @@ CPPSRCS = \
pk11_ecdsa_unittest.cc \
pk11_encrypt_derive_unittest.cc \
pk11_export_unittest.cc \
pk11_find_certs_unittest.cc \
pk11_import_unittest.cc \
pk11_pbkdf2_unittest.cc \
pk11_prf_unittest.cc \

Просмотреть файл

@ -0,0 +1,347 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set ts=4 et sw=4 tw=80: */
/* 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 <string.h>
#include "nss.h"
#include "pk11pub.h"
#include "prenv.h"
#include "prerror.h"
#include "secmod.h"
#include "gtest/gtest.h"
#include "nss_scoped_ptrs.h"
#include "util.h"
namespace nss_test {
// These test certificates were generated using pycert/pykey from
// mozilla-central (https://hg.mozilla.org/mozilla-central/file/ ...
// 9968319230a74eb8c1953444a0e6973c7500a9f8/security/manager/ssl/ ...
// tests/unit/pycert.py).
// issuer:test cert
// subject:test cert
// issuerKey:secp256r1
// subjectKey:secp256r1
// serialNumber:1
std::vector<uint8_t> kTestCert1DER = {
0x30, 0x82, 0x01, 0x1D, 0x30, 0x81, 0xC2, 0xA0, 0x03, 0x02, 0x01, 0x02,
0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10,
0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20,
0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37,
0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18,
0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x5A, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x65,
0x72, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01,
0x07, 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 0xBB, 0x61, 0xE0, 0xF8,
0xF9, 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 0xE2, 0xEC, 0x05, 0x0B,
0x42, 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 0x4F, 0x79, 0x4B, 0x45,
0x5C, 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 0xC4, 0x11, 0x9D, 0x07,
0x06, 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 0xD7, 0x99, 0x1B, 0x7B,
0x2D, 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 0xC0, 0x30, 0x0D, 0x06,
0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00,
0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x5C, 0x75, 0x51, 0x9F, 0x13,
0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 0xBC, 0x06, 0x30, 0x91,
0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 0xFD, 0xCB, 0x42, 0x80,
0x0A, 0x70, 0xE6, 0x02, 0x20, 0x11, 0xFA, 0xA2, 0xCA, 0x06, 0xF3, 0xBC,
0x5F, 0x8A, 0xCA, 0x17, 0x63, 0x36, 0x87, 0xCF, 0x8D, 0x5C, 0xA0, 0x56,
0x84, 0x44, 0x61, 0xB2, 0x33, 0x42, 0x07, 0x58, 0x9F, 0x0C, 0x9E, 0x49,
0x83,
};
// issuer:test cert
// subject:test cert
// issuerKey:secp256r1
// subjectKey:secp256r1
// serialNumber:2
std::vector<uint8_t> kTestCert2DER = {
0x30, 0x82, 0x01, 0x1E, 0x30, 0x81, 0xC2, 0xA0, 0x03, 0x02, 0x01, 0x02,
0x02, 0x01, 0x02, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10,
0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20,
0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37,
0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18,
0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x5A, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x65,
0x72, 0x74, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01,
0x07, 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 0xBB, 0x61, 0xE0, 0xF8,
0xF9, 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 0xE2, 0xEC, 0x05, 0x0B,
0x42, 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 0x4F, 0x79, 0x4B, 0x45,
0x5C, 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 0xC4, 0x11, 0x9D, 0x07,
0x06, 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 0xD7, 0x99, 0x1B, 0x7B,
0x2D, 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 0xC0, 0x30, 0x0D, 0x06,
0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00,
0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5C, 0x75, 0x51, 0x9F, 0x13,
0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 0xBC, 0x06, 0x30, 0x91,
0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 0xFD, 0xCB, 0x42, 0x80,
0x0A, 0x70, 0xE6, 0x02, 0x21, 0x00, 0xF6, 0x5E, 0x42, 0xC7, 0x54, 0x40,
0x81, 0xE9, 0x4C, 0x16, 0x48, 0xB1, 0x39, 0x0A, 0xA0, 0xE2, 0x8C, 0x23,
0xAA, 0xC5, 0xBB, 0xAC, 0xEB, 0x9B, 0x15, 0x0B, 0x2F, 0xB7, 0xF5, 0x85,
0xB2, 0x54,
};
std::vector<uint8_t> kTestCertSubjectDER = {
0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03,
0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20, 0x63, 0x65, 0x72, 0x74,
};
// issuer:test cert
// subject:unrelated subject DN
// issuerKey:secp256r1
// subjectKey:secp256r1
// serialNumber:3
std::vector<uint8_t> kUnrelatedTestCertDER = {
0x30, 0x82, 0x01, 0x28, 0x30, 0x81, 0xCD, 0xA0, 0x03, 0x02, 0x01, 0x02,
0x02, 0x01, 0x03, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10,
0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20,
0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37,
0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18,
0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x5A, 0x30, 0x1F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03,
0x55, 0x04, 0x03, 0x0C, 0x14, 0x75, 0x6E, 0x72, 0x65, 0x6C, 0x61, 0x74,
0x65, 0x64, 0x20, 0x73, 0x75, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x44,
0x4E, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB, 0xBB, 0x61, 0xE0, 0xF8, 0xF9,
0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04, 0xE2, 0xEC, 0x05, 0x0B, 0x42,
0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C, 0x4F, 0x79, 0x4B, 0x45, 0x5C,
0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36, 0xC4, 0x11, 0x9D, 0x07, 0x06,
0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90, 0xD7, 0x99, 0x1B, 0x7B, 0x2D,
0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6, 0xC0, 0x30, 0x0D, 0x06, 0x09,
0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03,
0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x5C, 0x75, 0x51, 0x9F, 0x13, 0x11,
0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3, 0xBC, 0x06, 0x30, 0x91, 0xFF,
0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC, 0xFD, 0xCB, 0x42, 0x80, 0x0A,
0x70, 0xE6, 0x02, 0x20, 0x0F, 0x1A, 0x04, 0xC2, 0xF8, 0xBA, 0xC2, 0x94,
0x26, 0x6E, 0xBC, 0x91, 0x7D, 0xDB, 0x75, 0x7B, 0xE8, 0xA3, 0x4F, 0x69,
0x1B, 0xF3, 0x1F, 0x2C, 0xCE, 0x82, 0x67, 0xC9, 0x5B, 0xBB, 0xBA, 0x0A,
};
class PK11FindRawCertsBySubjectTest : public ::testing::Test {
protected:
PK11FindRawCertsBySubjectTest()
: mSlot(nullptr), mTestCertDBDir("PK11FindRawCertsBySubjectTest-") {}
virtual void SetUp() {
std::string testCertDBPath(mTestCertDBDir.GetPath());
const char* testName =
::testing::UnitTest::GetInstance()->current_test_info()->name();
std::string modspec = "configDir='sql:";
modspec.append(testCertDBPath);
modspec.append("' tokenDescription='");
modspec.append(testName);
modspec.append("'");
mSlot = SECMOD_OpenUserDB(modspec.c_str());
ASSERT_NE(mSlot, nullptr);
}
virtual void TearDown() {
ASSERT_EQ(SECMOD_CloseUserDB(mSlot), SECSuccess);
PK11_FreeSlot(mSlot);
std::string testCertDBPath(mTestCertDBDir.GetPath());
ASSERT_EQ(0, unlink((testCertDBPath + "/cert9.db").c_str()));
ASSERT_EQ(0, unlink((testCertDBPath + "/key4.db").c_str()));
}
PK11SlotInfo* mSlot;
ScopedUniqueDirectory mTestCertDBDir;
};
// If we don't have any certificates, we shouldn't get any when we search for
// them.
TEST_F(PK11FindRawCertsBySubjectTest, TestNoCertsImportedNoCertsFound) {
SECItem subjectItem = {siBuffer,
const_cast<unsigned char*>(kTestCertSubjectDER.data()),
(unsigned int)kTestCertSubjectDER.size()};
CERTCertificateList* certificates = nullptr;
SECStatus rv =
PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates);
EXPECT_EQ(rv, SECSuccess);
EXPECT_EQ(certificates, nullptr);
}
// If we have one certificate but it has an unrelated subject DN, we shouldn't
// get it when we search.
TEST_F(PK11FindRawCertsBySubjectTest, TestOneCertImportedNoCertsFound) {
char certNickname[] = "Unrelated Cert";
SECItem certItem = {siBuffer,
const_cast<unsigned char*>(kUnrelatedTestCertDER.data()),
(unsigned int)kUnrelatedTestCertDER.size()};
ASSERT_EQ(PK11_ImportDERCert(mSlot, &certItem, CK_INVALID_HANDLE,
certNickname, false),
SECSuccess);
SECItem subjectItem = {siBuffer,
const_cast<unsigned char*>(kTestCertSubjectDER.data()),
(unsigned int)kTestCertSubjectDER.size()};
CERTCertificateList* certificates = nullptr;
SECStatus rv =
PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates);
EXPECT_EQ(rv, SECSuccess);
EXPECT_EQ(certificates, nullptr);
}
TEST_F(PK11FindRawCertsBySubjectTest, TestMultipleMatchingCertsFound) {
char cert1Nickname[] = "Test Cert 1";
SECItem cert1Item = {siBuffer,
const_cast<unsigned char*>(kTestCert1DER.data()),
(unsigned int)kTestCert1DER.size()};
ASSERT_EQ(PK11_ImportDERCert(mSlot, &cert1Item, CK_INVALID_HANDLE,
cert1Nickname, false),
SECSuccess);
char cert2Nickname[] = "Test Cert 2";
SECItem cert2Item = {siBuffer,
const_cast<unsigned char*>(kTestCert2DER.data()),
(unsigned int)kTestCert2DER.size()};
ASSERT_EQ(PK11_ImportDERCert(mSlot, &cert2Item, CK_INVALID_HANDLE,
cert2Nickname, false),
SECSuccess);
char unrelatedCertNickname[] = "Unrelated Test Cert";
SECItem unrelatedCertItem = {
siBuffer, const_cast<unsigned char*>(kUnrelatedTestCertDER.data()),
(unsigned int)kUnrelatedTestCertDER.size()};
ASSERT_EQ(PK11_ImportDERCert(mSlot, &unrelatedCertItem, CK_INVALID_HANDLE,
unrelatedCertNickname, false),
SECSuccess);
CERTCertificateList* certificates = nullptr;
SECItem subjectItem = {siBuffer,
const_cast<unsigned char*>(kTestCertSubjectDER.data()),
(unsigned int)kTestCertSubjectDER.size()};
SECStatus rv =
PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates);
EXPECT_EQ(rv, SECSuccess);
ASSERT_NE(certificates, nullptr);
ScopedCERTCertificateList scopedCertificates(certificates);
ASSERT_EQ(scopedCertificates->len, 2);
std::vector<uint8_t> foundCert1(
scopedCertificates->certs[0].data,
scopedCertificates->certs[0].data + scopedCertificates->certs[0].len);
std::vector<uint8_t> foundCert2(
scopedCertificates->certs[1].data,
scopedCertificates->certs[1].data + scopedCertificates->certs[1].len);
EXPECT_TRUE(foundCert1 == kTestCert1DER || foundCert1 == kTestCert2DER);
EXPECT_TRUE(foundCert2 == kTestCert1DER || foundCert2 == kTestCert2DER);
EXPECT_TRUE(foundCert1 != foundCert2);
}
// If we try to search the internal slots, we won't find the certificate we just
// imported (because it's on a different slot).
TEST_F(PK11FindRawCertsBySubjectTest, TestNoCertsOnInternalSlots) {
char cert1Nickname[] = "Test Cert 1";
SECItem cert1Item = {siBuffer,
const_cast<unsigned char*>(kTestCert1DER.data()),
(unsigned int)kTestCert1DER.size()};
ASSERT_EQ(PK11_ImportDERCert(mSlot, &cert1Item, CK_INVALID_HANDLE,
cert1Nickname, false),
SECSuccess);
SECItem subjectItem = {siBuffer,
const_cast<unsigned char*>(kTestCertSubjectDER.data()),
(unsigned int)kTestCertSubjectDER.size()};
CERTCertificateList* internalKeySlotCertificates = nullptr;
ScopedPK11SlotInfo internalKeySlot(PK11_GetInternalKeySlot());
SECStatus rv = PK11_FindRawCertsWithSubject(
internalKeySlot.get(), &subjectItem, &internalKeySlotCertificates);
EXPECT_EQ(rv, SECSuccess);
EXPECT_EQ(internalKeySlotCertificates, nullptr);
CERTCertificateList* internalSlotCertificates = nullptr;
ScopedPK11SlotInfo internalSlot(PK11_GetInternalSlot());
rv = PK11_FindRawCertsWithSubject(internalSlot.get(), &subjectItem,
&internalSlotCertificates);
EXPECT_EQ(rv, SECSuccess);
EXPECT_EQ(internalSlotCertificates, nullptr);
}
// issuer:test cert
// subject:(empty - this had to be done by hand as pycert doesn't support this)
// issuerKey:secp256r1
// subjectKey:secp256r1
// serialNumber:4
std::vector<uint8_t> kEmptySubjectCertDER = {
0x30, 0x82, 0x01, 0x09, 0x30, 0x81, 0xAE, 0xA0, 0x03, 0x02, 0x01, 0x02,
0x02, 0x01, 0x04, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10,
0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x09, 0x74, 0x65, 0x73, 0x74, 0x20,
0x63, 0x65, 0x72, 0x74, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37,
0x31, 0x31, 0x32, 0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x18,
0x0F, 0x32, 0x30, 0x32, 0x30, 0x30, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x5A, 0x30, 0x00, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48,
0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4F, 0xBF, 0xBB,
0xBB, 0x61, 0xE0, 0xF8, 0xF9, 0xB1, 0xA6, 0x0A, 0x59, 0xAC, 0x87, 0x04,
0xE2, 0xEC, 0x05, 0x0B, 0x42, 0x3E, 0x3C, 0xF7, 0x2E, 0x92, 0x3F, 0x2C,
0x4F, 0x79, 0x4B, 0x45, 0x5C, 0x2A, 0x69, 0xD2, 0x33, 0x45, 0x6C, 0x36,
0xC4, 0x11, 0x9D, 0x07, 0x06, 0xE0, 0x0E, 0xED, 0xC8, 0xD1, 0x93, 0x90,
0xD7, 0x99, 0x1B, 0x7B, 0x2D, 0x07, 0xA3, 0x04, 0xEA, 0xA0, 0x4A, 0xA6,
0xC0, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
0x01, 0x0B, 0x05, 0x00, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x5C,
0x75, 0x51, 0x9F, 0x13, 0x11, 0x50, 0xCD, 0x5D, 0x8A, 0xDE, 0x20, 0xA3,
0xBC, 0x06, 0x30, 0x91, 0xFF, 0xB2, 0x73, 0x75, 0x5F, 0x31, 0x64, 0xEC,
0xFD, 0xCB, 0x42, 0x80, 0x0A, 0x70, 0xE6, 0x02, 0x20, 0x31, 0x1B, 0x92,
0xAA, 0xA8, 0xB7, 0x51, 0x52, 0x7B, 0x64, 0xD6, 0xF7, 0x2F, 0x0C, 0xFB,
0xBB, 0xD5, 0xDF, 0x86, 0xA3, 0x97, 0x96, 0x60, 0x42, 0xDA, 0xD4, 0xA8,
0x5F, 0x2F, 0xA4, 0xDE, 0x7C};
std::vector<uint8_t> kEmptySubjectDER = {0x30, 0x00};
// This certificate has the smallest possible subject. Finding it should work.
TEST_F(PK11FindRawCertsBySubjectTest, TestFindEmptySubject) {
char emptySubjectCertNickname[] = "Empty Subject Cert";
SECItem emptySubjectCertItem = {
siBuffer, const_cast<unsigned char*>(kEmptySubjectCertDER.data()),
(unsigned int)kEmptySubjectCertDER.size()};
ASSERT_EQ(PK11_ImportDERCert(mSlot, &emptySubjectCertItem, CK_INVALID_HANDLE,
emptySubjectCertNickname, false),
SECSuccess);
SECItem subjectItem = {siBuffer,
const_cast<unsigned char*>(kEmptySubjectDER.data()),
(unsigned int)kEmptySubjectDER.size()};
CERTCertificateList* certificates = nullptr;
SECStatus rv =
PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates);
EXPECT_EQ(rv, SECSuccess);
ASSERT_NE(certificates, nullptr);
ScopedCERTCertificateList scopedCertificates(certificates);
ASSERT_EQ(scopedCertificates->len, 1);
std::vector<uint8_t> foundCert(
scopedCertificates->certs[0].data,
scopedCertificates->certs[0].data + scopedCertificates->certs[0].len);
EXPECT_EQ(foundCert, kEmptySubjectCertDER);
}
// Searching for a zero-length subject doesn't make sense (the minimum subject
// is the SEQUENCE tag followed by a length byte of 0), but it shouldn't cause
// problems.
TEST_F(PK11FindRawCertsBySubjectTest, TestSearchForNullSubject) {
char cert1Nickname[] = "Test Cert 1";
SECItem cert1Item = {siBuffer,
const_cast<unsigned char*>(kTestCert1DER.data()),
(unsigned int)kTestCert1DER.size()};
ASSERT_EQ(PK11_ImportDERCert(mSlot, &cert1Item, CK_INVALID_HANDLE,
cert1Nickname, false),
SECSuccess);
SECItem subjectItem = {siBuffer, nullptr, 0};
CERTCertificateList* certificates = nullptr;
SECStatus rv =
PK11_FindRawCertsWithSubject(mSlot, &subjectItem, &certificates);
EXPECT_EQ(rv, SECSuccess);
EXPECT_EQ(certificates, nullptr);
}
} // namespace nss_test

Просмотреть файл

@ -19,6 +19,7 @@
'pk11_curve25519_unittest.cc',
'pk11_ecdsa_unittest.cc',
'pk11_encrypt_derive_unittest.cc',
'pk11_find_certs_unittest.cc',
'pk11_import_unittest.cc',
'pk11_pbkdf2_unittest.cc',
'pk11_prf_unittest.cc',

Просмотреть файл

@ -12,6 +12,7 @@ CPPSRCS = \
INCLUDES += \
-I$(CORE_DEPTH)/gtests/google_test/gtest/include \
-I$(CORE_DEPTH)/gtests/common \
-I$(CORE_DEPTH)/cpputil \
$(NULL)

Просмотреть файл

@ -1,9 +1,3 @@
#include <cstdlib>
#if defined(_WIN32)
#include <windows.h>
#include <codecvt>
#endif
#include "cert.h"
#include "certdb.h"
#include "nspr.h"
@ -12,93 +6,13 @@
#include "secerr.h"
#include "nss_scoped_ptrs.h"
#include "util.h"
#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
namespace nss_test {
// Given a prefix, attempts to create a unique directory that the user can do
// work in without impacting other tests. For example, if given the prefix
// "scratch", a directory like "scratch05c17b25" will be created in the current
// working directory (or the location specified by NSS_GTEST_WORKDIR, if
// defined).
// Upon destruction, the implementation will attempt to delete the directory.
// However, no attempt is made to first remove files in the directory - the
// user is responsible for this. If the directory is not empty, deleting it will
// fail.
// Statistically, it is technically possible to fail to create a unique
// directory name, but this is extremely unlikely given the expected workload of
// this implementation.
class ScopedUniqueDirectory {
public:
explicit ScopedUniqueDirectory(const std::string &prefix);
// NB: the directory must be empty upon destruction
~ScopedUniqueDirectory() { assert(rmdir(mPath.c_str()) == 0); }
const std::string &GetPath() { return mPath; }
const std::string &GetUTF8Path() { return mUTF8Path; }
private:
static const int RETRY_LIMIT = 5;
static void GenerateRandomName(/*in/out*/ std::string &prefix);
static bool TryMakingDirectory(/*in/out*/ std::string &prefix);
std::string mPath;
std::string mUTF8Path;
};
ScopedUniqueDirectory::ScopedUniqueDirectory(const std::string &prefix) {
std::string path;
const char *workingDirectory = PR_GetEnvSecure("NSS_GTEST_WORKDIR");
if (workingDirectory) {
path.assign(workingDirectory);
}
path.append(prefix);
for (int i = 0; i < RETRY_LIMIT; i++) {
std::string pathCopy(path);
// TryMakingDirectory will modify its input. If it fails, we want to throw
// away the modified result.
if (TryMakingDirectory(pathCopy)) {
mPath.assign(pathCopy);
break;
}
}
assert(mPath.length() > 0);
#if defined(_WIN32)
// sqldb always uses UTF-8 regardless of the current system locale.
DWORD len =
MultiByteToWideChar(CP_ACP, 0, mPath.data(), mPath.size(), nullptr, 0);
std::vector<wchar_t> buf(len, L'\0');
MultiByteToWideChar(CP_ACP, 0, mPath.data(), mPath.size(), buf.data(),
buf.size());
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
mUTF8Path = converter.to_bytes(std::wstring(buf.begin(), buf.end()));
#else
mUTF8Path = mPath;
#endif
}
void ScopedUniqueDirectory::GenerateRandomName(std::string &prefix) {
std::stringstream ss;
ss << prefix;
// RAND_MAX is at least 32767.
ss << std::setfill('0') << std::setw(4) << std::hex << rand() << rand();
// This will overwrite the value of prefix. This is a little inefficient, but
// at least it makes the code simple.
ss >> prefix;
}
bool ScopedUniqueDirectory::TryMakingDirectory(std::string &prefix) {
GenerateRandomName(prefix);
#if defined(_WIN32)
return _mkdir(prefix.c_str()) == 0;
#else
return mkdir(prefix.c_str(), 0777) == 0;
#endif
}
class SoftokenTest : public ::testing::Test {
protected:
SoftokenTest() : mNSSDBDir("SoftokenTest.d-") {}

Просмотреть файл

@ -93,7 +93,7 @@
'<(DEPTH)/lib/dbm/src/src.gyp:dbm',
],
}],
[ 'enable_sslkeylogfile==1', {
[ 'enable_sslkeylogfile==1 and sanitizer_flags==0', {
'sources': [
'ssl_keylog_unittest.cc',
],

Просмотреть файл

@ -17745,172 +17745,6 @@ CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "Certinomis - Root CA"
#
# Issuer: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR
# Serial Number: 1 (0x1)
# Subject: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR
# Not Valid Before: Mon Oct 21 09:17:18 2013
# Not Valid After : Fri Oct 21 09:17:18 2033
# Fingerprint (SHA-256): 2A:99:F5:BC:11:74:B7:3C:BB:1D:62:08:84:E0:1C:34:E5:1C:CB:39:78:DA:12:5F:0E:33:26:88:83:BF:41:58
# Fingerprint (SHA1): 9D:70:BB:01:A5:A4:A0:18:11:2E:F7:1C:01:B9:32:C5:34:E7:88:A8
CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "Certinomis - Root CA"
CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509
CKA_SUBJECT MULTILINE_OCTAL
\060\132\061\013\060\011\006\003\125\004\006\023\002\106\122\061
\023\060\021\006\003\125\004\012\023\012\103\145\162\164\151\156
\157\155\151\163\061\027\060\025\006\003\125\004\013\023\016\060
\060\060\062\040\064\063\063\071\071\070\071\060\063\061\035\060
\033\006\003\125\004\003\023\024\103\145\162\164\151\156\157\155
\151\163\040\055\040\122\157\157\164\040\103\101
END
CKA_ID UTF8 "0"
CKA_ISSUER MULTILINE_OCTAL
\060\132\061\013\060\011\006\003\125\004\006\023\002\106\122\061
\023\060\021\006\003\125\004\012\023\012\103\145\162\164\151\156
\157\155\151\163\061\027\060\025\006\003\125\004\013\023\016\060
\060\060\062\040\064\063\063\071\071\070\071\060\063\061\035\060
\033\006\003\125\004\003\023\024\103\145\162\164\151\156\157\155
\151\163\040\055\040\122\157\157\164\040\103\101
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\001\001
END
CKA_VALUE MULTILINE_OCTAL
\060\202\005\222\060\202\003\172\240\003\002\001\002\002\001\001
\060\015\006\011\052\206\110\206\367\015\001\001\013\005\000\060
\132\061\013\060\011\006\003\125\004\006\023\002\106\122\061\023
\060\021\006\003\125\004\012\023\012\103\145\162\164\151\156\157
\155\151\163\061\027\060\025\006\003\125\004\013\023\016\060\060
\060\062\040\064\063\063\071\071\070\071\060\063\061\035\060\033
\006\003\125\004\003\023\024\103\145\162\164\151\156\157\155\151
\163\040\055\040\122\157\157\164\040\103\101\060\036\027\015\061
\063\061\060\062\061\060\071\061\067\061\070\132\027\015\063\063
\061\060\062\061\060\071\061\067\061\070\132\060\132\061\013\060
\011\006\003\125\004\006\023\002\106\122\061\023\060\021\006\003
\125\004\012\023\012\103\145\162\164\151\156\157\155\151\163\061
\027\060\025\006\003\125\004\013\023\016\060\060\060\062\040\064
\063\063\071\071\070\071\060\063\061\035\060\033\006\003\125\004
\003\023\024\103\145\162\164\151\156\157\155\151\163\040\055\040
\122\157\157\164\040\103\101\060\202\002\042\060\015\006\011\052
\206\110\206\367\015\001\001\001\005\000\003\202\002\017\000\060
\202\002\012\002\202\002\001\000\324\314\011\012\054\077\222\366
\177\024\236\013\234\232\152\035\100\060\144\375\252\337\016\036
\006\133\237\120\205\352\315\215\253\103\147\336\260\372\176\200
\226\236\204\170\222\110\326\343\071\356\316\344\131\130\227\345
\056\047\230\352\223\250\167\233\112\360\357\164\200\055\353\060
\037\265\331\307\200\234\142\047\221\210\360\112\211\335\334\210
\346\024\371\325\003\057\377\225\333\275\237\354\054\372\024\025
\131\225\012\306\107\174\151\030\271\247\003\371\312\166\251\317
\307\157\264\136\005\376\356\301\122\262\165\062\207\354\355\051
\146\073\363\112\026\202\366\326\232\333\162\230\351\336\360\305
\114\245\253\265\352\001\342\214\056\144\177\144\157\375\243\045
\223\213\310\242\016\111\215\064\360\037\354\130\105\056\064\252
\204\120\275\347\262\112\023\270\260\017\256\070\135\260\251\033
\346\163\311\132\241\331\146\100\252\251\115\246\064\002\255\204
\176\262\043\301\373\052\306\147\364\064\266\260\225\152\063\117
\161\104\265\255\300\171\063\210\340\277\355\243\240\024\264\234
\011\260\012\343\140\276\370\370\146\210\315\133\361\167\005\340
\265\163\156\301\175\106\056\216\113\047\246\315\065\012\375\345
\115\175\252\052\243\051\307\132\150\004\350\345\326\223\244\142
\302\305\346\364\117\306\371\237\032\215\202\111\031\212\312\131
\103\072\350\015\062\301\364\114\023\003\157\156\246\077\221\163
\313\312\163\157\022\040\213\356\300\202\170\336\113\056\302\111
\303\035\355\026\366\044\364\047\033\134\127\061\334\125\356\250
\036\157\154\254\342\105\314\127\127\212\165\127\031\340\265\130
\231\111\066\061\074\063\001\155\026\112\315\270\052\203\204\206
\233\371\140\322\037\155\221\003\323\140\246\325\075\232\335\167
\220\075\065\244\237\017\136\365\122\104\151\271\300\272\334\317
\175\337\174\331\304\254\206\042\062\274\173\153\221\357\172\370
\027\150\260\342\123\125\140\055\257\076\302\203\330\331\011\053
\360\300\144\333\207\213\221\314\221\353\004\375\166\264\225\232
\346\024\006\033\325\064\035\276\330\377\164\034\123\205\231\340
\131\122\112\141\355\210\236\153\111\211\106\176\040\132\331\347
\112\345\152\356\322\145\021\103\002\003\001\000\001\243\143\060
\141\060\016\006\003\125\035\017\001\001\377\004\004\003\002\001
\006\060\017\006\003\125\035\023\001\001\377\004\005\060\003\001
\001\377\060\035\006\003\125\035\016\004\026\004\024\357\221\114
\365\245\303\060\350\057\010\352\323\161\042\244\222\150\170\164
\331\060\037\006\003\125\035\043\004\030\060\026\200\024\357\221
\114\365\245\303\060\350\057\010\352\323\161\042\244\222\150\170
\164\331\060\015\006\011\052\206\110\206\367\015\001\001\013\005
\000\003\202\002\001\000\176\075\124\332\042\135\032\130\076\073
\124\047\272\272\314\310\343\032\152\352\076\371\022\353\126\137
\075\120\316\340\352\110\046\046\317\171\126\176\221\034\231\077
\320\241\221\034\054\017\117\230\225\131\123\275\320\042\330\210
\135\234\067\374\373\144\301\170\214\213\232\140\011\352\325\372
\041\137\320\164\145\347\120\305\277\056\271\013\013\255\265\260
\027\246\022\214\324\142\170\352\126\152\354\012\322\100\303\074
\005\060\076\115\224\267\237\112\003\323\175\047\113\266\376\104
\316\372\031\063\032\155\244\102\321\335\314\310\310\327\026\122
\203\117\065\224\263\022\125\175\345\342\102\353\344\234\223\011
\300\114\133\007\253\307\155\021\240\120\027\224\043\250\265\012
\222\017\262\172\301\140\054\070\314\032\246\133\377\362\014\343
\252\037\034\334\270\240\223\047\336\143\343\177\041\237\072\345
\236\372\340\023\152\165\353\226\134\142\221\224\216\147\123\266
\211\370\022\011\313\157\122\133\003\162\206\120\225\010\324\215
\207\206\025\037\225\044\330\244\157\232\316\244\235\233\155\322
\262\166\006\206\306\126\010\305\353\011\332\066\302\033\133\101
\276\141\052\343\160\346\270\246\370\266\132\304\275\041\367\377
\252\137\241\154\166\071\146\326\352\114\125\341\000\063\233\023
\230\143\311\157\320\001\040\011\067\122\347\014\117\076\315\274
\365\137\226\047\247\040\002\225\340\056\350\007\101\005\037\025
\156\326\260\344\031\340\017\002\223\000\047\162\305\213\321\124
\037\135\112\303\100\227\176\125\246\174\301\063\004\024\001\035
\111\040\151\013\031\223\235\156\130\042\367\100\014\106\014\043
\143\363\071\322\177\166\121\247\364\310\241\361\014\166\042\043
\106\122\051\055\342\243\101\007\126\151\230\322\005\011\274\151
\307\132\141\315\217\201\140\025\115\200\335\220\342\175\304\120
\362\214\073\156\112\307\306\346\200\053\074\201\274\021\200\026
\020\047\327\360\315\077\171\314\163\052\303\176\123\221\326\156
\370\365\363\307\320\121\115\216\113\245\133\346\031\027\073\326
\201\011\334\042\334\356\216\271\304\217\123\341\147\273\063\270
\210\025\106\317\355\151\065\377\165\015\106\363\316\161\341\305
\153\206\102\006\271\101
END
CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE
# Trust for "Certinomis - Root CA"
# Issuer: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR
# Serial Number: 1 (0x1)
# Subject: CN=Certinomis - Root CA,OU=0002 433998903,O=Certinomis,C=FR
# Not Valid Before: Mon Oct 21 09:17:18 2013
# Not Valid After : Fri Oct 21 09:17:18 2033
# Fingerprint (SHA-256): 2A:99:F5:BC:11:74:B7:3C:BB:1D:62:08:84:E0:1C:34:E5:1C:CB:39:78:DA:12:5F:0E:33:26:88:83:BF:41:58
# Fingerprint (SHA1): 9D:70:BB:01:A5:A4:A0:18:11:2E:F7:1C:01:B9:32:C5:34:E7:88:A8
CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST
CKA_TOKEN CK_BBOOL CK_TRUE
CKA_PRIVATE CK_BBOOL CK_FALSE
CKA_MODIFIABLE CK_BBOOL CK_FALSE
CKA_LABEL UTF8 "Certinomis - Root CA"
CKA_CERT_SHA1_HASH MULTILINE_OCTAL
\235\160\273\001\245\244\240\030\021\056\367\034\001\271\062\305
\064\347\210\250
END
CKA_CERT_MD5_HASH MULTILINE_OCTAL
\024\012\375\215\250\050\265\070\151\333\126\176\141\042\003\077
END
CKA_ISSUER MULTILINE_OCTAL
\060\132\061\013\060\011\006\003\125\004\006\023\002\106\122\061
\023\060\021\006\003\125\004\012\023\012\103\145\162\164\151\156
\157\155\151\163\061\027\060\025\006\003\125\004\013\023\016\060
\060\060\062\040\064\063\063\071\071\070\071\060\063\061\035\060
\033\006\003\125\004\003\023\024\103\145\162\164\151\156\157\155
\151\163\040\055\040\122\157\157\164\040\103\101
END
CKA_SERIAL_NUMBER MULTILINE_OCTAL
\002\001\001
END
CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST
CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE
#
# Certificate "OISTE WISeKey Global Root GB CA"
#

Просмотреть файл

@ -46,8 +46,8 @@
* It's recommend to switch back to 0 after having reached version 98/99.
*/
#define NSS_BUILTINS_LIBRARY_VERSION_MAJOR 2
#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 32
#define NSS_BUILTINS_LIBRARY_VERSION "2.32"
#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 34
#define NSS_BUILTINS_LIBRARY_VERSION "2.34"
/* These version numbers detail the semantic changes to the ckfw engine. */
#define NSS_BUILTINS_HARDWARE_VERSION_MAJOR 1

Просмотреть файл

@ -15,8 +15,10 @@
#include "seccomon.h" /* Required for RSA and DSA. */
#include "secerr.h"
#include "prtypes.h"
#include "secitem.h"
#include "pkcs11t.h"
#include "ec.h" /* Required for ECDSA */
#include "ec.h" /* Required for EC */
/*
* different platforms have different ways of calling and initial entry point
@ -288,6 +290,8 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
/* AES Known Plaintext (128-bits). (blocksize is 128-bits) */
static const PRUint8 aes_known_plaintext[] = { "NetscapeepacsteN" };
static const PRUint8 aes_gcm_known_aad[] = { "MozillaallizoM" };
/* AES Known Ciphertext (128-bit key). */
static const PRUint8 aes_ecb128_known_ciphertext[] = {
0x3c, 0xa5, 0x96, 0xf3, 0x34, 0x6a, 0x96, 0xc1,
@ -299,6 +303,13 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0x15, 0x54, 0x14, 0x1d, 0x4e, 0xd8, 0xd5, 0xea
};
static const PRUint8 aes_gcm128_known_ciphertext[] = {
0x63, 0xf4, 0x95, 0x28, 0xe6, 0x78, 0xee, 0x6e,
0x4f, 0xe0, 0xfc, 0x8d, 0xd7, 0xa2, 0xb1, 0xff,
0x0c, 0x97, 0x1b, 0x0a, 0xdd, 0x97, 0x75, 0xed,
0x8b, 0xde, 0xbf, 0x16, 0x5e, 0x57, 0x6b, 0x4f
};
/* AES Known Ciphertext (192-bit key). */
static const PRUint8 aes_ecb192_known_ciphertext[] = {
0xa0, 0x18, 0x62, 0xed, 0x88, 0x19, 0xcb, 0x62,
@ -310,6 +321,13 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0x07, 0xbc, 0x43, 0x2f, 0x6d, 0xad, 0x29, 0xe1
};
static const PRUint8 aes_gcm192_known_ciphertext[] = {
0xc1, 0x0b, 0x92, 0x1d, 0x68, 0x21, 0xf4, 0x25,
0x41, 0x61, 0x20, 0x2d, 0x59, 0x7f, 0x53, 0xde,
0x93, 0x39, 0xab, 0x09, 0x76, 0x41, 0x57, 0x2b,
0x90, 0x2e, 0x44, 0xbb, 0x52, 0x03, 0xe9, 0x07
};
/* AES Known Ciphertext (256-bit key). */
static const PRUint8 aes_ecb256_known_ciphertext[] = {
0xdb, 0xa6, 0x52, 0x01, 0x8a, 0x70, 0xae, 0x66,
@ -321,18 +339,29 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
0xc5, 0xc5, 0x68, 0x71, 0x6e, 0x34, 0x40, 0x16
};
static const PRUint8 aes_gcm256_known_ciphertext[] = {
0x5d, 0x9e, 0xd2, 0xa2, 0x74, 0x9c, 0xd9, 0x1c,
0xd1, 0xc9, 0xee, 0x5d, 0xb6, 0xf2, 0xc9, 0xb6,
0x79, 0x27, 0x53, 0x02, 0xa3, 0xdc, 0x22, 0xce,
0xf4, 0xb0, 0xc1, 0x8c, 0x86, 0x51, 0xf5, 0xa1
};
const PRUint8 *aes_ecb_known_ciphertext =
(aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_ecb128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_ecb192_known_ciphertext : aes_ecb256_known_ciphertext;
const PRUint8 *aes_cbc_known_ciphertext =
(aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_cbc128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_cbc192_known_ciphertext : aes_cbc256_known_ciphertext;
const PRUint8 *aes_gcm_known_ciphertext =
(aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_gcm128_known_ciphertext : (aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_gcm192_known_ciphertext : aes_gcm256_known_ciphertext;
/* AES variables. */
PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH];
PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH];
PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH * 2];
PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH * 2];
AESContext *aes_context;
unsigned int aes_bytes_encrypted;
unsigned int aes_bytes_decrypted;
CK_GCM_PARAMS gcmParams;
SECStatus aes_status;
/*check if aes_key_size is 128, 192, or 256 bits */
@ -455,6 +484,69 @@ freebl_fips_AES_PowerUpSelfTest(int aes_key_size)
return (SECFailure);
}
/******************************************************/
/* AES-GCM Single-Round Known Answer Encryption Test. */
/******************************************************/
gcmParams.pIv = (PRUint8 *)aes_cbc_known_initialization_vector;
gcmParams.ulIvLen = FIPS_AES_BLOCK_SIZE;
gcmParams.pAAD = (PRUint8 *)aes_gcm_known_aad;
gcmParams.ulAADLen = sizeof(aes_gcm_known_aad);
gcmParams.ulTagBits = FIPS_AES_BLOCK_SIZE * 8;
aes_context = AES_CreateContext(aes_known_key,
(PRUint8 *)&gcmParams,
NSS_AES_GCM, PR_TRUE, aes_key_size,
FIPS_AES_BLOCK_SIZE);
if (aes_context == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return (SECFailure);
}
aes_status = AES_Encrypt(aes_context, aes_computed_ciphertext,
&aes_bytes_encrypted, FIPS_AES_ENCRYPT_LENGTH * 2,
aes_known_plaintext,
FIPS_AES_DECRYPT_LENGTH);
AES_DestroyContext(aes_context, PR_TRUE);
if ((aes_status != SECSuccess) ||
(aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH * 2) ||
(PORT_Memcmp(aes_computed_ciphertext, aes_gcm_known_ciphertext,
FIPS_AES_ENCRYPT_LENGTH * 2) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
/******************************************************/
/* AES-GCM Single-Round Known Answer Decryption Test. */
/******************************************************/
aes_context = AES_CreateContext(aes_known_key,
(PRUint8 *)&gcmParams,
NSS_AES_GCM, PR_FALSE, aes_key_size,
FIPS_AES_BLOCK_SIZE);
if (aes_context == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return (SECFailure);
}
aes_status = AES_Decrypt(aes_context, aes_computed_plaintext,
&aes_bytes_decrypted, FIPS_AES_DECRYPT_LENGTH * 2,
aes_gcm_known_ciphertext,
FIPS_AES_ENCRYPT_LENGTH * 2);
AES_DestroyContext(aes_context, PR_TRUE);
if ((aes_status != SECSuccess) ||
(aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH) ||
(PORT_Memcmp(aes_computed_plaintext, aes_known_plaintext,
FIPS_AES_DECRYPT_LENGTH) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
return (SECSuccess);
}
@ -1094,7 +1186,7 @@ freebl_fips_ECDSA_Test(ECParams *ecparams,
"Firefox and ThunderBird are awesome!"
};
unsigned char sha1[SHA1_LENGTH]; /* SHA-1 hash (160 bits) */
unsigned char sha256[SHA256_LENGTH]; /* SHA-256 hash (256 bits) */
unsigned char sig[2 * MAX_ECKEY_LEN];
SECItem signature, digest;
ECPrivateKey *ecdsa_private_key = NULL;
@ -1136,13 +1228,13 @@ freebl_fips_ECDSA_Test(ECParams *ecparams,
/* ECDSA Single-Round Known Answer Signature Test. */
/***************************************************/
ecdsaStatus = SHA1_HashBuf(sha1, msg, sizeof msg);
ecdsaStatus = SHA256_HashBuf(sha256, msg, sizeof msg);
if (ecdsaStatus != SECSuccess) {
goto loser;
}
digest.type = siBuffer;
digest.data = sha1;
digest.len = SHA1_LENGTH;
digest.data = sha256;
digest.len = SHA256_LENGTH;
memset(sig, 0, sizeof sig);
signature.type = siBuffer;
@ -1181,10 +1273,83 @@ loser:
}
static SECStatus
freebl_fips_ECDSA_PowerUpSelfTest()
freebl_fips_ECDH_Test(ECParams *ecparams)
{
/* ECDSA Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
/* ECDH Known result (reused old CAVS vector) */
static const PRUint8 ecdh_known_pub_key_1[] = {
EC_POINT_FORM_UNCOMPRESSED,
/* pubX */
0x16, 0x81, 0x32, 0x86, 0xc8, 0xe4, 0x3a, 0x1f,
0x5d, 0xe3, 0x06, 0x22, 0x8b, 0x99, 0x14, 0x25,
0xf7, 0x9c, 0x5b, 0x1e, 0x96, 0x84, 0x85, 0x3b,
0x17, 0xfe, 0xf3, 0x1c, 0x0e, 0xed, 0xc4, 0xce,
/* pubY */
0x7a, 0x44, 0xfe, 0xbd, 0x91, 0x71, 0x7d, 0x73,
0xd9, 0x45, 0xea, 0xae, 0x66, 0x78, 0xfa, 0x6e,
0x46, 0xcd, 0xfa, 0x95, 0x15, 0x47, 0x62, 0x5d,
0xbb, 0x1b, 0x9f, 0xe6, 0x39, 0xfc, 0xfd, 0x47
};
static const PRUint8 ecdh_known_priv_key_2[] = {
0xb4, 0x2a, 0xe3, 0x69, 0x19, 0xec, 0xf0, 0x42,
0x6d, 0x45, 0x8c, 0x94, 0x4a, 0x26, 0xa7, 0x5c,
0xea, 0x9d, 0xd9, 0x0f, 0x59, 0xe0, 0x1a, 0x9d,
0x7c, 0xb7, 0x1c, 0x04, 0x53, 0xb8, 0x98, 0x5a
};
static const PRUint8 ecdh_known_hash_result[] = {
0x16, 0xf3, 0x85, 0xa2, 0x41, 0xf3, 0x7f, 0xc4,
0x0b, 0x56, 0x47, 0xee, 0xa7, 0x74, 0xb9, 0xdb,
0xe1, 0xfa, 0x22, 0xe9, 0x04, 0xf1, 0xb6, 0x12,
0x4b, 0x44, 0x8a, 0xbb, 0xbc, 0x08, 0x2b, 0xa7,
};
SECItem ecdh_priv_2, ecdh_pub_1;
SECItem ZZ = { 0, 0, 0 };
SECStatus ecdhStatus = SECSuccess;
PRUint8 computed_hash_result[HASH_LENGTH_MAX];
ecdh_priv_2.data = (PRUint8 *)ecdh_known_priv_key_2;
ecdh_priv_2.len = sizeof(ecdh_known_priv_key_2);
ecdh_pub_1.data = (PRUint8 *)ecdh_known_pub_key_1;
ecdh_pub_1.len = sizeof(ecdh_known_pub_key_1);
/* Generates a new EC key pair. The private key is a supplied
* random value (in seed) and the public key is the result of
* performing a scalar point multiplication of that value with
* the curve's base point.
*/
ecdhStatus = ECDH_Derive(&ecdh_pub_1, ecparams, &ecdh_priv_2, PR_FALSE, &ZZ);
if (ecdhStatus != SECSuccess) {
goto loser;
}
ecdhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
if (ecdhStatus != SECSuccess) {
goto loser;
}
if (PORT_Memcmp(computed_hash_result, ecdh_known_hash_result,
sizeof(ecdh_known_hash_result)) != 0) {
ecdhStatus = SECFailure;
goto loser;
}
loser:
if (ZZ.data) {
SECITEM_FreeItem(&ZZ, PR_FALSE);
}
if (ecdhStatus != SECSuccess) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
return (SECSuccess);
}
static SECStatus
freebl_fips_EC_PowerUpSelfTest()
{
/* EC Known curve nistp256 == ECCCurve_X9_62_PRIME_256V1 params */
static const unsigned char p256_prime[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@ -1217,7 +1382,7 @@ freebl_fips_ECDSA_PowerUpSelfTest()
static const unsigned char p256_encoding[] = {
0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
};
static const ECParams ecdsa_known_P256_Params = {
static const ECParams ec_known_P256_Params = {
NULL, ec_params_named, /* arena, type */
/* fieldID */
{ 256, ec_field_GFp, /* size and type */
@ -1250,10 +1415,10 @@ freebl_fips_ECDSA_PowerUpSelfTest()
0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff,
0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f,
0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5,
0x59, 0x6a, 0x62, 0x49, 0x3d, 0x50, 0xc9, 0xe1,
0x27, 0x3b, 0xff, 0x9b, 0x13, 0x66, 0x67, 0xdd,
0x7d, 0xd1, 0x0d, 0x2d, 0x7c, 0x44, 0x04, 0x1b,
0x16, 0x21, 0x12, 0xc5, 0xcb, 0xbd, 0x9e, 0x75
0xa7, 0xd2, 0x20, 0xdd, 0x45, 0xf9, 0x2b, 0xdd,
0xda, 0x98, 0x99, 0x5b, 0x1c, 0x02, 0x3a, 0x27,
0x8b, 0x7d, 0xb6, 0xed, 0x0e, 0xe0, 0xa7, 0xac,
0xaa, 0x36, 0x2c, 0xfa, 0x1a, 0xdf, 0x0d, 0xe1,
};
ECParams ecparams;
@ -1261,13 +1426,18 @@ freebl_fips_ECDSA_PowerUpSelfTest()
SECStatus rv;
/* ECDSA GF(p) prime field curve test */
ecparams = ecdsa_known_P256_Params;
ecparams = ec_known_P256_Params;
rv = freebl_fips_ECDSA_Test(&ecparams,
ecdsa_known_P256_signature,
sizeof ecdsa_known_P256_signature);
if (rv != SECSuccess) {
return (SECFailure);
}
/* ECDH GF(p) prime field curve test */
rv = freebl_fips_ECDH_Test(&ecparams);
if (rv != SECSuccess) {
return (SECFailure);
}
return (SECSuccess);
}
@ -1417,6 +1587,138 @@ freebl_fips_DSA_PowerUpSelfTest(void)
return (SECSuccess);
}
static SECStatus
freebl_fips_DH_PowerUpSelfTest(void)
{
/* DH Known P (2048-bits) */
static const PRUint8 dh_known_P[] = {
0xc2, 0x79, 0xbb, 0x76, 0x32, 0x0d, 0x43, 0xfd,
0x1b, 0x8c, 0xa2, 0x3c, 0x00, 0xdd, 0x6d, 0xef,
0xf8, 0x1a, 0xd9, 0xc1, 0xa2, 0xf5, 0x73, 0x2b,
0xdb, 0x1a, 0x3e, 0x84, 0x90, 0xeb, 0xe7, 0x8e,
0x5f, 0x5c, 0x6b, 0xb6, 0x61, 0x89, 0xd1, 0x03,
0xb0, 0x5f, 0x91, 0xe4, 0xd2, 0x82, 0x90, 0xfc,
0x3c, 0x49, 0x69, 0x59, 0xc1, 0x51, 0x6a, 0x85,
0x71, 0xe7, 0x5d, 0x72, 0x5a, 0x45, 0xad, 0x01,
0x6f, 0x82, 0xae, 0xec, 0x91, 0x08, 0x2e, 0x7c,
0x64, 0x93, 0x46, 0x1c, 0x68, 0xef, 0xc2, 0x03,
0x28, 0x1d, 0x75, 0x3a, 0xeb, 0x9c, 0x46, 0xf0,
0xc9, 0xdb, 0x99, 0x95, 0x13, 0x66, 0x4d, 0xd5,
0x1a, 0x78, 0x92, 0x51, 0x89, 0x72, 0x28, 0x7f,
0x20, 0x70, 0x41, 0x49, 0xa2, 0x86, 0xe9, 0xf9,
0x78, 0x5f, 0x8d, 0x2e, 0x5d, 0xfa, 0xdb, 0x57,
0xd4, 0x71, 0xdf, 0x66, 0xe3, 0x9e, 0x88, 0x70,
0xa4, 0x21, 0x44, 0x6a, 0xc7, 0xae, 0x30, 0x2c,
0x9c, 0x1f, 0x91, 0x57, 0xc8, 0x24, 0x34, 0x2d,
0x7a, 0x4a, 0x43, 0xc2, 0x5f, 0xab, 0x64, 0x2e,
0xaa, 0x28, 0x32, 0x95, 0x42, 0x7b, 0xa0, 0xcc,
0xdf, 0xfd, 0x22, 0xc8, 0x56, 0x84, 0xc1, 0x62,
0x15, 0xb2, 0x77, 0x86, 0x81, 0xfc, 0xa5, 0x12,
0x3c, 0xca, 0x28, 0x17, 0x8f, 0x03, 0x16, 0x6e,
0xb8, 0x24, 0xfa, 0x1b, 0x15, 0x02, 0xfd, 0x8b,
0xb6, 0x0a, 0x1a, 0xf7, 0x47, 0x41, 0xc5, 0x2b,
0x37, 0x3e, 0xa1, 0xbf, 0x68, 0xda, 0x1c, 0x55,
0x44, 0xc3, 0xee, 0xa1, 0x63, 0x07, 0x11, 0x3b,
0x5f, 0x00, 0x84, 0xb4, 0xc4, 0xe4, 0xa7, 0x97,
0x29, 0xf8, 0xce, 0xab, 0xfc, 0x27, 0x3e, 0x34,
0xe4, 0xc7, 0x81, 0x52, 0x32, 0x0e, 0x27, 0x3c,
0xa6, 0x70, 0x3f, 0x4a, 0x54, 0xda, 0xdd, 0x60,
0x26, 0xb3, 0x6e, 0x45, 0x26, 0x19, 0x41, 0x6f
};
static const PRUint8 dh_known_Y_1[] = {
0xb4, 0xc7, 0x85, 0xba, 0xa6, 0x98, 0xb3, 0x77,
0x41, 0x2b, 0xd9, 0x9a, 0x72, 0x90, 0xa4, 0xac,
0xc4, 0xf7, 0xc2, 0x23, 0x9a, 0x68, 0xe2, 0x7d,
0x3a, 0x54, 0x45, 0x91, 0xc1, 0xd7, 0x8a, 0x17,
0x54, 0xd3, 0x37, 0xaa, 0x0c, 0xcd, 0x0b, 0xe2,
0xf2, 0x34, 0x0f, 0x17, 0xa8, 0x07, 0x88, 0xaf,
0xed, 0xc1, 0x02, 0xd4, 0xdb, 0xdc, 0x0f, 0x22,
0x51, 0x23, 0x40, 0xb9, 0x65, 0x6d, 0x39, 0xf4,
0xe1, 0x8b, 0x57, 0x7d, 0xb6, 0xd3, 0xf2, 0x6b,
0x02, 0xa9, 0x36, 0xf0, 0x0d, 0xe3, 0xdb, 0x9a,
0xbf, 0x20, 0x00, 0x4d, 0xec, 0x6f, 0x68, 0x95,
0xee, 0x59, 0x4e, 0x3c, 0xb6, 0xda, 0x7b, 0x19,
0x08, 0x9a, 0xef, 0x61, 0x43, 0xf5, 0xfb, 0x25,
0x70, 0x19, 0xc1, 0x5f, 0x0e, 0x0f, 0x6a, 0x63,
0x44, 0xe9, 0xcf, 0x33, 0xce, 0x13, 0x4f, 0x34,
0x3c, 0x94, 0x40, 0x8d, 0xf2, 0x65, 0x42, 0xef,
0x70, 0x54, 0xdd, 0x5f, 0xc1, 0xd7, 0x0b, 0xa6,
0x06, 0xd5, 0xa6, 0x47, 0xae, 0x2c, 0x1f, 0x5a,
0xa6, 0xb3, 0xc1, 0x38, 0x3a, 0x3b, 0x60, 0x94,
0xa2, 0x95, 0xab, 0xb2, 0x86, 0x82, 0xc5, 0x3b,
0xb8, 0x6f, 0x3e, 0x55, 0x86, 0x84, 0xe0, 0x00,
0xe5, 0xef, 0xca, 0x5c, 0xec, 0x7e, 0x38, 0x0f,
0x82, 0xa2, 0xb1, 0xee, 0x48, 0x1b, 0x32, 0xbb,
0x5a, 0x33, 0xa5, 0x01, 0xba, 0xca, 0xa6, 0x64,
0x61, 0xb6, 0xe5, 0x5c, 0x0e, 0x5f, 0x2c, 0x66,
0x0d, 0x01, 0x6a, 0x20, 0x04, 0x70, 0x68, 0x82,
0x93, 0x29, 0x15, 0x3b, 0x7a, 0x06, 0xb2, 0x92,
0x61, 0xcd, 0x7e, 0xa4, 0xc1, 0x15, 0x64, 0x3b,
0x3c, 0x51, 0x10, 0x4c, 0x87, 0xa6, 0xaf, 0x07,
0xce, 0x46, 0x82, 0x75, 0xf3, 0x90, 0xf3, 0x21,
0x55, 0x74, 0xc2, 0xe4, 0x96, 0x7d, 0xc3, 0xe6,
0x33, 0xa5, 0xc6, 0x51, 0xef, 0xec, 0x90, 0x08
};
static const PRUint8 dh_known_x_2[] = {
0x9e, 0x9b, 0xc3, 0x25, 0x53, 0xf9, 0xfc, 0x92,
0xb6, 0xae, 0x54, 0x8e, 0x23, 0x4c, 0x94, 0xba,
0x41, 0xe6, 0x29, 0x33, 0xb9, 0xdb, 0xff, 0x6d,
0xa8, 0xb8, 0x48, 0x49, 0x66, 0x11, 0xa6, 0x13
};
static const PRUint8 dh_known_hash_result[] = {
0x93, 0xa2, 0x89, 0x1c, 0x8a, 0xc3, 0x70, 0xbf,
0xa7, 0xdf, 0xb6, 0xd7, 0x82, 0xfb, 0x87, 0x81,
0x09, 0x47, 0xf3, 0x9f, 0x5a, 0xbf, 0x4f, 0x3f,
0x8e, 0x5e, 0x06, 0xca, 0x30, 0xa7, 0xaf, 0x10
};
/* DH variables. */
SECStatus dhStatus;
SECItem dh_prime;
SECItem dh_pub_key_1;
SECItem dh_priv_key_2;
SECItem ZZ = { 0, 0, 0 };
PRUint8 computed_hash_result[HASH_LENGTH_MAX];
dh_prime.data = (PRUint8 *)dh_known_P;
dh_prime.len = sizeof(dh_known_P);
dh_pub_key_1.data = (PRUint8 *)dh_known_Y_1;
dh_pub_key_1.len = sizeof(dh_known_Y_1);
dh_priv_key_2.data = (PRUint8 *)dh_known_x_2;
dh_priv_key_2.len = sizeof(dh_known_x_2);
/* execute the derive */
dhStatus = DH_Derive(&dh_pub_key_1, &dh_prime, &dh_priv_key_2, &ZZ, dh_prime.len);
if (dhStatus != SECSuccess) {
goto loser;
}
dhStatus = SHA256_HashBuf(computed_hash_result, ZZ.data, ZZ.len);
if (dhStatus != SECSuccess) {
goto loser;
}
if (PORT_Memcmp(computed_hash_result, dh_known_hash_result,
sizeof(dh_known_hash_result)) != 0) {
dhStatus = SECFailure;
goto loser;
}
loser:
if (ZZ.data) {
SECITEM_FreeItem(&ZZ, PR_FALSE);
}
if (dhStatus != SECSuccess) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return (SECFailure);
}
return (SECSuccess);
}
static SECStatus
freebl_fips_RNG_PowerUpSelfTest(void)
{
@ -1541,7 +1843,7 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
return rv;
/* NOTE: RSA can only be tested in full freebl. It requires access to
* the locking primitives */
* the locking primitives */
/* RSA Power-Up SelfTest(s). */
rv = freebl_fips_RSA_PowerUpSelfTest();
@ -1554,8 +1856,14 @@ freebl_fipsPowerUpSelfTest(unsigned int tests)
if (rv != SECSuccess)
return rv;
/* ECDSA Power-Up SelfTest(s). */
rv = freebl_fips_ECDSA_PowerUpSelfTest();
/* DH Power-Up SelfTest(s). */
rv = freebl_fips_DH_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;
/* EC Power-Up SelfTest(s). */
rv = freebl_fips_EC_PowerUpSelfTest();
if (rv != SECSuccess)
return rv;

Просмотреть файл

@ -143,6 +143,7 @@ loser:
void
intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit)
{
PORT_Memset(gcm, 0, sizeof(intel_AES_GCMContext));
if (freeit) {
PORT_Free(gcm);
}

Просмотреть файл

@ -491,11 +491,11 @@ cleanup:
** This implments steps 4 thorough 22 of FIPS 186-3 A.1.2.1 and
** steps 16 through 34 of FIPS 186-2 C.6
*/
#define MAX_ST_SEED_BITS (HASH_LENGTH_MAX * PR_BITS_PER_BYTE)
static SECStatus
makePrimefromPrimesShaweTaylor(
HASH_HashType hashtype, /* selected Hashing algorithm */
unsigned int length, /* input. Length of prime in bits. */
unsigned int seedlen, /* input seed length in bits */
mp_int *c0, /* seed prime */
mp_int *q, /* sub prime, can be 1 */
mp_int *prime, /* output. */
@ -557,7 +557,7 @@ makePrimefromPrimesShaweTaylor(
old_counter = *prime_gen_counter;
/*
** Comment: Generate a pseudorandom integer x in the interval
** [2**(lenght-1), 2**length].
** [2**(length-1), 2**length].
**
** Step 6/18 x = 0
*/
@ -569,11 +569,10 @@ makePrimefromPrimesShaweTaylor(
for (i = 0; i < iterations; i++) {
/* is bigger than prime_seed should get to */
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
seedlen, &x[(iterations - i - 1) * hashlen]));
}
/* Step 8/20 prime_seed = prime_seed + iterations + 1 */
CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
prime_seed));
CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
/*
** Step 9/21 x = 2 ** (length-1) + x mod 2 ** (length-1)
**
@ -595,7 +594,7 @@ makePrimefromPrimesShaweTaylor(
x[offset] = (mask & x[offset]) | bit;
/*
** Comment: Generate a candidate prime c in the interval
** [2**(lenght-1), 2**length].
** [2**(length-1), 2**length].
**
** Step 10 t = ceiling(x/(2q(p0)))
** Step 22 t = ceiling(x/(2(c0)))
@ -624,7 +623,7 @@ step_23:
/* t = 2**(length-1) + 2qc0 -1 */
CHECK_MPI_OK(mp_add(&two_length_minus_1, &t, &t));
/* t = floor((2**(length-1)+2qc0 -1)/2qco)
* = ceil(2**(lenght-2)/2qc0) */
* = ceil(2**(length-2)/2qc0) */
CHECK_MPI_OK(mp_div(&t, &c0_2, &t, NULL));
CHECK_MPI_OK(mp_mul(&t, &c0_2, &c));
CHECK_MPI_OK(mp_add_d(&c, (mp_digit)1, &c)); /* c= 2tqc0 + 1*/
@ -645,13 +644,11 @@ step_23:
** NOTE: we reuse the x array for 'a' initially.
*/
for (i = 0; i < iterations; i++) {
/* MAX_ST_SEED_BITS is bigger than prime_seed should get to */
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, i,
MAX_ST_SEED_BITS, &x[(iterations - i - 1) * hashlen]));
seedlen, &x[(iterations - i - 1) * hashlen]));
}
/* Step 16/28 prime_seed = prime_seed + iterations + 1 */
CHECK_SEC_OK(addToSeed(prime_seed, iterations, MAX_ST_SEED_BITS,
prime_seed));
CHECK_SEC_OK(addToSeed(prime_seed, iterations, seedlen, prime_seed));
/* Step 17/29 a = 2 + (a mod (c-3)). */
CHECK_MPI_OK(mp_read_unsigned_octets(&a, x, iterations * hashlen));
CHECK_MPI_OK(mp_sub_d(&c, (mp_digit)3, &z)); /* z = c -3 */
@ -742,6 +739,7 @@ makePrimefromSeedShaweTaylor(
int hashlen = HASH_ResultLen(hashtype);
int outlen = hashlen * PR_BITS_PER_BYTE;
int offset;
int seedlen = input_seed->len * 8; /*seedlen is in bits */
unsigned char bit, mask;
unsigned char x[HASH_LENGTH_MAX * 2];
mp_digit dummy;
@ -775,7 +773,7 @@ makePrimefromSeedShaweTaylor(
goto cleanup;
}
/* Steps 16-34 */
rv = makePrimefromPrimesShaweTaylor(hashtype, length, &c0, &one,
rv = makePrimefromPrimesShaweTaylor(hashtype, length, seedlen, &c0, &one,
prime, prime_seed, prime_gen_counter);
goto cleanup; /* we're done, one way or the other */
}
@ -787,8 +785,7 @@ makePrimefromSeedShaweTaylor(
step_5:
/* Step 5 c = Hash(prime_seed) xor Hash(prime_seed+1). */
CHECK_SEC_OK(HASH_HashBuf(hashtype, x, prime_seed->data, prime_seed->len));
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1,
MAX_ST_SEED_BITS, &x[hashlen]));
CHECK_SEC_OK(addToSeedThenHash(hashtype, prime_seed, 1, seedlen, &x[hashlen]));
for (i = 0; i < hashlen; i++) {
x[i] = x[i] ^ x[i + hashlen];
}
@ -817,7 +814,7 @@ step_5:
/* Step 8 prime_gen_counter = prime_gen_counter + 1 */
(*prime_gen_counter)++;
/* Step 9 prime_seed = prime_seed + 2 */
CHECK_SEC_OK(addToSeed(prime_seed, 2, MAX_ST_SEED_BITS, prime_seed));
CHECK_SEC_OK(addToSeed(prime_seed, 2, seedlen, prime_seed));
/* Step 10 Perform deterministic primality test on c. For example, since
** c is small, it's primality can be tested by trial division, See
** See Appendic C.7.
@ -890,7 +887,8 @@ findQfromSeed(
mp_int *Q_, /* output. */
unsigned int *qseed_len, /* output */
HASH_HashType *hashtypePtr, /* output. Hash uses */
pqgGenType *typePtr) /* output. Generation Type used */
pqgGenType *typePtr, /* output. Generation Type used */
unsigned int *qgen_counter) /* output. q_counter */
{
HASH_HashType hashtype;
SECItem firstseed = { 0, 0, 0 };
@ -964,6 +962,7 @@ findQfromSeed(
*qseed_len = qseed.len;
*hashtypePtr = hashtype;
*typePtr = FIPS186_3_ST_TYPE;
*qgen_counter = count;
SECITEM_FreeItem(&qseed, PR_FALSE);
return SECSuccess;
}
@ -1390,19 +1389,26 @@ step_5:
CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
&qseed, &p0, &pseed, &pgen_counter));
/* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, seedBytes * 8,
&p0, &Q, &P, &pseed, &pgen_counter));
/* combine all the seeds */
seed->len = firstseed.len + qseed.len + pseed.len;
if ((qseed.len > firstseed.len) || (pseed.len > firstseed.len)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); /* shouldn't happen */
goto cleanup;
}
/* If the seed overflows, then pseed and qseed may have leading zeros which the mpl code clamps.
* we want to make sure those are added back in so the individual seed lengths are predictable from
* the overall seed length */
seed->len = firstseed.len * 3;
seed->data = PORT_ArenaZAlloc(verify->arena, seed->len);
if (seed->data == NULL) {
goto cleanup;
}
PORT_Memcpy(seed->data, firstseed.data, firstseed.len);
PORT_Memcpy(seed->data + firstseed.len, pseed.data, pseed.len);
PORT_Memcpy(seed->data + firstseed.len + pseed.len, qseed.data, qseed.len);
counter = 0; /* (qgen_counter << 16) | pgen_counter; */
PORT_Memcpy(seed->data + 2 * firstseed.len - pseed.len, pseed.data, pseed.len);
PORT_Memcpy(seed->data + 3 * firstseed.len - qseed.len, qseed.data, qseed.len);
counter = (qgen_counter << 16) | pgen_counter;
/* we've generated both P and Q now, skip to generating G */
goto generate_G;
@ -1622,6 +1628,7 @@ PQG_VerifyParams(const PQGParams *params,
int j;
unsigned int counter_max = 0; /* handle legacy L < 1024 */
unsigned int qseed_len;
unsigned int qgen_counter_ = 0;
SECItem pseed_ = { 0, 0, 0 };
HASH_HashType hashtype;
pqgGenType type;
@ -1701,48 +1708,55 @@ PQG_VerifyParams(const PQGParams *params,
/* Steps 7-12 are done only if the optional PQGVerify is supplied. */
/* continue processing P */
/* 7. counter < 4*L */
CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
/* 8. g >= N and g < 2*L (g is length of seed in bits) */
g = vfy->seed.len * 8;
CHECKPARAM(g >= N && g < counter_max / 2);
/* step 7 and 8 are delayed until we determine which type of generation
* was used */
/* 9. Q generated from SEED matches Q in PQGParams. */
/* This function checks all possible hash and generation types to
* find a Q_ which matches Q. */
g = vfy->seed.len * 8;
CHECKPARAM(findQfromSeed(L, N, g, &vfy->seed, &Q, &Q_, &qseed_len,
&hashtype, &type) == SECSuccess);
&hashtype, &type, &qgen_counter_) == SECSuccess);
CHECKPARAM(mp_cmp(&Q, &Q_) == 0);
/* now we can do steps 7 & 8*/
if ((type == FIPS186_1_TYPE) || (type == FIPS186_3_TYPE)) {
CHECKPARAM((vfy->counter == -1) || (vfy->counter < counter_max));
CHECKPARAM(g >= N && g < counter_max / 2);
}
if (type == FIPS186_3_ST_TYPE) {
SECItem qseed = { 0, 0, 0 };
SECItem pseed = { 0, 0, 0 };
unsigned int first_seed_len;
unsigned int pgen_counter = 0;
unsigned int pgen_counter_ = 0;
unsigned int qgen_counter = (vfy->counter >> 16) & 0xffff;
unsigned int pgen_counter = (vfy->counter) & 0xffff;
/* extract pseed and qseed from domain_parameter_seed, which is
* first_seed || pseed || qseed. qseed is first_seed + small_integer
* pseed is qseed + small_integer. This means most of the time
* mod the length of first_seed. pseed is qseed + small_integer mod
* the length of first_seed. This means most of the time
* first_seed.len == qseed.len == pseed.len. Rarely qseed.len and/or
* pseed.len will be one greater than first_seed.len, so we can
* depend on the fact that
* first_seed.len = floor(domain_parameter_seed.len/3).
* findQfromSeed returned qseed.len, so we can calculate pseed.len as
* pseed.len = domain_parameter_seed.len - first_seed.len - qseed.len
* this is probably over kill, since 99.999% of the time they will all
* be equal.
*
* With the lengths, we can now find the offsets;
* pseed.len will be smaller because mpi clamps them. pqgGen
* automatically adds the zero pad back though, so we can depend
* domain_parameter_seed.len to be a multiple of three. We only have
* to deal with the fact that the returned seeds from our functions
* could be shorter.
* first_seed.len = domain_parameter_seed.len/3
* We can now find the offsets;
* first_seed.data = domain_parameter_seed.data + 0
* pseed.data = domain_parameter_seed.data + first_seed.len
* qseed.data = domain_parameter_seed.data
* + domain_paramter_seed.len - qseed.len
*
* We deal with pseed possibly having zero pad in the pseed check later.
*/
first_seed_len = vfy->seed.len / 3;
CHECKPARAM(qseed_len < vfy->seed.len);
CHECKPARAM(first_seed_len * 8 > N - 1);
CHECKPARAM(first_seed_len + qseed_len < vfy->seed.len);
CHECKPARAM(first_seed_len * 8 < counter_max / 2);
CHECKPARAM(first_seed_len >= qseed_len);
qseed.len = qseed_len;
qseed.data = vfy->seed.data + vfy->seed.len - qseed.len;
pseed.len = vfy->seed.len - (first_seed_len + qseed_len);
pseed.len = first_seed_len;
pseed.data = vfy->seed.data + first_seed_len;
/*
@ -1754,14 +1768,34 @@ PQG_VerifyParams(const PQGParams *params,
** (ST_Random_Prime((ceil(length/2)+1, input_seed)
*/
CHECK_SEC_OK(makePrimefromSeedShaweTaylor(hashtype, (L + 1) / 2 + 1,
&qseed, &p0, &pseed_, &pgen_counter));
&qseed, &p0, &pseed_, &pgen_counter_));
/* Steps 4-22 FIPS 186-3 appendix A.1.2.1.2 */
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L,
&p0, &Q_, &P_, &pseed_, &pgen_counter));
CHECK_SEC_OK(makePrimefromPrimesShaweTaylor(hashtype, L, first_seed_len * 8,
&p0, &Q_, &P_, &pseed_, &pgen_counter_));
CHECKPARAM(mp_cmp(&P, &P_) == 0);
/* make sure pseed wasn't tampered with (since it is part of
* calculating G) */
if (pseed.len > pseed_.len) {
/* handle the case of zero pad for pseed */
int extra = pseed.len - pseed_.len;
int i;
for (i = 0; i < extra; i++) {
if (pseed.data[i] != 0) {
*result = SECFailure;
goto cleanup;
}
}
pseed.data += extra;
pseed.len -= extra;
/* the rest is handled in the normal compare below */
}
CHECKPARAM(SECITEM_CompareItem(&pseed, &pseed_) == SECEqual);
if (vfy->counter != -1) {
CHECKPARAM(pgen_counter < counter_max);
CHECKPARAM(qgen_counter < counter_max);
CHECKPARAM((pgen_counter_ == pgen_counter));
CHECKPARAM((qgen_counter_ == qgen_counter));
}
} else if (vfy->counter == -1) {
/* If counter is set to -1, we are really only verifying G, skip
* the remainder of the checks for P */

Просмотреть файл

@ -1032,13 +1032,19 @@ AES_CreateContext(const unsigned char *key, const unsigned char *iv,
void
AES_DestroyContext(AESContext *cx, PRBool freeit)
{
void *mem = cx->mem;
if (cx->worker_cx && cx->destroy) {
(*cx->destroy)(cx->worker_cx, PR_TRUE);
cx->worker_cx = NULL;
cx->destroy = NULL;
}
PORT_Memset(cx, 0, sizeof(AESContext));
if (freeit) {
PORT_Free(cx->mem);
PORT_Free(mem);
} else {
/* if we are not freeing the context, restore mem, We may get called
* again to actually free the context */
cx->mem = mem;
}
}

Просмотреть файл

@ -1151,3 +1151,9 @@ CERT_GetCertificateDer;
;+ local:
;+ *;
;+};
;+NSS_3.45 { # NSS 3.45 release
;+ global:
PK11_FindRawCertsWithSubject;
;+ local:
;+ *;
;+};

Просмотреть файл

@ -4,6 +4,8 @@
/*
* This file manages object type indepentent functions.
*/
#include <limits.h>
#include "seccomon.h"
#include "secmod.h"
#include "secmodi.h"
@ -1883,6 +1885,96 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
*object_count = -1;
return objID;
}
SECStatus
PK11_FindRawCertsWithSubject(PK11SlotInfo *slot, SECItem *derSubject,
CERTCertificateList **results)
{
if (!slot || !derSubject || !results) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
*results = NULL;
// derSubject->data may be null. If so, derSubject->len must be 0.
if (!derSubject->data && derSubject->len != 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
CK_CERTIFICATE_TYPE ckc_x_509 = CKC_X_509;
CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
CK_ATTRIBUTE subjectTemplate[] = {
{ CKA_CERTIFICATE_TYPE, &ckc_x_509, sizeof(ckc_x_509) },
{ CKA_CLASS, &cko_certificate, sizeof(cko_certificate) },
{ CKA_SUBJECT, derSubject->data, derSubject->len },
};
int templateCount = sizeof(subjectTemplate) / sizeof(subjectTemplate[0]);
int handleCount = 0;
CK_OBJECT_HANDLE *handles =
pk11_FindObjectsByTemplate(slot, subjectTemplate, templateCount,
&handleCount);
if (!handles) {
// pk11_FindObjectsByTemplate indicates there was an error by setting
// handleCount to -1 (and it has set an error with PORT_SetError).
if (handleCount == -1) {
return SECFailure;
}
return SECSuccess;
}
PORT_Assert(handleCount > 0);
if (handleCount <= 0) {
PORT_Free(handles);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
if (handleCount > INT_MAX / sizeof(SECItem)) {
PORT_Free(handles);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena) {
PORT_Free(handles);
return SECFailure;
}
CERTCertificateList *rawCertificates =
PORT_ArenaNew(arena, CERTCertificateList);
if (!rawCertificates) {
PORT_Free(handles);
PORT_FreeArena(arena, PR_FALSE);
return SECFailure;
}
rawCertificates->arena = arena;
rawCertificates->certs = PORT_ArenaNewArray(arena, SECItem, handleCount);
if (!rawCertificates->certs) {
PORT_Free(handles);
PORT_FreeArena(arena, PR_FALSE);
return SECFailure;
}
rawCertificates->len = handleCount;
int handleIndex;
for (handleIndex = 0; handleIndex < handleCount; handleIndex++) {
SECStatus rv =
PK11_ReadAttribute(slot, handles[handleIndex], CKA_VALUE, arena,
&rawCertificates->certs[handleIndex]);
if (rv != SECSuccess) {
PORT_Free(handles);
PORT_FreeArena(arena, PR_FALSE);
return SECFailure;
}
if (!rawCertificates->certs[handleIndex].data) {
PORT_Free(handles);
PORT_FreeArena(arena, PR_FALSE);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
}
PORT_Free(handles);
*results = rawCertificates;
return SECSuccess;
}
/*
* given a PKCS #11 object, match it's peer based on the KeyID. searchID
* is typically a privateKey or a certificate while the peer is the opposite

Просмотреть файл

@ -875,6 +875,17 @@ SECStatus PK11_WriteRawAttribute(PK11ObjectType type, void *object,
PK11SlotList *
PK11_GetAllSlotsForCert(CERTCertificate *cert, void *arg);
/*
* Finds all certificates on the given slot with the given subject distinguished
* name and returns them as DER bytes. If no such certificates can be found,
* returns SECSuccess and sets *results to NULL. If a failure is encountered
* while fetching any of the matching certificates, SECFailure is returned and
* *results will be NULL.
*/
SECStatus
PK11_FindRawCertsWithSubject(PK11SlotInfo *slot, SECItem *derSubject,
CERTCertificateList **results);
/**********************************************************************
* New functions which are already deprecated....
**********************************************************************/

Просмотреть файл

@ -4727,6 +4727,13 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
return crv;
}
/* detect trivial signing transforms */
if ((signature_length >= pairwise_digest_length) &&
(PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) {
PORT_Free(signature);
return CKR_DEVICE_ERROR;
}
/* Verify the known hash using the public key. */
crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
if (crv != CKR_OK) {
@ -7562,14 +7569,14 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
case CKM_DH_PKCS_DERIVE: {
SECItem derived, dhPublic;
SECItem dhPrime, dhValue;
SECItem dhPrime, dhSubPrime, dhValue;
/* sourceKey - values for the local existing low key */
/* get prime and value attributes */
crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
if (crv != SECSuccess)
if (crv != CKR_OK)
break;
crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
if (crv != SECSuccess) {
if (crv != CKR_OK) {
PORT_Free(dhPrime.data);
break;
}
@ -7577,6 +7584,20 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
dhPublic.data = pMechanism->pParameter;
dhPublic.len = pMechanism->ulParameterLen;
/* If the caller bothered to provide Q, use Q to validate
* the public key. */
crv = sftk_Attribute2SecItem(NULL, &dhSubPrime, sourceKey, CKA_SUBPRIME);
if (crv == CKR_OK) {
rv = KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime);
PORT_Free(dhSubPrime.data);
if (rv != SECSuccess) {
crv = CKR_ARGUMENTS_BAD;
PORT_Free(dhPrime.data);
PORT_Free(dhValue.data);
break;
}
}
/* calculate private value - oct */
rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
@ -7586,6 +7607,7 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
if (rv == SECSuccess) {
sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
PORT_ZFree(derived.data, derived.len);
crv = CKR_OK;
} else
crv = CKR_HOST_MEMORY;