зеркало из https://github.com/mozilla/pjs.git
Bug 599324, land NSPR_4_8_7_BETA1 and NSS_3_12_9_BETA2, a=blocking-2.0-beta8+
This commit is contained in:
Родитель
06c5fc57d3
Коммит
184e8c1f20
|
@ -1 +1 @@
|
|||
NSPR_HEAD_20101015
|
||||
NSPR_4_8_7_BETA1
|
||||
|
|
|
@ -42,4 +42,3 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -111,19 +111,19 @@ NSPR_API(PRInt32) PR_AtomicAdd(PRInt32 *ptr, PRInt32 val);
|
|||
** interchangeably.
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(_WIN32_WCE) && \
|
||||
defined(_MSC_VER) && (_MSC_VER >= 1310)
|
||||
(!defined(_MSC_VER) || (_MSC_VER >= 1310))
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma intrinsic(_InterlockedIncrement)
|
||||
#pragma intrinsic(_InterlockedDecrement)
|
||||
#pragma intrinsic(_InterlockedExchange)
|
||||
#pragma intrinsic(_InterlockedExchangeAdd)
|
||||
#endif
|
||||
|
||||
long __cdecl _InterlockedIncrement(long volatile *Addend);
|
||||
#pragma intrinsic(_InterlockedIncrement)
|
||||
|
||||
long __cdecl _InterlockedDecrement(long volatile *Addend);
|
||||
#pragma intrinsic(_InterlockedDecrement)
|
||||
|
||||
long __cdecl _InterlockedExchange(long volatile *Target, long Value);
|
||||
#pragma intrinsic(_InterlockedExchange)
|
||||
|
||||
long __cdecl _InterlockedExchangeAdd(long volatile *Addend, long Value);
|
||||
#pragma intrinsic(_InterlockedExchangeAdd)
|
||||
|
||||
#define PR_ATOMIC_INCREMENT(val) _InterlockedIncrement((long volatile *)(val))
|
||||
#define PR_ATOMIC_DECREMENT(val) _InterlockedDecrement((long volatile *)(val))
|
||||
|
|
|
@ -566,9 +566,8 @@ PR_IMPLEMENT(void) PR_Abort(void)
|
|||
PR_IMPLEMENT(void) PR_Assert(const char *s, const char *file, PRIntn ln)
|
||||
{
|
||||
PR_LogPrint("Assertion failure: %s, at %s:%d\n", s, file, ln);
|
||||
#if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
|
||||
fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
|
||||
#endif
|
||||
fflush(stderr);
|
||||
#ifdef WIN32
|
||||
DebugBreak();
|
||||
#endif
|
||||
|
|
|
@ -87,7 +87,7 @@ PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
|
|||
t->md.gcContext[0] = 0; /* context.Eax */
|
||||
t->md.gcContext[1] = fiberData[0x2e]; /* context.Ebx */
|
||||
t->md.gcContext[2] = 0; /* context.Ecx */
|
||||
t->md.gcContext[2] = 0; /* context.Edx */
|
||||
t->md.gcContext[3] = 0; /* context.Edx */
|
||||
t->md.gcContext[4] = fiberData[0x2d]; /* context.Esi */
|
||||
t->md.gcContext[5] = fiberData[0x2c]; /* context.Edi */
|
||||
t->md.gcContext[6] = fiberData[0x36]; /* context.Esp */
|
||||
|
|
|
@ -780,8 +780,28 @@ PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime ticks)
|
|||
|
||||
static void _pt_thread_death(void *arg)
|
||||
{
|
||||
void *thred;
|
||||
int rv;
|
||||
|
||||
_PT_PTHREAD_GETSPECIFIC(pt_book.key, thred);
|
||||
if (NULL == thred)
|
||||
{
|
||||
/*
|
||||
* Have PR_GetCurrentThread return the expected value to the
|
||||
* destructors.
|
||||
*/
|
||||
rv = pthread_setspecific(pt_book.key, arg);
|
||||
PR_ASSERT(0 == rv);
|
||||
}
|
||||
|
||||
/* PR_TRUE for: call destructors */
|
||||
_pt_thread_death_internal(arg, PR_TRUE);
|
||||
|
||||
if (NULL == thred)
|
||||
{
|
||||
rv = pthread_setspecific(pt_book.key, NULL);
|
||||
PR_ASSERT(0 == rv);
|
||||
}
|
||||
}
|
||||
|
||||
static void _pt_thread_death_internal(void *arg, PRBool callDestructors)
|
||||
|
|
|
@ -42,3 +42,5 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
NSS_3_12_8_RC0
|
||||
NSS_3_12_9_BETA2
|
||||
|
|
|
@ -121,7 +121,7 @@ static void Usage()
|
|||
#define PRINTUSAGE(subject, option, predicate) \
|
||||
fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate);
|
||||
fprintf(stderr, "\n");
|
||||
PRINTUSAGE(progName, "[-DEHSV]", "List available cipher modes"); /* XXX */
|
||||
PRINTUSAGE(progName, "[-DEHSVR]", "List available cipher modes"); /* XXX */
|
||||
fprintf(stderr, "\n");
|
||||
PRINTUSAGE(progName, "-E -m mode ", "Encrypt a buffer");
|
||||
PRINTUSAGE("", "", "[-i plaintext] [-o ciphertext] [-k key] [-v iv]");
|
||||
|
@ -218,6 +218,13 @@ static void Usage()
|
|||
PRINTUSAGE("", "-g", "key size (in bytes)");
|
||||
PRINTUSAGE("", "-u", "number of repetitions of context creation");
|
||||
fprintf(stderr, "\n");
|
||||
PRINTUSAGE(progName, "-R [-g keysize] [-e exp]",
|
||||
"Test the RSA populate key function");
|
||||
PRINTUSAGE("", "", "[-r repetitions]");
|
||||
PRINTUSAGE("", "-g", "key size (in bytes)");
|
||||
PRINTUSAGE("", "-e", "rsa public exponent");
|
||||
PRINTUSAGE("", "-r", "repetitions of the test");
|
||||
fprintf(stderr, "\n");
|
||||
PRINTUSAGE(progName, "-F", "Run the FIPS self-test");
|
||||
fprintf(stderr, "\n");
|
||||
PRINTUSAGE(progName, "-T [-m mode1,mode2...]", "Run the BLAPI self-test");
|
||||
|
@ -3137,6 +3144,192 @@ void ThreadExecTest(void *data)
|
|||
cipherFinish(cipherInfo);
|
||||
}
|
||||
|
||||
static void rsaPrivKeyReset(RSAPrivateKey *tstKey)
|
||||
{
|
||||
PLArenaPool *arena;
|
||||
|
||||
tstKey->version.data = NULL;
|
||||
tstKey->version.len = 0;
|
||||
tstKey->modulus.data = NULL;
|
||||
tstKey->modulus.len = 0;
|
||||
tstKey->publicExponent.data = NULL;
|
||||
tstKey->publicExponent.len = 0;
|
||||
tstKey->privateExponent.data = NULL;
|
||||
tstKey->privateExponent.len = 0;
|
||||
tstKey->prime1.data = NULL;
|
||||
tstKey->prime1.len = 0;
|
||||
tstKey->prime2.data = NULL;
|
||||
tstKey->prime2.len = 0;
|
||||
tstKey->exponent1.data = NULL;
|
||||
tstKey->exponent1.len = 0;
|
||||
tstKey->exponent2.data = NULL;
|
||||
tstKey->exponent2.len = 0;
|
||||
tstKey->coefficient.data = NULL;
|
||||
tstKey->coefficient.len = 0;
|
||||
|
||||
arena = tstKey->arena;
|
||||
tstKey->arena = NULL;
|
||||
if (arena) {
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define RSA_TEST_EQUAL(comp) \
|
||||
if (!SECITEM_ItemsAreEqual(&(src->comp),&(dest->comp))) { \
|
||||
fprintf(stderr, "key->" #comp " not equal"); \
|
||||
if (src->comp.len != dest->comp.len) { \
|
||||
fprintf(stderr, "src_len = %d, dest_len = %d", \
|
||||
src->comp.len, dest->comp.len); \
|
||||
} \
|
||||
fprintf(stderr, "\n"); \
|
||||
areEqual = PR_FALSE; \
|
||||
}
|
||||
|
||||
|
||||
static PRBool rsaPrivKeysAreEqual(RSAPrivateKey *src, RSAPrivateKey *dest)
|
||||
{
|
||||
PRBool areEqual = PR_TRUE;
|
||||
RSA_TEST_EQUAL(modulus)
|
||||
RSA_TEST_EQUAL(publicExponent)
|
||||
RSA_TEST_EQUAL(privateExponent)
|
||||
RSA_TEST_EQUAL(prime1)
|
||||
RSA_TEST_EQUAL(prime2)
|
||||
RSA_TEST_EQUAL(exponent1)
|
||||
RSA_TEST_EQUAL(exponent2)
|
||||
RSA_TEST_EQUAL(coefficient)
|
||||
if (!areEqual) {
|
||||
fprintf(stderr, "original key:\n");
|
||||
dump_rsakey(src);
|
||||
fprintf(stderr, "recreated key:\n");
|
||||
dump_rsakey(dest);
|
||||
}
|
||||
return areEqual;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test the RSA populate command to see that it can really build
|
||||
* keys from it's components.
|
||||
*/
|
||||
static int doRSAPopulateTest(unsigned int keySize, unsigned long exponent)
|
||||
{
|
||||
RSAPrivateKey *srcKey;
|
||||
RSAPrivateKey tstKey = { 0 };
|
||||
SECItem expitem = { 0, 0, 0 };
|
||||
SECStatus rv;
|
||||
unsigned char pubExp[4];
|
||||
int expLen = 0;
|
||||
int failed = 0;
|
||||
int i;
|
||||
|
||||
for (i=0; i < sizeof(unsigned long); i++) {
|
||||
int shift = (sizeof(unsigned long) - i -1 ) * 8;
|
||||
if (expLen || (exponent && ((unsigned long)0xffL << shift))) {
|
||||
pubExp[expLen] = (unsigned char) ((exponent >> shift) & 0xff);
|
||||
expLen++;
|
||||
}
|
||||
}
|
||||
|
||||
expitem.data = pubExp;
|
||||
expitem.len = expLen;
|
||||
|
||||
srcKey = RSA_NewKey(keySize, &expitem);
|
||||
if (srcKey == NULL) {
|
||||
fprintf(stderr, "RSA Key Gen failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* test the basic case - most common, public exponent, modulus, prime */
|
||||
tstKey.arena = NULL;
|
||||
rsaPrivKeyReset(&tstKey);
|
||||
|
||||
tstKey.publicExponent = srcKey->publicExponent;
|
||||
tstKey.modulus = srcKey->modulus;
|
||||
tstKey.prime1 = srcKey->prime1;
|
||||
|
||||
rv = RSA_PopulatePrivateKey(&tstKey);
|
||||
if (rv != SECSuccess) {
|
||||
fprintf(stderr, "RSA Populate failed: pubExp mod p\n");
|
||||
failed = 1;
|
||||
} else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
|
||||
fprintf(stderr, "RSA Populate key mismatch: pubExp mod p\n");
|
||||
failed = 1;
|
||||
}
|
||||
|
||||
/* test the basic2 case, public exponent, modulus, prime2 */
|
||||
rsaPrivKeyReset(&tstKey);
|
||||
|
||||
tstKey.publicExponent = srcKey->publicExponent;
|
||||
tstKey.modulus = srcKey->modulus;
|
||||
tstKey.prime1 = srcKey->prime2; /* test with q in the prime1 position */
|
||||
|
||||
rv = RSA_PopulatePrivateKey(&tstKey);
|
||||
if (rv != SECSuccess) {
|
||||
fprintf(stderr, "RSA Populate failed: pubExp mod q\n");
|
||||
failed = 1;
|
||||
} else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
|
||||
fprintf(stderr, "RSA Populate key mismatch: pubExp mod q\n");
|
||||
failed = 1;
|
||||
}
|
||||
|
||||
/* test the medium case, private exponent, prime1, prime2 */
|
||||
rsaPrivKeyReset(&tstKey);
|
||||
|
||||
tstKey.privateExponent = srcKey->privateExponent;
|
||||
tstKey.prime1 = srcKey->prime2; /* purposefully swap them to make */
|
||||
tstKey.prime2 = srcKey->prime1; /* sure populated swaps them back */
|
||||
|
||||
rv = RSA_PopulatePrivateKey(&tstKey);
|
||||
if (rv != SECSuccess) {
|
||||
fprintf(stderr, "RSA Populate failed: privExp p q\n");
|
||||
failed = 1;
|
||||
} else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
|
||||
fprintf(stderr, "RSA Populate key mismatch: privExp p q\n");
|
||||
failed = 1;
|
||||
}
|
||||
|
||||
/* test the advanced case, public exponent, private exponent, prime2 */
|
||||
rsaPrivKeyReset(&tstKey);
|
||||
|
||||
tstKey.privateExponent = srcKey->privateExponent;
|
||||
tstKey.publicExponent = srcKey->publicExponent;
|
||||
tstKey.prime2 = srcKey->prime2; /* use q in the prime2 position */
|
||||
|
||||
rv = RSA_PopulatePrivateKey(&tstKey);
|
||||
if (rv != SECSuccess) {
|
||||
fprintf(stderr, "RSA Populate failed: pubExp privExp q\n");
|
||||
fprintf(stderr, " - not fatal\n");
|
||||
/* it's possible that we can't uniquely determine the original key
|
||||
* from just the exponents and prime. Populate returns an error rather
|
||||
* than return the wrong key. */
|
||||
} else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
|
||||
/* if we returned a key, it *must* be correct */
|
||||
fprintf(stderr, "RSA Populate key mismatch: pubExp privExp q\n");
|
||||
rv = RSA_PrivateKeyCheck(&tstKey);
|
||||
failed = 1;
|
||||
}
|
||||
|
||||
/* test the advanced case2, public exponent, private exponent, modulus */
|
||||
rsaPrivKeyReset(&tstKey);
|
||||
|
||||
tstKey.privateExponent = srcKey->privateExponent;
|
||||
tstKey.publicExponent = srcKey->publicExponent;
|
||||
tstKey.modulus = srcKey->modulus;
|
||||
|
||||
rv = RSA_PopulatePrivateKey(&tstKey);
|
||||
if (rv != SECSuccess) {
|
||||
fprintf(stderr, "RSA Populate failed: pubExp privExp mod\n");
|
||||
failed = 1;
|
||||
} else if (!rsaPrivKeysAreEqual(&tstKey, srcKey)) {
|
||||
fprintf(stderr, "RSA Populate key mismatch: pubExp privExp mod\n");
|
||||
failed = 1;
|
||||
}
|
||||
|
||||
return failed ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* bltest commands */
|
||||
enum {
|
||||
cmd_Decrypt = 0,
|
||||
|
@ -3145,6 +3338,7 @@ enum {
|
|||
cmd_Hash,
|
||||
cmd_Nonce,
|
||||
cmd_Dump,
|
||||
cmd_RSAPopulate,
|
||||
cmd_Sign,
|
||||
cmd_SelfTest,
|
||||
cmd_Verify
|
||||
|
@ -3196,6 +3390,7 @@ static secuCommandFlag bltest_commands[] =
|
|||
{ /* cmd_Hash */ 'H', PR_FALSE, 0, PR_FALSE },
|
||||
{ /* cmd_Nonce */ 'N', PR_FALSE, 0, PR_FALSE },
|
||||
{ /* cmd_Dump */ 'P', PR_FALSE, 0, PR_FALSE },
|
||||
{ /* cmd_RSAPopulate*/ 'R', PR_FALSE, 0, PR_FALSE },
|
||||
{ /* cmd_Sign */ 'S', PR_FALSE, 0, PR_FALSE },
|
||||
{ /* cmd_SelfTest */ 'T', PR_FALSE, 0, PR_FALSE },
|
||||
{ /* cmd_Verify */ 'V', PR_FALSE, 0, PR_FALSE }
|
||||
|
@ -3309,6 +3504,7 @@ int main(int argc, char **argv)
|
|||
goto print_usage;
|
||||
}
|
||||
|
||||
|
||||
if (bltest.commands[cmd_Sign].activated)
|
||||
bltest.commands[cmd_Encrypt].activated = PR_TRUE;
|
||||
if (bltest.commands[cmd_Verify].activated)
|
||||
|
@ -3329,6 +3525,36 @@ int main(int argc, char **argv)
|
|||
* Handle three simple cases first
|
||||
*/
|
||||
|
||||
/* test the RSA_PopulatePrivateKey function */
|
||||
if (bltest.commands[cmd_RSAPopulate].activated) {
|
||||
unsigned int keySize = 1024;
|
||||
unsigned long exponent = 65537;
|
||||
int rounds = 1;
|
||||
int ret;
|
||||
|
||||
if (bltest.options[opt_KeySize].activated) {
|
||||
keySize = PORT_Atoi(bltest.options[opt_KeySize].arg);
|
||||
}
|
||||
if (bltest.options[opt_Rounds].activated) {
|
||||
rounds = PORT_Atoi(bltest.options[opt_Rounds].arg);
|
||||
}
|
||||
if (bltest.options[opt_Exponent].activated) {
|
||||
exponent = PORT_Atoi(bltest.options[opt_Exponent].arg);
|
||||
}
|
||||
|
||||
for (i=0; i < rounds; i++) {
|
||||
printf("Running RSA Populate test round %d\n",i);
|
||||
ret = doRSAPopulateTest(keySize,exponent);
|
||||
if (ret != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret != 0) {
|
||||
fprintf(stderr,"RSA Populate test round %d: FAILED\n",i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Do BLAPI self-test */
|
||||
if (bltest.commands[cmd_SelfTest].activated) {
|
||||
PRBool encrypt = PR_TRUE, decrypt = PR_TRUE;
|
||||
|
|
|
@ -462,7 +462,7 @@ DumpChain(CERTCertDBHandle *handle, char *name, PRBool ascii)
|
|||
}
|
||||
|
||||
static SECStatus
|
||||
listCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot,
|
||||
listCerts(CERTCertDBHandle *handle, char *name, char *email, PK11SlotInfo *slot,
|
||||
PRBool raw, PRBool ascii, PRFileDesc *outfile, void *pwarg)
|
||||
{
|
||||
SECItem data;
|
||||
|
@ -530,8 +530,45 @@ listCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot,
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else if (email) {
|
||||
CERTCertificate *the_cert;
|
||||
certs = PK11_FindCertsFromEmailAddress(email, NULL);
|
||||
if (!certs) {
|
||||
SECU_PrintError(progName,
|
||||
"Could not find certificates for email address: %s\n",
|
||||
email);
|
||||
return SECFailure;
|
||||
}
|
||||
for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
|
||||
node = CERT_LIST_NEXT(node)) {
|
||||
the_cert = node->cert;
|
||||
/* now get the subjectList that matches this cert */
|
||||
data.data = the_cert->derCert.data;
|
||||
data.len = the_cert->derCert.len;
|
||||
if (ascii) {
|
||||
PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER,
|
||||
BTOA_DataToAscii(data.data, data.len),
|
||||
NS_CERT_TRAILER);
|
||||
rv = SECSuccess;
|
||||
} else if (raw) {
|
||||
numBytes = PR_Write(outfile, data.data, data.len);
|
||||
rv = SECSuccess;
|
||||
if (numBytes != (PRInt32) data.len) {
|
||||
SECU_PrintSystemError(progName, "error writing raw cert");
|
||||
rv = SECFailure;
|
||||
}
|
||||
} else {
|
||||
rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate",
|
||||
the_cert->trust);
|
||||
if (rv != SECSuccess) {
|
||||
SECU_PrintError(progName, "problem printing certificate");
|
||||
}
|
||||
}
|
||||
if (rv != SECSuccess) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
certs = PK11_ListCertsInSlot(slot);
|
||||
if (certs) {
|
||||
for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs);
|
||||
|
@ -553,12 +590,13 @@ listCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot,
|
|||
}
|
||||
|
||||
static SECStatus
|
||||
ListCerts(CERTCertDBHandle *handle, char *nickname, PK11SlotInfo *slot,
|
||||
PRBool raw, PRBool ascii, PRFileDesc *outfile, secuPWData *pwdata)
|
||||
ListCerts(CERTCertDBHandle *handle, char *nickname, char *email,
|
||||
PK11SlotInfo *slot, PRBool raw, PRBool ascii, PRFileDesc *outfile,
|
||||
secuPWData *pwdata)
|
||||
{
|
||||
SECStatus rv;
|
||||
|
||||
if (!ascii && !raw && !nickname) {
|
||||
if (!ascii && !raw && !nickname && !email) {
|
||||
PR_fprintf(outfile, "\n%-60s %-5s\n%-60s %-5s\n\n",
|
||||
"Certificate Nickname", "Trust Attributes", "",
|
||||
"SSL,S/MIME,JAR/XPI");
|
||||
|
@ -569,15 +607,13 @@ ListCerts(CERTCertDBHandle *handle, char *nickname, PK11SlotInfo *slot,
|
|||
|
||||
list = PK11_ListCerts(PK11CertListAll, pwdata);
|
||||
for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
|
||||
node = CERT_LIST_NEXT(node))
|
||||
{
|
||||
node = CERT_LIST_NEXT(node)) {
|
||||
SECU_PrintCertNickname(node, stdout);
|
||||
}
|
||||
CERT_DestroyCertList(list);
|
||||
return SECSuccess;
|
||||
} else {
|
||||
rv = listCerts(handle,nickname,slot,raw,ascii,outfile,pwdata);
|
||||
}
|
||||
}
|
||||
rv = listCerts(handle, nickname, email, slot, raw, ascii, outfile, pwdata);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -598,10 +634,8 @@ DeleteCert(CERTCertDBHandle *handle, char *name)
|
|||
CERT_DestroyCertificate(cert);
|
||||
if (rv) {
|
||||
SECU_PrintError(progName, "unable to delete certificate");
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
|
@ -995,7 +1029,9 @@ Usage(char *progName)
|
|||
progName);
|
||||
FPS "\t\t [-P targetDBPrefix] [--source-prefix sourceDBPrefix]\n");
|
||||
FPS "\t\t [-f targetPWfile] [-@ sourcePWFile]\n");
|
||||
FPS "\t%s -L [-n cert-name] [-X] [-d certdir] [-P dbprefix] [-r] [-a]\n", progName);
|
||||
FPS "\t%s -L [-n cert-name] [--email email-address] [-X] [-r] [-a]\n",
|
||||
progName);
|
||||
FPS "\t\t [-d certdir] [-P dbprefix]\n");
|
||||
FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n",
|
||||
progName);
|
||||
FPS "\t%s -O -n cert-name [-X] [-d certdir] [-a] [-P dbprefix]\n", progName);
|
||||
|
@ -1208,6 +1244,9 @@ static void LongUsage(char *progName)
|
|||
"-L");
|
||||
FPS "%-20s Pretty print named cert (list all if unspecified)\n",
|
||||
" -n cert-name");
|
||||
FPS "%-20s \n"
|
||||
"%-20s Pretty print cert with email address (list all if unspecified)\n",
|
||||
" --email email-address", "");
|
||||
FPS "%-20s Cert database directory (default is ~/.netscape)\n",
|
||||
" -d certdir");
|
||||
FPS "%-20s Cert & Key database prefix\n",
|
||||
|
@ -1827,6 +1866,7 @@ enum certutilOpts {
|
|||
opt_KeySize,
|
||||
opt_TokenName,
|
||||
opt_InputFile,
|
||||
opt_Emailaddress,
|
||||
opt_KeyIndex,
|
||||
opt_KeyType,
|
||||
opt_DetailedInfo,
|
||||
|
@ -1914,6 +1954,7 @@ secuCommandFlag options_init[] =
|
|||
{ /* opt_KeySize */ 'g', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_InputFile */ 'i', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_Emailaddress */ 0, PR_TRUE, 0, PR_FALSE, "email" },
|
||||
{ /* opt_KeyIndex */ 'j', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_KeyType */ 'k', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_DetailedInfo */ 'l', PR_FALSE, 0, PR_FALSE },
|
||||
|
@ -1991,6 +2032,7 @@ certutil_main(int argc, char **argv, PRBool initialize)
|
|||
char * upgradeTokenName = "";
|
||||
KeyType keytype = rsaKey;
|
||||
char * name = NULL;
|
||||
char * email = NULL;
|
||||
char * keysource = NULL;
|
||||
SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
|
||||
int keysize = DEFAULT_KEY_BITS;
|
||||
|
@ -2389,6 +2431,7 @@ certutil_main(int argc, char **argv, PRBool initialize)
|
|||
}
|
||||
|
||||
name = SECU_GetOptionArg(&certutil, opt_Nickname);
|
||||
email = SECU_GetOptionArg(&certutil, opt_Emailaddress);
|
||||
|
||||
PK11_SetPasswordFunc(SECU_GetModulePassword);
|
||||
|
||||
|
@ -2579,7 +2622,7 @@ merge_fail:
|
|||
|
||||
/* List certs (-L) */
|
||||
if (certutil.commands[cmd_ListCerts].activated) {
|
||||
rv = ListCerts(certHandle, name, slot,
|
||||
rv = ListCerts(certHandle, name, email, slot,
|
||||
certutil.options[opt_BinaryDER].activated,
|
||||
certutil.options[opt_ASCIIForIO].activated,
|
||||
(outFile) ? outFile : PR_STDOUT, &pwdata);
|
||||
|
|
|
@ -567,3 +567,9 @@ ER3(SEC_ERROR_EXPIRED_PASSWORD, (SEC_ERROR_BASE + 172),
|
|||
|
||||
ER3(SEC_ERROR_LOCKED_PASSWORD, (SEC_ERROR_BASE + 173),
|
||||
"The password is locked.")
|
||||
|
||||
ER3(SEC_ERROR_UNKNOWN_PKCS11_ERROR, (SEC_ERROR_BASE + 174),
|
||||
"Unknown PKCS #11 error.")
|
||||
|
||||
ER3(SEC_ERROR_BAD_CRL_DP_URL, (SEC_ERROR_BASE + 175),
|
||||
"Invalid or unsupported URL in CRL distribution point name.")
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
#######################################################################
|
||||
# (1) Include initial platform-independent assignments (MANDATORY). #
|
||||
#######################################################################
|
||||
|
||||
include manifest.mn
|
||||
#MKPROG = purify -cache-dir=/u/mcgreer/pcache -best-effort \
|
||||
# -always-use-cache-dir $(CC)
|
||||
|
||||
#######################################################################
|
||||
# (2) Include "global" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/config.mk
|
||||
|
||||
#######################################################################
|
||||
# (3) Include "component" configuration information. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include ../platlibs.mk
|
||||
|
||||
#EXTRA_SHARED_LIBS += \
|
||||
# -L/usr/lib \
|
||||
# -lposix4 \
|
||||
# $(NULL)
|
||||
|
||||
#######################################################################
|
||||
# (5) Execute "global" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
include $(CORE_DEPTH)/coreconf/rules.mk
|
||||
|
||||
#######################################################################
|
||||
# (6) Execute "component" rules. (OPTIONAL) #
|
||||
#######################################################################
|
||||
|
||||
|
||||
|
||||
#######################################################################
|
||||
# (7) Execute "local" rules. (OPTIONAL). #
|
||||
#######################################################################
|
||||
|
||||
include ../platrules.mk
|
|
@ -0,0 +1,54 @@
|
|||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Netscape security libraries.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Netscape Communications Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
CORE_DEPTH = ../../..
|
||||
|
||||
MODULE = nss
|
||||
|
||||
REQUIRES = seccmd dbm softoken
|
||||
|
||||
PROGRAM = rsapoptst
|
||||
|
||||
EXPORTS = \
|
||||
$(NULL)
|
||||
|
||||
PRIVATE_EXPORTS = \
|
||||
$(NULL)
|
||||
|
||||
CSRCS = \
|
||||
rsapoptst.c \
|
||||
$(NULL)
|
||||
|
|
@ -0,0 +1,550 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1994-2000
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
* Portions created by the Red Hat, Inc. are Copyright (C) 2010
|
||||
* the Red Hat, Inc.. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "plgetopt.h"
|
||||
#include "nss.h"
|
||||
#include "secutil.h"
|
||||
#include "pk11table.h"
|
||||
#include "secmodt.h"
|
||||
#include "pk11pub.h"
|
||||
|
||||
|
||||
struct test_args {
|
||||
char *arg;
|
||||
int mask_value;
|
||||
char *description;
|
||||
};
|
||||
|
||||
static const struct test_args test_array[] = {
|
||||
{"all", 0x1f, "run all the tests" },
|
||||
{"e_n_p", 0x01, "public exponent, modulus, prime1"},
|
||||
{"d_n_q", 0x02, "private exponent, modulus, prime2"},
|
||||
{"d_p_q", 0x04, "private exponent, prime1, prime2"},
|
||||
{"e_d_q", 0x08, "public exponent, private exponent, prime2"},
|
||||
{"e_d_n", 0x10, "public exponent, private exponent, moduls"}
|
||||
};
|
||||
static const int test_array_size =
|
||||
(sizeof(test_array)/sizeof(struct test_args));
|
||||
|
||||
static void Usage(char *progName)
|
||||
{
|
||||
int i;
|
||||
#define PRINTUSAGE(subject, option, predicate) \
|
||||
fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate);
|
||||
fprintf(stderr, "%s [-k keysize] [-e exp] [-r rounds] [-t tests]\n "
|
||||
"Test creating RSA private keys from Partial components\n",
|
||||
progName);
|
||||
PRINTUSAGE("", "-k", "key size (in bit)");
|
||||
PRINTUSAGE("", "-e", "rsa public exponent");
|
||||
PRINTUSAGE("", "-r", "number times to repeat the test");
|
||||
PRINTUSAGE("", "-t", "run the specified tests");
|
||||
for (i=0; i < test_array_size; i++) {
|
||||
PRINTUSAGE("", test_array[i].arg, test_array[i].description);
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Test the RSA populate command to see that it can really build
|
||||
* keys from it's components.
|
||||
*/
|
||||
|
||||
const static CK_ATTRIBUTE rsaTemplate[] = {
|
||||
{CKA_CLASS, NULL, 0 },
|
||||
{CKA_KEY_TYPE, NULL, 0 },
|
||||
{CKA_TOKEN, NULL, 0 },
|
||||
{CKA_SENSITIVE, NULL, 0 },
|
||||
{CKA_PRIVATE, NULL, 0 },
|
||||
{CKA_MODULUS, NULL, 0 },
|
||||
{CKA_PUBLIC_EXPONENT, NULL, 0 },
|
||||
{CKA_PRIVATE_EXPONENT, NULL, 0 },
|
||||
{CKA_PRIME_1, NULL, 0 },
|
||||
{CKA_PRIME_2, NULL, 0 },
|
||||
{CKA_EXPONENT_1, NULL, 0 },
|
||||
{CKA_EXPONENT_2, NULL, 0 },
|
||||
{CKA_COEFFICIENT, NULL, 0 },
|
||||
};
|
||||
|
||||
#define RSA_SIZE (sizeof(rsaTemplate))
|
||||
#define RSA_ATTRIBUTES (sizeof(rsaTemplate)/sizeof(CK_ATTRIBUTE))
|
||||
|
||||
static void
|
||||
resetTemplate(CK_ATTRIBUTE *attribute, int start, int end)
|
||||
{
|
||||
int i;
|
||||
for (i=start; i < end; i++) {
|
||||
if (attribute[i].pValue) {
|
||||
PORT_Free(attribute[i].pValue);
|
||||
}
|
||||
attribute[i].pValue = NULL;
|
||||
attribute[i].ulValueLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
copyAttribute(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template,
|
||||
int offset, CK_ATTRIBUTE_TYPE attrType)
|
||||
{
|
||||
SECItem attributeItem = {0, 0, 0};
|
||||
SECStatus rv;
|
||||
|
||||
rv = PK11_ReadRawAttribute(objType, object, attrType, &attributeItem);
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
}
|
||||
template[offset].type = attrType;
|
||||
template[offset].pValue = attributeItem.data;
|
||||
template[offset].ulValueLen = attributeItem.len;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
readKey(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template,
|
||||
int start, int end)
|
||||
{
|
||||
int i;
|
||||
SECStatus rv;
|
||||
|
||||
for (i=start; i < end; i++) {
|
||||
rv = copyAttribute(objType, object, template, i, template[i].type);
|
||||
if (rv != SECSuccess) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return SECSuccess;
|
||||
|
||||
fail:
|
||||
resetTemplate(template, start, i);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define ATTR_STRING(x) getNameFromAttribute(x)
|
||||
|
||||
void
|
||||
dumpTemplate(CK_ATTRIBUTE *template, int start, int end)
|
||||
{
|
||||
int i,j;
|
||||
for (i=0; i < end; i++) {
|
||||
unsigned char cval;
|
||||
CK_ULONG ulval;
|
||||
unsigned char *cpval;
|
||||
|
||||
fprintf(stderr, "%s:", ATTR_STRING(template[i].type));
|
||||
switch (template[i].ulValueLen) {
|
||||
case 1:
|
||||
cval =*(unsigned char *)template[i].pValue;
|
||||
switch(cval) {
|
||||
case 0: fprintf(stderr, " false"); break;
|
||||
case 1: fprintf(stderr, " true"); break;
|
||||
default:
|
||||
fprintf(stderr, " %d (=0x%02x,'%c')",cval,cval,cval);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case sizeof(CK_ULONG):
|
||||
ulval = *(CK_ULONG *)template[i].pValue;
|
||||
fprintf(stderr," %ld (=0x%04lx)", ulval, ulval);
|
||||
break;
|
||||
default:
|
||||
cpval = (unsigned char *)template[i].pValue;
|
||||
for (j=0; j < template[i].ulValueLen; j++) {
|
||||
if ((j % 16) == 0) fprintf(stderr, "\n ");
|
||||
fprintf(stderr," %02x",cpval[j]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
rsaKeysAreEqual(PK11ObjectType srcType, void *src,
|
||||
PK11ObjectType destType, void *dest)
|
||||
{
|
||||
|
||||
CK_ATTRIBUTE srcTemplate[RSA_ATTRIBUTES];
|
||||
CK_ATTRIBUTE destTemplate[RSA_ATTRIBUTES];
|
||||
PRBool areEqual = PR_TRUE;
|
||||
SECStatus rv;
|
||||
int i;
|
||||
|
||||
memcpy(srcTemplate, rsaTemplate, RSA_SIZE);
|
||||
memcpy(destTemplate, rsaTemplate, RSA_SIZE);
|
||||
|
||||
rv = readKey(srcType, src, srcTemplate, 0, RSA_ATTRIBUTES);
|
||||
if (rv != SECSuccess) {
|
||||
printf("Could read source key\n");
|
||||
return PR_FALSE;
|
||||
}
|
||||
readKey(destType, dest, destTemplate, 0, RSA_ATTRIBUTES);
|
||||
if (rv != SECSuccess) {
|
||||
printf("Could read dest key\n");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
for (i=0; i < RSA_ATTRIBUTES; i++) {
|
||||
if (srcTemplate[i].ulValueLen != destTemplate[i].ulValueLen) {
|
||||
printf("key->%s not equal src_len = %ld, dest_len=%ld\n",
|
||||
ATTR_STRING(srcTemplate[i].type),
|
||||
srcTemplate[i].ulValueLen, destTemplate[i].ulValueLen);
|
||||
areEqual = 0;
|
||||
} else if (memcmp(srcTemplate[i].pValue, destTemplate[i].pValue,
|
||||
destTemplate[i].ulValueLen) != 0) {
|
||||
printf("key->%s not equal.\n", ATTR_STRING(srcTemplate[i].type));
|
||||
areEqual = 0;
|
||||
}
|
||||
}
|
||||
if (!areEqual) {
|
||||
fprintf(stderr, "original key:\n");
|
||||
dumpTemplate(srcTemplate,0, RSA_ATTRIBUTES);
|
||||
fprintf(stderr, "created key:\n");
|
||||
dumpTemplate(destTemplate,0, RSA_ATTRIBUTES);
|
||||
}
|
||||
return areEqual;
|
||||
}
|
||||
|
||||
static int exp_exp_prime_fail_count = 0;
|
||||
|
||||
static int
|
||||
doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
|
||||
int mask, void *pwarg)
|
||||
{
|
||||
SECKEYPrivateKey *rsaPrivKey;
|
||||
SECKEYPublicKey *rsaPubKey;
|
||||
PK11GenericObject *tstPrivKey;
|
||||
CK_ATTRIBUTE tstTemplate[RSA_ATTRIBUTES];
|
||||
int tstHeaderCount;
|
||||
PK11SlotInfo *slot = NULL;
|
||||
PK11RSAGenParams rsaParams;
|
||||
CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY;
|
||||
CK_KEY_TYPE key_type = CKK_RSA;
|
||||
CK_BBOOL ck_false = CK_FALSE;
|
||||
int failed = 0;
|
||||
|
||||
rsaParams.pe = exponent;
|
||||
rsaParams.keySizeInBits = keySize;
|
||||
|
||||
slot = PK11_GetInternalSlot();
|
||||
if (slot == NULL) {
|
||||
fprintf(stderr, "Couldn't get the internal slot for the test \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rsaPrivKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
|
||||
&rsaParams, &rsaPubKey, PR_FALSE,
|
||||
PR_FALSE, pwarg);
|
||||
if (rsaPrivKey == NULL) {
|
||||
fprintf(stderr, "RSA Key Gen failed");
|
||||
PK11_FreeSlot(slot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(tstTemplate, rsaTemplate, RSA_SIZE);
|
||||
|
||||
tstTemplate[0].pValue = &obj_class;
|
||||
tstTemplate[0].ulValueLen = sizeof(obj_class);
|
||||
tstTemplate[1].pValue = &key_type;
|
||||
tstTemplate[1].ulValueLen = sizeof(key_type);
|
||||
tstTemplate[2].pValue = &ck_false;
|
||||
tstTemplate[2].ulValueLen = sizeof(ck_false);
|
||||
tstTemplate[3].pValue = &ck_false;
|
||||
tstTemplate[3].ulValueLen = sizeof(ck_false);
|
||||
tstTemplate[4].pValue = &ck_false;
|
||||
tstTemplate[4].ulValueLen = sizeof(ck_false);
|
||||
tstHeaderCount = 5;
|
||||
|
||||
if (mask & 1) {
|
||||
printf("%s\n",test_array[1].description);
|
||||
resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount, CKA_PUBLIC_EXPONENT);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount+1, CKA_MODULUS);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount+2, CKA_PRIME_1);
|
||||
|
||||
tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
|
||||
tstHeaderCount+3, PR_FALSE);
|
||||
if (tstPrivKey == NULL) {
|
||||
fprintf(stderr, "RSA Populate failed: pubExp mod p\n");
|
||||
failed = 1;
|
||||
} else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
|
||||
PK11_TypeGeneric, tstPrivKey)) {
|
||||
fprintf(stderr, "RSA Populate key mismatch: pubExp mod p\n");
|
||||
failed = 1;
|
||||
}
|
||||
if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
|
||||
}
|
||||
if (mask & 2) {
|
||||
printf("%s\n",test_array[2].description);
|
||||
/* test the basic2 case, public exponent, modulus, prime2 */
|
||||
resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount, CKA_PUBLIC_EXPONENT);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount+1, CKA_MODULUS);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount+2, CKA_PRIME_2);
|
||||
/* test with q in the prime1 position */
|
||||
tstTemplate[tstHeaderCount+2].type = CKA_PRIME_1;
|
||||
|
||||
tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
|
||||
tstHeaderCount+3, PR_FALSE);
|
||||
if (tstPrivKey == NULL) {
|
||||
fprintf(stderr, "RSA Populate failed: pubExp mod q\n");
|
||||
failed = 1;
|
||||
} else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
|
||||
PK11_TypeGeneric, tstPrivKey)) {
|
||||
fprintf(stderr, "RSA Populate key mismatch: pubExp mod q\n");
|
||||
failed = 1;
|
||||
}
|
||||
if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
|
||||
}
|
||||
if (mask & 4) {
|
||||
printf("%s\n",test_array[3].description);
|
||||
/* test the medium case, private exponent, prime1, prime2 */
|
||||
resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
|
||||
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount, CKA_PRIVATE_EXPONENT);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount+1, CKA_PRIME_1);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount+2, CKA_PRIME_2);
|
||||
/* test with p & q swapped. Underlying code should swap these back */
|
||||
tstTemplate[tstHeaderCount+2].type = CKA_PRIME_1;
|
||||
tstTemplate[tstHeaderCount+1].type = CKA_PRIME_2;
|
||||
|
||||
tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
|
||||
tstHeaderCount+3, PR_FALSE);
|
||||
if (tstPrivKey == NULL) {
|
||||
fprintf(stderr, "RSA Populate failed: privExp p q\n");
|
||||
failed = 1;
|
||||
} else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
|
||||
PK11_TypeGeneric, tstPrivKey)) {
|
||||
fprintf(stderr, "RSA Populate key mismatch: privExp p q\n");
|
||||
failed = 1;
|
||||
}
|
||||
if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
|
||||
}
|
||||
if (mask & 8) {
|
||||
printf("%s\n",test_array[4].description);
|
||||
/* test the advanced case, public exponent, private exponent, prime2 */
|
||||
resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount, CKA_PRIVATE_EXPONENT);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount+1, CKA_PUBLIC_EXPONENT);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount+2, CKA_PRIME_2);
|
||||
|
||||
tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
|
||||
tstHeaderCount+3, PR_FALSE);
|
||||
if (tstPrivKey == NULL) {
|
||||
fprintf(stderr, "RSA Populate failed: pubExp privExp q\n");
|
||||
fprintf(stderr, " this is expected periodically. It means we\n");
|
||||
fprintf(stderr, " had more than one key that meets the "
|
||||
"specification\n");
|
||||
exp_exp_prime_fail_count++;
|
||||
} else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
|
||||
PK11_TypeGeneric, tstPrivKey)) {
|
||||
fprintf(stderr, "RSA Populate key mismatch: pubExp privExp q\n");
|
||||
failed = 1;
|
||||
}
|
||||
if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
|
||||
}
|
||||
if (mask & 16) {
|
||||
printf("%s\n",test_array[5].description);
|
||||
/* test the advanced case2, public exponent, private exponent, modulus
|
||||
*/
|
||||
resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES);
|
||||
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount, CKA_PRIVATE_EXPONENT);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount+1, CKA_PUBLIC_EXPONENT);
|
||||
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
|
||||
tstHeaderCount+2, CKA_MODULUS);
|
||||
|
||||
tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
|
||||
tstHeaderCount+3, PR_FALSE);
|
||||
if (tstPrivKey == NULL) {
|
||||
fprintf(stderr, "RSA Populate failed: pubExp privExp mod\n");
|
||||
failed = 1;
|
||||
} else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey,
|
||||
PK11_TypeGeneric, tstPrivKey)) {
|
||||
fprintf(stderr, "RSA Populate key mismatch: pubExp privExp mod\n");
|
||||
failed = 1;
|
||||
}
|
||||
if (tstPrivKey) PK11_DestroyGenericObject(tstPrivKey);
|
||||
}
|
||||
|
||||
|
||||
PK11_FreeSlot(slot);
|
||||
return failed ? -1 : 0;
|
||||
}
|
||||
|
||||
/* populate options */
|
||||
enum {
|
||||
opt_Exponent = 0,
|
||||
opt_KeySize,
|
||||
opt_Repeat,
|
||||
opt_Tests
|
||||
};
|
||||
|
||||
static secuCommandFlag populate_options[] =
|
||||
{
|
||||
{ /* opt_Exponent */ 'e', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_KeySize */ 'k', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_Repeat */ 'r', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_Tests */ 't', PR_TRUE, 0, PR_FALSE },
|
||||
};
|
||||
|
||||
int
|
||||
is_delimiter(char c)
|
||||
{
|
||||
if ((c=='+') || (c==',') || (c=='|')) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
parse_tests(char *test_string)
|
||||
{
|
||||
int mask = 0;
|
||||
int i;
|
||||
|
||||
while (*test_string) {
|
||||
if (is_delimiter(*test_string)) {
|
||||
test_string++;
|
||||
}
|
||||
for (i=0; i < test_array_size; i++) {
|
||||
char *arg = test_array[i].arg;
|
||||
int len = strlen(arg);
|
||||
if (strncmp(test_string,arg,len) == 0) {
|
||||
test_string += len;
|
||||
mask |= test_array[i].mask_value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == test_array_size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned int keySize = 1024;
|
||||
unsigned long exponent = 65537;
|
||||
int i, repeat = 1, ret = 0;
|
||||
SECStatus rv = SECFailure;
|
||||
secuCommand populateArgs;
|
||||
char *progName;
|
||||
int mask = 0xff;
|
||||
|
||||
populateArgs.numCommands = 0;
|
||||
populateArgs.numOptions = sizeof(populate_options) /
|
||||
sizeof(secuCommandFlag);
|
||||
populateArgs.commands = NULL;
|
||||
populateArgs.options = populate_options;
|
||||
|
||||
progName = strrchr(argv[0], '/');
|
||||
if (!progName)
|
||||
progName = strrchr(argv[0], '\\');
|
||||
progName = progName ? progName+1 : argv[0];
|
||||
|
||||
rv = NSS_NoDB_Init(NULL);
|
||||
if (rv != SECSuccess) {
|
||||
SECU_PrintPRandOSError(progName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = SECU_ParseCommandLine(argc, argv, progName, &populateArgs);
|
||||
if (rv == SECFailure) {
|
||||
fprintf(stderr, "%s: command line parsing error!\n", progName);
|
||||
Usage(progName);
|
||||
return -1;
|
||||
}
|
||||
rv = SECFailure;
|
||||
|
||||
|
||||
if (populateArgs.options[opt_KeySize].activated) {
|
||||
keySize = PORT_Atoi(populateArgs.options[opt_KeySize].arg);
|
||||
}
|
||||
if (populateArgs.options[opt_Repeat].activated) {
|
||||
repeat = PORT_Atoi(populateArgs.options[opt_Repeat].arg);
|
||||
}
|
||||
if (populateArgs.options[opt_Exponent].activated) {
|
||||
exponent = PORT_Atoi(populateArgs.options[opt_Exponent].arg);
|
||||
}
|
||||
if (populateArgs.options[opt_Tests].activated) {
|
||||
char * test_string = populateArgs.options[opt_Tests].arg;
|
||||
mask = PORT_Atoi(test_string);
|
||||
if (mask == 0) {
|
||||
mask = parse_tests(test_string);
|
||||
}
|
||||
if (mask == 0) {
|
||||
Usage(progName);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
exp_exp_prime_fail_count = 0;
|
||||
for (i=0; i < repeat; i++) {
|
||||
printf("Running RSA Populate test run %d\n",i);
|
||||
ret = doRSAPopulateTest(keySize, exponent, mask, NULL);
|
||||
if (ret != 0) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret != 0) {
|
||||
fprintf(stderr,"RSA Populate test round %d: FAILED\n",i);
|
||||
}
|
||||
if (repeat > 1) {
|
||||
printf(" pub priv prime test: %d failures out of %d runs (%f %%)\n",
|
||||
exp_exp_prime_fail_count, i,
|
||||
(((double)exp_exp_prime_fail_count) * 100.0)/(double) i);
|
||||
}
|
||||
return ret;
|
||||
}
|
|
@ -729,8 +729,7 @@ breakout:
|
|||
/* Display validation results */
|
||||
if (secStatus != SECSuccess || log.count > 0) {
|
||||
CERTVerifyLogNode *node = NULL;
|
||||
PRIntn err = PR_GetError();
|
||||
fprintf(stderr, "Chain is bad, %d = %s\n", err, SECU_Strerror(err));
|
||||
fprintf(stderr, "Chain is bad!\n");
|
||||
|
||||
SECU_displayVerifyLog(stderr, &log, verbose);
|
||||
/* Have cert refs in the log only in case of failure.
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
/*
|
||||
* cert.h - public data structures and prototypes for the certificate library
|
||||
*
|
||||
* $Id: cert.h,v 1.80 2010/04/30 07:47:47 nelson%bolyard.com Exp $
|
||||
* $Id: cert.h,v 1.80.2.1 2010/09/24 13:31:57 kaie%kuix.de Exp $
|
||||
*/
|
||||
|
||||
#ifndef _CERT_H_
|
||||
|
@ -606,6 +606,16 @@ CERT_FindCertByEmailAddr(CERTCertDBHandle *handle, char *emailAddr);
|
|||
CERTCertificate *
|
||||
CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name);
|
||||
|
||||
/*
|
||||
** Find a certificate in the database by a email address or nickname
|
||||
** and require it to have the given usage.
|
||||
** "name" is the email address or nickname to look up
|
||||
*/
|
||||
CERTCertificate *
|
||||
CERT_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle,
|
||||
const char *name,
|
||||
SECCertUsage lookingForUsage);
|
||||
|
||||
/*
|
||||
** Find a certificate in the database by a digest of a subject public key
|
||||
** "spkDigest" is the digest to look up
|
||||
|
|
|
@ -614,19 +614,30 @@ CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert)
|
|||
return STAN_GetCERTCertificateOrRelease(c);
|
||||
}
|
||||
|
||||
CERTCertificate *
|
||||
CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name)
|
||||
static CERTCertificate *
|
||||
common_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle,
|
||||
char *name,
|
||||
PRBool anyUsage,
|
||||
SECCertUsage lookingForUsage)
|
||||
{
|
||||
NSSCryptoContext *cc;
|
||||
NSSCertificate *c, *ct;
|
||||
CERTCertificate *cert;
|
||||
NSSUsage usage;
|
||||
CERTCertList *certlist;
|
||||
|
||||
if (NULL == name) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
usage.anyUsage = PR_TRUE;
|
||||
|
||||
usage.anyUsage = anyUsage;
|
||||
|
||||
if (!anyUsage) {
|
||||
usage.nss3lookingForCA = PR_FALSE;
|
||||
usage.nss3usage = lookingForUsage;
|
||||
}
|
||||
|
||||
cc = STAN_GetDefaultCryptoContext();
|
||||
ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name,
|
||||
NULL, &usage, NULL);
|
||||
|
@ -638,7 +649,34 @@ CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name)
|
|||
PORT_Free(lowercaseName);
|
||||
}
|
||||
}
|
||||
cert = PK11_FindCertFromNickname(name, NULL);
|
||||
|
||||
if (anyUsage) {
|
||||
cert = PK11_FindCertFromNickname(name, NULL);
|
||||
}
|
||||
else {
|
||||
if (ct) {
|
||||
/* Does ct really have the required usage? */
|
||||
nssDecodedCert *dc;
|
||||
dc = nssCertificate_GetDecoding(ct);
|
||||
if (!dc->matchUsage(dc, &usage)) {
|
||||
CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
|
||||
ct = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
certlist = PK11_FindCertsFromNickname(name, NULL);
|
||||
if (certlist) {
|
||||
SECStatus rv = CERT_FilterCertListByUsage(certlist,
|
||||
lookingForUsage,
|
||||
PR_FALSE);
|
||||
if (SECSuccess == rv &&
|
||||
!CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist)) {
|
||||
cert = CERT_DupCertificate(CERT_LIST_HEAD(certlist)->cert);
|
||||
}
|
||||
CERT_DestroyCertList(certlist);
|
||||
}
|
||||
}
|
||||
|
||||
if (cert) {
|
||||
c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
|
||||
CERT_DestroyCertificate(cert);
|
||||
|
@ -651,6 +689,23 @@ CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name)
|
|||
return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
|
||||
}
|
||||
|
||||
CERTCertificate *
|
||||
CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name)
|
||||
{
|
||||
return common_FindCertByNicknameOrEmailAddrForUsage(handle, name,
|
||||
PR_TRUE, 0);
|
||||
}
|
||||
|
||||
CERTCertificate *
|
||||
CERT_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle,
|
||||
const char *name,
|
||||
SECCertUsage lookingForUsage)
|
||||
{
|
||||
return common_FindCertByNicknameOrEmailAddrForUsage(handle, name,
|
||||
PR_FALSE,
|
||||
lookingForUsage);
|
||||
}
|
||||
|
||||
static void
|
||||
add_to_subject_list(CERTCertList *certList, CERTCertificate *cert,
|
||||
PRBool validOnly, int64 sorttime)
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
/*
|
||||
* Interface to the OCSP implementation.
|
||||
*
|
||||
* $Id: ocsp.h,v 1.17 2010/02/01 20:09:32 wtc%google.com Exp $
|
||||
* $Id: ocsp.h,v 1.17.2.1 2010/09/27 21:22:20 wtc%google.com Exp $
|
||||
*/
|
||||
|
||||
#ifndef _OCSP_H_
|
||||
|
@ -476,9 +476,10 @@ CERT_RegisterAlternateOCSPAIAInfoCallBack(
|
|||
|
||||
/*
|
||||
* FUNCTION: CERT_ParseURL
|
||||
* Parse the URI of a OCSP responder into hostname, port, and path.
|
||||
* Parse a URI into hostname, port, and path. The scheme in the URI must
|
||||
* be "http".
|
||||
* INPUTS:
|
||||
* const char *location
|
||||
* const char *url
|
||||
* The URI to be parsed
|
||||
* OUTPUTS:
|
||||
* char *pHostname
|
||||
|
@ -490,9 +491,8 @@ CERT_RegisterAlternateOCSPAIAInfoCallBack(
|
|||
* Pointer to store the path obtained from the URI.
|
||||
* This result should be freed (via PORT_Free) when no longer in use.
|
||||
* RETURN:
|
||||
* Returns SECSuccess when parsing was successful. Anything else means
|
||||
* Returns SECSuccess when parsing was successful. Returns SECFailure when
|
||||
* problems were encountered.
|
||||
*
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -77,8 +77,8 @@
|
|||
* of the comment in the CK_VERSION type definition.
|
||||
*/
|
||||
#define NSS_BUILTINS_LIBRARY_VERSION_MAJOR 1
|
||||
#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 80
|
||||
#define NSS_BUILTINS_LIBRARY_VERSION "1.80"
|
||||
#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 81
|
||||
#define NSS_BUILTINS_LIBRARY_VERSION "1.81"
|
||||
|
||||
/* These version numbers detail the semantic changes to the ckfw engine. */
|
||||
#define NSS_BUILTINS_HARDWARE_VERSION_MAJOR 1
|
||||
|
|
|
@ -168,8 +168,8 @@ ifeq ($(CPU_ARCH),x86_64)
|
|||
DEFINES += -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN
|
||||
# DEFINES += -DMPI_AMD64_ADD
|
||||
# comment the next two lines to turn off intel HW accelleration
|
||||
# DEFINES += -DUSE_HW_AES
|
||||
# ASFILES += intel-aes.s
|
||||
DEFINES += -DUSE_HW_AES
|
||||
ASFILES += intel-aes.s
|
||||
MPI_SRCS += mpi_amd64.c mp_comba.c
|
||||
endif
|
||||
ifeq ($(CPU_ARCH),x86)
|
||||
|
@ -415,8 +415,8 @@ else
|
|||
DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY
|
||||
DEFINES += -DNSS_USE_COMBA -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN
|
||||
# comment the next two lines to turn off intel HW accelleration
|
||||
# DEFINES += -DUSE_HW_AES
|
||||
# ASFILES += intel-aes.s
|
||||
DEFINES += -DUSE_HW_AES
|
||||
ASFILES += intel-aes.s
|
||||
MPI_SRCS += mpi_amd64.c
|
||||
else
|
||||
# Solaris x86
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: blapi.h,v 1.33 2009/03/29 03:45:32 wtc%google.com Exp $ */
|
||||
/* $Id: blapi.h,v 1.33.22.2 2010/12/04 18:59:01 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifndef _BLAPI_H_
|
||||
#define _BLAPI_H_
|
||||
|
@ -98,11 +98,58 @@ extern SECStatus RSA_PrivateKeyOpDoubleChecked(RSAPrivateKey * key,
|
|||
*/
|
||||
extern SECStatus RSA_PrivateKeyCheck(RSAPrivateKey *key);
|
||||
|
||||
/*
|
||||
** Given only minimal private key parameters, fill in the rest of the
|
||||
** parameters.
|
||||
**
|
||||
**
|
||||
** All the entries, including those supplied by the caller, will be
|
||||
** overwritten with data alocated out of the arena.
|
||||
**
|
||||
** If no arena is supplied, one will be created.
|
||||
**
|
||||
** The following fields must be supplied in order for this function
|
||||
** to succeed:
|
||||
** one of either publicExponent or privateExponent
|
||||
** two more of the following 5 parameters (not counting the above).
|
||||
** modulus (n)
|
||||
** prime1 (p)
|
||||
** prime2 (q)
|
||||
** publicExponent (e)
|
||||
** privateExponent (d)
|
||||
**
|
||||
** NOTE: if only the publicExponent, privateExponent, and one prime is given,
|
||||
** then there may be more than one RSA key that matches that combination. If
|
||||
** we find 2 possible valid keys that meet this criteria, we return an error.
|
||||
** If we return the wrong key, and the original modulus is compared to the
|
||||
** new modulus, both can be factored by calculateing gcd(n_old,n_new) to get
|
||||
** the common prime.
|
||||
**
|
||||
** NOTE: in some cases the publicExponent must be less than 2^23 for this
|
||||
** function to work correctly. (The case where we have only one of: modulus
|
||||
** prime1 and prime2).
|
||||
**
|
||||
** All parameters will be replaced in the key structure with new parameters
|
||||
** allocated out of the arena. There is no attempt to free the old structures.
|
||||
** prime1 will always be greater than prime2 (even if the caller supplies the
|
||||
** smaller prime as prime1 or the larger prime as prime2). The parameters are
|
||||
** not overwritten on failure.
|
||||
**
|
||||
** While the remaining Chinese remainder theorem parameters (dp,dp, and qinv)
|
||||
** can also be used in reconstructing the private key, they are currently
|
||||
** ignored in this implementation.
|
||||
*/
|
||||
extern SECStatus RSA_PopulatePrivateKey(RSAPrivateKey *key);
|
||||
|
||||
/********************************************************************
|
||||
** DSA signing algorithm
|
||||
*/
|
||||
|
||||
/* Generate a new random value within the interval [2, q-1].
|
||||
*/
|
||||
extern SECStatus DSA_NewRandom(PLArenaPool * arena, const SECItem * q,
|
||||
SECItem * random);
|
||||
|
||||
/*
|
||||
** Generate and return a new DSA public and private key pair,
|
||||
** both of which are encoded into a single DSAPrivateKey struct.
|
||||
|
@ -193,6 +240,72 @@ extern SECStatus KEA_Derive(SECItem *prime,
|
|||
*/
|
||||
extern PRBool KEA_Verify(SECItem *Y, SECItem *prime, SECItem *subPrime);
|
||||
|
||||
/****************************************
|
||||
* J-PAKE key transport
|
||||
*/
|
||||
|
||||
/* Given gx == g^x, create a Schnorr zero-knowledge proof for the value x
|
||||
* using the specified hash algorithm and signer ID. The signature is
|
||||
* returned in the values gv and r. testRandom must be NULL for a PRNG
|
||||
* generated random committment to be used in the sigature. When testRandom
|
||||
* is non-NULL, that value must contain a value in the subgroup q; that
|
||||
* value will be used instead of a PRNG-generated committment in order to
|
||||
* facilitate known-answer tests.
|
||||
*
|
||||
* If gxIn is non-NULL then it must contain a pre-computed value of g^x that
|
||||
* will be used by the function; in this case, the gxOut parameter must be NULL.
|
||||
* If the gxIn parameter is NULL then gxOut must be non-NULL; in this case
|
||||
* gxOut will contain the value g^x on output.
|
||||
*
|
||||
* gx (if not supplied by the caller), gv, and r will be allocated in the arena.
|
||||
* The arena is *not* optional so do not pass NULL for the arena parameter.
|
||||
* The arena should be zeroed when it is freed.
|
||||
*/
|
||||
SECStatus
|
||||
JPAKE_Sign(PLArenaPool * arena, const PQGParams * pqg, HASH_HashType hashType,
|
||||
const SECItem * signerID, const SECItem * x,
|
||||
const SECItem * testRandom, const SECItem * gxIn, SECItem * gxOut,
|
||||
SECItem * gv, SECItem * r);
|
||||
|
||||
/* Given gx == g^x, verify the Schnorr zero-knowledge proof (gv, r) for the
|
||||
* value x using the specified hash algorithm and signer ID.
|
||||
*
|
||||
* The arena is *not* optional so do not pass NULL for the arena parameter.
|
||||
*/
|
||||
SECStatus
|
||||
JPAKE_Verify(PRArenaPool * arena, const PQGParams * pqg,
|
||||
HASH_HashType hashType, const SECItem * signerID,
|
||||
const SECItem * peerID, const SECItem * gx,
|
||||
const SECItem * gv, const SECItem * r);
|
||||
|
||||
/* Call before round 2 with x2, s, and x2s all non-NULL. This will calculate
|
||||
* base = g^(x1+x3+x4) (mod p) and x2s = x2*s (mod q). The values to send in
|
||||
* round 2 (A and the proof of knowledge of x2s) can then be calculated with
|
||||
* JPAKE_Sign using pqg->base = base and x = x2s.
|
||||
*
|
||||
* Call after round 2 with x2, s, and x2s all NULL, and passing (gx1, gx2, gx3)
|
||||
* instead of (gx1, gx3, gx4). This will calculate base = g^(x1+x2+x3). Then call
|
||||
* JPAKE_Verify with pqg->base = base and then JPAKE_Final.
|
||||
*
|
||||
* base and x2s will be allocated in the arena. The arena is *not* optional so
|
||||
* do not pass NULL for the arena parameter. The arena should be zeroed when it
|
||||
* is freed.
|
||||
*/
|
||||
SECStatus
|
||||
JPAKE_Round2(PLArenaPool * arena, const SECItem * p, const SECItem *q,
|
||||
const SECItem * gx1, const SECItem * gx3, const SECItem * gx4,
|
||||
SECItem * base, const SECItem * x2, const SECItem * s, SECItem * x2s);
|
||||
|
||||
/* K = (B/g^(x2*x4*s))^x2 (mod p)
|
||||
*
|
||||
* K will be allocated in the arena. The arena is *not* optional so do not pass
|
||||
* NULL for the arena parameter. The arena should be zeroed when it is freed.
|
||||
*/
|
||||
SECStatus
|
||||
JPAKE_Final(PLArenaPool * arena, const SECItem * p, const SECItem *q,
|
||||
const SECItem * x2, const SECItem * gx4, const SECItem * x2s,
|
||||
const SECItem * B, SECItem * K);
|
||||
|
||||
/******************************************************
|
||||
** Elliptic Curve algorithms
|
||||
*/
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: dsa.c,v 1.20 2009/03/29 16:51:58 wtc%google.com Exp $ */
|
||||
/* $Id: dsa.c,v 1.20.22.1 2010/12/04 18:59:01 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
|
@ -56,21 +56,17 @@
|
|||
/* XXX to be replaced by define in blapit.h */
|
||||
#define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048
|
||||
|
||||
#define FIPS_DSA_Q 160
|
||||
#define QSIZE (FIPS_DSA_Q / PR_BITS_PER_BYTE)
|
||||
|
||||
/*
|
||||
* FIPS 186-2 requires result from random output to be reduced mod q when
|
||||
* generating random numbers for DSA.
|
||||
*
|
||||
* Input: w, 2*QSIZE bytes
|
||||
* q, DSA_SUBPRIME_LEN bytes
|
||||
* Output: xj, DSA_SUBPRIME_LEN bytes
|
||||
* Input: w, 2*qLen bytes
|
||||
* q, qLen bytes
|
||||
* Output: xj, qLen bytes
|
||||
*/
|
||||
SECStatus
|
||||
FIPS186Change_ReduceModQForDSA(const PRUint8 *w,
|
||||
const PRUint8 *q,
|
||||
PRUint8 *xj)
|
||||
static SECStatus
|
||||
fips186Change_ReduceModQForDSA(const PRUint8 *w, const PRUint8 *q,
|
||||
unsigned int qLen, PRUint8 * xj)
|
||||
{
|
||||
mp_int W, Q, Xj;
|
||||
mp_err err;
|
||||
|
@ -86,15 +82,16 @@ FIPS186Change_ReduceModQForDSA(const PRUint8 *w,
|
|||
/*
|
||||
* Convert input arguments into MPI integers.
|
||||
*/
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&W, w, 2*QSIZE) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Q, q, DSA_SUBPRIME_LEN) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&W, w, 2*qLen) );
|
||||
CHECK_MPI_OK( mp_read_unsigned_octets(&Q, q, qLen) );
|
||||
|
||||
/*
|
||||
* Algorithm 1 of FIPS 186-2 Change Notice 1, Step 3.3
|
||||
*
|
||||
* xj = (w0 || w1) mod q
|
||||
*/
|
||||
CHECK_MPI_OK( mp_mod(&W, &Q, &Xj) );
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&Xj, xj, DSA_SUBPRIME_LEN) );
|
||||
CHECK_MPI_OK( mp_to_fixlen_octets(&Xj, xj, qLen) );
|
||||
cleanup:
|
||||
mp_clear(&W);
|
||||
mp_clear(&Q);
|
||||
|
@ -106,6 +103,17 @@ cleanup:
|
|||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIPS 186-2 requires result from random output to be reduced mod q when
|
||||
* generating random numbers for DSA.
|
||||
*/
|
||||
SECStatus
|
||||
FIPS186Change_ReduceModQForDSA(const unsigned char *w,
|
||||
const unsigned char *q,
|
||||
unsigned char *xj) {
|
||||
return fips186Change_ReduceModQForDSA(w, q, DSA_SUBPRIME_LEN, xj);
|
||||
}
|
||||
|
||||
/*
|
||||
* The core of Algorithm 1 of FIPS 186-2 Change Notice 1.
|
||||
*
|
||||
|
@ -137,24 +145,36 @@ FIPS186Change_GenerateX(PRUint8 *XKEY, const PRUint8 *XSEEDj,
|
|||
** object. In DSA mode, so there is a q.
|
||||
*/
|
||||
static SECStatus
|
||||
dsa_GenerateGlobalRandomBytes(void *dest, size_t len, const PRUint8 *q)
|
||||
dsa_GenerateGlobalRandomBytes(const SECItem * qItem, PRUint8 * dest,
|
||||
unsigned int * destLen, unsigned int maxDestLen)
|
||||
{
|
||||
SECStatus rv;
|
||||
PRUint8 w[2*QSIZE];
|
||||
SECItem w;
|
||||
const PRUint8 * q = qItem->data;
|
||||
unsigned int qLen = qItem->len;
|
||||
|
||||
PORT_Assert(q && len == DSA_SUBPRIME_LEN);
|
||||
if (len != DSA_SUBPRIME_LEN) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
if (*q == 0) {
|
||||
++q;
|
||||
--qLen;
|
||||
}
|
||||
rv = RNG_GenerateGlobalRandomBytes(w, 2*QSIZE);
|
||||
if (rv != SECSuccess) {
|
||||
return rv;
|
||||
if (maxDestLen < qLen) {
|
||||
/* This condition can occur when DSA_SignDigest is passed a group
|
||||
with a subprime that is larger than DSA_SUBPRIME_LEN. */
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
FIPS186Change_ReduceModQForDSA(w, q, (PRUint8 *)dest);
|
||||
w.data = NULL; /* otherwise SECITEM_AllocItem asserts */
|
||||
if (!SECITEM_AllocItem(NULL, &w, 2*qLen)) {
|
||||
return SECFailure;
|
||||
}
|
||||
*destLen = qLen;
|
||||
|
||||
rv = RNG_GenerateGlobalRandomBytes(w.data, w.len);
|
||||
if (rv == SECSuccess) {
|
||||
rv = fips186Change_ReduceModQForDSA(w.data, q, qLen, dest);
|
||||
}
|
||||
|
||||
SECITEM_FreeItem(&w, PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -163,9 +183,9 @@ static void translate_mpi_error(mp_err err)
|
|||
MP_TO_SEC_ERROR(err);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
dsa_NewKey(const PQGParams *params, DSAPrivateKey **privKey,
|
||||
const unsigned char *xb)
|
||||
static SECStatus
|
||||
dsa_NewKeyExtended(const PQGParams *params, const SECItem * seed,
|
||||
DSAPrivateKey **privKey)
|
||||
{
|
||||
mp_int p, g;
|
||||
mp_int x, y;
|
||||
|
@ -173,7 +193,7 @@ dsa_NewKey(const PQGParams *params, DSAPrivateKey **privKey,
|
|||
PRArenaPool *arena;
|
||||
DSAPrivateKey *key;
|
||||
/* Check args. */
|
||||
if (!params || !privKey) {
|
||||
if (!params || !privKey || !seed || !seed->data) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
@ -208,10 +228,10 @@ dsa_NewKey(const PQGParams *params, DSAPrivateKey **privKey,
|
|||
/* Convert stored p, g, and received x into MPI integers. */
|
||||
SECITEM_TO_MPINT(params->prime, &p);
|
||||
SECITEM_TO_MPINT(params->base, &g);
|
||||
OCTETS_TO_MPINT(xb, &x, DSA_SUBPRIME_LEN);
|
||||
OCTETS_TO_MPINT(seed->data, &x, seed->len);
|
||||
/* Store x in private key */
|
||||
SECITEM_AllocItem(arena, &key->privateValue, DSA_SUBPRIME_LEN);
|
||||
memcpy(key->privateValue.data, xb, DSA_SUBPRIME_LEN);
|
||||
SECITEM_AllocItem(arena, &key->privateValue, seed->len);
|
||||
PORT_Memcpy(key->privateValue.data, seed->data, seed->len);
|
||||
/* Compute public key y = g**x mod p */
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &x, &p, &y) );
|
||||
/* Store y in public key */
|
||||
|
@ -232,6 +252,53 @@ cleanup:
|
|||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DSA_NewRandom(PLArenaPool * arena, const SECItem * q, SECItem * seed)
|
||||
{
|
||||
int retries = 10;
|
||||
unsigned int i;
|
||||
PRBool good;
|
||||
|
||||
if (q == NULL || q->data == NULL || q->len == 0 ||
|
||||
(q->data[0] == 0 && q->len == 1)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (!SECITEM_AllocItem(arena, seed, q->len)) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
do {
|
||||
/* Generate seed bytes for x according to FIPS 186-1 appendix 3 */
|
||||
if (dsa_GenerateGlobalRandomBytes(q, seed->data, &seed->len,
|
||||
seed->len)) {
|
||||
goto loser;
|
||||
}
|
||||
/* Disallow values of 0 and 1 for x. */
|
||||
good = PR_FALSE;
|
||||
for (i = 0; i < seed->len-1; i++) {
|
||||
if (seed->data[i] != 0) {
|
||||
good = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!good && seed->data[i] > 1) {
|
||||
good = PR_TRUE;
|
||||
}
|
||||
} while (!good && --retries > 0);
|
||||
|
||||
if (!good) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
loser: if (arena != NULL) {
|
||||
SECITEM_FreeItem(seed, PR_FALSE);
|
||||
}
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate and return a new DSA public and private key pair,
|
||||
** both of which are encoded into a single DSAPrivateKey struct.
|
||||
|
@ -241,37 +308,21 @@ cleanup:
|
|||
SECStatus
|
||||
DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey)
|
||||
{
|
||||
SECItem seed;
|
||||
SECStatus rv;
|
||||
unsigned char seed[DSA_SUBPRIME_LEN];
|
||||
int retries = 10;
|
||||
int i;
|
||||
PRBool good;
|
||||
|
||||
do {
|
||||
/* Generate seed bytes for x according to FIPS 186-1 appendix 3 */
|
||||
if (dsa_GenerateGlobalRandomBytes(seed, DSA_SUBPRIME_LEN,
|
||||
params->subPrime.data))
|
||||
return SECFailure;
|
||||
/* Disallow values of 0 and 1 for x. */
|
||||
good = PR_FALSE;
|
||||
for (i = 0; i < DSA_SUBPRIME_LEN-1; i++) {
|
||||
if (seed[i] != 0) {
|
||||
good = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!good && seed[i] > 1) {
|
||||
good = PR_TRUE;
|
||||
}
|
||||
} while (!good && --retries > 0);
|
||||
seed.data = NULL;
|
||||
|
||||
if (!good) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
return SECFailure;
|
||||
rv = DSA_NewRandom(NULL, ¶ms->subPrime, &seed);
|
||||
if (rv == SECSuccess) {
|
||||
if (seed.len != DSA_SUBPRIME_LEN) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
rv = SECFailure;
|
||||
} else {
|
||||
rv = dsa_NewKeyExtended(params, &seed, privKey);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate a new DSA key using random seed. */
|
||||
rv = dsa_NewKey(params, privKey, seed);
|
||||
SECITEM_FreeItem(&seed, PR_FALSE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -281,9 +332,11 @@ DSA_NewKeyFromSeed(const PQGParams *params,
|
|||
const unsigned char *seed,
|
||||
DSAPrivateKey **privKey)
|
||||
{
|
||||
SECStatus rv;
|
||||
rv = dsa_NewKey(params, privKey, seed);
|
||||
return rv;
|
||||
/* TODO: check Q size */
|
||||
SECItem seedItem;
|
||||
seedItem.data = (unsigned char*) seed;
|
||||
seedItem.len = DSA_SUBPRIME_LEN;
|
||||
return dsa_NewKeyExtended(params, &seedItem, privKey);
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
|
@ -393,18 +446,24 @@ DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
|
|||
SECStatus rv;
|
||||
int retries = 10;
|
||||
unsigned char kSeed[DSA_SUBPRIME_LEN];
|
||||
int i;
|
||||
unsigned int kSeedLen = 0;
|
||||
unsigned int i;
|
||||
PRBool good;
|
||||
|
||||
PORT_SetError(0);
|
||||
do {
|
||||
rv = dsa_GenerateGlobalRandomBytes(kSeed, DSA_SUBPRIME_LEN,
|
||||
key->params.subPrime.data);
|
||||
rv = dsa_GenerateGlobalRandomBytes(&key->params.subPrime,
|
||||
kSeed, &kSeedLen, sizeof kSeed);
|
||||
if (rv != SECSuccess)
|
||||
break;
|
||||
if (kSeedLen != DSA_SUBPRIME_LEN) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
rv = SECFailure;
|
||||
break;
|
||||
}
|
||||
/* Disallow a value of 0 for k. */
|
||||
good = PR_FALSE;
|
||||
for (i = 0; i < DSA_SUBPRIME_LEN; i++) {
|
||||
for (i = 0; i < kSeedLen; i++) {
|
||||
if (kSeed[i] != 0) {
|
||||
good = PR_TRUE;
|
||||
break;
|
||||
|
|
|
@ -438,22 +438,18 @@ intel_aes_encrypt_cbc_128:
|
|||
.globl intel_aes_decrypt_cbc_128
|
||||
.align 16
|
||||
intel_aes_decrypt_cbc_128:
|
||||
// leaq IV_OFFSET(%rdi), %rdx
|
||||
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
|
||||
leaq 16(%rdi), %rdx
|
||||
leaq 48(%rdi), %rdi
|
||||
leaq 16(%rdi), %rdx /* iv */
|
||||
leaq 48(%rdi), %rdi /* expanded key */
|
||||
|
||||
movdqu (%rdx), %xmm0
|
||||
movdqu (%rdi), %xmm2
|
||||
movdqu 160(%rdi), %xmm12
|
||||
movdqu (%rdx), %xmm0 /* iv */
|
||||
movdqu (%rdi), %xmm2 /* first key block */
|
||||
movdqu 160(%rdi), %xmm12 /* last key block */
|
||||
xorl %eax, %eax
|
||||
// cmpq $8*16, %r9
|
||||
cmpq $128, %r9
|
||||
jb 1f
|
||||
// leaq -8*16(%r9), %r11
|
||||
leaq -128(%r9), %r11
|
||||
2: movdqu (%r8, %rax), %xmm3
|
||||
movdqu 16(%r8, %rax), %xmm4
|
||||
2: movdqu (%r8, %rax), %xmm3 /* 1st data block */
|
||||
movdqu 16(%r8, %rax), %xmm4 /* 2d data block */
|
||||
movdqu 32(%r8, %rax), %xmm5
|
||||
movdqu 48(%r8, %rax), %xmm6
|
||||
movdqu 64(%r8, %rax), %xmm7
|
||||
|
@ -469,7 +465,7 @@ intel_aes_decrypt_cbc_128:
|
|||
pxor %xmm12, %xmm9
|
||||
pxor %xmm12, %xmm10
|
||||
movq $144, %r10
|
||||
3: movdqu (%rdi, %r10), %xmm1
|
||||
3: movdqu (%rdi, %r10), %xmm1 /* n-th block of the key */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xd9 /* aesdec %xmm1, %xmm3 */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xe1 /* aesdec %xmm1, %xmm4 */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xe9 /* aesdec %xmm1, %xmm5 */
|
||||
|
@ -488,14 +484,21 @@ intel_aes_decrypt_cbc_128:
|
|||
.byte 0x66,0x44,0x0f,0x38,0xdf,0xc2 /* aesdeclast %xmm2, %xmm8 */
|
||||
.byte 0x66,0x44,0x0f,0x38,0xdf,0xca /* aesdeclast %xmm2, %xmm9 */
|
||||
.byte 0x66,0x44,0x0f,0x38,0xdf,0xd2 /* aesdeclast %xmm2, %xmm10 */
|
||||
pxor %xmm0, %xmm3
|
||||
pxor (%r8, %rax), %xmm4
|
||||
pxor 16(%r8, %rax), %xmm5
|
||||
pxor 32(%r8, %rax), %xmm6
|
||||
pxor 48(%r8, %rax), %xmm7
|
||||
pxor 64(%r8, %rax), %xmm8
|
||||
pxor 80(%r8, %rax), %xmm9
|
||||
pxor 96(%r8, %rax), %xmm10
|
||||
pxor %xmm0, %xmm3
|
||||
movdqu (%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm4
|
||||
movdqu 16(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm5
|
||||
movdqu 32(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm6
|
||||
movdqu 48(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm7
|
||||
movdqu 64(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm8
|
||||
movdqu 80(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm9
|
||||
movdqu 96(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm10
|
||||
movdqu 112(%r8, %rax), %xmm0
|
||||
movdqu %xmm3, (%rsi, %rax)
|
||||
movdqu %xmm4, 16(%rsi, %rax)
|
||||
|
@ -505,7 +508,6 @@ intel_aes_decrypt_cbc_128:
|
|||
movdqu %xmm8, 80(%rsi, %rax)
|
||||
movdqu %xmm9, 96(%rsi, %rax)
|
||||
movdqu %xmm10, 112(%rsi, %rax)
|
||||
// addq $8*16, %rax
|
||||
addq $128, %rax
|
||||
cmpq %r11, %rax
|
||||
jbe 2b
|
||||
|
@ -547,8 +549,7 @@ intel_aes_decrypt_cbc_128:
|
|||
xor %eax, %eax
|
||||
ret
|
||||
.size intel_aes_decrypt_cbc_128, .-intel_aes_decrypt_cbc_128
|
||||
|
||||
|
||||
|
||||
/* in %rdi : the key
|
||||
in %rsi : buffer for expanded key
|
||||
*/
|
||||
|
@ -974,8 +975,6 @@ intel_aes_encrypt_cbc_192:
|
|||
.globl intel_aes_decrypt_cbc_192
|
||||
.align 16
|
||||
intel_aes_decrypt_cbc_192:
|
||||
// leaq IV_OFFSET(%rdi), %rdx
|
||||
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
|
||||
leaq 16(%rdi), %rdx
|
||||
leaq 48(%rdi), %rdi
|
||||
|
||||
|
@ -983,10 +982,8 @@ intel_aes_decrypt_cbc_192:
|
|||
movdqu (%rdi), %xmm2
|
||||
movdqu 192(%rdi), %xmm14
|
||||
xorl %eax, %eax
|
||||
// cmpq $8*16, %r9
|
||||
cmpq $128, %r9
|
||||
jb 1f
|
||||
// leaq -8*16(%r9), %r11
|
||||
leaq -128(%r9), %r11
|
||||
2: movdqu (%r8, %rax), %xmm3
|
||||
movdqu 16(%r8, %rax), %xmm4
|
||||
|
@ -1024,14 +1021,21 @@ intel_aes_decrypt_cbc_192:
|
|||
.byte 0x66,0x44,0x0f,0x38,0xdf,0xc2 /* aesdeclast %xmm2, %xmm8 */
|
||||
.byte 0x66,0x44,0x0f,0x38,0xdf,0xca /* aesdeclast %xmm2, %xmm9 */
|
||||
.byte 0x66,0x44,0x0f,0x38,0xdf,0xd2 /* aesdeclast %xmm2, %xmm10 */
|
||||
pxor %xmm0, %xmm3
|
||||
pxor (%r8, %rax), %xmm4
|
||||
pxor 16(%r8, %rax), %xmm5
|
||||
pxor 32(%r8, %rax), %xmm6
|
||||
pxor 48(%r8, %rax), %xmm7
|
||||
pxor 64(%r8, %rax), %xmm8
|
||||
pxor 80(%r8, %rax), %xmm9
|
||||
pxor 96(%r8, %rax), %xmm10
|
||||
pxor %xmm0, %xmm3
|
||||
movdqu (%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm4
|
||||
movdqu 16(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm5
|
||||
movdqu 32(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm6
|
||||
movdqu 48(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm7
|
||||
movdqu 64(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm8
|
||||
movdqu 80(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm9
|
||||
movdqu 96(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm10
|
||||
movdqu 112(%r8, %rax), %xmm0
|
||||
movdqu %xmm3, (%rsi, %rax)
|
||||
movdqu %xmm4, 16(%rsi, %rax)
|
||||
|
@ -1041,7 +1045,6 @@ intel_aes_decrypt_cbc_192:
|
|||
movdqu %xmm8, 80(%rsi, %rax)
|
||||
movdqu %xmm9, 96(%rsi, %rax)
|
||||
movdqu %xmm10, 112(%rsi, %rax)
|
||||
// addq $8*16, %rax
|
||||
addq $128, %rax
|
||||
cmpq %r11, %rax
|
||||
jbe 2b
|
||||
|
@ -1088,7 +1091,6 @@ intel_aes_decrypt_cbc_192:
|
|||
ret
|
||||
.size intel_aes_decrypt_cbc_192, .-intel_aes_decrypt_cbc_192
|
||||
|
||||
|
||||
/* in %rdi : the key
|
||||
in %rsi : buffer for expanded key
|
||||
*/
|
||||
|
@ -1296,13 +1298,13 @@ intel_aes_encrypt_ecb_256:
|
|||
1: cmpq %rax, %r9
|
||||
je 5f
|
||||
|
||||
movdqu (%rdi), %xmm8
|
||||
movdqu 16(%rdi), %xmm2
|
||||
movdqu 32(%rdi), %xmm3
|
||||
movdqu 48(%rdi), %xmm4
|
||||
movdqu 64(%rdi), %xmm5
|
||||
movdqu 80(%rdi), %xmm6
|
||||
movdqu 96(%rdi), %xmm7
|
||||
movdqu 112(%rdi), %xmm8
|
||||
movdqu 128(%rdi), %xmm9
|
||||
movdqu 144(%rdi), %xmm10
|
||||
movdqu 160(%rdi), %xmm11
|
||||
|
@ -1311,7 +1313,8 @@ intel_aes_encrypt_ecb_256:
|
|||
movdqu 208(%rdi), %xmm14
|
||||
|
||||
4: movdqu (%r8, %rax), %xmm1
|
||||
pxor (%rdi), %xmm1
|
||||
pxor %xmm8, %xmm1
|
||||
movdqu 112(%rdi), %xmm8
|
||||
.byte 0x66,0x0f,0x38,0xdc,0xca /* aesenc %xmm2, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xdc,0xcb /* aesenc %xmm3, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xdc,0xcc /* aesenc %xmm4, %xmm1 */
|
||||
|
@ -1319,6 +1322,7 @@ intel_aes_encrypt_ecb_256:
|
|||
.byte 0x66,0x0f,0x38,0xdc,0xce /* aesenc %xmm6, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xdc,0xcf /* aesenc %xmm7, %xmm1 */
|
||||
.byte 0x66,0x41,0x0f,0x38,0xdc,0xc8 /* aesenc %xmm8, %xmm1 */
|
||||
movdqu (%rdi), %xmm8
|
||||
.byte 0x66,0x41,0x0f,0x38,0xdc,0xc9 /* aesenc %xmm9, %xmm1 */
|
||||
.byte 0x66,0x41,0x0f,0x38,0xdc,0xca /* aesenc %xmm10, %xmm1 */
|
||||
.byte 0x66,0x41,0x0f,0x38,0xdc,0xcb /* aesenc %xmm11, %xmm1 */
|
||||
|
@ -1434,13 +1438,15 @@ intel_aes_decrypt_ecb_256:
|
|||
.byte 0x66,0x41,0x0f,0x38,0xde,0xca /* aesdec %xmm10, %xmm1 */
|
||||
.byte 0x66,0x41,0x0f,0x38,0xde,0xc9 /* aesdec %xmm9, %xmm1 */
|
||||
.byte 0x66,0x41,0x0f,0x38,0xde,0xc8 /* aesdec %xmm8, %xmm1 */
|
||||
movdqu (%rdi), %xmm8
|
||||
.byte 0x66,0x0f,0x38,0xde,0xcf /* aesdec %xmm7, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xce /* aesdec %xmm6, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xcd /* aesdec %xmm5, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xcc /* aesdec %xmm4, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xcb /* aesdec %xmm3, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xca /* aesdec %xmm2, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xdf,0x0f /* aesdeclast (%rdi), %xmm1 */
|
||||
.byte 0x66,0x41,0x0f,0x38,0xdf,0xc8 /* aesdeclast %xmm8, %xmm1 */
|
||||
movdqu 112(%rdi), %xmm8
|
||||
movdqu %xmm1, (%rsi, %rax)
|
||||
addq $16, %rax
|
||||
cmpq %rax, %r9
|
||||
|
@ -1473,13 +1479,13 @@ intel_aes_encrypt_cbc_256:
|
|||
leaq 48(%rdi), %rdi
|
||||
|
||||
movdqu (%rdx), %xmm0
|
||||
movdqu (%rdi), %xmm8
|
||||
movdqu 16(%rdi), %xmm2
|
||||
movdqu 32(%rdi), %xmm3
|
||||
movdqu 48(%rdi), %xmm4
|
||||
movdqu 64(%rdi), %xmm5
|
||||
movdqu 80(%rdi), %xmm6
|
||||
movdqu 96(%rdi), %xmm7
|
||||
movdqu 112(%rdi), %xmm8
|
||||
movdqu 128(%rdi), %xmm9
|
||||
movdqu 144(%rdi), %xmm10
|
||||
movdqu 160(%rdi), %xmm11
|
||||
|
@ -1491,7 +1497,8 @@ intel_aes_encrypt_cbc_256:
|
|||
xorl %eax, %eax
|
||||
1: movdqu (%r8, %rax), %xmm1
|
||||
pxor %xmm0, %xmm1
|
||||
pxor (%rdi), %xmm1
|
||||
pxor %xmm8, %xmm1
|
||||
movdqu 112(%rdi), %xmm8
|
||||
.byte 0x66,0x0f,0x38,0xdc,0xca /* aesenc %xmm2, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xdc,0xcb /* aesenc %xmm3, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xdc,0xcc /* aesenc %xmm4, %xmm1 */
|
||||
|
@ -1499,6 +1506,7 @@ intel_aes_encrypt_cbc_256:
|
|||
.byte 0x66,0x0f,0x38,0xdc,0xce /* aesenc %xmm6, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xdc,0xcf /* aesenc %xmm7, %xmm1 */
|
||||
.byte 0x66,0x41,0x0f,0x38,0xdc,0xc8 /* aesenc %xmm8, %xmm1 */
|
||||
movdqu (%rdi), %xmm8
|
||||
.byte 0x66,0x41,0x0f,0x38,0xdc,0xc9 /* aesenc %xmm9, %xmm1 */
|
||||
.byte 0x66,0x41,0x0f,0x38,0xdc,0xca /* aesenc %xmm10, %xmm1 */
|
||||
.byte 0x66,0x41,0x0f,0x38,0xdc,0xcb /* aesenc %xmm11, %xmm1 */
|
||||
|
@ -1582,14 +1590,21 @@ intel_aes_decrypt_cbc_256:
|
|||
.byte 0x66,0x44,0x0f,0x38,0xdf,0xc2 /* aesdeclast %xmm2, %xmm8 */
|
||||
.byte 0x66,0x44,0x0f,0x38,0xdf,0xca /* aesdeclast %xmm2, %xmm9 */
|
||||
.byte 0x66,0x44,0x0f,0x38,0xdf,0xd2 /* aesdeclast %xmm2, %xmm10 */
|
||||
pxor %xmm0, %xmm3
|
||||
pxor (%r8, %rax), %xmm4
|
||||
pxor 16(%r8, %rax), %xmm5
|
||||
pxor 32(%r8, %rax), %xmm6
|
||||
pxor 48(%r8, %rax), %xmm7
|
||||
pxor 64(%r8, %rax), %xmm8
|
||||
pxor 80(%r8, %rax), %xmm9
|
||||
pxor 96(%r8, %rax), %xmm10
|
||||
pxor %xmm0, %xmm3
|
||||
movdqu (%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm4
|
||||
movdqu 16(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm5
|
||||
movdqu 32(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm6
|
||||
movdqu 48(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm7
|
||||
movdqu 64(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm8
|
||||
movdqu 80(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm9
|
||||
movdqu 96(%r8, %rax), %xmm0
|
||||
pxor %xmm0, %xmm10
|
||||
movdqu 112(%r8, %rax), %xmm0
|
||||
movdqu %xmm3, (%rsi, %rax)
|
||||
movdqu %xmm4, 16(%rsi, %rax)
|
||||
|
@ -1629,13 +1644,15 @@ intel_aes_decrypt_cbc_256:
|
|||
.byte 0x66,0x41,0x0f,0x38,0xde,0xca /* aesdec %xmm10, %xmm1 */
|
||||
.byte 0x66,0x41,0x0f,0x38,0xde,0xc9 /* aesdec %xmm9, %xmm1 */
|
||||
.byte 0x66,0x41,0x0f,0x38,0xde,0xc8 /* aesdec %xmm8, %xmm1 */
|
||||
movdqu (%rdi), %xmm8
|
||||
.byte 0x66,0x0f,0x38,0xde,0xcf /* aesdec %xmm7, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xce /* aesdec %xmm6, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xcd /* aesdec %xmm5, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xcc /* aesdec %xmm4, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xcb /* aesdec %xmm3, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xde,0xca /* aesdec %xmm2, %xmm1 */
|
||||
.byte 0x66,0x0f,0x38,0xdf,0x0f /* aesdeclast (%rdi), %xmm1 */
|
||||
.byte 0x66,0x41,0x0f,0x38,0xdf,0xc8 /* aesdeclast %xmm8, %xmm1 */
|
||||
movdqu 112(%rdi), %xmm8
|
||||
pxor %xmm0, %xmm1
|
||||
movdqu %xmm1, (%rsi, %rax)
|
||||
movdqu (%r8, %rax), %xmm0
|
||||
|
|
|
@ -0,0 +1,525 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Fonudation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
#endif
|
||||
|
||||
#include "blapi.h"
|
||||
#include "secerr.h"
|
||||
#include "secitem.h"
|
||||
#include "secmpi.h"
|
||||
|
||||
/* Hash an item's length and then its value. Only items smaller than 2^16 bytes
|
||||
* are allowed. Lengths are hashed in network byte order. This is designed
|
||||
* to match the OpenSSL J-PAKE implementation.
|
||||
*/
|
||||
static mp_err
|
||||
hashSECItem(HASHContext * hash, const SECItem * it)
|
||||
{
|
||||
unsigned char length[2];
|
||||
|
||||
if (it->len > 0xffff)
|
||||
return MP_BADARG;
|
||||
|
||||
length[0] = (unsigned char) (it->len >> 8);
|
||||
length[1] = (unsigned char) (it->len);
|
||||
hash->hashobj->update(hash->hash_context, length, 2);
|
||||
hash->hashobj->update(hash->hash_context, it->data, it->len);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Hash all public components of the signature, each prefixed with its
|
||||
length, and then convert the hash to an mp_int. */
|
||||
static mp_err
|
||||
hashPublicParams(HASH_HashType hashType, const SECItem * g,
|
||||
const SECItem * gv, const SECItem * gx,
|
||||
const SECItem * signerID, mp_int * h)
|
||||
{
|
||||
mp_err err;
|
||||
unsigned char hBuf[HASH_LENGTH_MAX];
|
||||
SECItem hItem;
|
||||
HASHContext hash;
|
||||
|
||||
hash.hashobj = HASH_GetRawHashObject(hashType);
|
||||
if (hash.hashobj == NULL || hash.hashobj->length > sizeof hBuf) {
|
||||
return MP_BADARG;
|
||||
}
|
||||
hash.hash_context = hash.hashobj->create();
|
||||
if (hash.hash_context == NULL) {
|
||||
return MP_MEM;
|
||||
}
|
||||
|
||||
hItem.data = hBuf;
|
||||
hItem.len = hash.hashobj->length;
|
||||
|
||||
hash.hashobj->begin(hash.hash_context);
|
||||
CHECK_MPI_OK( hashSECItem(&hash, g) );
|
||||
CHECK_MPI_OK( hashSECItem(&hash, gv) );
|
||||
CHECK_MPI_OK( hashSECItem(&hash, gx) );
|
||||
CHECK_MPI_OK( hashSECItem(&hash, signerID) );
|
||||
hash.hashobj->end(hash.hash_context, hItem.data, &hItem.len,
|
||||
sizeof hBuf);
|
||||
SECITEM_TO_MPINT(hItem, h);
|
||||
|
||||
cleanup:
|
||||
if (hash.hash_context != NULL) {
|
||||
hash.hashobj->destroy(hash.hash_context, PR_TRUE);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Generate a Schnorr signature for round 1 or round 2 */
|
||||
SECStatus
|
||||
JPAKE_Sign(PLArenaPool * arena, const PQGParams * pqg, HASH_HashType hashType,
|
||||
const SECItem * signerID, const SECItem * x,
|
||||
const SECItem * testRandom, const SECItem * gxIn, SECItem * gxOut,
|
||||
SECItem * gv, SECItem * r)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
mp_err err;
|
||||
mp_int p;
|
||||
mp_int q;
|
||||
mp_int g;
|
||||
mp_int X;
|
||||
mp_int GX;
|
||||
mp_int V;
|
||||
mp_int GV;
|
||||
mp_int h;
|
||||
mp_int tmp;
|
||||
mp_int R;
|
||||
SECItem v;
|
||||
|
||||
if (!arena ||
|
||||
!pqg || !pqg->prime.data || pqg->prime.len == 0 ||
|
||||
!pqg->subPrime.data || pqg->subPrime.len == 0 ||
|
||||
!pqg->base.data || pqg->base.len == 0 ||
|
||||
!signerID || !signerID->data || signerID->len == 0 ||
|
||||
!x || !x->data || x->len == 0 ||
|
||||
(testRandom && (!testRandom->data || testRandom->len == 0)) ||
|
||||
(gxIn == NULL && (!gxOut || gxOut->data != NULL)) ||
|
||||
(gxIn != NULL && (!gxIn->data || gxIn->len == 0 || gxOut != NULL)) ||
|
||||
!gv || gv->data != NULL ||
|
||||
!r || r->data != NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&X) = 0;
|
||||
MP_DIGITS(&GX) = 0;
|
||||
MP_DIGITS(&V) = 0;
|
||||
MP_DIGITS(&GV) = 0;
|
||||
MP_DIGITS(&h) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
MP_DIGITS(&R) = 0;
|
||||
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&X) );
|
||||
CHECK_MPI_OK( mp_init(&GX) );
|
||||
CHECK_MPI_OK( mp_init(&V) );
|
||||
CHECK_MPI_OK( mp_init(&GV) );
|
||||
CHECK_MPI_OK( mp_init(&h) );
|
||||
CHECK_MPI_OK( mp_init(&tmp) );
|
||||
CHECK_MPI_OK( mp_init(&R) );
|
||||
|
||||
SECITEM_TO_MPINT(pqg->prime, &p);
|
||||
SECITEM_TO_MPINT(pqg->subPrime, &q);
|
||||
SECITEM_TO_MPINT(pqg->base, &g);
|
||||
SECITEM_TO_MPINT(*x, &X);
|
||||
|
||||
/* gx = g^x */
|
||||
if (gxIn == NULL) {
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &X, &p, &GX) );
|
||||
MPINT_TO_SECITEM(&GX, gxOut, arena);
|
||||
gxIn = gxOut;
|
||||
} else {
|
||||
SECITEM_TO_MPINT(*gxIn, &GX);
|
||||
}
|
||||
|
||||
/* v is a random value in the q subgroup */
|
||||
if (testRandom == NULL) {
|
||||
v.data = NULL;
|
||||
rv = DSA_NewRandom(arena, &pqg->subPrime, &v);
|
||||
if (rv != SECSuccess) {
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
v.data = testRandom->data;
|
||||
v.len = testRandom->len;
|
||||
}
|
||||
SECITEM_TO_MPINT(v, &V);
|
||||
|
||||
/* gv = g^v (mod q), random v, 1 <= v < q */
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &V, &p, &GV) );
|
||||
MPINT_TO_SECITEM(&GV, gv, arena);
|
||||
|
||||
/* h = H(g, gv, gx, signerID) */
|
||||
CHECK_MPI_OK( hashPublicParams(hashType, &pqg->base, gv, gxIn, signerID,
|
||||
&h) );
|
||||
|
||||
/* r = v - x*h (mod q) */
|
||||
CHECK_MPI_OK( mp_mulmod(&X, &h, &q, &tmp) );
|
||||
CHECK_MPI_OK( mp_submod(&V, &tmp, &q, &R) );
|
||||
MPINT_TO_SECITEM(&R, r, arena);
|
||||
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&g);
|
||||
mp_clear(&X);
|
||||
mp_clear(&GX);
|
||||
mp_clear(&V);
|
||||
mp_clear(&GV);
|
||||
mp_clear(&h);
|
||||
mp_clear(&tmp);
|
||||
mp_clear(&R);
|
||||
|
||||
if (rv == SECSuccess && err != MP_OKAY) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Verify a Schnorr signature generated by the peer in round 1 or round 2. */
|
||||
SECStatus
|
||||
JPAKE_Verify(PRArenaPool * arena, const PQGParams * pqg, HASH_HashType hashType,
|
||||
const SECItem * signerID, const SECItem * peerID,
|
||||
const SECItem * gx, const SECItem * gv, const SECItem * r)
|
||||
{
|
||||
SECStatus rv = SECSuccess;
|
||||
mp_err err;
|
||||
mp_int p;
|
||||
mp_int q;
|
||||
mp_int g;
|
||||
mp_int p_minus_1;
|
||||
mp_int GX;
|
||||
mp_int h;
|
||||
mp_int one;
|
||||
mp_int R;
|
||||
mp_int gr;
|
||||
mp_int gxh;
|
||||
mp_int gr_gxh;
|
||||
SECItem calculated;
|
||||
|
||||
if (!arena ||
|
||||
!pqg || !pqg->prime.data || pqg->prime.len == 0 ||
|
||||
!pqg->subPrime.data || pqg->subPrime.len == 0 ||
|
||||
!pqg->base.data || pqg->base.len == 0 ||
|
||||
!signerID || !signerID->data || signerID->len == 0 ||
|
||||
!peerID || !peerID->data || peerID->len == 0 ||
|
||||
!gx || !gx->data || gx->len == 0 ||
|
||||
!gv || !gv->data || gv->len == 0 ||
|
||||
!r || !r->data || r->len == 0 ||
|
||||
SECITEM_CompareItem(signerID, peerID) == SECEqual) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&g) = 0;
|
||||
MP_DIGITS(&p_minus_1) = 0;
|
||||
MP_DIGITS(&GX) = 0;
|
||||
MP_DIGITS(&h) = 0;
|
||||
MP_DIGITS(&one) = 0;
|
||||
MP_DIGITS(&R) = 0;
|
||||
MP_DIGITS(&gr) = 0;
|
||||
MP_DIGITS(&gxh) = 0;
|
||||
MP_DIGITS(&gr_gxh) = 0;
|
||||
calculated.data = NULL;
|
||||
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&g) );
|
||||
CHECK_MPI_OK( mp_init(&p_minus_1) );
|
||||
CHECK_MPI_OK( mp_init(&GX) );
|
||||
CHECK_MPI_OK( mp_init(&h) );
|
||||
CHECK_MPI_OK( mp_init(&one) );
|
||||
CHECK_MPI_OK( mp_init(&R) );
|
||||
CHECK_MPI_OK( mp_init(&gr) );
|
||||
CHECK_MPI_OK( mp_init(&gxh) );
|
||||
CHECK_MPI_OK( mp_init(&gr_gxh) );
|
||||
|
||||
SECITEM_TO_MPINT(pqg->prime, &p);
|
||||
SECITEM_TO_MPINT(pqg->subPrime, &q);
|
||||
SECITEM_TO_MPINT(pqg->base, &g);
|
||||
SECITEM_TO_MPINT(*gx, &GX);
|
||||
SECITEM_TO_MPINT(*r, &R);
|
||||
|
||||
CHECK_MPI_OK( mp_sub_d(&p, 1, &p_minus_1) );
|
||||
CHECK_MPI_OK( mp_exptmod(&GX, &q, &p, &one) );
|
||||
/* Check g^x is in [1, p-2], R is in [0, q-1], and (g^x)^q mod p == 1 */
|
||||
if (!(mp_cmp_z(&GX) > 0 &&
|
||||
mp_cmp(&GX, &p_minus_1) < 0 &&
|
||||
mp_cmp(&R, &q) < 0 &&
|
||||
mp_cmp_d(&one, 1) == 0)) {
|
||||
goto badSig;
|
||||
}
|
||||
|
||||
CHECK_MPI_OK( hashPublicParams(hashType, &pqg->base, gv, gx, peerID,
|
||||
&h) );
|
||||
|
||||
/* Calculate g^v = g^r * g^x^h */
|
||||
CHECK_MPI_OK( mp_exptmod(&g, &R, &p, &gr) );
|
||||
CHECK_MPI_OK( mp_exptmod(&GX, &h, &p, &gxh) );
|
||||
CHECK_MPI_OK( mp_mulmod(&gr, &gxh, &p, &gr_gxh) );
|
||||
|
||||
/* Compare calculated g^v to given g^v */
|
||||
MPINT_TO_SECITEM(&gr_gxh, &calculated, arena);
|
||||
if (calculated.len == gv->len &&
|
||||
NSS_SecureMemcmp(calculated.data, gv->data, calculated.len) == 0) {
|
||||
rv = SECSuccess;
|
||||
} else {
|
||||
badSig: PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||
rv = SECFailure;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&g);
|
||||
mp_clear(&p_minus_1);
|
||||
mp_clear(&GX);
|
||||
mp_clear(&h);
|
||||
mp_clear(&one);
|
||||
mp_clear(&R);
|
||||
mp_clear(&gr);
|
||||
mp_clear(&gxh);
|
||||
mp_clear(&gr_gxh);
|
||||
|
||||
if (rv == SECSuccess && err != MP_OKAY) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Calculate base = gx1*gx3*gx4 (mod p), i.e. g^(x1+x3+x4) (mod p) */
|
||||
static mp_err
|
||||
jpake_Round2Base(const SECItem * gx1, const SECItem * gx3,
|
||||
const SECItem * gx4, const mp_int * p, mp_int * base)
|
||||
{
|
||||
mp_err err;
|
||||
mp_int GX1;
|
||||
mp_int GX3;
|
||||
mp_int GX4;
|
||||
mp_int tmp;
|
||||
|
||||
MP_DIGITS(&GX1) = 0;
|
||||
MP_DIGITS(&GX3) = 0;
|
||||
MP_DIGITS(&GX4) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
|
||||
CHECK_MPI_OK( mp_init(&GX1) );
|
||||
CHECK_MPI_OK( mp_init(&GX3) );
|
||||
CHECK_MPI_OK( mp_init(&GX4) );
|
||||
CHECK_MPI_OK( mp_init(&tmp) );
|
||||
|
||||
SECITEM_TO_MPINT(*gx1, &GX1);
|
||||
SECITEM_TO_MPINT(*gx3, &GX3);
|
||||
SECITEM_TO_MPINT(*gx4, &GX4);
|
||||
|
||||
/* In round 2, the peer/attacker sends us g^x3 and g^x4 and the protocol
|
||||
requires that these values are distinct. */
|
||||
if (mp_cmp(&GX3, &GX4) == 0) {
|
||||
return MP_BADARG;
|
||||
}
|
||||
|
||||
CHECK_MPI_OK( mp_mul(&GX1, &GX3, &tmp) );
|
||||
CHECK_MPI_OK( mp_mul(&tmp, &GX4, &tmp) );
|
||||
CHECK_MPI_OK( mp_mod(&tmp, p, base) );
|
||||
|
||||
cleanup:
|
||||
mp_clear(&GX1);
|
||||
mp_clear(&GX3);
|
||||
mp_clear(&GX4);
|
||||
mp_clear(&tmp);
|
||||
return err;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
JPAKE_Round2(PLArenaPool * arena,
|
||||
const SECItem * p, const SECItem *q, const SECItem * gx1,
|
||||
const SECItem * gx3, const SECItem * gx4, SECItem * base,
|
||||
const SECItem * x2, const SECItem * s, SECItem * x2s)
|
||||
{
|
||||
mp_err err;
|
||||
mp_int P;
|
||||
mp_int Q;
|
||||
mp_int X2;
|
||||
mp_int S;
|
||||
mp_int result;
|
||||
|
||||
if (!arena ||
|
||||
!p || !p->data || p->len == 0 ||
|
||||
!q || !q->data || q->len == 0 ||
|
||||
!gx1 || !gx1->data || gx1->len == 0 ||
|
||||
!gx3 || !gx3->data || gx3->len == 0 ||
|
||||
!gx4 || !gx4->data || gx4->len == 0 ||
|
||||
!base || base->data != NULL ||
|
||||
(x2s != NULL && (x2s->data != NULL ||
|
||||
!x2 || !x2->data || x2->len == 0 ||
|
||||
!s || !s->data || s->len == 0))) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
MP_DIGITS(&P) = 0;
|
||||
MP_DIGITS(&Q) = 0;
|
||||
MP_DIGITS(&X2) = 0;
|
||||
MP_DIGITS(&S) = 0;
|
||||
MP_DIGITS(&result) = 0;
|
||||
|
||||
CHECK_MPI_OK( mp_init(&P) );
|
||||
CHECK_MPI_OK( mp_init(&Q) );
|
||||
CHECK_MPI_OK( mp_init(&result) );
|
||||
|
||||
if (x2s != NULL) {
|
||||
CHECK_MPI_OK( mp_init(&X2) );
|
||||
CHECK_MPI_OK( mp_init(&S) );
|
||||
|
||||
SECITEM_TO_MPINT(*q, &Q);
|
||||
SECITEM_TO_MPINT(*x2, &X2);
|
||||
|
||||
SECITEM_TO_MPINT(*s, &S);
|
||||
if (mp_cmp(&S, &Q) >= 0) {
|
||||
err = MP_BADARG;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
CHECK_MPI_OK( mp_mulmod(&X2, &S, &Q, &result) );
|
||||
MPINT_TO_SECITEM(&result, x2s, arena);
|
||||
}
|
||||
|
||||
SECITEM_TO_MPINT(*p, &P);
|
||||
CHECK_MPI_OK( jpake_Round2Base(gx1, gx3, gx4, &P, &result) );
|
||||
MPINT_TO_SECITEM(&result, base, arena);
|
||||
|
||||
cleanup:
|
||||
mp_clear(&P);
|
||||
mp_clear(&Q);
|
||||
mp_clear(&X2);
|
||||
mp_clear(&S);
|
||||
mp_clear(&result);
|
||||
|
||||
if (err != MP_OKAY) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
JPAKE_Final(PLArenaPool * arena, const SECItem * p, const SECItem * q,
|
||||
const SECItem * x2, const SECItem * gx4, const SECItem * x2s,
|
||||
const SECItem * B, SECItem * K)
|
||||
{
|
||||
mp_err err;
|
||||
mp_int P;
|
||||
mp_int Q;
|
||||
mp_int tmp;
|
||||
mp_int exponent;
|
||||
mp_int divisor;
|
||||
mp_int base;
|
||||
|
||||
if (!arena ||
|
||||
!p || !p->data || p->len == 0 ||
|
||||
!q || !q->data || q->len == 0 ||
|
||||
!x2 || !x2->data || x2->len == 0 ||
|
||||
!gx4 || !gx4->data || gx4->len == 0 ||
|
||||
!x2s || !x2s->data || x2s->len == 0 ||
|
||||
!B || !B->data || B->len == 0 ||
|
||||
!K || K->data != NULL) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
MP_DIGITS(&P) = 0;
|
||||
MP_DIGITS(&Q) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
MP_DIGITS(&exponent) = 0;
|
||||
MP_DIGITS(&divisor) = 0;
|
||||
MP_DIGITS(&base) = 0;
|
||||
|
||||
CHECK_MPI_OK( mp_init(&P) );
|
||||
CHECK_MPI_OK( mp_init(&Q) );
|
||||
CHECK_MPI_OK( mp_init(&tmp) );
|
||||
CHECK_MPI_OK( mp_init(&exponent) );
|
||||
CHECK_MPI_OK( mp_init(&divisor) );
|
||||
CHECK_MPI_OK( mp_init(&base) );
|
||||
|
||||
/* exponent = -x2s (mod q) */
|
||||
SECITEM_TO_MPINT(*q, &Q);
|
||||
SECITEM_TO_MPINT(*x2s, &tmp);
|
||||
/* q == 0 (mod q), so q - x2s == -x2s (mod q) */
|
||||
CHECK_MPI_OK( mp_sub(&Q, &tmp, &exponent) );
|
||||
|
||||
/* divisor = gx4^-x2s = 1/(gx4^x2s) (mod p) */
|
||||
SECITEM_TO_MPINT(*p, &P);
|
||||
SECITEM_TO_MPINT(*gx4, &tmp);
|
||||
CHECK_MPI_OK( mp_exptmod(&tmp, &exponent, &P, &divisor) );
|
||||
|
||||
/* base = B*divisor = B/(gx4^x2s) (mod p) */
|
||||
SECITEM_TO_MPINT(*B, &tmp);
|
||||
CHECK_MPI_OK( mp_mulmod(&divisor, &tmp, &P, &base) );
|
||||
|
||||
/* tmp = base^x2 (mod p) */
|
||||
SECITEM_TO_MPINT(*x2, &exponent);
|
||||
CHECK_MPI_OK( mp_exptmod(&base, &exponent, &P, &tmp) );
|
||||
|
||||
MPINT_TO_SECITEM(&tmp, K, arena);
|
||||
|
||||
cleanup:
|
||||
mp_clear(&P);
|
||||
mp_clear(&Q);
|
||||
mp_clear(&tmp);
|
||||
mp_clear(&exponent);
|
||||
mp_clear(&divisor);
|
||||
mp_clear(&base);
|
||||
|
||||
if (err != MP_OKAY) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
|
@ -37,7 +37,7 @@
|
|||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: ldvector.c,v 1.21.22.1 2010/07/31 00:11:52 wtc%google.com Exp $ */
|
||||
/* $Id: ldvector.c,v 1.21.22.3 2010/12/04 18:59:01 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
extern int FREEBL_InitStubs(void);
|
||||
|
@ -257,9 +257,20 @@ static const struct FREEBLVectorStr vector =
|
|||
PRNGTEST_Instantiate,
|
||||
PRNGTEST_Reseed,
|
||||
PRNGTEST_Generate,
|
||||
PRNGTEST_Uninstantiate
|
||||
PRNGTEST_Uninstantiate,
|
||||
|
||||
/* End of Version 3.011. */
|
||||
|
||||
RSA_PopulatePrivateKey,
|
||||
|
||||
DSA_NewRandom,
|
||||
|
||||
JPAKE_Sign,
|
||||
JPAKE_Verify,
|
||||
JPAKE_Round2,
|
||||
JPAKE_Final,
|
||||
|
||||
/* End of Version 3.012. */
|
||||
};
|
||||
|
||||
const FREEBLVector *
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: loader.c,v 1.44 2009/03/29 03:45:32 wtc%google.com Exp $ */
|
||||
/* $Id: loader.c,v 1.44.22.2 2010/12/04 18:59:01 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#include "loader.h"
|
||||
#include "prmem.h"
|
||||
|
@ -295,6 +295,14 @@ DSA_SignDigestWithSeed(DSAPrivateKey * key, SECItem * signature,
|
|||
return (vector->p_DSA_SignDigestWithSeed)( key, signature, digest, seed);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DSA_NewRandom(PLArenaPool * arena, const SECItem * q, SECItem * seed)
|
||||
{
|
||||
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
|
||||
return SECFailure;
|
||||
return (vector->p_DSA_NewRandom)(arena, q, seed);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
DH_GenParam(int primeLen, DHParams ** params)
|
||||
{
|
||||
|
@ -1696,4 +1704,54 @@ PRNGTEST_Uninstantiate()
|
|||
return (vector->p_PRNGTEST_Uninstantiate)();
|
||||
}
|
||||
|
||||
SECStatus
|
||||
RSA_PopulatePrivateKey(RSAPrivateKey *key)
|
||||
{
|
||||
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
|
||||
return SECFailure;
|
||||
return (vector->p_RSA_PopulatePrivateKey)(key);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
JPAKE_Sign(PLArenaPool * arena, const PQGParams * pqg, HASH_HashType hashType,
|
||||
const SECItem * signerID, const SECItem * x,
|
||||
const SECItem * testRandom, const SECItem * gxIn, SECItem * gxOut,
|
||||
SECItem * gv, SECItem * r)
|
||||
{
|
||||
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
|
||||
return SECFailure;
|
||||
return (vector->p_JPAKE_Sign)(arena, pqg, hashType, signerID, x,
|
||||
testRandom, gxIn, gxOut, gv, r);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
JPAKE_Verify(PLArenaPool * arena, const PQGParams * pqg,
|
||||
HASH_HashType hashType, const SECItem * signerID,
|
||||
const SECItem * peerID, const SECItem * gx,
|
||||
const SECItem * gv, const SECItem * r)
|
||||
{
|
||||
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
|
||||
return SECFailure;
|
||||
return (vector->p_JPAKE_Verify)(arena, pqg, hashType, signerID, peerID,
|
||||
gx, gv, r);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
JPAKE_Round2(PLArenaPool * arena, const SECItem * p, const SECItem *q,
|
||||
const SECItem * gx1, const SECItem * gx3, const SECItem * gx4,
|
||||
SECItem * base, const SECItem * x2, const SECItem * s, SECItem * x2s)
|
||||
{
|
||||
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
|
||||
return SECFailure;
|
||||
return (vector->p_JPAKE_Round2)(arena, p, q, gx1, gx3, gx4, base, x2, s, x2s);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
JPAKE_Final(PLArenaPool * arena, const SECItem * p, const SECItem *q,
|
||||
const SECItem * x2, const SECItem * gx4, const SECItem * x2s,
|
||||
const SECItem * B, SECItem * K)
|
||||
{
|
||||
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
|
||||
return SECFailure;
|
||||
return (vector->p_JPAKE_Final)(arena, p, q, x2, gx4, x2s, B, K);
|
||||
}
|
||||
|
|
|
@ -37,14 +37,14 @@
|
|||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: loader.h,v 1.26 2009/03/29 03:45:32 wtc%google.com Exp $ */
|
||||
/* $Id: loader.h,v 1.26.22.2 2010/12/04 18:59:01 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifndef _LOADER_H_
|
||||
#define _LOADER_H_ 1
|
||||
|
||||
#include "blapi.h"
|
||||
|
||||
#define FREEBL_VERSION 0x030B
|
||||
#define FREEBL_VERSION 0x030C
|
||||
|
||||
struct FREEBLVectorStr {
|
||||
|
||||
|
@ -540,6 +540,37 @@ struct FREEBLVectorStr {
|
|||
|
||||
SECStatus (* p_PRNGTEST_Uninstantiate)(void);
|
||||
/* Version 3.011 came to here */
|
||||
|
||||
|
||||
SECStatus (*p_RSA_PopulatePrivateKey)(RSAPrivateKey *key);
|
||||
|
||||
SECStatus (*p_DSA_NewRandom)(PLArenaPool * arena, const SECItem * q,
|
||||
SECItem * seed);
|
||||
|
||||
SECStatus (*p_JPAKE_Sign)(PLArenaPool * arena, const PQGParams * pqg,
|
||||
HASH_HashType hashType, const SECItem * signerID,
|
||||
const SECItem * x, const SECItem * testRandom,
|
||||
const SECItem * gxIn, SECItem * gxOut,
|
||||
SECItem * gv, SECItem * r);
|
||||
|
||||
SECStatus (*p_JPAKE_Verify)(PLArenaPool * arena, const PQGParams * pqg,
|
||||
HASH_HashType hashType, const SECItem * signerID,
|
||||
const SECItem * peerID, const SECItem * gx,
|
||||
const SECItem * gv, const SECItem * r);
|
||||
|
||||
SECStatus (*p_JPAKE_Round2)(PLArenaPool * arena, const SECItem * p,
|
||||
const SECItem *q, const SECItem * gx1,
|
||||
const SECItem * gx3, const SECItem * gx4,
|
||||
SECItem * base, const SECItem * x2,
|
||||
const SECItem * s, SECItem * x2s);
|
||||
|
||||
SECStatus (*p_JPAKE_Final)(PLArenaPool * arena, const SECItem * p,
|
||||
const SECItem *q, const SECItem * x2,
|
||||
const SECItem * gx4, const SECItem * x2s,
|
||||
const SECItem * B, SECItem * K);
|
||||
|
||||
/* Version 3.012 came to here */
|
||||
|
||||
};
|
||||
|
||||
typedef struct FREEBLVectorStr FREEBLVector;
|
||||
|
|
|
@ -146,6 +146,7 @@ CSRCS = \
|
|||
shvfy.c \
|
||||
tlsprfalg.c \
|
||||
seed.c \
|
||||
jpake.c \
|
||||
$(MPI_SRCS) \
|
||||
$(MPCPU_SRCS) \
|
||||
$(ECL_SRCS) \
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: rijndael.c,v 1.25 2009/04/09 22:11:07 julien.pierre.boogz%sun.com Exp $ */
|
||||
/* $Id: rijndael.c,v 1.25.6.1 2010/11/18 01:33:42 rrelyea%redhat.com Exp $ */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
|
@ -1027,9 +1027,14 @@ AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize,
|
|||
#if USE_HW_AES
|
||||
if (has_intel_aes == 0) {
|
||||
unsigned long eax, ebx, ecx, edx;
|
||||
char *disable_hw_aes = getenv("NSS_DISABLE_HW_AES");
|
||||
|
||||
freebl_cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
has_intel_aes = (ecx & (1 << 25)) != 0 ? 1 : -1;
|
||||
if (disable_hw_aes == NULL) {
|
||||
freebl_cpuid(1, &eax, &ebx, &ecx, &edx);
|
||||
has_intel_aes = (ecx & (1 << 25)) != 0 ? 1 : -1;
|
||||
} else {
|
||||
has_intel_aes = -1;
|
||||
}
|
||||
}
|
||||
use_hw_aes = (PRBool)
|
||||
(has_intel_aes > 0 && (keysize % 8) == 0 && blocksize == 16);
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
/*
|
||||
* RSA key generation, public key op, private key op.
|
||||
*
|
||||
* $Id: rsa.c,v 1.39 2009/02/03 05:34:41 julien.pierre.boogz%sun.com Exp $
|
||||
* $Id: rsa.c,v 1.39.22.1 2010/11/16 19:06:38 rrelyea%redhat.com Exp $
|
||||
*/
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
|
@ -116,21 +116,21 @@ static struct RSABlindingParamsListStr blindingParamsList = { 0 };
|
|||
static PRBool nssRSAUseBlinding = PR_TRUE;
|
||||
|
||||
static SECStatus
|
||||
rsa_keygen_from_primes(mp_int *p, mp_int *q, mp_int *e, RSAPrivateKey *key,
|
||||
unsigned int keySizeInBits)
|
||||
rsa_build_from_primes(mp_int *p, mp_int *q,
|
||||
mp_int *e, PRBool needPublicExponent,
|
||||
mp_int *d, PRBool needPrivateExponent,
|
||||
RSAPrivateKey *key, unsigned int keySizeInBits)
|
||||
{
|
||||
mp_int n, d, phi;
|
||||
mp_int n, phi;
|
||||
mp_int psub1, qsub1, tmp;
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
MP_DIGITS(&n) = 0;
|
||||
MP_DIGITS(&d) = 0;
|
||||
MP_DIGITS(&phi) = 0;
|
||||
MP_DIGITS(&psub1) = 0;
|
||||
MP_DIGITS(&qsub1) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
CHECK_MPI_OK( mp_init(&n) );
|
||||
CHECK_MPI_OK( mp_init(&d) );
|
||||
CHECK_MPI_OK( mp_init(&phi) );
|
||||
CHECK_MPI_OK( mp_init(&psub1) );
|
||||
CHECK_MPI_OK( mp_init(&qsub1) );
|
||||
|
@ -143,12 +143,25 @@ rsa_keygen_from_primes(mp_int *p, mp_int *q, mp_int *e, RSAPrivateKey *key,
|
|||
rv = SECFailure;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* at least one exponent must be given */
|
||||
PORT_Assert(!(needPublicExponent && needPrivateExponent));
|
||||
|
||||
/* 2. Compute phi = (p-1)*(q-1) */
|
||||
CHECK_MPI_OK( mp_sub_d(p, 1, &psub1) );
|
||||
CHECK_MPI_OK( mp_sub_d(q, 1, &qsub1) );
|
||||
CHECK_MPI_OK( mp_mul(&psub1, &qsub1, &phi) );
|
||||
/* 3. Compute d = e**-1 mod(phi) */
|
||||
err = mp_invmod(e, &phi, &d);
|
||||
if (needPublicExponent || needPrivateExponent) {
|
||||
CHECK_MPI_OK( mp_mul(&psub1, &qsub1, &phi) );
|
||||
/* 3. Compute d = e**-1 mod(phi) */
|
||||
/* or e = d**-1 mod(phi) as necessary */
|
||||
if (needPublicExponent) {
|
||||
err = mp_invmod(d, &phi, e);
|
||||
} else {
|
||||
err = mp_invmod(e, &phi, d);
|
||||
}
|
||||
} else {
|
||||
err = MP_OKAY;
|
||||
}
|
||||
/* Verify that phi(n) and e have no common divisors */
|
||||
if (err != MP_OKAY) {
|
||||
if (err == MP_UNDEF) {
|
||||
|
@ -158,20 +171,30 @@ rsa_keygen_from_primes(mp_int *p, mp_int *q, mp_int *e, RSAPrivateKey *key,
|
|||
}
|
||||
goto cleanup;
|
||||
}
|
||||
MPINT_TO_SECITEM(&n, &key->modulus, key->arena);
|
||||
MPINT_TO_SECITEM(&d, &key->privateExponent, key->arena);
|
||||
|
||||
/* 4. Compute exponent1 = d mod (p-1) */
|
||||
CHECK_MPI_OK( mp_mod(&d, &psub1, &tmp) );
|
||||
CHECK_MPI_OK( mp_mod(d, &psub1, &tmp) );
|
||||
MPINT_TO_SECITEM(&tmp, &key->exponent1, key->arena);
|
||||
/* 5. Compute exponent2 = d mod (q-1) */
|
||||
CHECK_MPI_OK( mp_mod(&d, &qsub1, &tmp) );
|
||||
CHECK_MPI_OK( mp_mod(d, &qsub1, &tmp) );
|
||||
MPINT_TO_SECITEM(&tmp, &key->exponent2, key->arena);
|
||||
/* 6. Compute coefficient = q**-1 mod p */
|
||||
CHECK_MPI_OK( mp_invmod(q, p, &tmp) );
|
||||
MPINT_TO_SECITEM(&tmp, &key->coefficient, key->arena);
|
||||
|
||||
/* copy our calculated results, overwrite what is there */
|
||||
key->modulus.data = NULL;
|
||||
MPINT_TO_SECITEM(&n, &key->modulus, key->arena);
|
||||
key->privateExponent.data = NULL;
|
||||
MPINT_TO_SECITEM(d, &key->privateExponent, key->arena);
|
||||
key->publicExponent.data = NULL;
|
||||
MPINT_TO_SECITEM(e, &key->publicExponent, key->arena);
|
||||
key->prime1.data = NULL;
|
||||
MPINT_TO_SECITEM(p, &key->prime1, key->arena);
|
||||
key->prime2.data = NULL;
|
||||
MPINT_TO_SECITEM(q, &key->prime2, key->arena);
|
||||
cleanup:
|
||||
mp_clear(&n);
|
||||
mp_clear(&d);
|
||||
mp_clear(&phi);
|
||||
mp_clear(&psub1);
|
||||
mp_clear(&qsub1);
|
||||
|
@ -229,7 +252,7 @@ RSAPrivateKey *
|
|||
RSA_NewKey(int keySizeInBits, SECItem *publicExponent)
|
||||
{
|
||||
unsigned int primeLen;
|
||||
mp_int p, q, e;
|
||||
mp_int p, q, e, d;
|
||||
int kiter;
|
||||
mp_err err = MP_OKAY;
|
||||
SECStatus rv = SECSuccess;
|
||||
|
@ -260,14 +283,15 @@ RSA_NewKey(int keySizeInBits, SECItem *publicExponent)
|
|||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&e) = 0;
|
||||
MP_DIGITS(&d) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&e) );
|
||||
CHECK_MPI_OK( mp_init(&d) );
|
||||
/* 2. Set the version number (PKCS1 v1.5 says it should be zero) */
|
||||
SECITEM_AllocItem(arena, &key->version, 1);
|
||||
key->version.data[0] = 0;
|
||||
/* 3. Set the public exponent */
|
||||
SECITEM_CopyItem(arena, &key->publicExponent, publicExponent);
|
||||
SECITEM_TO_MPINT(*publicExponent, &e);
|
||||
kiter = 0;
|
||||
do {
|
||||
|
@ -279,7 +303,10 @@ RSA_NewKey(int keySizeInBits, SECItem *publicExponent)
|
|||
if (mp_cmp(&p, &q) < 0)
|
||||
mp_exch(&p, &q);
|
||||
/* Attempt to use these primes to generate a key */
|
||||
rv = rsa_keygen_from_primes(&p, &q, &e, key, keySizeInBits);
|
||||
rv = rsa_build_from_primes(&p, &q,
|
||||
&e, PR_FALSE, /* needPublicExponent=false */
|
||||
&d, PR_TRUE, /* needPrivateExponent=true */
|
||||
key, keySizeInBits);
|
||||
if (rv == SECSuccess)
|
||||
break; /* generated two good primes */
|
||||
prerr = PORT_GetError();
|
||||
|
@ -288,12 +315,11 @@ RSA_NewKey(int keySizeInBits, SECItem *publicExponent)
|
|||
} while (prerr == SEC_ERROR_NEED_RANDOM && kiter < MAX_KEY_GEN_ATTEMPTS);
|
||||
if (prerr)
|
||||
goto cleanup;
|
||||
MPINT_TO_SECITEM(&p, &key->prime1, arena);
|
||||
MPINT_TO_SECITEM(&q, &key->prime2, arena);
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&e);
|
||||
mp_clear(&d);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
|
@ -305,6 +331,484 @@ cleanup:
|
|||
return key;
|
||||
}
|
||||
|
||||
mp_err
|
||||
rsa_is_prime(mp_int *p) {
|
||||
int res;
|
||||
|
||||
/* run a Fermat test */
|
||||
res = mpp_fermat(p, 2);
|
||||
if (res != MP_OKAY) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* If that passed, run some Miller-Rabin tests */
|
||||
res = mpp_pprime(p, 2);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to find the two primes based on 2 exponents plus either a prime
|
||||
* or a modulus.
|
||||
*
|
||||
* In: e, d and either p or n (depending on the setting of hasModulus).
|
||||
* Out: p,q.
|
||||
*
|
||||
* Step 1, Since d = e**-1 mod phi, we know that d*e == 1 mod phi, or
|
||||
* d*e = 1+k*phi, or d*e-1 = k*phi. since d is less than phi and e is
|
||||
* usually less than d, then k must be an integer between e-1 and 1
|
||||
* (probably on the order of e).
|
||||
* Step 1a, If we were passed just a prime, we can divide k*phi by that
|
||||
* prime-1 and get k*(q-1). This will reduce the size of our division
|
||||
* through the rest of the loop.
|
||||
* Step 2, Loop through the values k=e-1 to 1 looking for k. k should be on
|
||||
* the order or e, and e is typically small. This may take a while for
|
||||
* a large random e. We are looking for a k that divides kphi
|
||||
* evenly. Once we find a k that divides kphi evenly, we assume it
|
||||
* is the true k. It's possible this k is not the 'true' k but has
|
||||
* swapped factors of p-1 and/or q-1. Because of this, we
|
||||
* tentatively continue Steps 3-6 inside this loop, and may return looking
|
||||
* for another k on failure.
|
||||
* Step 3, Calculate are tentative phi=kphi/k. Note: real phi is (p-1)*(q-1).
|
||||
* Step 4a, if we have a prime, kphi is already k*(q-1), so phi is or tenative
|
||||
* q-1. q = phi+1. If k is correct, q should be the right length and
|
||||
* prime.
|
||||
* Step 4b, It's possible q-1 and k could have swapped factors. We now have a
|
||||
* possible solution that meets our criteria. It may not be the only
|
||||
* solution, however, so we keep looking. If we find more than one,
|
||||
* we will fail since we cannot determine which is the correct
|
||||
* solution, and returning the wrong modulus will compromise both
|
||||
* moduli. If no other solution is found, we return the unique solution.
|
||||
* Step 5a, If we have the modulus (n=pq), then use the following formula to
|
||||
* calculate s=(p+q): , phi = (p-1)(q-1) = pq -p-q +1 = n-s+1. so
|
||||
* s=n-phi+1.
|
||||
* Step 5b, Use n=pq and s=p+q to solve for p and q as follows:
|
||||
* since q=s-p, then n=p*(s-p)= sp - p^2, rearranging p^2-s*p+n = 0.
|
||||
* from the quadratic equation we have p=1/2*(s+sqrt(s*s-4*n)) and
|
||||
* q=1/2*(s-sqrt(s*s-4*n)) if s*s-4*n is a perfect square, we are DONE.
|
||||
* If it is not, continue in our look looking for another k. NOTE: the
|
||||
* code actually distributes the 1/2 and results in the equations:
|
||||
* sqrt = sqrt(s/2*s/2-n), p=s/2+sqrt, q=s/2-sqrt. The algebra saves us
|
||||
* and extra divide by 2 and a multiply by 4.
|
||||
*
|
||||
* This will return p & q. q may be larger than p in the case that p was given
|
||||
* and it was the smaller prime.
|
||||
*/
|
||||
static mp_err
|
||||
rsa_get_primes_from_exponents(mp_int *e, mp_int *d, mp_int *p, mp_int *q,
|
||||
mp_int *n, PRBool hasModulus,
|
||||
unsigned int keySizeInBits)
|
||||
{
|
||||
mp_int kphi; /* k*phi */
|
||||
mp_int k; /* current guess at 'k' */
|
||||
mp_int phi; /* (p-1)(q-1) */
|
||||
mp_int s; /* p+q/2 (s/2 in the algebra) */
|
||||
mp_int r; /* remainder */
|
||||
mp_int tmp; /* p-1 if p is given, n+1 is modulus is given */
|
||||
mp_int sqrt; /* sqrt(s/2*s/2-n) */
|
||||
mp_err err = MP_OKAY;
|
||||
unsigned int order_k;
|
||||
|
||||
MP_DIGITS(&kphi) = 0;
|
||||
MP_DIGITS(&phi) = 0;
|
||||
MP_DIGITS(&s) = 0;
|
||||
MP_DIGITS(&k) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
MP_DIGITS(&tmp) = 0;
|
||||
MP_DIGITS(&sqrt) = 0;
|
||||
CHECK_MPI_OK( mp_init(&kphi) );
|
||||
CHECK_MPI_OK( mp_init(&phi) );
|
||||
CHECK_MPI_OK( mp_init(&s) );
|
||||
CHECK_MPI_OK( mp_init(&k) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
CHECK_MPI_OK( mp_init(&tmp) );
|
||||
CHECK_MPI_OK( mp_init(&sqrt) );
|
||||
|
||||
/* our algorithm looks for a factor k whose maximum size is dependent
|
||||
* on the size of our smallest exponent, which had better be the public
|
||||
* exponent (if it's the private, the key is vulnerable to a brute force
|
||||
* attack).
|
||||
*
|
||||
* since our factor search is linear, we need to limit the maximum
|
||||
* size of the public key. this should not be a problem normally, since
|
||||
* public keys are usually small.
|
||||
*
|
||||
* if we want to handle larger public key sizes, we should have
|
||||
* a version which tries to 'completely' factor k*phi (where completely
|
||||
* means 'factor into primes, or composites with which are products of
|
||||
* large primes). Once we have all the factors, we can sort them out and
|
||||
* try different combinations to form our phi. The risk is if (p-1)/2,
|
||||
* (q-1)/2, and k are all large primes. In any case if the public key
|
||||
* is small (order of 20 some bits), then a linear search for k is
|
||||
* manageable.
|
||||
*/
|
||||
if (mpl_significant_bits(e) > 23) {
|
||||
err=MP_RANGE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* calculate k*phi = e*d - 1 */
|
||||
CHECK_MPI_OK( mp_mul(e, d, &kphi) );
|
||||
CHECK_MPI_OK( mp_sub_d(&kphi, 1, &kphi) );
|
||||
|
||||
|
||||
/* kphi is (e*d)-1, which is the same as k*(p-1)(q-1)
|
||||
* d < (p-1)(q-1), therefor k must be less than e-1
|
||||
* We can narrow down k even more, though. Since p and q are odd and both
|
||||
* have their high bit set, then we know that phi must be on order of
|
||||
* keySizeBits.
|
||||
*/
|
||||
order_k = (unsigned)mpl_significant_bits(&kphi) - keySizeInBits;
|
||||
|
||||
/* for (k=kinit; order(k) >= order_k; k--) { */
|
||||
/* k=kinit: k can't be bigger than kphi/2^(keySizeInBits -1) */
|
||||
CHECK_MPI_OK( mp_2expt(&k,keySizeInBits-1) );
|
||||
CHECK_MPI_OK( mp_div(&kphi, &k, &k, NULL));
|
||||
if (mp_cmp(&k,e) >= 0) {
|
||||
/* also can't be bigger then e-1 */
|
||||
CHECK_MPI_OK( mp_sub_d(e, 1, &k) );
|
||||
}
|
||||
|
||||
/* calculate our temp value */
|
||||
/* This saves recalculating this value when the k guess is wrong, which
|
||||
* is reasonably frequent. */
|
||||
/* for the modulus case, tmp = n+1 (used to calculate p+q = tmp - phi) */
|
||||
/* for the prime case, tmp = p-1 (used to calculate q-1= phi/tmp) */
|
||||
if (hasModulus) {
|
||||
CHECK_MPI_OK( mp_add_d(n, 1, &tmp) );
|
||||
} else {
|
||||
CHECK_MPI_OK( mp_sub_d(p, 1, &tmp) );
|
||||
CHECK_MPI_OK(mp_div(&kphi,&tmp,&kphi,&r));
|
||||
if (mp_cmp_z(&r) != 0) {
|
||||
/* p-1 doesn't divide kphi, some parameter wasn't correct */
|
||||
err=MP_RANGE;
|
||||
goto cleanup;
|
||||
}
|
||||
mp_zero(q);
|
||||
/* kphi is now k*(q-1) */
|
||||
}
|
||||
|
||||
/* rest of the for loop */
|
||||
for (; (err == MP_OKAY) && (mpl_significant_bits(&k) >= order_k);
|
||||
err = mp_sub_d(&k, 1, &k)) {
|
||||
/* looking for k as a factor of kphi */
|
||||
CHECK_MPI_OK(mp_div(&kphi,&k,&phi,&r));
|
||||
if (mp_cmp_z(&r) != 0) {
|
||||
/* not a factor, try the next one */
|
||||
continue;
|
||||
}
|
||||
/* we have a possible phi, see if it works */
|
||||
if (!hasModulus) {
|
||||
if ((unsigned)mpl_significant_bits(&phi) != keySizeInBits/2) {
|
||||
/* phi is not the right size */
|
||||
continue;
|
||||
}
|
||||
/* phi should be divisible by 2, since
|
||||
* q is odd and phi=(q-1). */
|
||||
if (mpp_divis_d(&phi,2) == MP_NO) {
|
||||
/* phi is not divisible by 4 */
|
||||
continue;
|
||||
}
|
||||
/* we now have a candidate for the second prime */
|
||||
CHECK_MPI_OK(mp_add_d(&phi, 1, &tmp));
|
||||
|
||||
/* check to make sure it is prime */
|
||||
err = rsa_is_prime(&tmp);
|
||||
if (err != MP_OKAY) {
|
||||
if (err == MP_NO) {
|
||||
/* No, then we still have the wrong phi */
|
||||
err = MP_OKAY;
|
||||
continue;
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
/*
|
||||
* It is possible that we have the wrong phi if
|
||||
* k_guess*(q_guess-1) = k*(q-1) (k and q-1 have swapped factors).
|
||||
* since our q_quess is prime, however. We have found a valid
|
||||
* rsa key because:
|
||||
* q is the correct order of magnitude.
|
||||
* phi = (p-1)(q-1) where p and q are both primes.
|
||||
* e*d mod phi = 1.
|
||||
* There is no way to know from the info given if this is the
|
||||
* original key. We never want to return the wrong key because if
|
||||
* two moduli with the same factor is known, then euclid's gcd
|
||||
* algorithm can be used to find that factor. Even though the
|
||||
* caller didn't pass the original modulus, it doesn't mean the
|
||||
* modulus wasn't known or isn't available somewhere. So to be safe
|
||||
* if we can't be sure we have the right q, we don't return any.
|
||||
*
|
||||
* So to make sure we continue looking for other valid q's. If none
|
||||
* are found, then we can safely return this one, otherwise we just
|
||||
* fail */
|
||||
if (mp_cmp_z(q) != 0) {
|
||||
/* this is the second valid q, don't return either,
|
||||
* just fail */
|
||||
err = MP_RANGE;
|
||||
break;
|
||||
}
|
||||
/* we only have one q so far, save it and if no others are found,
|
||||
* it's safe to return it */
|
||||
CHECK_MPI_OK(mp_copy(&tmp, q));
|
||||
continue;
|
||||
}
|
||||
/* test our tentative phi */
|
||||
/* phi should be the correct order */
|
||||
if ((unsigned)mpl_significant_bits(&phi) != keySizeInBits) {
|
||||
/* phi is not the right size */
|
||||
continue;
|
||||
}
|
||||
/* phi should be divisible by 4, since
|
||||
* p and q are odd and phi=(p-1)(q-1). */
|
||||
if (mpp_divis_d(&phi,4) == MP_NO) {
|
||||
/* phi is not divisible by 4 */
|
||||
continue;
|
||||
}
|
||||
/* n was given, calculate s/2=(p+q)/2 */
|
||||
CHECK_MPI_OK( mp_sub(&tmp, &phi, &s) );
|
||||
CHECK_MPI_OK( mp_div_2(&s, &s) );
|
||||
|
||||
/* calculate sqrt(s/2*s/2-n) */
|
||||
CHECK_MPI_OK(mp_sqr(&s,&sqrt));
|
||||
CHECK_MPI_OK(mp_sub(&sqrt,n,&r)); /* r as a tmp */
|
||||
CHECK_MPI_OK(mp_sqrt(&r,&sqrt));
|
||||
/* make sure it's a perfect square */
|
||||
/* r is our original value we took the square root of */
|
||||
/* q is the square of our tentative square root. They should be equal*/
|
||||
CHECK_MPI_OK(mp_sqr(&sqrt,q)); /* q as a tmp */
|
||||
if (mp_cmp(&r,q) != 0) {
|
||||
/* sigh according to the doc, mp_sqrt could return sqrt-1 */
|
||||
CHECK_MPI_OK(mp_add_d(&sqrt,1,&sqrt));
|
||||
CHECK_MPI_OK(mp_sqr(&sqrt,q));
|
||||
if (mp_cmp(&r,q) != 0) {
|
||||
/* s*s-n not a perfect square, this phi isn't valid, find * another.*/
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: In this case we know we have the one and only answer.
|
||||
* "Why?", you ask. Because:
|
||||
* 1) n is a composite of two large primes (or it wasn't a
|
||||
* valid RSA modulus).
|
||||
* 2) If we know any number such that x^2-n is a perfect square
|
||||
* and x is not (n+1)/2, then we can calculate 2 non-trivial
|
||||
* factors of n.
|
||||
* 3) Since we know that n has only 2 non-trivial prime factors,
|
||||
* we know the two factors we have are the only possible factors.
|
||||
*/
|
||||
|
||||
/* Now we are home free to calculate p and q */
|
||||
/* p = s/2 + sqrt, q= s/2 - sqrt */
|
||||
CHECK_MPI_OK(mp_add(&s,&sqrt,p));
|
||||
CHECK_MPI_OK(mp_sub(&s,&sqrt,q));
|
||||
break;
|
||||
}
|
||||
if ((unsigned)mpl_significant_bits(&k) < order_k) {
|
||||
if (hasModulus || (mp_cmp_z(q) == 0)) {
|
||||
/* If we get here, something was wrong with the parameters we
|
||||
* were given */
|
||||
err = MP_RANGE;
|
||||
}
|
||||
}
|
||||
cleanup:
|
||||
mp_clear(&kphi);
|
||||
mp_clear(&phi);
|
||||
mp_clear(&s);
|
||||
mp_clear(&k);
|
||||
mp_clear(&r);
|
||||
mp_clear(&tmp);
|
||||
mp_clear(&sqrt);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* take a private key with only a few elements and fill out the missing pieces.
|
||||
*
|
||||
* All the entries will be overwritten with data allocated out of the arena
|
||||
* If no arena is supplied, one will be created.
|
||||
*
|
||||
* The following fields must be supplied in order for this function
|
||||
* to succeed:
|
||||
* one of either publicExponent or privateExponent
|
||||
* two more of the following 5 parameters.
|
||||
* modulus (n)
|
||||
* prime1 (p)
|
||||
* prime2 (q)
|
||||
* publicExponent (e)
|
||||
* privateExponent (d)
|
||||
*
|
||||
* NOTE: if only the publicExponent, privateExponent, and one prime is given,
|
||||
* then there may be more than one RSA key that matches that combination.
|
||||
*
|
||||
* All parameters will be replaced in the key structure with new parameters
|
||||
* Allocated out of the arena. There is no attempt to free the old structures.
|
||||
* Prime1 will always be greater than prime2 (even if the caller supplies the
|
||||
* smaller prime as prime1 or the larger prime as prime2). The parameters are
|
||||
* not overwritten on failure.
|
||||
*
|
||||
* How it works:
|
||||
* We can generate all the parameters from:
|
||||
* one of the exponents, plus the two primes. (rsa_build_key_from_primes) *
|
||||
* If we are given one of the exponents and both primes, we are done.
|
||||
* If we are given one of the exponents, the modulus and one prime, we
|
||||
* caclulate the second prime by dividing the modulus by the given
|
||||
* prime, giving us and exponent and 2 primes.
|
||||
* If we are given 2 exponents and either the modulus or one of the primes
|
||||
* we calculate k*phi = d*e-1, where k is an integer less than d which
|
||||
* divides d*e-1. We find factor k so we can isolate phi.
|
||||
* phi = (p-1)(q-1)
|
||||
* If one of the primes are given, we can use phi to find the other prime
|
||||
* as follows: q = (phi/(p-1)) + 1. We now have 2 primes and an
|
||||
* exponent. (NOTE: if more then one prime meets this condition, the
|
||||
* operation will fail. See comments elsewhere in this file about this).
|
||||
* If the modulus is given, then we can calculate the sum of the primes
|
||||
* as follows: s := (p+q), phi = (p-1)(q-1) = pq -p - q +1, pq = n ->
|
||||
* phi = n - s + 1, s = n - phi +1. Now that we have s = p+q and n=pq,
|
||||
* we can solve our 2 equations and 2 unknowns as follows: q=s-p ->
|
||||
* n=p*(s-p)= sp -p^2 -> p^2-sp+n = 0. Using the quadratic to solve for
|
||||
* p, p=1/2*(s+ sqrt(s*s-4*n)) [q=1/2*(s-sqrt(s*s-4*n)]. We again have
|
||||
* 2 primes and an exponent.
|
||||
*
|
||||
*/
|
||||
SECStatus
|
||||
RSA_PopulatePrivateKey(RSAPrivateKey *key)
|
||||
{
|
||||
PRArenaPool *arena = NULL;
|
||||
PRBool needPublicExponent = PR_TRUE;
|
||||
PRBool needPrivateExponent = PR_TRUE;
|
||||
PRBool hasModulus = PR_FALSE;
|
||||
unsigned int keySizeInBits = 0;
|
||||
int prime_count = 0;
|
||||
/* standard RSA nominclature */
|
||||
mp_int p, q, e, d, n;
|
||||
/* remainder */
|
||||
mp_int r;
|
||||
mp_err err = 0;
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
MP_DIGITS(&p) = 0;
|
||||
MP_DIGITS(&q) = 0;
|
||||
MP_DIGITS(&e) = 0;
|
||||
MP_DIGITS(&d) = 0;
|
||||
MP_DIGITS(&n) = 0;
|
||||
MP_DIGITS(&r) = 0;
|
||||
CHECK_MPI_OK( mp_init(&p) );
|
||||
CHECK_MPI_OK( mp_init(&q) );
|
||||
CHECK_MPI_OK( mp_init(&e) );
|
||||
CHECK_MPI_OK( mp_init(&d) );
|
||||
CHECK_MPI_OK( mp_init(&n) );
|
||||
CHECK_MPI_OK( mp_init(&r) );
|
||||
|
||||
/* if the key didn't already have an arena, create one. */
|
||||
if (key->arena == NULL) {
|
||||
arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
goto cleanup;
|
||||
}
|
||||
key->arena = arena;
|
||||
}
|
||||
|
||||
/* load up the known exponents */
|
||||
if (key->publicExponent.data) {
|
||||
SECITEM_TO_MPINT(key->publicExponent, &e);
|
||||
needPublicExponent = PR_FALSE;
|
||||
}
|
||||
if (key->privateExponent.data) {
|
||||
SECITEM_TO_MPINT(key->privateExponent, &d);
|
||||
needPrivateExponent = PR_FALSE;
|
||||
}
|
||||
if (needPrivateExponent && needPublicExponent) {
|
||||
/* Not enough information, we need at least one exponent */
|
||||
err = MP_BADARG;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* load up the known primes. If only one prime is given, it will be
|
||||
* assigned 'p'. Once we have both primes, well make sure p is the larger.
|
||||
* The value prime_count tells us howe many we have acquired.
|
||||
*/
|
||||
if (key->prime1.data) {
|
||||
int primeLen = key->prime1.len;
|
||||
if (key->prime1.data[0] == 0) {
|
||||
primeLen--;
|
||||
}
|
||||
keySizeInBits = primeLen * 2 * BITS_PER_BYTE;
|
||||
SECITEM_TO_MPINT(key->prime1, &p);
|
||||
prime_count++;
|
||||
}
|
||||
if (key->prime2.data) {
|
||||
int primeLen = key->prime2.len;
|
||||
if (key->prime2.data[0] == 0) {
|
||||
primeLen--;
|
||||
}
|
||||
keySizeInBits = primeLen * 2 * BITS_PER_BYTE;
|
||||
SECITEM_TO_MPINT(key->prime2, prime_count ? &q : &p);
|
||||
prime_count++;
|
||||
}
|
||||
/* load up the modulus */
|
||||
if (key->modulus.data) {
|
||||
int modLen = key->modulus.len;
|
||||
if (key->modulus.data[0] == 0) {
|
||||
modLen--;
|
||||
}
|
||||
keySizeInBits = modLen * BITS_PER_BYTE;
|
||||
SECITEM_TO_MPINT(key->modulus, &n);
|
||||
hasModulus = PR_TRUE;
|
||||
}
|
||||
/* if we have the modulus and one prime, calculate the second. */
|
||||
if ((prime_count == 1) && (hasModulus)) {
|
||||
mp_div(&n,&p,&q,&r);
|
||||
if (mp_cmp_z(&r) != 0) {
|
||||
/* p is not a factor or n, fail */
|
||||
err = MP_BADARG;
|
||||
goto cleanup;
|
||||
}
|
||||
prime_count++;
|
||||
}
|
||||
|
||||
/* If we didn't have enough primes try to calculate the primes from
|
||||
* the exponents */
|
||||
if (prime_count < 2) {
|
||||
/* if we don't have at least 2 primes at this point, then we need both
|
||||
* exponents and one prime or a modulus*/
|
||||
if (!needPublicExponent && !needPrivateExponent &&
|
||||
((prime_count > 0) || hasModulus)) {
|
||||
CHECK_MPI_OK(rsa_get_primes_from_exponents(&e,&d,&p,&q,
|
||||
&n,hasModulus,keySizeInBits));
|
||||
} else {
|
||||
/* not enough given parameters to get both primes */
|
||||
err = MP_BADARG;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* force p to the the larger prime */
|
||||
if (mp_cmp(&p, &q) < 0)
|
||||
mp_exch(&p, &q);
|
||||
|
||||
/* we now have our 2 primes and at least one exponent, we can fill
|
||||
* in the key */
|
||||
rv = rsa_build_from_primes(&p, &q,
|
||||
&e, needPublicExponent,
|
||||
&d, needPrivateExponent,
|
||||
key, keySizeInBits);
|
||||
cleanup:
|
||||
mp_clear(&p);
|
||||
mp_clear(&q);
|
||||
mp_clear(&e);
|
||||
mp_clear(&d);
|
||||
mp_clear(&n);
|
||||
mp_clear(&r);
|
||||
if (err) {
|
||||
MP_TO_SEC_ERROR(err);
|
||||
rv = SECFailure;
|
||||
}
|
||||
if (rv && arena) {
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
key->arena = NULL;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
rsa_modulusLen(SECItem *modulus)
|
||||
{
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: sha512.c,v 1.14 2009/04/09 22:11:07 julien.pierre.boogz%sun.com Exp $ */
|
||||
/* $Id: sha512.c,v 1.14.6.1 2010/11/18 18:32:52 kaie%kuix.de Exp $ */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "stubs.h"
|
||||
|
@ -48,6 +48,7 @@
|
|||
#undef HAVE_LONG_LONG
|
||||
#endif
|
||||
#include "prtypes.h" /* for PRUintXX */
|
||||
#include "prlong.h"
|
||||
#include "secport.h" /* for PORT_XXX */
|
||||
#include "blapi.h"
|
||||
#include "sha256.h" /* for struct SHA256ContextStr */
|
||||
|
@ -1106,16 +1107,14 @@ SHA512_End(SHA512Context *ctx, unsigned char *digest,
|
|||
{
|
||||
#if defined(HAVE_LONG_LONG)
|
||||
unsigned int inBuf = (unsigned int)ctx->sizeLo & 0x7f;
|
||||
unsigned int padLen = (inBuf < 112) ? (112 - inBuf) : (112 + 128 - inBuf);
|
||||
PRUint64 lo, t1;
|
||||
lo = (ctx->sizeLo << 3);
|
||||
PRUint64 t1;
|
||||
#else
|
||||
unsigned int inBuf = (unsigned int)ctx->sizeLo.lo & 0x7f;
|
||||
unsigned int padLen = (inBuf < 112) ? (112 - inBuf) : (112 + 128 - inBuf);
|
||||
PRUint64 lo = ctx->sizeLo;
|
||||
PRUint32 t1;
|
||||
lo.lo <<= 3;
|
||||
#endif
|
||||
unsigned int padLen = (inBuf < 112) ? (112 - inBuf) : (112 + 128 - inBuf);
|
||||
PRUint64 lo;
|
||||
LL_SHL(lo, ctx->sizeLo, 3);
|
||||
|
||||
SHA512_Update(ctx, pad, padLen);
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ STUB_DECLARE(SECStatus,SECITEM_CopyItem_Util,(PRArenaPool *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));
|
||||
STUB_DECLARE(int, NSS_SecureMemcmp,(const void *a, const void *b, size_t n));
|
||||
|
||||
|
||||
#define PORT_ZNew_stub(type) (type*)PORT_ZAlloc_stub(sizeof(type))
|
||||
|
@ -482,6 +483,13 @@ SECITEM_ZfreeItem_stub(SECItem *zap, PRBool freeit)
|
|||
abort();
|
||||
}
|
||||
|
||||
extern int
|
||||
NSS_SecureMemcmp_stub(const void *a, const void *b, size_t n)
|
||||
{
|
||||
STUB_SAFE_CALL3(NSS_SecureMemcmp, a, b, n);
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef FREEBL_NO_WEAK
|
||||
|
||||
static const char *nsprLibName = SHLIB_PREFIX"nspr4."SHLIB_SUFFIX;
|
||||
|
@ -523,6 +531,7 @@ freebl_InitNSSUtil(void *lib)
|
|||
STUB_FETCH_FUNCTION(SECITEM_CompareItem_Util);
|
||||
STUB_FETCH_FUNCTION(SECITEM_CopyItem_Util);
|
||||
STUB_FETCH_FUNCTION(SECITEM_ZfreeItem_Util);
|
||||
STUB_FETCH_FUNCTION(NSS_SecureMemcmp);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,8 @@
|
|||
#define SECITEM_FreeItem SECITEM_FreeItem_stub
|
||||
#define SECITEM_ZfreeItem SECITEM_ZfreeItem_stub
|
||||
|
||||
#define NSS_SecureMemcmp NSS_SecureMemcmp_stub
|
||||
|
||||
#define PR_Assert PR_Assert_stub
|
||||
#define PR_CallOnce PR_CallOnce_stub
|
||||
#define PR_Close PR_Close_stub
|
||||
|
|
|
@ -610,8 +610,8 @@ PKIX_ERRORENTRY(INFOACCESSCREATELISTFAILED,pkix_pl_InfoAccess_CreateList failed,
|
|||
PKIX_ERRORENTRY(INFOACCESSGETLOCATIONFAILED,PKIX_PL_InfoAccess_GetLocation failed,0),
|
||||
PKIX_ERRORENTRY(INFOACCESSGETLOCATIONTYPEFAILED,PKIX_PL_InfoAccess_GetLocationType failed,0),
|
||||
PKIX_ERRORENTRY(INFOACCESSGETMETHODFAILED,PKIX_PL_InfoAccess_GetMethod failed,0),
|
||||
PKIX_ERRORENTRY(INFOACCESSPARSELOCATIONFAILED,pkix_pl_InfoAccess_ParseLocation failed,0),
|
||||
PKIX_ERRORENTRY(INFOACCESSPARSETOKENSFAILED,pkix_pl_InfoAccess_ParseTokens failed,0),
|
||||
PKIX_ERRORENTRY(INFOACCESSPARSELOCATIONFAILED,pkix_pl_InfoAccess_ParseLocation failed,SEC_ERROR_BAD_INFO_ACCESS_LOCATION),
|
||||
PKIX_ERRORENTRY(INFOACCESSPARSETOKENSFAILED,pkix_pl_InfoAccess_ParseTokens failed,SEC_ERROR_BAD_INFO_ACCESS_LOCATION),
|
||||
PKIX_ERRORENTRY(INITIALIZECHECKERSFAILED,pkix_InitializeCheckers failed,0),
|
||||
PKIX_ERRORENTRY(INITIALIZEFAILED,PKIX_PL_Initialize failed,0),
|
||||
PKIX_ERRORENTRY(INPUTLISTMUSTBEHEADER,Input List must be header,SEC_ERROR_INVALID_ARGS),
|
||||
|
@ -732,7 +732,7 @@ PKIX_ERRORENTRY(NORESPONSEDATAINHTTPRESPONSE,No responseData in Http Response,SE
|
|||
PKIX_ERRORENTRY(NOTARGETCERTSUPPLIED,No target cert supplied,SEC_ERROR_INVALID_ARGS),
|
||||
PKIX_ERRORENTRY(NOTCONFORMINGCRLDP,Cert CRL DP does not conform to the rfc, 0),
|
||||
PKIX_ERRORENTRY(NOTDERPACKAGE,Not a DER package,0),
|
||||
PKIX_ERRORENTRY(NOTENOUGHNAMECOMPONENTSINGENERALNAME,Not enough name components in GeneralName,0),
|
||||
PKIX_ERRORENTRY(NOTENOUGHNAMECOMPONENTSINGENERALNAME,Not enough name components in GeneralName,SEC_ERROR_BAD_INFO_ACCESS_LOCATION),
|
||||
PKIX_ERRORENTRY(NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED,Failed to convert nss certificate usage to pkix ku and eku data structures,0),
|
||||
PKIX_ERRORENTRY(NSSCONTEXTCREATEFAILED,PKIX_PL_NssContext_Create failed,0),
|
||||
PKIX_ERRORENTRY(NSSCONTEXTDESTROYFAILED,PKIX_PL_NssContext_Destroy failed,0),
|
||||
|
@ -1071,7 +1071,6 @@ PKIX_ERRORENTRY(UNDEFINEDEQUALSCALLBACK,Undefined equals callback,0),
|
|||
PKIX_ERRORENTRY(UNEXPECTEDERRORINESTABLISHINGCONNECTION,Unexpected error in establishing connection,0),
|
||||
PKIX_ERRORENTRY(UNEXPECTEDRESULTCODEINRESPONSE,Unexpected result code in Response,SEC_ERROR_BAD_LDAP_RESPONSE),
|
||||
PKIX_ERRORENTRY(UNKNOWNFORMAT,Unknown format,SEC_ERROR_INVALID_ARGS),
|
||||
PKIX_ERRORENTRY(UNKNOWNINFOACCESSTYPE,Unknown InfoAccess type,SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE),
|
||||
PKIX_ERRORENTRY(UNKNOWNINFOACCESSMETHOD,Unknown InfoAccess method,SEC_ERROR_BAD_INFO_ACCESS_METHOD),
|
||||
PKIX_ERRORENTRY(UNKNOWNOBJECTOID,Unknown object OID,0),
|
||||
PKIX_ERRORENTRY(UNKNOWNOBJECTTYPE,Unknown object type,0),
|
||||
|
|
|
@ -658,7 +658,8 @@ PKIX_PL_AIAMgr_GetAIACerts(
|
|||
PKIX_AIAMGRGETLDAPCERTSFAILED);
|
||||
} else {
|
||||
/* We only support http and ldap requests. */
|
||||
PKIX_ERROR(PKIX_UNKNOWNINFOACCESSTYPE);
|
||||
PKIX_DECREF(ia);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nbio != NULL) { /* WOULDBLOCK */
|
||||
|
|
|
@ -849,7 +849,7 @@ DownloadCrl(pkix_pl_CrlDp *dp, PKIX_PL_CRL **crl,
|
|||
location[uri->len] = 0;
|
||||
if (CERT_ParseURL(location, &hostname,
|
||||
&port, &path) != SECSuccess) {
|
||||
PORT_SetError(SEC_ERROR_BAD_INFO_ACCESS_LOCATION);
|
||||
PORT_SetError(SEC_ERROR_BAD_CRL_DP_URL);
|
||||
savedError = PKIX_URLPARSINGFAILED;
|
||||
break;
|
||||
}
|
||||
|
@ -859,7 +859,7 @@ DownloadCrl(pkix_pl_CrlDp *dp, PKIX_PL_CRL **crl,
|
|||
|
||||
if ((*hcv1->createSessionFcn)(hostname, port,
|
||||
&pServerSession) != SECSuccess) {
|
||||
PORT_SetError(SEC_ERROR_BAD_INFO_ACCESS_LOCATION);
|
||||
PORT_SetError(SEC_ERROR_BAD_CRL_DP_URL);
|
||||
savedError = PKIX_URLPARSINGFAILED;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1003,3 +1003,13 @@ CERT_GetConstrainedCertificateNames;
|
|||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
;+NSS_3.12.9 { # NSS 3.12.9 release
|
||||
;+ global:
|
||||
CERT_FindCertByNicknameOrEmailAddrForUsage;
|
||||
PK11_DeriveWithTemplate;
|
||||
PK11_FindCertsFromEmailAddress;
|
||||
PK11_KeyGenWithTemplate;
|
||||
SECMOD_RestartModules;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/* $Id: nss.h,v 1.81.2.2 2010/09/16 18:08:52 christophe.ravel.bugs%sun.com Exp $ */
|
||||
/* $Id: nss.h,v 1.81.2.3 2010/09/23 17:07:52 christophe.ravel.bugs%sun.com Exp $ */
|
||||
|
||||
#ifndef __nss_h_
|
||||
#define __nss_h_
|
||||
|
@ -66,12 +66,12 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define NSS_VERSION "3.12.8.0" _NSS_ECC_STRING _NSS_CUSTOMIZED
|
||||
#define NSS_VERSION "3.12.9.0" _NSS_ECC_STRING _NSS_CUSTOMIZED " Beta"
|
||||
#define NSS_VMAJOR 3
|
||||
#define NSS_VMINOR 12
|
||||
#define NSS_VPATCH 8
|
||||
#define NSS_VPATCH 9
|
||||
#define NSS_VBUILD 0
|
||||
#define NSS_BETA PR_FALSE
|
||||
#define NSS_BETA PR_TRUE
|
||||
|
||||
#ifndef RC_INVOKED
|
||||
|
||||
|
|
|
@ -653,6 +653,82 @@ loser:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Traverse slots callback */
|
||||
typedef struct FindCertsEmailArgStr {
|
||||
char *email;
|
||||
CERTCertList *certList;
|
||||
} FindCertsEmailArg;
|
||||
|
||||
SECStatus
|
||||
FindCertsEmailCallback(CERTCertificate *cert, SECItem *item, void *arg)
|
||||
{
|
||||
FindCertsEmailArg *cbparam = (FindCertsEmailArg *) arg;
|
||||
const char *cert_email = CERT_GetFirstEmailAddress(cert);
|
||||
PRBool found = PR_FALSE;
|
||||
|
||||
/* Email address present in certificate? */
|
||||
if (cert_email == NULL){
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* Parameter correctly set? */
|
||||
if (cbparam->email == NULL) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Loop over all email addresses */
|
||||
do {
|
||||
if (!strcmp(cert_email, cbparam->email)) {
|
||||
/* found one matching email address */
|
||||
PRTime now = PR_Now();
|
||||
found = PR_TRUE;
|
||||
CERT_AddCertToListSorted(cbparam->certList,
|
||||
CERT_DupCertificate(cert),
|
||||
CERT_SortCBValidity, &now);
|
||||
}
|
||||
cert_email = CERT_GetNextEmailAddress(cert, cert_email);
|
||||
} while (cert_email && !found);
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* Find all certificates with matching email address */
|
||||
CERTCertList *
|
||||
PK11_FindCertsFromEmailAddress(const char *email, void *wincx)
|
||||
{
|
||||
FindCertsEmailArg cbparam;
|
||||
SECStatus rv;
|
||||
|
||||
cbparam.certList = CERT_NewCertList();
|
||||
if (cbparam.certList == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cbparam.email = CERT_FixupEmailAddr(email);
|
||||
if (cbparam.email == NULL) {
|
||||
CERT_DestroyCertList(cbparam.certList);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rv = PK11_TraverseSlotCerts(FindCertsEmailCallback, &cbparam, NULL);
|
||||
if (rv != SECSuccess) {
|
||||
CERT_DestroyCertList(cbparam.certList);
|
||||
PORT_Free(cbparam.email);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* empty list? */
|
||||
if (CERT_LIST_HEAD(cbparam.certList) == NULL ||
|
||||
CERT_LIST_END(CERT_LIST_HEAD(cbparam.certList), cbparam.certList)) {
|
||||
CERT_DestroyCertList(cbparam.certList);
|
||||
cbparam.certList = NULL;
|
||||
}
|
||||
|
||||
PORT_Free(cbparam.email);
|
||||
return cbparam.certList;
|
||||
}
|
||||
|
||||
|
||||
CERTCertList *
|
||||
PK11_FindCertsFromNickname(const char *nickname, void *wincx)
|
||||
{
|
||||
|
|
|
@ -334,6 +334,19 @@ PK11SymKey *PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot,
|
|||
CK_MECHANISM_TYPE type, SECItem *param,
|
||||
int keySize, SECItem *keyid, CK_FLAGS opFlags,
|
||||
PK11AttrFlags attrFlags, void *wincx);
|
||||
/* Generates a key using the exact template supplied by the caller. The other
|
||||
* PK11_[Token]KeyGen mechanisms should be used instead of this one whenever
|
||||
* they work because they include/exclude the CKA_VALUE_LEN template value
|
||||
* based on the mechanism type as required by many tokens.
|
||||
*
|
||||
* keyGenType should be PK11_GetKeyGenWithSize(type, <key size>) or it should
|
||||
* be equal to type if PK11_GetKeyGenWithSize cannot be used (e.g. because
|
||||
* pk11wrap does not know about the mechanisms).
|
||||
*/
|
||||
PK11SymKey *PK11_KeyGenWithTemplate(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
|
||||
CK_MECHANISM_TYPE keyGenType,
|
||||
SECItem *param, CK_ATTRIBUTE * attrs,
|
||||
unsigned int attrsCount, void *wincx);
|
||||
PK11SymKey * PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname,
|
||||
void *wincx);
|
||||
PK11SymKey *PK11_GetNextSymKey(PK11SymKey *symKey);
|
||||
|
@ -403,6 +416,12 @@ PK11SymKey * PK11_DeriveWithFlagsPerm( PK11SymKey *baseKey,
|
|||
CK_MECHANISM_TYPE derive,
|
||||
SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
|
||||
int keySize, CK_FLAGS flags, PRBool isPerm);
|
||||
PK11SymKey *
|
||||
PK11_DeriveWithTemplate( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
|
||||
SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
|
||||
int keySize, CK_ATTRIBUTE *userAttr, unsigned int numAttrs,
|
||||
PRBool isPerm);
|
||||
|
||||
|
||||
PK11SymKey *PK11_PubDerive( SECKEYPrivateKey *privKey,
|
||||
SECKEYPublicKey *pubKey, PRBool isSender, SECItem *randomA, SECItem *randomB,
|
||||
|
@ -604,6 +623,7 @@ SECStatus PK11_TraverseSlotCerts(
|
|||
SECStatus(* callback)(CERTCertificate*,SECItem *,void *),
|
||||
void *arg, void *wincx);
|
||||
CERTCertificate * PK11_FindCertFromNickname(const char *nickname, void *wincx);
|
||||
CERTCertList * PK11_FindCertsFromEmailAddress(const char *email, void *wincx);
|
||||
CERTCertList * PK11_FindCertsFromNickname(const char *nickname, void *wincx);
|
||||
CERTCertificate *PK11_GetCertFromPrivateKey(SECKEYPrivateKey *privKey);
|
||||
SECStatus PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert,
|
||||
|
|
|
@ -52,12 +52,6 @@
|
|||
#include "secerr.h"
|
||||
#include "hasht.h"
|
||||
|
||||
/* forward static declarations. */
|
||||
static PK11SymKey *pk11_DeriveWithTemplate(PK11SymKey *baseKey,
|
||||
CK_MECHANISM_TYPE derive, SECItem *param, CK_MECHANISM_TYPE target,
|
||||
CK_ATTRIBUTE_TYPE operation, int keySize, CK_ATTRIBUTE *userAttr,
|
||||
unsigned int numAttrs, PRBool isPerm);
|
||||
|
||||
static void
|
||||
pk11_EnterKeyMonitor(PK11SymKey *symKey) {
|
||||
if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe))
|
||||
|
@ -921,7 +915,7 @@ pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
|
|||
CK_ATTRIBUTE *attrs = genTemplate;
|
||||
int count = sizeof(genTemplate)/sizeof(genTemplate[0]);
|
||||
CK_SESSION_HANDLE session;
|
||||
CK_MECHANISM mechanism;
|
||||
CK_MECHANISM_TYPE keyGenType;
|
||||
CK_RV crv;
|
||||
CK_BBOOL cktrue = CK_TRUE;
|
||||
CK_BBOOL ckfalse = CK_FALSE;
|
||||
|
@ -957,76 +951,16 @@ pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
|
|||
count = attrs - genTemplate;
|
||||
PR_ASSERT(count <= sizeof(genTemplate)/sizeof(CK_ATTRIBUTE));
|
||||
|
||||
/* Initialize the Key Gen Mechanism */
|
||||
mechanism.mechanism = PK11_GetKeyGenWithSize(type, keySize);
|
||||
if (mechanism.mechanism == CKM_FAKE_RANDOM) {
|
||||
PORT_SetError( SEC_ERROR_NO_MODULE );
|
||||
return NULL;
|
||||
keyGenType = PK11_GetKeyGenWithSize(type, keySize);
|
||||
if (keyGenType == CKM_FAKE_RANDOM) {
|
||||
PORT_SetError( SEC_ERROR_NO_MODULE );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* find a slot to generate the key into */
|
||||
/* Only do slot management if this is not a token key */
|
||||
if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot,type))) {
|
||||
PK11SlotInfo *bestSlot;
|
||||
|
||||
bestSlot = PK11_GetBestSlot(type,wincx);
|
||||
if (bestSlot == NULL) {
|
||||
PORT_SetError( SEC_ERROR_NO_MODULE );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
symKey = pk11_CreateSymKey(bestSlot, type, !isToken, PR_TRUE, wincx);
|
||||
|
||||
PK11_FreeSlot(bestSlot);
|
||||
} else {
|
||||
symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx);
|
||||
symKey = PK11_KeyGenWithTemplate(slot, type, keyGenType,
|
||||
param, genTemplate, count, wincx);
|
||||
if (symKey != NULL) {
|
||||
symKey->size = keySize;
|
||||
}
|
||||
if (symKey == NULL) return NULL;
|
||||
|
||||
symKey->size = keySize;
|
||||
symKey->origin = PK11_OriginGenerated;
|
||||
|
||||
/* Set the parameters for the key gen if provided */
|
||||
mechanism.pParameter = NULL;
|
||||
mechanism.ulParameterLen = 0;
|
||||
if (param) {
|
||||
mechanism.pParameter = param->data;
|
||||
mechanism.ulParameterLen = param->len;
|
||||
}
|
||||
|
||||
/* Get session and perform locking */
|
||||
if (isToken) {
|
||||
PK11_Authenticate(symKey->slot,PR_TRUE,wincx);
|
||||
/* Should always be original slot */
|
||||
session = PK11_GetRWSession(symKey->slot);
|
||||
symKey->owner = PR_FALSE;
|
||||
} else {
|
||||
session = symKey->session;
|
||||
if (session != CK_INVALID_SESSION)
|
||||
pk11_EnterKeyMonitor(symKey);
|
||||
}
|
||||
if (session == CK_INVALID_SESSION) {
|
||||
PK11_FreeSymKey(symKey);
|
||||
PORT_SetError(SEC_ERROR_BAD_DATA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session,
|
||||
&mechanism, genTemplate, count, &symKey->objectID);
|
||||
|
||||
/* Release lock and session */
|
||||
if (isToken) {
|
||||
PK11_RestoreROSession(symKey->slot, session);
|
||||
} else {
|
||||
pk11_ExitKeyMonitor(symKey);
|
||||
}
|
||||
|
||||
if (crv != CKR_OK) {
|
||||
PK11_FreeSymKey(symKey);
|
||||
PORT_SetError( PK11_MapError(crv) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return symKey;
|
||||
}
|
||||
|
||||
|
@ -1098,6 +1032,107 @@ PK11_KeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param,
|
|||
return PK11_TokenKeyGen(slot, type, param, keySize, 0, PR_FALSE, wincx);
|
||||
}
|
||||
|
||||
PK11SymKey *
|
||||
PK11_KeyGenWithTemplate(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
|
||||
CK_MECHANISM_TYPE keyGenType,
|
||||
SECItem *param, CK_ATTRIBUTE * attrs,
|
||||
unsigned int attrsCount, void *wincx)
|
||||
{
|
||||
PK11SymKey *symKey;
|
||||
CK_SESSION_HANDLE session;
|
||||
CK_MECHANISM mechanism;
|
||||
CK_RV crv;
|
||||
PRBool isToken = CK_FALSE;
|
||||
CK_ULONG keySize = 0;
|
||||
unsigned i;
|
||||
|
||||
/* Extract the template's CKA_VALUE_LEN into keySize and CKA_TOKEN into
|
||||
isToken. */
|
||||
for (i = 0; i < attrsCount; ++i) {
|
||||
switch (attrs[i].type) {
|
||||
case CKA_VALUE_LEN:
|
||||
if (attrs[i].pValue == NULL ||
|
||||
attrs[i].ulValueLen != sizeof(CK_ULONG)) {
|
||||
PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT));
|
||||
return NULL;
|
||||
}
|
||||
keySize = * (CK_ULONG *) attrs[i].pValue;
|
||||
break;
|
||||
case CKA_TOKEN:
|
||||
if (attrs[i].pValue == NULL ||
|
||||
attrs[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT));
|
||||
return NULL;
|
||||
}
|
||||
isToken = (*(CK_BBOOL*)attrs[i].pValue) ? PR_TRUE : PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* find a slot to generate the key into */
|
||||
/* Only do slot management if this is not a token key */
|
||||
if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot,type))) {
|
||||
PK11SlotInfo *bestSlot = PK11_GetBestSlot(type,wincx);
|
||||
if (bestSlot == NULL) {
|
||||
PORT_SetError( SEC_ERROR_NO_MODULE );
|
||||
return NULL;
|
||||
}
|
||||
symKey = pk11_CreateSymKey(bestSlot, type, !isToken, PR_TRUE, wincx);
|
||||
PK11_FreeSlot(bestSlot);
|
||||
} else {
|
||||
symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx);
|
||||
}
|
||||
if (symKey == NULL) return NULL;
|
||||
|
||||
symKey->size = keySize;
|
||||
symKey->origin = PK11_OriginGenerated;
|
||||
|
||||
/* Set the parameters for the key gen if provided */
|
||||
mechanism.mechanism = keyGenType;
|
||||
mechanism.pParameter = NULL;
|
||||
mechanism.ulParameterLen = 0;
|
||||
if (param) {
|
||||
mechanism.pParameter = param->data;
|
||||
mechanism.ulParameterLen = param->len;
|
||||
}
|
||||
|
||||
/* Get session and perform locking */
|
||||
if (isToken) {
|
||||
PK11_Authenticate(symKey->slot,PR_TRUE,wincx);
|
||||
/* Should always be original slot */
|
||||
session = PK11_GetRWSession(symKey->slot);
|
||||
symKey->owner = PR_FALSE;
|
||||
} else {
|
||||
session = symKey->session;
|
||||
if (session != CK_INVALID_SESSION)
|
||||
pk11_EnterKeyMonitor(symKey);
|
||||
}
|
||||
if (session == CK_INVALID_SESSION) {
|
||||
PK11_FreeSymKey(symKey);
|
||||
PORT_SetError(SEC_ERROR_BAD_DATA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session,
|
||||
&mechanism, attrs, attrsCount, &symKey->objectID);
|
||||
|
||||
/* Release lock and session */
|
||||
if (isToken) {
|
||||
PK11_RestoreROSession(symKey->slot, session);
|
||||
} else {
|
||||
pk11_ExitKeyMonitor(symKey);
|
||||
}
|
||||
|
||||
if (crv != CKR_OK) {
|
||||
PK11_FreeSymKey(symKey);
|
||||
PORT_SetError( PK11_MapError(crv) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return symKey;
|
||||
}
|
||||
|
||||
|
||||
/* --- */
|
||||
PK11SymKey *
|
||||
PK11_GenDES3TokenKey(PK11SlotInfo *slot, SECItem *keyid, void *cx)
|
||||
|
@ -1368,7 +1403,7 @@ PK11_Derive( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, SECItem *param,
|
|||
CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
|
||||
int keySize)
|
||||
{
|
||||
return pk11_DeriveWithTemplate(baseKey, derive, param, target, operation,
|
||||
return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation,
|
||||
keySize, NULL, 0, PR_FALSE);
|
||||
}
|
||||
|
||||
|
@ -1383,7 +1418,7 @@ PK11_DeriveWithFlags( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
|
|||
unsigned int templateCount;
|
||||
|
||||
templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
|
||||
return pk11_DeriveWithTemplate(baseKey, derive, param, target, operation,
|
||||
return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation,
|
||||
keySize, keyTemplate, templateCount, PR_FALSE);
|
||||
}
|
||||
|
||||
|
@ -1403,12 +1438,12 @@ PK11_DeriveWithFlagsPerm( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
|
|||
}
|
||||
templateCount = attrs - keyTemplate;
|
||||
templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
|
||||
return pk11_DeriveWithTemplate(baseKey, derive, param, target, operation,
|
||||
return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation,
|
||||
keySize, keyTemplate, templateCount, isPerm);
|
||||
}
|
||||
|
||||
static PK11SymKey *
|
||||
pk11_DeriveWithTemplate( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
|
||||
PK11SymKey *
|
||||
PK11_DeriveWithTemplate( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
|
||||
SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
|
||||
int keySize, CK_ATTRIBUTE *userAttr, unsigned int numAttrs,
|
||||
PRBool isPerm)
|
||||
|
|
|
@ -1504,3 +1504,82 @@ SECMOD_CloseUserDB(PK11SlotInfo *slot)
|
|||
PR_smprintf_free(sendSpec);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restart PKCS #11 modules after a fork(). See secmod.h for more information.
|
||||
*/
|
||||
SECStatus
|
||||
SECMOD_RestartModules(PRBool force)
|
||||
{
|
||||
SECMODModuleList *mlp;
|
||||
SECStatus rrv = SECSuccess;
|
||||
int lastError = 0;
|
||||
|
||||
if (!moduleLock) {
|
||||
PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Only need to restart the PKCS #11 modules that were initialized */
|
||||
SECMOD_GetReadLock(moduleLock);
|
||||
for (mlp = modules; mlp != NULL; mlp = mlp->next) {
|
||||
SECMODModule *mod = mlp->module;
|
||||
CK_ULONG count;
|
||||
SECStatus rv;
|
||||
int i;
|
||||
|
||||
/* If the module needs to be reset, do so */
|
||||
if (force || (PK11_GETTAB(mod)->
|
||||
C_GetSlotList(CK_FALSE, NULL, &count) != CKR_OK)) {
|
||||
PRBool alreadyLoaded;
|
||||
/* first call Finalize. This is not required by PKCS #11, but some
|
||||
* older modules require it, and it doesn't hurt (compliant modules
|
||||
* will return CKR_NOT_INITIALIZED */
|
||||
(void) PK11_GETTAB(mod)->C_Finalize(NULL);
|
||||
/* now initialize the module, this function reinitializes
|
||||
* a module in place, preserving existing slots (even if they
|
||||
* no longer exist) */
|
||||
rv = secmod_ModuleInit(mod, NULL, &alreadyLoaded);
|
||||
if (rv != SECSuccess) {
|
||||
/* save the last error code */
|
||||
lastError = PORT_GetError();
|
||||
rrv = rv;
|
||||
/* couldn't reinit the module, disable all its slots */
|
||||
for (i=0; i < mod->slotCount; i++) {
|
||||
mod->slots[i]->disabled = PR_TRUE;
|
||||
mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for (i=0; i < mod->slotCount; i++) {
|
||||
/* get new token sessions, bump the series up so that
|
||||
* we refresh other old sessions. This will tell much of
|
||||
* NSS to flush cached handles it may hold as well */
|
||||
rv = PK11_InitToken(mod->slots[i],PR_TRUE);
|
||||
/* PK11_InitToken could fail if the slot isn't present.
|
||||
* If it is present, though, something is wrong and we should
|
||||
* disable the slot and let the caller know. */
|
||||
if (rv != SECSuccess && PK11_IsPresent(mod->slots[i])) {
|
||||
/* save the last error code */
|
||||
lastError = PORT_GetError();
|
||||
rrv = rv;
|
||||
/* disable the token */
|
||||
mod->slots[i]->disabled = PR_TRUE;
|
||||
mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SECMOD_ReleaseReadLock(moduleLock);
|
||||
|
||||
/*
|
||||
* on multiple failures, we are only returning the lastError. The caller
|
||||
* can determine which slots are bad by calling PK11_IsDisabled().
|
||||
*/
|
||||
if (rrv != SECSuccess) {
|
||||
/* restore the last error code */
|
||||
PORT_SetError(lastError);
|
||||
}
|
||||
|
||||
return rrv;
|
||||
}
|
||||
|
|
|
@ -95,6 +95,18 @@ SECStatus SECMOD_UnloadUserModule(SECMODModule *mod);
|
|||
|
||||
SECMODModule * SECMOD_CreateModule(const char *lib, const char *name,
|
||||
const char *param, const char *nss);
|
||||
/*
|
||||
* After a fork(), PKCS #11 says we need to call C_Initialize again in
|
||||
* the child before we can use the module. This function causes this
|
||||
* reinitialization.
|
||||
* NOTE: Any outstanding handles will become invalid, which means your
|
||||
* keys and contexts will fail, but new ones can be created.
|
||||
*
|
||||
* Setting 'force' to true means to do the reinitialization even if the
|
||||
* PKCS #11 module does not seem to need it. This allows software modules
|
||||
* which ignore fork to preserve their keys across the fork().
|
||||
*/
|
||||
SECStatus SECMOD_RestartModules(PRBool force);
|
||||
|
||||
|
||||
/* Module Management */
|
||||
|
|
|
@ -0,0 +1,396 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Netscape security libraries.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Fonudation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "seccomon.h"
|
||||
#include "secerr.h"
|
||||
#include "blapi.h"
|
||||
#include "pkcs11i.h"
|
||||
#include "softoken.h"
|
||||
|
||||
static CK_RV
|
||||
jpake_mapStatus(SECStatus rv, CK_RV invalidArgsMapping) {
|
||||
int err;
|
||||
if (rv == SECSuccess)
|
||||
return CKR_OK;
|
||||
err = PORT_GetError();
|
||||
switch (err) {
|
||||
/* XXX: SEC_ERROR_INVALID_ARGS might be caused by invalid template
|
||||
parameters. */
|
||||
case SEC_ERROR_INVALID_ARGS: return invalidArgsMapping;
|
||||
case SEC_ERROR_BAD_SIGNATURE: return CKR_SIGNATURE_INVALID;
|
||||
case SEC_ERROR_NO_MEMORY: return CKR_HOST_MEMORY;
|
||||
}
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
/* If key is not NULL then the gx value will be stored as an attribute with
|
||||
the type given by the gxAttrType parameter. */
|
||||
static CK_RV
|
||||
jpake_Sign(PLArenaPool * arena, const PQGParams * pqg, HASH_HashType hashType,
|
||||
const SECItem * signerID, const SECItem * x,
|
||||
CK_NSS_JPAKEPublicValue * out)
|
||||
{
|
||||
SECItem gx, gv, r;
|
||||
CK_RV crv;
|
||||
|
||||
PORT_Assert(arena != NULL);
|
||||
|
||||
gx.data = NULL;
|
||||
gv.data = NULL;
|
||||
r.data = NULL;
|
||||
crv = jpake_mapStatus(JPAKE_Sign(arena, pqg, hashType, signerID, x, NULL,
|
||||
NULL, &gx, &gv, &r),
|
||||
CKR_MECHANISM_PARAM_INVALID);
|
||||
if (crv == CKR_OK) {
|
||||
if (out->pGX != NULL && out->ulGXLen >= gx.len ||
|
||||
out->pGV != NULL && out->ulGVLen >= gv.len ||
|
||||
out->pR != NULL && out->ulRLen >= r.len) {
|
||||
PORT_Memcpy(out->pGX, gx.data, gx.len);
|
||||
PORT_Memcpy(out->pGV, gv.data, gv.len);
|
||||
PORT_Memcpy(out->pR, r.data, r.len);
|
||||
out->ulGXLen = gx.len;
|
||||
out->ulGVLen = gv.len;
|
||||
out->ulRLen = r.len;
|
||||
} else {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
}
|
||||
}
|
||||
return crv;
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
jpake_Verify(PLArenaPool * arena, const PQGParams * pqg,
|
||||
HASH_HashType hashType, const SECItem * signerID,
|
||||
const CK_BYTE * peerIDData, CK_ULONG peerIDLen,
|
||||
const CK_NSS_JPAKEPublicValue * publicValueIn)
|
||||
{
|
||||
SECItem peerID, gx, gv, r;
|
||||
peerID.data = (unsigned char *) peerIDData; peerID.len = peerIDLen;
|
||||
gx.data = publicValueIn->pGX; gx.len = publicValueIn->ulGXLen;
|
||||
gv.data = publicValueIn->pGV; gv.len = publicValueIn->ulGVLen;
|
||||
r.data = publicValueIn->pR; r.len = publicValueIn->ulRLen;
|
||||
return jpake_mapStatus(JPAKE_Verify(arena, pqg, hashType, signerID, &peerID,
|
||||
&gx, &gv, &r),
|
||||
CKR_MECHANISM_PARAM_INVALID);
|
||||
}
|
||||
|
||||
#define NUM_ELEM(x) (sizeof (x) / sizeof (x)[0])
|
||||
|
||||
/* Ensure that the key is of the given type. */
|
||||
static CK_RV
|
||||
jpake_ensureKeyType(SFTKObject * key, CK_KEY_TYPE keyType)
|
||||
{
|
||||
CK_RV crv;
|
||||
SFTKAttribute * keyTypeAttr = sftk_FindAttribute(key, CKA_KEY_TYPE);
|
||||
crv = keyTypeAttr != NULL &&
|
||||
*(CK_KEY_TYPE *)keyTypeAttr->attrib.pValue == keyType
|
||||
? CKR_OK
|
||||
: CKR_TEMPLATE_INCONSISTENT;
|
||||
if (keyTypeAttr != NULL)
|
||||
sftk_FreeAttribute(keyTypeAttr);
|
||||
return crv;
|
||||
}
|
||||
|
||||
/* If the template has the key type set, ensure that it was set to the correct
|
||||
* value. If the template did not have the key type set, set it to the
|
||||
* correct value.
|
||||
*/
|
||||
static CK_RV
|
||||
jpake_enforceKeyType(SFTKObject * key, CK_KEY_TYPE keyType) {
|
||||
CK_RV crv;
|
||||
SFTKAttribute * keyTypeAttr = sftk_FindAttribute(key, CKA_KEY_TYPE);
|
||||
if (keyTypeAttr != NULL) {
|
||||
crv = *(CK_KEY_TYPE *)keyTypeAttr->attrib.pValue == keyType
|
||||
? CKR_OK
|
||||
: CKR_TEMPLATE_INCONSISTENT;
|
||||
sftk_FreeAttribute(keyTypeAttr);
|
||||
} else {
|
||||
crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof keyType);
|
||||
}
|
||||
return crv;
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
jpake_MultipleSecItem2Attribute(SFTKObject * key, const SFTKItemTemplate * attrs,
|
||||
size_t attrsCount)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < attrsCount; ++i) {
|
||||
CK_RV crv = sftk_forceAttribute(key, attrs[i].type, attrs[i].item->data,
|
||||
attrs[i].item->len);
|
||||
if (crv != CKR_OK)
|
||||
return crv;
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
jpake_Round1(HASH_HashType hashType, CK_NSS_JPAKERound1Params * params,
|
||||
SFTKObject * key)
|
||||
{
|
||||
CK_RV crv;
|
||||
PQGParams pqg;
|
||||
PLArenaPool * arena;
|
||||
SECItem signerID;
|
||||
SFTKItemTemplate templateAttrs[] = {
|
||||
{ CKA_PRIME, &pqg.prime },
|
||||
{ CKA_SUBPRIME, &pqg.subPrime },
|
||||
{ CKA_BASE, &pqg.base },
|
||||
{ CKA_NSS_JPAKE_SIGNERID, &signerID }
|
||||
};
|
||||
SECItem x2, gx1, gx2;
|
||||
const SFTKItemTemplate generatedAttrs[] = {
|
||||
{ CKA_NSS_JPAKE_X2, &x2 },
|
||||
{ CKA_NSS_JPAKE_GX1, &gx1 },
|
||||
{ CKA_NSS_JPAKE_GX2, &gx2 },
|
||||
};
|
||||
SECItem x1;
|
||||
|
||||
PORT_Assert(params != NULL);
|
||||
PORT_Assert(key != NULL);
|
||||
|
||||
arena = PORT_NewArena(NSS_SOFTOKEN_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL)
|
||||
crv = CKR_HOST_MEMORY;
|
||||
|
||||
crv = sftk_MultipleAttribute2SecItem(arena, key, templateAttrs,
|
||||
NUM_ELEM(templateAttrs));
|
||||
|
||||
if (crv == CKR_OK && (signerID.data == NULL || signerID.len == 0))
|
||||
crv = CKR_TEMPLATE_INCOMPLETE;
|
||||
|
||||
/* generate x1, g^x1 and the proof of knowledge of x1 */
|
||||
if (crv == CKR_OK) {
|
||||
x1.data = NULL;
|
||||
crv = jpake_mapStatus(DSA_NewRandom(arena, &pqg.subPrime, &x1),
|
||||
CKR_TEMPLATE_INCONSISTENT);
|
||||
}
|
||||
if (crv == CKR_OK)
|
||||
crv = jpake_Sign(arena, &pqg, hashType, &signerID, &x1, ¶ms->gx1);
|
||||
|
||||
/* generate x2, g^x2 and the proof of knowledge of x2 */
|
||||
if (crv == CKR_OK) {
|
||||
x2.data = NULL;
|
||||
crv = jpake_mapStatus(DSA_NewRandom(arena, &pqg.subPrime, &x2),
|
||||
CKR_TEMPLATE_INCONSISTENT);
|
||||
}
|
||||
if (crv == CKR_OK)
|
||||
crv = jpake_Sign(arena, &pqg, hashType, &signerID, &x2, ¶ms->gx2);
|
||||
|
||||
/* Save the values needed for round 2 into CKA_VALUE */
|
||||
if (crv == CKR_OK) {
|
||||
gx1.data = params->gx1.pGX;
|
||||
gx1.len = params->gx1.ulGXLen;
|
||||
gx2.data = params->gx2.pGX;
|
||||
gx2.len = params->gx2.ulGXLen;
|
||||
crv = jpake_MultipleSecItem2Attribute(key, generatedAttrs,
|
||||
NUM_ELEM(generatedAttrs));
|
||||
}
|
||||
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return crv;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
jpake_Round2(HASH_HashType hashType, CK_NSS_JPAKERound2Params * params,
|
||||
SFTKObject * sourceKey, SFTKObject * key)
|
||||
{
|
||||
CK_RV crv;
|
||||
PLArenaPool * arena;
|
||||
PQGParams pqg;
|
||||
SECItem signerID, x2, gx1, gx2;
|
||||
SFTKItemTemplate sourceAttrs[] = {
|
||||
{ CKA_PRIME, &pqg.prime },
|
||||
{ CKA_SUBPRIME, &pqg.subPrime },
|
||||
{ CKA_BASE, &pqg.base },
|
||||
{ CKA_NSS_JPAKE_SIGNERID, &signerID },
|
||||
{ CKA_NSS_JPAKE_X2, &x2 },
|
||||
{ CKA_NSS_JPAKE_GX1, &gx1 },
|
||||
{ CKA_NSS_JPAKE_GX2, &gx2 },
|
||||
};
|
||||
SECItem x2s, gx3, gx4;
|
||||
const SFTKItemTemplate copiedAndGeneratedAttrs[] = {
|
||||
{ CKA_NSS_JPAKE_SIGNERID, &signerID },
|
||||
{ CKA_PRIME, &pqg.prime },
|
||||
{ CKA_SUBPRIME, &pqg.subPrime },
|
||||
{ CKA_NSS_JPAKE_X2, &x2 },
|
||||
{ CKA_NSS_JPAKE_X2S, &x2s },
|
||||
{ CKA_NSS_JPAKE_GX1, &gx1 },
|
||||
{ CKA_NSS_JPAKE_GX2, &gx2 },
|
||||
{ CKA_NSS_JPAKE_GX3, &gx3 },
|
||||
{ CKA_NSS_JPAKE_GX4, &gx4 }
|
||||
};
|
||||
SECItem peerID;
|
||||
|
||||
PORT_Assert(params != NULL);
|
||||
PORT_Assert(sourceKey != NULL);
|
||||
PORT_Assert(key != NULL);
|
||||
|
||||
arena = PORT_NewArena(NSS_SOFTOKEN_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL)
|
||||
crv = CKR_HOST_MEMORY;
|
||||
|
||||
/* TODO: check CKK_NSS_JPAKE_ROUND1 */
|
||||
|
||||
crv = sftk_MultipleAttribute2SecItem(arena, sourceKey, sourceAttrs,
|
||||
NUM_ELEM(sourceAttrs));
|
||||
|
||||
/* Get the peer's ID out of the template and sanity-check it. */
|
||||
if (crv == CKR_OK)
|
||||
crv = sftk_Attribute2SecItem(arena, &peerID, key,
|
||||
CKA_NSS_JPAKE_PEERID);
|
||||
if (crv == CKR_OK && (peerID.data == NULL || peerID.len == 0))
|
||||
crv = CKR_TEMPLATE_INCOMPLETE;
|
||||
if (crv == CKR_OK && SECITEM_CompareItem(&signerID, &peerID) == SECEqual)
|
||||
crv = CKR_TEMPLATE_INCONSISTENT;
|
||||
|
||||
/* Verify zero-knowledge proofs for g^x3 and g^x4 */
|
||||
if (crv == CKR_OK)
|
||||
crv = jpake_Verify(arena, &pqg, hashType, &signerID,
|
||||
peerID.data, peerID.len, ¶ms->gx3);
|
||||
if (crv == CKR_OK)
|
||||
crv = jpake_Verify(arena, &pqg, hashType, &signerID,
|
||||
peerID.data, peerID.len, ¶ms->gx4);
|
||||
|
||||
/* Calculate the base and x2s for A=base^x2s */
|
||||
if (crv == CKR_OK) {
|
||||
SECItem s;
|
||||
s.data = params->pSharedKey;
|
||||
s.len = params->ulSharedKeyLen;
|
||||
gx3.data = params->gx3.pGX;
|
||||
gx3.len = params->gx3.ulGXLen;
|
||||
gx4.data = params->gx4.pGX;
|
||||
gx4.len = params->gx4.ulGXLen;
|
||||
pqg.base.data = NULL;
|
||||
x2s.data = NULL;
|
||||
crv = jpake_mapStatus(JPAKE_Round2(arena, &pqg.prime, &pqg.subPrime,
|
||||
&gx1, &gx3, &gx4, &pqg.base,
|
||||
&x2, &s, &x2s),
|
||||
CKR_MECHANISM_PARAM_INVALID);
|
||||
}
|
||||
|
||||
/* Generate A=base^x2s and its zero-knowledge proof. */
|
||||
if (crv == CKR_OK)
|
||||
crv = jpake_Sign(arena, &pqg, hashType, &signerID, &x2s, ¶ms->A);
|
||||
|
||||
/* Copy P and Q from the ROUND1 key to the ROUND2 key and save the values
|
||||
needed for the final key material derivation into CKA_VALUE. */
|
||||
if (crv == CKR_OK)
|
||||
crv = sftk_forceAttribute(key, CKA_PRIME, pqg.prime.data,
|
||||
pqg.prime.len);
|
||||
if (crv == CKR_OK)
|
||||
crv = sftk_forceAttribute(key, CKA_SUBPRIME, pqg.subPrime.data,
|
||||
pqg.subPrime.len);
|
||||
if (crv == CKR_OK) {
|
||||
crv = jpake_MultipleSecItem2Attribute(key, copiedAndGeneratedAttrs,
|
||||
NUM_ELEM(copiedAndGeneratedAttrs));
|
||||
}
|
||||
|
||||
if (crv == CKR_OK)
|
||||
crv = jpake_enforceKeyType(key, CKK_NSS_JPAKE_ROUND2);
|
||||
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return crv;
|
||||
}
|
||||
|
||||
CK_RV
|
||||
jpake_Final(HASH_HashType hashType, const CK_NSS_JPAKEFinalParams * param,
|
||||
SFTKObject * sourceKey, SFTKObject * key)
|
||||
{
|
||||
PLArenaPool * arena;
|
||||
SECItem K;
|
||||
PQGParams pqg;
|
||||
CK_RV crv;
|
||||
SECItem peerID, signerID, x2s, x2, gx1, gx2, gx3, gx4;
|
||||
SFTKItemTemplate sourceAttrs[] = {
|
||||
{ CKA_NSS_JPAKE_PEERID, &peerID },
|
||||
{ CKA_NSS_JPAKE_SIGNERID, &signerID },
|
||||
{ CKA_PRIME, &pqg.prime },
|
||||
{ CKA_SUBPRIME, &pqg.subPrime },
|
||||
{ CKA_NSS_JPAKE_X2, &x2 },
|
||||
{ CKA_NSS_JPAKE_X2S, &x2s },
|
||||
{ CKA_NSS_JPAKE_GX1, &gx1 },
|
||||
{ CKA_NSS_JPAKE_GX2, &gx2 },
|
||||
{ CKA_NSS_JPAKE_GX3, &gx3 },
|
||||
{ CKA_NSS_JPAKE_GX4, &gx4 }
|
||||
};
|
||||
|
||||
PORT_Assert(param != NULL);
|
||||
PORT_Assert(sourceKey != NULL);
|
||||
PORT_Assert(key != NULL);
|
||||
|
||||
arena = PORT_NewArena(NSS_SOFTOKEN_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL)
|
||||
crv = CKR_HOST_MEMORY;
|
||||
|
||||
/* TODO: verify key type CKK_NSS_JPAKE_ROUND2 */
|
||||
|
||||
crv = sftk_MultipleAttribute2SecItem(arena, sourceKey, sourceAttrs,
|
||||
NUM_ELEM(sourceAttrs));
|
||||
|
||||
/* Calculate base for B=base^x4s */
|
||||
if (crv == CKR_OK) {
|
||||
pqg.base.data = NULL;
|
||||
crv = jpake_mapStatus(JPAKE_Round2(arena, &pqg.prime, &pqg.subPrime,
|
||||
&gx1, &gx2, &gx3, &pqg.base,
|
||||
NULL, NULL, NULL),
|
||||
CKR_MECHANISM_PARAM_INVALID);
|
||||
}
|
||||
|
||||
/* Verify zero-knowledge proof for B */
|
||||
if (crv == CKR_OK)
|
||||
crv = jpake_Verify(arena, &pqg, hashType, &signerID,
|
||||
peerID.data, peerID.len, ¶m->B);
|
||||
if (crv == CKR_OK) {
|
||||
SECItem B;
|
||||
B.data = param->B.pGX;
|
||||
B.len = param->B.ulGXLen;
|
||||
K.data = NULL;
|
||||
crv = jpake_mapStatus(JPAKE_Final(arena, &pqg.prime, &pqg.subPrime,
|
||||
&x2, &gx4, &x2s, &B, &K),
|
||||
CKR_MECHANISM_PARAM_INVALID);
|
||||
}
|
||||
|
||||
/* Save key material into CKA_VALUE. */
|
||||
if (crv == CKR_OK)
|
||||
crv = sftk_forceAttribute(key, CKA_VALUE, K.data, K.len);
|
||||
|
||||
if (crv == CKR_OK)
|
||||
crv = jpake_enforceKeyType(key, CKK_GENERIC_SECRET);
|
||||
|
||||
PORT_FreeArena(arena, PR_TRUE);
|
||||
return crv;
|
||||
}
|
|
@ -714,7 +714,7 @@ lg_searchTokenList(SDB *sdb, SDBFind *search,
|
|||
crv = lg_GetULongAttribute(CKA_CLASS,&pTemplate[i],1, &objectClass);
|
||||
if (crv != CKR_OK) {
|
||||
classFlags = 0;
|
||||
break;;
|
||||
break;
|
||||
}
|
||||
switch (objectClass) {
|
||||
case CKO_CERTIFICATE:
|
||||
|
@ -746,6 +746,7 @@ lg_searchTokenList(SDB *sdb, SDBFind *search,
|
|||
case CKA_PRIVATE:
|
||||
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
classFlags = 0;
|
||||
break;
|
||||
}
|
||||
if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
|
||||
classFlags &= (LG_PRIVATE|LG_KEY);
|
||||
|
@ -756,6 +757,7 @@ lg_searchTokenList(SDB *sdb, SDBFind *search,
|
|||
case CKA_SENSITIVE:
|
||||
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
classFlags = 0;
|
||||
break;
|
||||
}
|
||||
if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
|
||||
classFlags &= (LG_PRIVATE|LG_KEY);
|
||||
|
@ -766,6 +768,7 @@ lg_searchTokenList(SDB *sdb, SDBFind *search,
|
|||
case CKA_TOKEN:
|
||||
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
classFlags = 0;
|
||||
break;
|
||||
}
|
||||
if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) {
|
||||
classFlags = 0;
|
||||
|
@ -778,9 +781,11 @@ lg_searchTokenList(SDB *sdb, SDBFind *search,
|
|||
classFlags &= LG_TRUST;
|
||||
copy = &cert_md5_hash; break;
|
||||
case CKA_CERTIFICATE_TYPE:
|
||||
crv = lg_GetULongAttribute(CKA_CLASS,&pTemplate[i],1,&certType);
|
||||
crv = lg_GetULongAttribute(CKA_CERTIFICATE_TYPE,&pTemplate[i],
|
||||
1,&certType);
|
||||
if (crv != CKR_OK) {
|
||||
classFlags = 0;
|
||||
break;
|
||||
}
|
||||
classFlags &= LG_CERT;
|
||||
if (certType != CKC_X_509) {
|
||||
|
@ -794,6 +799,7 @@ lg_searchTokenList(SDB *sdb, SDBFind *search,
|
|||
case CKA_NETSCAPE_KRL:
|
||||
if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
|
||||
classFlags = 0;
|
||||
break;
|
||||
}
|
||||
classFlags &= LG_CRL;
|
||||
isKrl = (PRBool)(*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE);
|
||||
|
|
|
@ -89,6 +89,7 @@ CSRCS = \
|
|||
sftkpwd.c \
|
||||
softkver.c \
|
||||
tlsprf.c \
|
||||
jpakesftk.c \
|
||||
$(NULL)
|
||||
|
||||
ifdef SQLITE_UNSAFE_THREADS
|
||||
|
|
|
@ -407,6 +407,11 @@ static const struct mechanismList mechanisms[] = {
|
|||
{CKM_SHA512_HMAC, {1, 128, CKF_SN_VR}, PR_TRUE},
|
||||
{CKM_SHA512_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_TRUE},
|
||||
{CKM_TLS_PRF_GENERAL, {0, 512, CKF_SN_VR}, PR_FALSE},
|
||||
/* ------------------------- HKDF Operations -------------------------- */
|
||||
{CKM_NSS_HKDF_SHA1, {1, 128, CKF_DERIVE}, PR_TRUE},
|
||||
{CKM_NSS_HKDF_SHA256, {1, 128, CKF_DERIVE}, PR_TRUE},
|
||||
{CKM_NSS_HKDF_SHA384, {1, 128, CKF_DERIVE}, PR_TRUE},
|
||||
{CKM_NSS_HKDF_SHA512, {1, 128, CKF_DERIVE}, PR_TRUE},
|
||||
/* ------------------------- CAST Operations --------------------------- */
|
||||
#ifdef NSS_SOFTOKEN_DOES_CAST
|
||||
/* Cast operations are not supported ( yet? ) */
|
||||
|
@ -487,6 +492,19 @@ static const struct mechanismList mechanisms[] = {
|
|||
/* ------------------ AES Key Wrap (also encrypt) ------------------- */
|
||||
{CKM_NETSCAPE_AES_KEY_WRAP, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
|
||||
{CKM_NETSCAPE_AES_KEY_WRAP_PAD, {16, 32, CKF_EN_DE_WR_UN}, PR_TRUE},
|
||||
/* --------------------------- J-PAKE -------------------------------- */
|
||||
{CKM_NSS_JPAKE_ROUND1_SHA1, {0, 0, CKF_GENERATE}, PR_TRUE},
|
||||
{CKM_NSS_JPAKE_ROUND1_SHA256, {0, 0, CKF_GENERATE}, PR_TRUE},
|
||||
{CKM_NSS_JPAKE_ROUND1_SHA384, {0, 0, CKF_GENERATE}, PR_TRUE},
|
||||
{CKM_NSS_JPAKE_ROUND1_SHA512, {0, 0, CKF_GENERATE}, PR_TRUE},
|
||||
{CKM_NSS_JPAKE_ROUND2_SHA1, {0, 0, CKF_DERIVE}, PR_TRUE},
|
||||
{CKM_NSS_JPAKE_ROUND2_SHA256, {0, 0, CKF_DERIVE}, PR_TRUE},
|
||||
{CKM_NSS_JPAKE_ROUND2_SHA384, {0, 0, CKF_DERIVE}, PR_TRUE},
|
||||
{CKM_NSS_JPAKE_ROUND2_SHA512, {0, 0, CKF_DERIVE}, PR_TRUE},
|
||||
{CKM_NSS_JPAKE_FINAL_SHA1, {0, 0, CKF_DERIVE}, PR_TRUE},
|
||||
{CKM_NSS_JPAKE_FINAL_SHA256, {0, 0, CKF_DERIVE}, PR_TRUE},
|
||||
{CKM_NSS_JPAKE_FINAL_SHA384, {0, 0, CKF_DERIVE}, PR_TRUE},
|
||||
{CKM_NSS_JPAKE_FINAL_SHA512, {0, 0, CKF_DERIVE}, PR_TRUE}
|
||||
};
|
||||
static const CK_ULONG mechanismCount = sizeof(mechanisms)/sizeof(mechanisms[0]);
|
||||
|
||||
|
@ -969,6 +987,9 @@ sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object,
|
|||
static NSSLOWKEYPrivateKey *
|
||||
sftk_mkPrivKey(SFTKObject *object,CK_KEY_TYPE key, CK_RV *rvp);
|
||||
|
||||
static SECStatus
|
||||
sftk_fillRSAPrivateKey(SFTKObject *object);
|
||||
|
||||
/*
|
||||
* check the consistancy and initialize a Private Key Object
|
||||
*/
|
||||
|
@ -982,35 +1003,60 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
|
|||
CK_BBOOL wrap = CK_TRUE;
|
||||
CK_BBOOL derive = CK_TRUE;
|
||||
CK_BBOOL ckfalse = CK_FALSE;
|
||||
PRBool createObjectInfo = PR_TRUE;
|
||||
int missing_rsa_mod_component = 0;
|
||||
int missing_rsa_exp_component = 0;
|
||||
int missing_rsa_crt_component = 0;
|
||||
|
||||
SECItem mod;
|
||||
CK_RV crv;
|
||||
|
||||
switch (key_type) {
|
||||
case CKK_RSA:
|
||||
if ( !sftk_hasAttribute(object, CKA_MODULUS)) {
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
missing_rsa_mod_component++;
|
||||
}
|
||||
if ( !sftk_hasAttribute(object, CKA_PUBLIC_EXPONENT)) {
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
missing_rsa_exp_component++;
|
||||
}
|
||||
if ( !sftk_hasAttribute(object, CKA_PRIVATE_EXPONENT)) {
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
missing_rsa_exp_component++;
|
||||
}
|
||||
if ( !sftk_hasAttribute(object, CKA_PRIME_1)) {
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
missing_rsa_mod_component++;
|
||||
}
|
||||
if ( !sftk_hasAttribute(object, CKA_PRIME_2)) {
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
missing_rsa_mod_component++;
|
||||
}
|
||||
if ( !sftk_hasAttribute(object, CKA_EXPONENT_1)) {
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
missing_rsa_crt_component++;
|
||||
}
|
||||
if ( !sftk_hasAttribute(object, CKA_EXPONENT_2)) {
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
missing_rsa_crt_component++;
|
||||
}
|
||||
if ( !sftk_hasAttribute(object, CKA_COEFFICIENT)) {
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
missing_rsa_crt_component++;
|
||||
}
|
||||
if (missing_rsa_mod_component || missing_rsa_exp_component ||
|
||||
missing_rsa_crt_component) {
|
||||
/* we are missing a component, see if we have enough to rebuild
|
||||
* the rest */
|
||||
int have_exp = 2- missing_rsa_exp_component;
|
||||
int have_component = 5-
|
||||
(missing_rsa_exp_component+missing_rsa_mod_component);
|
||||
SECStatus rv;
|
||||
|
||||
if ((have_exp == 0) || (have_component < 3)) {
|
||||
/* nope, not enough to reconstruct the private key */
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
}
|
||||
/*fill in the missing parameters */
|
||||
rv = sftk_fillRSAPrivateKey(object);
|
||||
if (rv != SECSuccess) {
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
}
|
||||
}
|
||||
|
||||
/* make sure Netscape DB attribute is set correctly */
|
||||
crv = sftk_Attribute2SSecItem(NULL, &mod, object, CKA_MODULUS);
|
||||
if (crv != CKR_OK) return crv;
|
||||
|
@ -1057,6 +1103,20 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
|
|||
wrap = CK_FALSE;
|
||||
break;
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
case CKK_NSS_JPAKE_ROUND1:
|
||||
if (!sftk_hasAttribute(object, CKA_PRIME ||
|
||||
!sftk_hasAttribute(object, CKA_SUBPRIME) ||
|
||||
!sftk_hasAttribute(object, CKA_BASE))) {
|
||||
return CKR_TEMPLATE_INCOMPLETE;
|
||||
}
|
||||
/* fall through */
|
||||
case CKK_NSS_JPAKE_ROUND2:
|
||||
/* CKA_NSS_JPAKE_SIGNERID and CKA_NSS_JPAKE_PEERID are checked in
|
||||
the J-PAKE code. */
|
||||
encrypt = sign = recover = wrap = CK_FALSE;
|
||||
derive = CK_TRUE;
|
||||
createObjectInfo = PR_FALSE;
|
||||
break;
|
||||
default:
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
@ -1099,7 +1159,7 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
|
|||
crv = sftkdb_write(keyHandle, object, &object->handle);
|
||||
sftk_freeDB(keyHandle);
|
||||
return crv;
|
||||
} else {
|
||||
} else if (createObjectInfo) {
|
||||
object->objectInfo = sftk_mkPrivKey(object,key_type,&crv);
|
||||
if (object->objectInfo == NULL) return crv;
|
||||
object->infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey;
|
||||
|
@ -1835,6 +1895,116 @@ sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp)
|
|||
return privKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* we have a partial rsa private key, fill in the rest
|
||||
*/
|
||||
static SECStatus
|
||||
sftk_fillRSAPrivateKey(SFTKObject *object)
|
||||
{
|
||||
RSAPrivateKey tmpKey = { 0 };
|
||||
SFTKAttribute *modulus = NULL;
|
||||
SFTKAttribute *prime1 = NULL;
|
||||
SFTKAttribute *prime2 = NULL;
|
||||
SFTKAttribute *privateExponent = NULL;
|
||||
SFTKAttribute *publicExponent = NULL;
|
||||
SECStatus rv;
|
||||
CK_RV crv;
|
||||
|
||||
/* first fill in the components that we have. Populate only uses
|
||||
* the non-crt components, so only fill those in */
|
||||
tmpKey.arena = NULL;
|
||||
modulus = sftk_FindAttribute(object, CKA_MODULUS);
|
||||
if (modulus) {
|
||||
tmpKey.modulus.data = modulus->attrib.pValue;
|
||||
tmpKey.modulus.len = modulus->attrib.ulValueLen;
|
||||
}
|
||||
prime1 = sftk_FindAttribute(object, CKA_PRIME_1);
|
||||
if (prime1) {
|
||||
tmpKey.prime1.data = prime1->attrib.pValue;
|
||||
tmpKey.prime1.len = prime1->attrib.ulValueLen;
|
||||
}
|
||||
prime2 = sftk_FindAttribute(object, CKA_PRIME_2);
|
||||
if (prime2) {
|
||||
tmpKey.prime2.data = prime2->attrib.pValue;
|
||||
tmpKey.prime2.len = prime2->attrib.ulValueLen;
|
||||
}
|
||||
privateExponent = sftk_FindAttribute(object, CKA_PRIVATE_EXPONENT);
|
||||
if (privateExponent) {
|
||||
tmpKey.privateExponent.data = privateExponent->attrib.pValue;
|
||||
tmpKey.privateExponent.len = privateExponent->attrib.ulValueLen;
|
||||
}
|
||||
publicExponent = sftk_FindAttribute(object, CKA_PUBLIC_EXPONENT);
|
||||
if (publicExponent) {
|
||||
tmpKey.publicExponent.data = publicExponent->attrib.pValue;
|
||||
tmpKey.publicExponent.len = publicExponent->attrib.ulValueLen;
|
||||
}
|
||||
|
||||
/*
|
||||
* populate requires one exponent plus 2 other components to work.
|
||||
* we expected our caller to check that first. If that didn't happen,
|
||||
* populate will simply return an error here.
|
||||
*/
|
||||
rv = RSA_PopulatePrivateKey(&tmpKey);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* now that we have a fully populated key, set all our attribute values */
|
||||
rv = SECFailure;
|
||||
crv = sftk_forceAttribute(object,CKA_MODULUS,
|
||||
sftk_item_expand(&tmpKey.modulus));
|
||||
if (crv != CKR_OK) goto loser;
|
||||
crv = sftk_forceAttribute(object,CKA_PUBLIC_EXPONENT,
|
||||
sftk_item_expand(&tmpKey.publicExponent));
|
||||
if (crv != CKR_OK) goto loser;
|
||||
crv = sftk_forceAttribute(object,CKA_PRIVATE_EXPONENT,
|
||||
sftk_item_expand(&tmpKey.privateExponent));
|
||||
if (crv != CKR_OK) goto loser;
|
||||
crv = sftk_forceAttribute(object,CKA_PRIME_1,
|
||||
sftk_item_expand(&tmpKey.prime1));
|
||||
if (crv != CKR_OK) goto loser;
|
||||
crv = sftk_forceAttribute(object,CKA_PRIME_2,
|
||||
sftk_item_expand(&tmpKey.prime2));
|
||||
if (crv != CKR_OK) goto loser;
|
||||
crv = sftk_forceAttribute(object,CKA_EXPONENT_1,
|
||||
sftk_item_expand(&tmpKey.exponent1));
|
||||
if (crv != CKR_OK) goto loser;
|
||||
crv = sftk_forceAttribute(object,CKA_EXPONENT_2,
|
||||
sftk_item_expand(&tmpKey.exponent2));
|
||||
if (crv != CKR_OK) goto loser;
|
||||
crv = sftk_forceAttribute(object,CKA_COEFFICIENT,
|
||||
sftk_item_expand(&tmpKey.coefficient));
|
||||
if (crv != CKR_OK) goto loser;
|
||||
rv = SECSuccess;
|
||||
|
||||
/* we're done (one way or the other), clean up all our stuff */
|
||||
loser:
|
||||
if (tmpKey.arena) {
|
||||
PORT_FreeArena(tmpKey.arena,PR_TRUE);
|
||||
}
|
||||
if (modulus) {
|
||||
sftk_FreeAttribute(modulus);
|
||||
}
|
||||
if (prime1) {
|
||||
sftk_FreeAttribute(prime1);
|
||||
}
|
||||
if (prime2) {
|
||||
sftk_FreeAttribute(prime2);
|
||||
}
|
||||
if (privateExponent) {
|
||||
sftk_FreeAttribute(privateExponent);
|
||||
}
|
||||
if (publicExponent) {
|
||||
sftk_FreeAttribute(publicExponent);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Generate a low private key structure from an object */
|
||||
NSSLOWKEYPrivateKey *
|
||||
|
|
|
@ -3141,7 +3141,7 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
|
|||
int i;
|
||||
SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
|
||||
unsigned char buf[MAX_KEY_LEN];
|
||||
enum {nsc_pbe, nsc_ssl, nsc_bulk, nsc_param} key_gen_type;
|
||||
enum {nsc_pbe, nsc_ssl, nsc_bulk, nsc_param, nsc_jpake} key_gen_type;
|
||||
NSSPKCS5PBEParameter *pbe_param;
|
||||
SSL3RSAPreMasterSecret *rsa_pms;
|
||||
CK_VERSION *version;
|
||||
|
@ -3150,6 +3150,7 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
|
|||
* produce them any more. The affected algorithm was 3DES.
|
||||
*/
|
||||
PRBool faultyPBE3DES = PR_FALSE;
|
||||
HASH_HashType hashType;
|
||||
|
||||
CHECK_FORK();
|
||||
|
||||
|
@ -3249,6 +3250,24 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
|
|||
objclass = CKO_KG_PARAMETERS;
|
||||
crv = CKR_OK;
|
||||
break;
|
||||
case CKM_NSS_JPAKE_ROUND1_SHA1: hashType = HASH_AlgSHA1; goto jpake1;
|
||||
case CKM_NSS_JPAKE_ROUND1_SHA256: hashType = HASH_AlgSHA256; goto jpake1;
|
||||
case CKM_NSS_JPAKE_ROUND1_SHA384: hashType = HASH_AlgSHA384; goto jpake1;
|
||||
case CKM_NSS_JPAKE_ROUND1_SHA512: hashType = HASH_AlgSHA512; goto jpake1;
|
||||
jpake1:
|
||||
key_gen_type = nsc_jpake;
|
||||
key_type = CKK_NSS_JPAKE_ROUND1;
|
||||
objclass = CKO_PRIVATE_KEY;
|
||||
if (pMechanism->pParameter == NULL ||
|
||||
pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
if (sftk_isTrue(key, CKA_TOKEN)) {
|
||||
crv = CKR_TEMPLATE_INCONSISTENT;
|
||||
}
|
||||
crv = CKR_OK;
|
||||
break;
|
||||
default:
|
||||
crv = CKR_MECHANISM_INVALID;
|
||||
break;
|
||||
|
@ -3295,6 +3314,11 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
|
|||
*buf = 0;
|
||||
crv = nsc_parameter_gen(key_type,key);
|
||||
break;
|
||||
case nsc_jpake:
|
||||
crv = jpake_Round1(hashType,
|
||||
(CK_NSS_JPAKERound1Params *) pMechanism->pParameter,
|
||||
key);
|
||||
break;
|
||||
}
|
||||
|
||||
if (crv != CKR_OK) { sftk_FreeObject(key); return crv; }
|
||||
|
@ -5000,8 +5024,8 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
|
|||
SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession);
|
||||
SFTKObject * key;
|
||||
SFTKObject * sourceKey;
|
||||
SFTKAttribute * att;
|
||||
SFTKAttribute * att2;
|
||||
SFTKAttribute * att = NULL;
|
||||
SFTKAttribute * att2 = NULL;
|
||||
unsigned char * buf;
|
||||
SHA1Context * sha;
|
||||
MD5Context * md5;
|
||||
|
@ -5024,6 +5048,8 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
|
|||
unsigned char key_block[NUM_MIXERS * MD5_LENGTH];
|
||||
unsigned char key_block2[MD5_LENGTH];
|
||||
PRBool isFIPS;
|
||||
HASH_HashType hashType;
|
||||
PRBool extractValue = PR_TRUE;
|
||||
|
||||
CHECK_FORK();
|
||||
|
||||
|
@ -5061,8 +5087,24 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
|
|||
keySize = sftk_MapKeySize(keyType);
|
||||
}
|
||||
|
||||
/* Derive can only create SECRET KEY's currently... */
|
||||
classType = CKO_SECRET_KEY;
|
||||
switch (pMechanism->mechanism) {
|
||||
case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */
|
||||
case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */
|
||||
case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */
|
||||
case CKM_NSS_JPAKE_ROUND2_SHA512:
|
||||
extractValue = PR_FALSE;
|
||||
classType = CKO_PRIVATE_KEY;
|
||||
break;
|
||||
case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */
|
||||
case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
|
||||
case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
|
||||
case CKM_NSS_JPAKE_FINAL_SHA512:
|
||||
extractValue = PR_FALSE;
|
||||
/* fall through */
|
||||
default:
|
||||
classType = CKO_SECRET_KEY;
|
||||
}
|
||||
|
||||
crv = sftk_forceAttribute (key,CKA_CLASS,&classType,sizeof(classType));
|
||||
if (crv != CKR_OK) {
|
||||
sftk_FreeObject(key);
|
||||
|
@ -5083,12 +5125,14 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
|
|||
return CKR_KEY_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
/* get the value of the base key */
|
||||
att = sftk_FindAttribute(sourceKey,CKA_VALUE);
|
||||
if (att == NULL) {
|
||||
sftk_FreeObject(key);
|
||||
sftk_FreeObject(sourceKey);
|
||||
return CKR_KEY_HANDLE_INVALID;
|
||||
if (extractValue) {
|
||||
/* get the value of the base key */
|
||||
att = sftk_FindAttribute(sourceKey,CKA_VALUE);
|
||||
if (att == NULL) {
|
||||
sftk_FreeObject(key);
|
||||
sftk_FreeObject(sourceKey);
|
||||
return CKR_KEY_HANDLE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
switch (pMechanism->mechanism) {
|
||||
|
@ -6008,10 +6052,161 @@ ec_loser:
|
|||
}
|
||||
#endif /* NSS_ENABLE_ECC */
|
||||
|
||||
/* See RFC 5869 and CK_NSS_HKDFParams for documentation. */
|
||||
case CKM_NSS_HKDF_SHA1: hashType = HASH_AlgSHA1; goto hkdf;
|
||||
case CKM_NSS_HKDF_SHA256: hashType = HASH_AlgSHA256; goto hkdf;
|
||||
case CKM_NSS_HKDF_SHA384: hashType = HASH_AlgSHA384; goto hkdf;
|
||||
case CKM_NSS_HKDF_SHA512: hashType = HASH_AlgSHA512; goto hkdf;
|
||||
hkdf: {
|
||||
const CK_NSS_HKDFParams * params =
|
||||
(const CK_NSS_HKDFParams *) pMechanism->pParameter;
|
||||
const SECHashObject * rawHash;
|
||||
unsigned hashLen;
|
||||
CK_BYTE buf[HASH_LENGTH_MAX];
|
||||
/* const */ CK_BYTE * prk; /* psuedo-random key */
|
||||
CK_ULONG prkLen;
|
||||
const CK_BYTE * okm; /* output keying material */
|
||||
|
||||
rawHash = HASH_GetRawHashObject(hashType);
|
||||
if (rawHash == NULL || rawHash->length > sizeof buf) {
|
||||
crv = CKR_FUNCTION_FAILED;
|
||||
break;
|
||||
}
|
||||
hashLen = rawHash->length;
|
||||
|
||||
if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams) ||
|
||||
!params || (!params->bExpand && !params->bExtract) ||
|
||||
(params->bExtract && params->ulSaltLen > 0 && !params->pSalt) ||
|
||||
(params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) {
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
break;
|
||||
}
|
||||
if (keySize == 0 || keySize > sizeof key_block ||
|
||||
(!params->bExpand && keySize > hashLen) ||
|
||||
(params->bExpand && keySize > 255 * hashLen)) {
|
||||
crv = CKR_TEMPLATE_INCONSISTENT;
|
||||
break;
|
||||
}
|
||||
crv = sftk_DeriveSensitiveCheck(sourceKey, key);
|
||||
if (crv != CKR_OK)
|
||||
break;
|
||||
|
||||
/* HKDF-Extract(salt, base key value) */
|
||||
if (params->bExtract) {
|
||||
CK_BYTE * salt;
|
||||
CK_ULONG saltLen;
|
||||
HMACContext * hmac;
|
||||
unsigned int bufLen;
|
||||
|
||||
salt = params->pSalt;
|
||||
saltLen = params->ulSaltLen;
|
||||
if (salt == NULL) {
|
||||
saltLen = hashLen;
|
||||
salt = buf;
|
||||
memset(salt, 0, saltLen);
|
||||
}
|
||||
hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
|
||||
if (!hmac) {
|
||||
crv = CKR_HOST_MEMORY;
|
||||
break;
|
||||
}
|
||||
HMAC_Begin(hmac);
|
||||
HMAC_Update(hmac, (const unsigned char*) att->attrib.pValue,
|
||||
att->attrib.ulValueLen);
|
||||
HMAC_Finish(hmac, buf, &bufLen, sizeof(buf));
|
||||
HMAC_Destroy(hmac, PR_TRUE);
|
||||
PORT_Assert(bufLen == rawHash->length);
|
||||
prk = buf;
|
||||
prkLen = bufLen;
|
||||
} else {
|
||||
/* PRK = base key value */
|
||||
prk = (CK_BYTE*) att->attrib.pValue;
|
||||
prkLen = att->attrib.ulValueLen;
|
||||
}
|
||||
|
||||
/* HKDF-Expand */
|
||||
if (!params->bExpand) {
|
||||
okm = prk;
|
||||
} else {
|
||||
/* T(1) = HMAC-Hash(prk, "" | info | 0x01)
|
||||
* T(n) = HMAC-Hash(prk, T(n-1) | info | n
|
||||
* key material = T(1) | ... | T(n)
|
||||
*/
|
||||
HMACContext * hmac;
|
||||
CK_BYTE i;
|
||||
unsigned iterations = PR_ROUNDUP(keySize, hashLen) / hashLen;
|
||||
hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS);
|
||||
if (hmac == NULL) {
|
||||
crv = CKR_HOST_MEMORY;
|
||||
break;
|
||||
}
|
||||
for (i = 1; i <= iterations; ++i) {
|
||||
unsigned len;
|
||||
HMAC_Begin(hmac);
|
||||
if (i > 1) {
|
||||
HMAC_Update(hmac, key_block + ((i-2) * hashLen), hashLen);
|
||||
}
|
||||
if (params->ulInfoLen != 0) {
|
||||
HMAC_Update(hmac, params->pInfo, params->ulInfoLen);
|
||||
}
|
||||
HMAC_Update(hmac, &i, 1);
|
||||
HMAC_Finish(hmac, key_block + ((i-1) * hashLen), &len,
|
||||
hashLen);
|
||||
PORT_Assert(len == hashLen);
|
||||
}
|
||||
HMAC_Destroy(hmac, PR_TRUE);
|
||||
okm = key_block;
|
||||
}
|
||||
/* key material = prk */
|
||||
crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize);
|
||||
break;
|
||||
} /* end of CKM_NSS_HKDF_* */
|
||||
|
||||
case CKM_NSS_JPAKE_ROUND2_SHA1: hashType = HASH_AlgSHA1; goto jpake2;
|
||||
case CKM_NSS_JPAKE_ROUND2_SHA256: hashType = HASH_AlgSHA256; goto jpake2;
|
||||
case CKM_NSS_JPAKE_ROUND2_SHA384: hashType = HASH_AlgSHA384; goto jpake2;
|
||||
case CKM_NSS_JPAKE_ROUND2_SHA512: hashType = HASH_AlgSHA512; goto jpake2;
|
||||
jpake2:
|
||||
if (pMechanism->pParameter == NULL ||
|
||||
pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params))
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN))
|
||||
crv = CKR_TEMPLATE_INCONSISTENT;
|
||||
if (crv == CKR_OK)
|
||||
crv = sftk_DeriveSensitiveCheck(sourceKey, key);
|
||||
if (crv == CKR_OK)
|
||||
crv = jpake_Round2(hashType,
|
||||
(CK_NSS_JPAKERound2Params *) pMechanism->pParameter,
|
||||
sourceKey, key);
|
||||
break;
|
||||
|
||||
case CKM_NSS_JPAKE_FINAL_SHA1: hashType = HASH_AlgSHA1; goto jpakeFinal;
|
||||
case CKM_NSS_JPAKE_FINAL_SHA256: hashType = HASH_AlgSHA256; goto jpakeFinal;
|
||||
case CKM_NSS_JPAKE_FINAL_SHA384: hashType = HASH_AlgSHA384; goto jpakeFinal;
|
||||
case CKM_NSS_JPAKE_FINAL_SHA512: hashType = HASH_AlgSHA512; goto jpakeFinal;
|
||||
jpakeFinal:
|
||||
if (pMechanism->pParameter == NULL ||
|
||||
pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams))
|
||||
crv = CKR_MECHANISM_PARAM_INVALID;
|
||||
/* We purposely do not do the derive sensitivity check; we want to be
|
||||
able to derive non-sensitive keys while allowing the ROUND1 and
|
||||
ROUND2 keys to be sensitive (which they always are, since they are
|
||||
in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE
|
||||
in the template in order for the resultant keyblock key to be
|
||||
sensitive.
|
||||
*/
|
||||
if (crv == CKR_OK)
|
||||
crv = jpake_Final(hashType,
|
||||
(CK_NSS_JPAKEFinalParams *) pMechanism->pParameter,
|
||||
sourceKey, key);
|
||||
break;
|
||||
|
||||
default:
|
||||
crv = CKR_MECHANISM_INVALID;
|
||||
}
|
||||
sftk_FreeAttribute(att);
|
||||
if (att) {
|
||||
sftk_FreeAttribute(att);
|
||||
}
|
||||
sftk_FreeObject(sourceKey);
|
||||
if (crv != CKR_OK) {
|
||||
if (key) sftk_FreeObject(key);
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#include "pkcs11t.h"
|
||||
|
||||
#include "sftkdbt.h"
|
||||
|
||||
#include "hasht.h"
|
||||
|
||||
/*
|
||||
* Configuration Defines
|
||||
|
@ -702,6 +702,21 @@ SFTKObject * sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey,
|
|||
CK_OBJECT_HANDLE handle);
|
||||
SFTKTokenObject *sftk_convertSessionToToken(SFTKObject *so);
|
||||
|
||||
|
||||
/* J-PAKE (jpakesftk.c) */
|
||||
extern
|
||||
CK_RV jpake_Round1(HASH_HashType hashType,
|
||||
CK_NSS_JPAKERound1Params * params,
|
||||
SFTKObject * key);
|
||||
extern
|
||||
CK_RV jpake_Round2(HASH_HashType hashType,
|
||||
CK_NSS_JPAKERound2Params * params,
|
||||
SFTKObject * sourceKey, SFTKObject * key);
|
||||
extern
|
||||
CK_RV jpake_Final(HASH_HashType hashType,
|
||||
const CK_NSS_JPAKEFinalParams * params,
|
||||
SFTKObject * sourceKey, SFTKObject * key);
|
||||
|
||||
/****************************************
|
||||
* implement TLS Pseudo Random Function (PRF)
|
||||
*/
|
||||
|
|
|
@ -57,11 +57,11 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define SOFTOKEN_VERSION "3.12.8.0" SOFTOKEN_ECC_STRING
|
||||
#define SOFTOKEN_VERSION "3.12.9.0" SOFTOKEN_ECC_STRING " Beta"
|
||||
#define SOFTOKEN_VMAJOR 3
|
||||
#define SOFTOKEN_VMINOR 12
|
||||
#define SOFTOKEN_VPATCH 8
|
||||
#define SOFTOKEN_VPATCH 9
|
||||
#define SOFTOKEN_VBUILD 0
|
||||
#define SOFTOKEN_BETA PR_FALSE
|
||||
#define SOFTOKEN_BETA PR_TRUE
|
||||
|
||||
#endif /* _SOFTKVER_H_ */
|
||||
|
|
|
@ -51,11 +51,11 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
|
||||
*/
|
||||
#define NSSUTIL_VERSION "3.12.8.0"
|
||||
#define NSSUTIL_VERSION "3.12.9.0 Beta"
|
||||
#define NSSUTIL_VMAJOR 3
|
||||
#define NSSUTIL_VMINOR 12
|
||||
#define NSSUTIL_VPATCH 8
|
||||
#define NSSUTIL_VPATCH 9
|
||||
#define NSSUTIL_VBUILD 0
|
||||
#define NSSUTIL_BETA PR_FALSE
|
||||
#define NSSUTIL_BETA PR_TRUE
|
||||
|
||||
#endif /* __nssutil_h_ */
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#define _PKCS11N_H_
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.19 $ $Date: 2009/03/25 05:21:03 $";
|
||||
static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.19.22.2 $ $Date: 2010/12/04 19:10:46 $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
|
@ -84,6 +84,10 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.19 $
|
|||
#define CKK_NSS (CKK_VENDOR_DEFINED|NSSCK_VENDOR_NSS)
|
||||
|
||||
#define CKK_NSS_PKCS8 (CKK_NSS + 1)
|
||||
|
||||
#define CKK_NSS_JPAKE_ROUND1 (CKK_NSS + 2)
|
||||
#define CKK_NSS_JPAKE_ROUND2 (CKK_NSS + 3)
|
||||
|
||||
/*
|
||||
* NSS-defined certificate types
|
||||
*
|
||||
|
@ -116,6 +120,15 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.19 $
|
|||
#define CKA_NSS_MODULE_SPEC (CKA_NSS + 24)
|
||||
#define CKA_NSS_OVERRIDE_EXTENSIONS (CKA_NSS + 25)
|
||||
|
||||
#define CKA_NSS_JPAKE_SIGNERID (CKA_NSS + 26)
|
||||
#define CKA_NSS_JPAKE_PEERID (CKA_NSS + 27)
|
||||
#define CKA_NSS_JPAKE_GX1 (CKA_NSS + 28)
|
||||
#define CKA_NSS_JPAKE_GX2 (CKA_NSS + 29)
|
||||
#define CKA_NSS_JPAKE_GX3 (CKA_NSS + 30)
|
||||
#define CKA_NSS_JPAKE_GX4 (CKA_NSS + 31)
|
||||
#define CKA_NSS_JPAKE_X2 (CKA_NSS + 32)
|
||||
#define CKA_NSS_JPAKE_X2S (CKA_NSS + 33)
|
||||
|
||||
/*
|
||||
* Trust attributes:
|
||||
*
|
||||
|
@ -168,6 +181,54 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.19 $
|
|||
#define CKM_NSS_AES_KEY_WRAP (CKM_NSS + 1)
|
||||
#define CKM_NSS_AES_KEY_WRAP_PAD (CKM_NSS + 2)
|
||||
|
||||
/* HKDF key derivation mechanisms. See CK_NSS_HKDFParams for documentation. */
|
||||
#define CKM_NSS_HKDF_SHA1 (CKM_NSS + 3)
|
||||
#define CKM_NSS_HKDF_SHA256 (CKM_NSS + 4)
|
||||
#define CKM_NSS_HKDF_SHA384 (CKM_NSS + 5)
|
||||
#define CKM_NSS_HKDF_SHA512 (CKM_NSS + 6)
|
||||
|
||||
/* J-PAKE round 1 key generation mechanisms.
|
||||
*
|
||||
* Required template attributes: CKA_PRIME, CKA_SUBPRIME, CKA_BASE,
|
||||
* CKA_NSS_JPAKE_SIGNERID
|
||||
* Output key type: CKK_NSS_JPAKE_ROUND1
|
||||
* Output key class: CKO_PRIVATE_KEY
|
||||
* Parameter type: CK_NSS_JPAKERound1Params
|
||||
*
|
||||
*/
|
||||
#define CKM_NSS_JPAKE_ROUND1_SHA1 (CKM_NSS + 7)
|
||||
#define CKM_NSS_JPAKE_ROUND1_SHA256 (CKM_NSS + 8)
|
||||
#define CKM_NSS_JPAKE_ROUND1_SHA384 (CKM_NSS + 9)
|
||||
#define CKM_NSS_JPAKE_ROUND1_SHA512 (CKM_NSS + 10)
|
||||
|
||||
/* J-PAKE round 2 key derivation mechanisms.
|
||||
*
|
||||
* Required template attributes: CKA_NSS_JPAKE_PEERID
|
||||
* Input key type: CKK_NSS_JPAKE_ROUND1
|
||||
* Output key type: CKK_NSS_JPAKE_ROUND2
|
||||
* Output key class: CKO_PRIVATE_KEY
|
||||
* Parameter type: CK_NSS_JPAKERound2Params
|
||||
*/
|
||||
#define CKM_NSS_JPAKE_ROUND2_SHA1 (CKM_NSS + 11)
|
||||
#define CKM_NSS_JPAKE_ROUND2_SHA256 (CKM_NSS + 12)
|
||||
#define CKM_NSS_JPAKE_ROUND2_SHA384 (CKM_NSS + 13)
|
||||
#define CKM_NSS_JPAKE_ROUND2_SHA512 (CKM_NSS + 14)
|
||||
|
||||
/* J-PAKE final key material derivation mechanisms
|
||||
*
|
||||
* Input key type: CKK_NSS_JPAKE_ROUND2
|
||||
* Output key type: CKK_GENERIC_SECRET
|
||||
* Output key class: CKO_SECRET_KEY
|
||||
* Parameter type: CK_NSS_JPAKEFinalParams
|
||||
*
|
||||
* You must apply a KDF (e.g. CKM_NSS_HKDF_*) to resultant keying material
|
||||
* to get a key with uniformly distributed bits.
|
||||
*/
|
||||
#define CKM_NSS_JPAKE_FINAL_SHA1 (CKM_NSS + 15)
|
||||
#define CKM_NSS_JPAKE_FINAL_SHA256 (CKM_NSS + 16)
|
||||
#define CKM_NSS_JPAKE_FINAL_SHA384 (CKM_NSS + 17)
|
||||
#define CKM_NSS_JPAKE_FINAL_SHA512 (CKM_NSS + 18)
|
||||
|
||||
/*
|
||||
* HISTORICAL:
|
||||
* Do not attempt to use these. They are only used by NETSCAPE's internal
|
||||
|
@ -187,6 +248,32 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.19 $
|
|||
|
||||
#define CKM_TLS_PRF_GENERAL 0x80000373UL
|
||||
|
||||
typedef struct CK_NSS_JPAKEPublicValue {
|
||||
CK_BYTE * pGX;
|
||||
CK_ULONG ulGXLen;
|
||||
CK_BYTE * pGV;
|
||||
CK_ULONG ulGVLen;
|
||||
CK_BYTE * pR;
|
||||
CK_ULONG ulRLen;
|
||||
} CK_NSS_JPAKEPublicValue;
|
||||
|
||||
typedef struct CK_NSS_JPAKERound1Params {
|
||||
CK_NSS_JPAKEPublicValue gx1; /* out */
|
||||
CK_NSS_JPAKEPublicValue gx2; /* out */
|
||||
} CK_NSS_JPAKERound1Params;
|
||||
|
||||
typedef struct CK_NSS_JPAKERound2Params {
|
||||
CK_BYTE * pSharedKey; /* in */
|
||||
CK_ULONG ulSharedKeyLen; /* in */
|
||||
CK_NSS_JPAKEPublicValue gx3; /* in */
|
||||
CK_NSS_JPAKEPublicValue gx4; /* in */
|
||||
CK_NSS_JPAKEPublicValue A; /* out */
|
||||
} CK_NSS_JPAKERound2Params;
|
||||
|
||||
typedef struct CK_NSS_JPAKEFinalParams {
|
||||
CK_NSS_JPAKEPublicValue B; /* in */
|
||||
} CK_NSS_JPAKEFinalParams;
|
||||
|
||||
/*
|
||||
* NSS-defined return values
|
||||
*
|
||||
|
@ -196,6 +283,33 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.19 $
|
|||
#define CKR_NSS_CERTDB_FAILED (CKR_NSS + 1)
|
||||
#define CKR_NSS_KEYDB_FAILED (CKR_NSS + 2)
|
||||
|
||||
/* Mandatory parameter for the CKM_NSS_HKDF_* key deriviation mechanisms.
|
||||
See RFC 5869.
|
||||
|
||||
bExtract: If set, HKDF-Extract will be applied to the input key. If
|
||||
the optional salt is given, it is used; otherwise, the salt is
|
||||
set to a sequence of zeros equal in length to the HMAC output.
|
||||
If bExpand is not set, then the key template given to
|
||||
C_DeriveKey must indicate an output key size less than or equal
|
||||
to the output size of the HMAC.
|
||||
|
||||
bExpand: If set, HKDF-Expand will be applied to the input key (if
|
||||
bExtract is not set) or to the result of HKDF-Extract (if
|
||||
bExtract is set). Any info given in the optional pInfo field will
|
||||
be included in the calculation.
|
||||
|
||||
The size of the output key must be specified in the template passed to
|
||||
C_DeriveKey.
|
||||
*/
|
||||
typedef struct CK_NSS_HKDFParams {
|
||||
CK_BBOOL bExtract;
|
||||
CK_BYTE_PTR pSalt;
|
||||
CK_ULONG ulSaltLen;
|
||||
CK_BBOOL bExpand;
|
||||
CK_BYTE_PTR pInfo;
|
||||
CK_ULONG ulInfoLen;
|
||||
} CK_NSS_HKDFParams;
|
||||
|
||||
/*
|
||||
* Trust info
|
||||
*
|
||||
|
|
|
@ -213,6 +213,7 @@ SEC_ERROR_OCSP_BAD_SIGNATURE = (SEC_ERROR_BASE + 157),
|
|||
SEC_ERROR_OUT_OF_SEARCH_LIMITS = (SEC_ERROR_BASE + 158),
|
||||
SEC_ERROR_INVALID_POLICY_MAPPING = (SEC_ERROR_BASE + 159),
|
||||
SEC_ERROR_POLICY_VALIDATION_FAILED = (SEC_ERROR_BASE + 160),
|
||||
/* No longer used. Unknown AIA location types are now silently ignored. */
|
||||
SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE = (SEC_ERROR_BASE + 161),
|
||||
SEC_ERROR_BAD_HTTP_RESPONSE = (SEC_ERROR_BASE + 162),
|
||||
SEC_ERROR_BAD_LDAP_RESPONSE = (SEC_ERROR_BASE + 163),
|
||||
|
@ -231,6 +232,10 @@ SEC_ERROR_CRL_IMPORT_FAILED = (SEC_ERROR_BASE + 171),
|
|||
SEC_ERROR_EXPIRED_PASSWORD = (SEC_ERROR_BASE + 172),
|
||||
SEC_ERROR_LOCKED_PASSWORD = (SEC_ERROR_BASE + 173),
|
||||
|
||||
SEC_ERROR_UNKNOWN_PKCS11_ERROR = (SEC_ERROR_BASE + 174),
|
||||
|
||||
SEC_ERROR_BAD_CRL_DP_URL = (SEC_ERROR_BASE + 175),
|
||||
|
||||
/* Add new error codes above here. */
|
||||
SEC_ERROR_END_OF_LIST
|
||||
} SECErrorCodes;
|
||||
|
|
Загрузка…
Ссылка в новой задаче