Bug 475578 - Implement Extended DSA as defined in FIPS 186-3 (DSS)

r wtc Patches 1 and 4 in the original bug (lib/softoken lib/freebl, and lib/ssl)


git-svn-id: svn://10.0.0.236/trunk@263930 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rrelyea%redhat.com 2012-06-12 16:39:03 +00:00
parent 59a2cacd1c
commit 528d2c4c19
13 changed files with 1657 additions and 299 deletions

View File

@ -4,7 +4,7 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* $Id: blapi.h,v 1.46 2012-04-25 14:49:43 gerv%gerv.net Exp $ */
/* $Id: blapi.h,v 1.47 2012-06-12 16:39:00 rrelyea%redhat.com Exp $ */
#ifndef _BLAPI_H_
#define _BLAPI_H_
@ -1232,6 +1232,8 @@ PRNGTEST_Uninstantiate(void);
/* Generate PQGParams and PQGVerify structs.
* Length of seed and length of h both equal length of P.
* All lengths are specified by "j", according to the table above.
*
* The verify parameters will conform to FIPS186-1.
*/
extern SECStatus
PQG_ParamGen(unsigned int j, /* input : determines length of P. */
@ -1242,6 +1244,8 @@ PQG_ParamGen(unsigned int j, /* input : determines length of P. */
* Length of P specified by j. Length of h will match length of P.
* Length of SEED in bytes specified in seedBytes.
* seedBbytes must be in the range [20..255] or an error will result.
*
* The verify parameters will conform to FIPS186-1.
*/
extern SECStatus
PQG_ParamGenSeedLen(
@ -1250,6 +1254,32 @@ PQG_ParamGenSeedLen(
PQGParams **pParams, /* output: P Q and G returned here */
PQGVerify **pVfy); /* output: counter and seed. */
/* Generate PQGParams and PQGVerify structs.
* Length of P specified by L in bits.
* Length of Q specified by N in bits.
* Length of SEED in bytes specified in seedBytes.
* seedBbytes must be in the range [N..L*2] or an error will result.
*
* Not that J uses the above table, L is the length exact. L and N must
* match the table below or an error will result:
*
* L N
* 1024 160
* 2048 224
* 2048 256
* 3072 256
*
* The verify parameters will conform to FIPS186-3 using the smallest
* permissible hash for the key strength.
*/
extern SECStatus
PQG_ParamGenV2(
unsigned int L, /* input : determines length of P. */
unsigned int N, /* input : determines length of Q. */
unsigned int seedBytes, /* input : length of seed in bytes.*/
PQGParams **pParams, /* output: P Q and G returned here */
PQGVerify **pVfy); /* output: counter and seed. */
/* Test PQGParams for validity as DSS PQG values.
* If vfy is non-NULL, test PQGParams to make sure they were generated
@ -1261,20 +1291,9 @@ PQG_ParamGenSeedLen(
* SECSuccess: PQGParams are valid.
* SECFailure: PQGParams are invalid.
*
* Verify the following 12 facts about PQG counter SEED g and h
* 1. Q is 160 bits long.
* 2. P is one of the 9 valid lengths.
* 3. G < P
* 4. P % Q == 1
* 5. Q is prime
* 6. P is prime
* Steps 7-12 are done only if the optional PQGVerify is supplied.
* 7. counter < 4096
* 8. g >= 160 and g < 2048 (g is length of seed in bits)
* 9. Q generated from SEED matches Q in PQGParams.
* 10. P generated from (L, counter, g, SEED, Q) matches P in PQGParams.
* 11. 1 < h < P-1
* 12. G generated from h matches G in PQGParams.
* Verify the PQG againts the counter, SEED and h.
* These tests are specified in FIPS 186-3 Appendix A.1.1.1, A.1.1.3, and A.2.2
* PQG_VerifyParams will automatically choose the appropriate test.
*/
extern SECStatus PQG_VerifyParams(const PQGParams *params,

View File

@ -4,7 +4,7 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* $Id: blapit.h,v 1.27 2012-04-25 14:49:43 gerv%gerv.net Exp $ */
/* $Id: blapit.h,v 1.28 2012-06-12 16:39:00 rrelyea%redhat.com Exp $ */
#ifndef _BLAPIT_H_
#define _BLAPIT_H_
@ -43,8 +43,32 @@
#define NSS_SEED 0
#define NSS_SEED_CBC 1
#define DSA_SIGNATURE_LEN 40 /* Bytes */
#define DSA_SUBPRIME_LEN 20 /* Bytes */
#define DSA1_SUBPRIME_LEN 20 /* Bytes */
#define DSA1_SIGNATURE_LEN (DSA1_SUBPRIME_LEN*2) /* Bytes */
#define DSA_MAX_SUBPRIME_LEN 32 /* Bytes */
#define DSA_MAX_SIGNATURE_LEN (DSA_MAX_SUBPRIME_LEN*2)/* Bytes */
/*
* Mark the old defines as deprecated. This will warn code that expected
* DSA1 only that they need to change if the are to support DSA2.
*/
#if defined(__GNUC__) && (__GNUC__ > 3)
/* make GCC warn when we use these #defines */
typedef int __BLAPI_DEPRECATED __attribute__((deprecated));
#define DSA_SUBPRIME_LEN ((__BLAPI_DEPRECATED)DSA1_SUBPRIME_LEN)
#define DSA_SIGNATURE_LEN ((__BLAPI_DEPRECATED)DSA1_SIGNATURE_LEN)
#define DSA_Q_BITS ((__BLAPI_DEPRECATED)(DSA1_SUBPRIME_LEN*8))
#else
#ifdef _WIN32
/* This magic gets the windows compiler to give us a deprecation
* warning */
#pragma deprecated(DSA_SUBPRIME_LEN, DSA_SIGNATURE_LEN, DSA_QBITS)
#endif
#define DSA_SUBPRIME_LEN DSA1_SUBPRIME_LEN
#define DSA_SIGNATURE_LEN DSA1_SIGNATURE_LEN
#define DSA_Q_BITS (DSA1_SUBPRIME_LEN*8)
#endif
/* XXX We shouldn't have to hard code this limit. For
* now, this is the quickest way to support ECDSA signature
@ -111,7 +135,7 @@
#define DH_MAX_P_BITS 3072
/*
* The FIPS 186 algorithm for generating primes P and Q allows only 9
* The FIPS 186-1 algorithm for generating primes P and Q allows only 9
* distinct values for the length of P, and only one value for the
* length of Q.
* The algorithm uses a variable j to indicate which of the 9 lengths
@ -130,12 +154,31 @@
* 7 960 160
* 8 1024 160
*
* The FIPS-186 compliant PQG generator takes j as an input parameter.
* The FIPS-186-1 compliant PQG generator takes j as an input parameter.
*
* FIPS 186-3 algorithm specifies 4 distinct P and Q sizes:
*
* bits in P bits in Q
* _________ _________
* 1024 160
* 2048 224
* 2048 256
* 3072 256
*
* The FIPS-186-3 complaiant PQG generator (PQG V2) takes arbitrary p and q
* lengths as input and returns an error if they aren't in this list.
*/
#define DSA_Q_BITS 160
#define DSA_MAX_P_BITS 1024
#define DSA1_Q_BITS 160
#define DSA_MAX_P_BITS 3072
#define DSA_MIN_P_BITS 512
#define DSA_MAX_Q_BITS 256
#define DSA_MIN_Q_BITS 160
#if DSA_MAX_Q_BITS != DSA_MAX_SUBPRIME_LEN*8
#error "Inconsistent declaration of DSA SUBPRIME/Q parameters in blapit.h"
#endif
/*
* function takes desired number of bits in P,

View File

@ -3,7 +3,7 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* $Id: dsa.c,v 1.22 2012-04-25 14:49:43 gerv%gerv.net Exp $ */
/* $Id: dsa.c,v 1.23 2012-06-12 16:39:00 rrelyea%redhat.com Exp $ */
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
@ -20,6 +20,7 @@
#include "blapi.h"
#include "mpi.h"
#include "secmpi.h"
#include "pqg.h"
/* XXX to be replaced by define in blapit.h */
#define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048
@ -79,7 +80,7 @@ SECStatus
FIPS186Change_ReduceModQForDSA(const unsigned char *w,
const unsigned char *q,
unsigned char *xj) {
return fips186Change_ReduceModQForDSA(w, q, DSA_SUBPRIME_LEN, xj);
return fips186Change_ReduceModQForDSA(w, q, DSA1_SUBPRIME_LEN, xj);
}
/*
@ -127,7 +128,7 @@ dsa_GenerateGlobalRandomBytes(const SECItem * qItem, PRUint8 * dest,
}
if (maxDestLen < qLen) {
/* This condition can occur when DSA_SignDigest is passed a group
with a subprime that is larger than DSA_SUBPRIME_LEN. */
with a subprime that is larger than DSA_MAX_SUBPRIME_LEN. */
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@ -279,11 +280,15 @@ DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey)
SECItem seed;
SECStatus rv;
rv = PQG_Check(params);
if (rv != SECSuccess) {
return rv;
}
seed.data = NULL;
rv = DSA_NewRandom(NULL, &params->subPrime, &seed);
if (rv == SECSuccess) {
if (seed.len != DSA_SUBPRIME_LEN) {
if (seed.len != PQG_GetLength(&params->subPrime)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
} else {
@ -294,16 +299,15 @@ DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey)
return rv;
}
/* For FIPS compliance testing. Seed must be exactly 20 bytes long */
/* For FIPS compliance testing. Seed must be exactly the size of subPrime */
SECStatus
DSA_NewKeyFromSeed(const PQGParams *params,
const unsigned char *seed,
DSAPrivateKey **privKey)
{
/* TODO: check Q size */
SECItem seedItem;
seedItem.data = (unsigned char*) seed;
seedItem.len = DSA_SUBPRIME_LEN;
seedItem.len = PQG_GetLength(&params->subPrime);
return dsa_NewKeyExtended(params, &seedItem, privKey);
}
@ -316,16 +320,39 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
mp_int r, s; /* tuple (r, s) is signature) */
mp_err err = MP_OKAY;
SECStatus rv = SECSuccess;
unsigned int dsa_subprime_len, dsa_signature_len, offset;
SECItem localDigest;
unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN];
/* FIPS-compliance dictates that digest is a SHA1 hash. */
/* FIPS-compliance dictates that digest is a SHA hash. */
/* Check args. */
if (!key || !signature || !digest ||
(signature->len < DSA_SIGNATURE_LEN) ||
(digest->len != SHA1_LENGTH)) {
if (!key || !signature || !digest) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
dsa_signature_len = dsa_subprime_len*2;
if ((signature->len < dsa_signature_len) ||
(digest->len > HASH_LENGTH_MAX) ||
(digest->len < SHA1_LENGTH)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* DSA accepts digests not equal to dsa_subprime_len, if the
* digests are greater, then they are truncated to the size of
* dsa_subprime_len, using the left most bits. If they are less
* then they are padded on the left.*/
PORT_Memset(localDigestData, 0, dsa_subprime_len);
offset = (digest->len < dsa_subprime_len) ?
(dsa_subprime_len - digest->len) : 0;
PORT_Memcpy(localDigestData+offset, digest->data,
dsa_subprime_len - offset);
localDigest.data = localDigestData;
localDigest.len = dsa_subprime_len;
/* Initialize MPI integers. */
MP_DIGITS(&p) = 0;
MP_DIGITS(&q) = 0;
@ -348,7 +375,7 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
SECITEM_TO_MPINT(key->params.subPrime, &q);
SECITEM_TO_MPINT(key->params.base, &g);
SECITEM_TO_MPINT(key->privateValue, &x);
OCTETS_TO_MPINT(kb, &k, DSA_SUBPRIME_LEN);
OCTETS_TO_MPINT(kb, &k, dsa_subprime_len);
/*
** FIPS 186-1, Section 5, Step 1
**
@ -359,9 +386,9 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
/*
** FIPS 186-1, Section 5, Step 2
**
** s = (k**-1 * (SHA1(M) + x*r)) mod q
** s = (k**-1 * (HASH(M) + x*r)) mod q
*/
SECITEM_TO_MPINT(*digest, &s); /* s = SHA1(M) */
SECITEM_TO_MPINT(localDigest, &s); /* s = HASH(M) */
CHECK_MPI_OK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */
CHECK_MPI_OK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */
CHECK_MPI_OK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */
@ -380,14 +407,15 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest,
**
** Signature is tuple (r, s)
*/
err = mp_to_fixlen_octets(&r, signature->data, DSA_SUBPRIME_LEN);
err = mp_to_fixlen_octets(&r, signature->data, dsa_subprime_len);
if (err < 0) goto cleanup;
err = mp_to_fixlen_octets(&s, signature->data + DSA_SUBPRIME_LEN,
DSA_SUBPRIME_LEN);
err = mp_to_fixlen_octets(&s, signature->data + dsa_subprime_len,
dsa_subprime_len);
if (err < 0) goto cleanup;
err = MP_OKAY;
signature->len = DSA_SIGNATURE_LEN;
signature->len = dsa_signature_len;
cleanup:
PORT_Memset(localDigestData, 0, DSA_MAX_SUBPRIME_LEN);
mp_clear(&p);
mp_clear(&q);
mp_clear(&g);
@ -413,9 +441,10 @@ DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
{
SECStatus rv;
int retries = 10;
unsigned char kSeed[DSA_SUBPRIME_LEN];
unsigned char kSeed[DSA_MAX_SUBPRIME_LEN];
unsigned int kSeedLen = 0;
unsigned int i;
unsigned int dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
PRBool good;
PORT_SetError(0);
@ -424,7 +453,7 @@ DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest)
kSeed, &kSeedLen, sizeof kSeed);
if (rv != SECSuccess)
break;
if (kSeedLen != DSA_SUBPRIME_LEN) {
if (kSeedLen != dsa_subprime_len) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
break;
@ -468,21 +497,44 @@ SECStatus
DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
const SECItem *digest)
{
/* FIPS-compliance dictates that digest is a SHA1 hash. */
/* FIPS-compliance dictates that digest is a SHA hash. */
mp_int p, q, g; /* PQG parameters */
mp_int r_, s_; /* tuple (r', s') is received signature) */
mp_int u1, u2, v, w; /* intermediate values used in verification */
mp_int y; /* public key */
mp_err err;
int dsa_subprime_len, dsa_signature_len, offset;
SECItem localDigest;
unsigned char localDigestData[DSA_MAX_SUBPRIME_LEN];
SECStatus verified = SECFailure;
/* Check args. */
if (!key || !signature || !digest ||
(signature->len != DSA_SIGNATURE_LEN) ||
(digest->len != SHA1_LENGTH)) {
if (!key || !signature || !digest ) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
dsa_subprime_len = PQG_GetLength(&key->params.subPrime);
dsa_signature_len = dsa_subprime_len*2;
if ((signature->len != dsa_signature_len) ||
(digest->len > HASH_LENGTH_MAX) ||
(digest->len < SHA1_LENGTH)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* DSA accepts digests not equal to dsa_subprime_len, if the
* digests are greater, than they are truncated to the size of
* dsa_subprime_len, using the left most bits. If they are less
* then they are padded on the left.*/
PORT_Memset(localDigestData, 0, dsa_subprime_len);
offset = (digest->len < dsa_subprime_len) ?
(dsa_subprime_len - digest->len) : 0;
PORT_Memcpy(localDigestData+offset, digest->data,
dsa_subprime_len - offset);
localDigest.data = localDigestData;
localDigest.len = dsa_subprime_len;
/* Initialize MPI integers. */
MP_DIGITS(&p) = 0;
MP_DIGITS(&q) = 0;
@ -514,8 +566,8 @@ DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
/*
** Convert received signature (r', s') into MPI integers.
*/
OCTETS_TO_MPINT(signature->data, &r_, DSA_SUBPRIME_LEN);
OCTETS_TO_MPINT(signature->data + DSA_SUBPRIME_LEN, &s_, DSA_SUBPRIME_LEN);
OCTETS_TO_MPINT(signature->data, &r_, dsa_subprime_len);
OCTETS_TO_MPINT(signature->data + dsa_subprime_len, &s_, dsa_subprime_len);
/*
** Verify that 0 < r' < q and 0 < s' < q
*/
@ -534,9 +586,9 @@ DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature,
/*
** FIPS 186-1, Section 6, Step 2
**
** u1 = ((SHA1(M')) * w) mod q
** u1 = ((Hash(M')) * w) mod q
*/
SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */
SECITEM_TO_MPINT(localDigest, &u1); /* u1 = HASH(M') */
CHECK_MPI_OK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */
/*
** FIPS 186-1, Section 6, Step 3

View File

@ -4,7 +4,7 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* $Id: ldvector.c,v 1.30 2012-04-25 14:49:43 gerv%gerv.net Exp $ */
/* $Id: ldvector.c,v 1.31 2012-06-12 16:39:00 rrelyea%redhat.com Exp $ */
#ifdef FREEBL_NO_DEPEND
extern int FREEBL_InitStubs(void);
@ -253,9 +253,13 @@ static const struct FREEBLVectorStr vector =
SHA224_Flatten,
SHA224_Resurrect,
SHA224_Clone,
BLAPI_SHVerifyFile
BLAPI_SHVerifyFile,
/* End of Version 3.013 */
PQG_ParamGenV2
/* End of Version 3.014 */
};
const FREEBLVector *

View File

@ -4,7 +4,7 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* $Id: loader.c,v 1.55 2012-04-25 14:49:43 gerv%gerv.net Exp $ */
/* $Id: loader.c,v 1.56 2012-06-12 16:39:00 rrelyea%redhat.com Exp $ */
#include "loader.h"
#include "prmem.h"
@ -850,6 +850,7 @@ PQG_ParamGenSeedLen( unsigned int j, unsigned int seedBytes,
return (vector->p_PQG_ParamGenSeedLen)(j, seedBytes, pParams, pVfy);
}
SECStatus
PQG_VerifyParams(const PQGParams *params, const PQGVerify *vfy,
SECStatus *result)
@ -1839,3 +1840,13 @@ BLAPI_SHVerifyFile(const char *name)
return PR_FALSE;
return vector->p_BLAPI_SHVerifyFile(name);
}
/* === new for DSA-2 === */
SECStatus
PQG_ParamGenV2( unsigned int L, unsigned int N, unsigned int seedBytes,
PQGParams **pParams, PQGVerify **pVfy)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return (vector->p_PQG_ParamGenV2)(L, N, seedBytes, pParams, pVfy);
}

View File

@ -4,14 +4,14 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* $Id: loader.h,v 1.36 2012-04-25 14:49:43 gerv%gerv.net Exp $ */
/* $Id: loader.h,v 1.37 2012-06-12 16:39:00 rrelyea%redhat.com Exp $ */
#ifndef _LOADER_H_
#define _LOADER_H_ 1
#include "blapi.h"
#define FREEBL_VERSION 0x030D
#define FREEBL_VERSION 0x030E
struct FREEBLVectorStr {
@ -563,6 +563,12 @@ struct FREEBLVectorStr {
/* Version 3.013 came to here */
SECStatus (* p_PQG_ParamGenV2)( unsigned int L, unsigned int N,
unsigned int seedBytes,
PQGParams **pParams, PQGVerify **pVfy);
/* Version 3.014 came to here */
};
typedef struct FREEBLVectorStr FREEBLVector;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* pqg.h
*
* header file for pqg functions exported just to freebl
*/
#ifndef _PQG_H_
#define _PQG_H_ 1
/* PQG_GetLength returns the significant bytes in the SECItem object (that is
* the length of the object minus any leading zeros. Any SECItem may be used,
* though this function is usually used for P, Q, or G values */
unsigned int PQG_GetLength(const SECItem *obj);
/* Check to see the PQG parameters patch a NIST defined DSA size,
* returns SECFaillure and sets SEC_ERROR_INVALID_ARGS if it doesn't.
* See blapi.h for legal DSA PQG sizes. */
SECStatus PQG_Check(const PQGParams *params);
/* Return the prefered hash algorithm for the given PQGParameters. */
HASH_HashType PQG_GetHashType(const PQGParams *params);
#endif

View File

@ -145,3 +145,37 @@ HASH_GetRawHashObject(HASH_HashType hashType)
}
return &SECRawHashObjects[hashType];
}
unsigned int
HASH_ResultLen(HASH_HashType type)
{
const SECHashObject *hash_obj = HASH_GetRawHashObject(type);
if (hash_obj == NULL) {
return 0;
}
return hash_obj->length;
}
SECStatus
HASH_HashBuf(HASH_HashType type, unsigned char *dest, unsigned char *src,
PRUint32 src_len)
{
const SECHashObject *hash_obj = HASH_GetRawHashObject(type);
void *hashcx = NULL;
unsigned int dummy;
if (hash_obj == NULL) {
return SECFailure;
}
hashcx = hash_obj->create();
if (hashcx == NULL) {
return SECFailure;
}
hash_obj->begin(hashcx);
hash_obj->update(hashcx,src,src_len);
hash_obj->end(hashcx,dest, &dummy, hash_obj->length);
hash_obj->destroy(hashcx, PR_TRUE);
return SECSuccess;
}

View File

@ -2,7 +2,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* $Id: shvfy.c,v 1.16 2012-04-25 14:49:43 gerv%gerv.net Exp $ */
/* $Id: shvfy.c,v 1.17 2012-06-12 16:39:00 rrelyea%redhat.com Exp $ */
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
@ -15,6 +15,8 @@
#include "seccomon.h"
#include "stdio.h"
#include "prmem.h"
#include "hasht.h"
#include "pqg.h"
/*
* Most modern version of Linux support a speed optimization scheme where an
@ -298,7 +300,8 @@ BLAPI_SHVerifyFile(const char *shName)
char *checkName = NULL;
PRFileDesc *checkFD = NULL;
PRFileDesc *shFD = NULL;
SHA1Context *hashcx = NULL;
void *hashcx = NULL;
SECHashObject *hashObj = NULL;
SECItem signature = { 0, NULL, 0 };
SECItem hash;
int bytesRead, offset;
@ -312,7 +315,7 @@ BLAPI_SHVerifyFile(const char *shName)
PRBool result = PR_FALSE; /* if anything goes wrong,
* the signature does not verify */
unsigned char buf[4096];
unsigned char hashBuf[SHA1_LENGTH];
unsigned char hashBuf[HASH_LENGTH_MAX];
PORT_Memset(&key,0,sizeof(key));
hash.data = hashBuf;
@ -387,6 +390,11 @@ BLAPI_SHVerifyFile(const char *shName)
PR_Close(checkFD);
checkFD = NULL;
hashObj = HASH_GetRawHashObject(PQG_GetHashType(&key.params));
if (hashObj == NULL) {
goto loser;
}
/* open our library file */
#ifdef FREEBL_USE_PRELINK
shFD = bl_OpenUnPrelink(shName,&pid);
@ -402,15 +410,15 @@ BLAPI_SHVerifyFile(const char *shName)
}
/* hash our library file with SHA1 */
hashcx = SHA1_NewContext();
hashcx = hashObj->create();
if (hashcx == NULL) {
goto loser;
}
SHA1_Begin(hashcx);
hashObj->begin(hashcx);
count = 0;
while ((bytesRead = PR_Read(shFD, buf, sizeof(buf))) > 0) {
SHA1_Update(hashcx, buf, bytesRead);
hashObj->update(hashcx, buf, bytesRead);
count += bytesRead;
}
#ifdef FREEBL_USE_PRELINK
@ -420,7 +428,7 @@ BLAPI_SHVerifyFile(const char *shName)
#endif
shFD = NULL;
SHA1_End(hashcx, hash.data, &hash.len, hash.len);
hashObj->end(hashcx, hash.data, &hash.len, hash.len);
/* verify the hash against the check file */
@ -464,7 +472,9 @@ loser:
PR_Close(shFD);
}
if (hashcx != NULL) {
SHA1_DestroyContext(hashcx,PR_TRUE);
if (hashObj) {
hashObj->destroy(hashcx,PR_TRUE);
}
}
if (signature.data != NULL) {
PORT_Free(signature.data);

View File

@ -290,6 +290,8 @@ static const struct mechanismList mechanisms[] = {
CKF_GENERATE_KEY_PAIR}, PR_TRUE},
{CKM_DSA, {DSA_MIN_P_BITS, DSA_MAX_P_BITS,
CKF_SN_VR}, PR_TRUE},
{CKM_DSA_PARAMETER_GEN, {DSA_MIN_P_BITS, DSA_MAX_P_BITS,
CKF_GENERATE}, PR_TRUE},
{CKM_DSA_SHA1, {DSA_MIN_P_BITS, DSA_MAX_P_BITS,
CKF_SN_VR}, PR_TRUE},
/* -------------------- Diffie Hellman Operations --------------------- */
@ -860,7 +862,7 @@ sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object,
break;
case CKK_DSA:
crv = sftk_ConstrainAttribute(object, CKA_SUBPRIME,
DSA_Q_BITS, DSA_Q_BITS, 0);
DSA_MIN_Q_BITS, DSA_MAX_Q_BITS, 0);
if (crv != CKR_OK) {
return crv;
}
@ -869,11 +871,11 @@ sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object,
if (crv != CKR_OK) {
return crv;
}
crv = sftk_ConstrainAttribute(object, CKA_BASE, 1, DSA_MAX_P_BITS, 0);
crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DSA_MAX_P_BITS, 0);
if (crv != CKR_OK) {
return crv;
}
crv = sftk_ConstrainAttribute(object, CKA_VALUE, 1, DSA_MAX_P_BITS, 0);
crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DSA_MAX_P_BITS, 0);
if (crv != CKR_OK) {
return crv;
}
@ -887,11 +889,11 @@ sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object,
if (crv != CKR_OK) {
return crv;
}
crv = sftk_ConstrainAttribute(object, CKA_BASE, 1, DH_MAX_P_BITS, 0);
crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DH_MAX_P_BITS, 0);
if (crv != CKR_OK) {
return crv;
}
crv = sftk_ConstrainAttribute(object, CKA_VALUE, 1, DH_MAX_P_BITS, 0);
crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DH_MAX_P_BITS, 0);
if (crv != CKR_OK) {
return crv;
}
@ -1349,6 +1351,23 @@ sftk_handleDSAParameterObject(SFTKSession *session, SFTKObject *object)
PQGParams params;
PQGVerify vfy, *verify = NULL;
SECStatus result,rv;
/* This bool keeps track of whether or not we need verify parameters.
* If a P, Q and G or supplied, we dont' need verify parameters, as we
* have PQ and G.
* - If G is not supplied, the presumption is that we want to
* verify P and Q only.
* - If counter is supplied, it is presumed we want to verify PQ because
* the counter is only used in verification.
* - If H is supplied, is is presumed we want to verify G because H is
* only used to verify G.
* - Any verification step must have the SEED (counter or H could be
* missing depending on exactly what we want to verify). If SEED is supplied,
* the code just goes ahead and runs verify (other errors are parameter
* errors are detected by the PQG_VerifyParams function). If SEED is not
* supplied, but we determined that we are trying to verify (because needVfy
* is set, go ahead and return CKR_TEMPLATE_INCOMPLETE.
*/
PRBool needVfy = PR_FALSE;
primeAttr = sftk_FindAttribute(object,CKA_PRIME);
if (primeAttr == NULL) goto loser;
@ -1361,26 +1380,43 @@ sftk_handleDSAParameterObject(SFTKSession *session, SFTKObject *object)
params.subPrime.len = subPrimeAttr->attrib.ulValueLen;
baseAttr = sftk_FindAttribute(object,CKA_BASE);
if (baseAttr == NULL) goto loser;
params.base.data = baseAttr->attrib.pValue;
params.base.len = baseAttr->attrib.ulValueLen;
if (baseAttr != NULL) {
params.base.data = baseAttr->attrib.pValue;
params.base.len = baseAttr->attrib.ulValueLen;
} else {
params.base.data = NULL;
params.base.len = 0;
needVfy = PR_TRUE; /* presumably only including PQ so we can verify
* them. */
}
attribute = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_COUNTER);
if (attribute != NULL) {
vfy.counter = *(CK_ULONG *) attribute->attrib.pValue;
sftk_FreeAttribute(attribute);
needVfy = PR_TRUE; /* included a count so we can verify PQ */
} else {
vfy.counter = -1;
}
seedAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_SEED);
if (seedAttr == NULL) goto loser;
hAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_H);
if (hAttr != NULL) {
vfy.h.data = hAttr->attrib.pValue;
vfy.h.len = hAttr->attrib.ulValueLen;
needVfy = PR_TRUE; /* included H so we can verify G */
} else {
vfy.h.data = NULL;
vfy.h.len = 0;
}
seedAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_SEED);
if (seedAttr != NULL) {
vfy.seed.data = seedAttr->attrib.pValue;
vfy.seed.len = seedAttr->attrib.ulValueLen;
hAttr = sftk_FindAttribute(object, CKA_NETSCAPE_PQG_H);
if (hAttr == NULL) goto loser;
vfy.h.data = hAttr->attrib.pValue;
vfy.h.len = hAttr->attrib.ulValueLen;
verify = &vfy;
} else if (needVfy) {
goto loser; /* Verify always needs seed, if we need verify and not seed
* then fail */
}
crv = CKR_FUNCTION_FAILED;

View File

@ -2057,7 +2057,7 @@ finish_rsa:
context->update = (SFTKCipher) nsc_DSA_Sign_Stub;
context->destroy = (privKey == key->objectInfo) ?
(SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey;
context->maxLen = DSA_SIGNATURE_LEN;
context->maxLen = DSA_MAX_SIGNATURE_LEN;
break;
@ -2905,14 +2905,36 @@ nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism,
return CKR_OK;
}
/*
* this is coded for "full" support. These selections will be limitted to
* the official subset by freebl.
*/
static unsigned int
sftk_GetSubPrimeFromPrime(unsigned int primeBits)
{
if (primeBits <= 1024) {
return 160;
} else if (primeBits <= 2048) {
return 224;
} else if (primeBits <= 3072) {
return 256;
} else if (primeBits <= 7680) {
return 384;
} else {
return 512;
}
}
static CK_RV
nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key)
{
SFTKAttribute *attribute;
CK_ULONG counter;
unsigned int seedBits = 0;
unsigned int subprimeBits = 0;
unsigned int primeBits;
unsigned int j;
unsigned int j = 8; /* default to 1024 bits */
CK_RV crv = CKR_OK;
PQGParams *params = NULL;
PQGVerify *vfy = NULL;
@ -2924,9 +2946,11 @@ nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key)
}
primeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue;
sftk_FreeAttribute(attribute);
j = PQG_PBITS_TO_INDEX(primeBits);
if (j == (unsigned int)-1) {
return CKR_ATTRIBUTE_VALUE_INVALID;
if (primeBits < 1024) {
j = PQG_PBITS_TO_INDEX(primeBits);
if (j == (unsigned int)-1) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
attribute = sftk_FindAttribute(key, CKA_NETSCAPE_PQG_SEED_BITS);
@ -2935,14 +2959,34 @@ nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key)
sftk_FreeAttribute(attribute);
}
attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS);
if (attribute != NULL) {
subprimeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue;
sftk_FreeAttribute(attribute);
}
sftk_DeleteAttributeType(key,CKA_PRIME_BITS);
sftk_DeleteAttributeType(key,CKA_SUBPRIME_BITS);
sftk_DeleteAttributeType(key,CKA_NETSCAPE_PQG_SEED_BITS);
if (seedBits == 0) {
rv = PQG_ParamGen(j, &params, &vfy);
/* use the old PQG interface if we have old input data */
if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) {
if (seedBits == 0) {
rv = PQG_ParamGen(j, &params, &vfy);
} else {
rv = PQG_ParamGenSeedLen(j,seedBits/8, &params, &vfy);
}
} else {
rv = PQG_ParamGenSeedLen(j,seedBits/8, &params, &vfy);
if (subprimeBits == 0) {
subprimeBits = sftk_GetSubPrimeFromPrime(primeBits);
}
if (seedBits == 0) {
seedBits = primeBits;
}
rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits/8, &params, &vfy);
}
if (rv != SECSuccess) {
if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
@ -3459,6 +3503,7 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
CK_MECHANISM mech = {0, NULL, 0};
CK_ULONG modulusLen;
CK_ULONG subPrimeLen;
PRBool isEncryptable = PR_FALSE;
PRBool canSignVerify = PR_FALSE;
PRBool isDerivable = PR_FALSE;
@ -3472,10 +3517,12 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
unsigned char *text_compared;
CK_ULONG bytes_encrypted;
CK_ULONG bytes_compared;
CK_ULONG pairwise_digest_length = PAIRWISE_DIGEST_LENGTH;
/* Variables used for Signature/Verification functions. */
/* always uses SHA-1 digest */
unsigned char *known_digest = (unsigned char *)"Mozilla Rules World!";
/* Must be at least 256 bits for DSA2 digest */
unsigned char *known_digest = (unsigned char *)
"Mozilla Rules the World through NSS!";
unsigned char *signature;
CK_ULONG signature_length;
@ -3492,6 +3539,19 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
modulusLen--;
}
sftk_FreeAttribute(attribute);
} else if (keyType == CKK_DSA) {
SFTKAttribute *attribute;
/* Get subprime length of private key. */
attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME);
if (attribute == NULL) {
return CKR_DEVICE_ERROR;
}
subPrimeLen = attribute->attrib.ulValueLen;
if (subPrimeLen > 1 && *(unsigned char *)attribute->attrib.pValue == 0) {
subPrimeLen--;
}
sftk_FreeAttribute(attribute);
}
/**************************************************/
@ -3617,7 +3677,8 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
mech.mechanism = CKM_RSA_PKCS;
break;
case CKK_DSA:
signature_length = DSA_SIGNATURE_LEN;
signature_length = DSA_MAX_SIGNATURE_LEN;
pairwise_digest_length = subPrimeLen;
mech.mechanism = CKM_DSA;
break;
#ifdef NSS_ENABLE_ECC
@ -3645,7 +3706,7 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
crv = NSC_Sign(hSession,
known_digest,
PAIRWISE_DIGEST_LENGTH,
pairwise_digest_length,
signature,
&signature_length);
if (crv != CKR_OK) {
@ -3662,7 +3723,7 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession,
crv = NSC_Verify(hSession,
known_digest,
PAIRWISE_DIGEST_LENGTH,
pairwise_digest_length,
signature,
signature_length);
@ -3945,9 +4006,12 @@ kpg_done:
break;
}
/*
* these are checked by DSA_NewKey
*/
bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data,
pqgParam.subPrime.len);
if (bitSize != DSA_Q_BITS) {
if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) {
crv = CKR_TEMPLATE_INCOMPLETE;
PORT_Free(pqgParam.prime.data);
PORT_Free(pqgParam.subPrime.data);
@ -3963,7 +4027,7 @@ kpg_done:
break;
}
bitSize = sftk_GetLengthInBits(pqgParam.base.data,pqgParam.base.len);
if ((bitSize < 1) || (bitSize > DSA_MAX_P_BITS)) {
if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) {
crv = CKR_TEMPLATE_INCOMPLETE;
PORT_Free(pqgParam.prime.data);
PORT_Free(pqgParam.subPrime.data);

View File

@ -5,7 +5,7 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* $Id: ssl3con.c,v 1.183 2012-06-11 02:38:30 emaldona%redhat.com Exp $ */
/* $Id: ssl3con.c,v 1.184 2012-06-12 16:39:03 rrelyea%redhat.com Exp $ */
/* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */
@ -901,7 +901,7 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert,
hashItem.data = hash->sha;
hashItem.len = sizeof(hash->sha);
/* Allow DER encoded DSA signatures in SSL 3.0 */
if (isTLS || buf->len != DSA_SIGNATURE_LEN) {
if (isTLS || buf->len != SECKEY_SignatureLen(key)) {
signature = DSAU_DecodeDerSig(buf);
if (!signature) {
PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);