Bug 320583 Support for SHA256/384/512 with ECC signing

This commit is contained in:
rrelyea%redhat.com 2006-02-08 06:14:31 +00:00
parent fa8f6f3926
commit 2c3bfd1312
21 changed files with 720 additions and 499 deletions

View File

@ -2153,17 +2153,11 @@ SignCert(CERTCertificate *cert,
arena = cert->arena;
switch(caPrivateKey->keyType) {
case rsaKey:
algID = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
break;
case dsaKey:
algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
break;
default:
algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType,
SEC_OID_UNKNOWN);
if (algID == SEC_OID_UNKNOWN) {
error_out("ERROR: Unknown key type for issuer.");
goto done;
break;
}
rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0);

View File

@ -146,48 +146,6 @@ void checkName(CERTName *n, char *fieldName, int verbose)
}
/*
* Private version of verification that checks for agreement between
* signature algorithm oid (at the SignedData level) and oid in DigestInfo.
*
*/
/* Returns the tag for the hash algorithm in the given signature algorithm */
static
int hashAlg(int sigAlgTag) {
int rv;
switch(sigAlgTag) {
case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
rv = SEC_OID_MD2;
break;
case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
rv = SEC_OID_MD5;
break;
case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
rv = SEC_OID_SHA1;
break;
default:
rv = -1;
}
return rv;
}
struct VFYContextStr {
int alg;
unsigned char digest[32];
void *hasher;
void (*begin)(void *);
void (*update)(void *, unsigned char*, unsigned);
SECStatus (*end)(void *, unsigned char*, unsigned int*, unsigned);
void (*destroy)(void *, PRBool);
};
static
SECStatus
OurVerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
@ -200,7 +158,7 @@ OurVerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
int hashAlgTag;
int showDigestOid=0;
cx = VFY_CreateContext(key, sig, SECOID_GetAlgorithmTag(sigAlgorithm),
cx = VFY_CreateContextWithAlgorithmID(key, sig, sigAlgorithm, &hashAlgTag,
NULL);
if (cx == NULL)
return SECFailure;
@ -210,18 +168,9 @@ OurVerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
return SECFailure;
sigAlgTag = sigAlgOid->offset;
hashAlgTag = hashAlg(sigAlgTag);
if (hashAlgTag == -1) {
printf("PROBLEM: Unsupported Digest Algorithm in DigestInfo");
showDigestOid = 1;
} else if (hashAlgTag != cx->alg) {
printf("PROBLEM: Digest OID in DigestInfo is incompatible "
"with Signature Algorithm\n");
showDigestOid = 1;
}
if (showDigestOid) {
oiddata = SECOID_FindOIDByTag(cx->alg);
oiddata = SECOID_FindOIDByTag(hashAlgTag);
if ( oiddata ) {
printf("PROBLEM: (cont) Digest OID is %s\n", oiddata->desc);
} else {

View File

@ -414,14 +414,9 @@ createNewCert(CERTCertificate**issuedCert,CERTCertificateRequest *oldCertReq,
if (issuerPrivKey == NULL) {
rv = COULD_NOT_FIND_ISSUER_PRIVATE_KEY;
}
switch(issuerPrivKey->keyType) {
case rsaKey:
signTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
break;
case dsaKey:
signTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
break;
default:
signTag = SEC_GetSignatureAlgorithmOidTag(issuerPrivatekey->keytype,
SEC_OID_UNKNOWN);
if (signTag == SEC_OID_UNKNOWN) {
rv = UNSUPPORTED_SIGN_OPERATION_FOR_ISSUER;
goto loser;
}
@ -644,8 +639,8 @@ verifySignature(CGIVarTable *varTable, CRMFCertReqMsg *currReq,
rv = ERROR_ENCODING_CERT_REQ_FOR_POP;
goto loser;
}
srv = VFY_VerifyData(reqDER->data, reqDER->len, pubKey, signature,
SECOID_FindOIDTag(&algID->algorithm), varTable);
srv = VFY_VerifyDataWithAlgorithmID(reqDER->data, reqDER->len, pubKey,
signature, &algID->algorithm, NULL, varTable);
if (srv != SECSuccess) {
rv = ERROR_VERIFYING_SIGNATURE_POP;
goto loser;

View File

@ -455,18 +455,10 @@ sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk)
void *dummy;
SECOidTag alg = SEC_OID_UNKNOWN;
switch (privk->keyType) {
case rsaKey:
alg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
break;
case dsaKey:
alg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
break;
default:
alg = SEC_GetSignatureAlgorithmOidTag(privk->keyType, SEC_OID_UNKNOWN);
if (alg == SEC_OID_UNKNOWN) {
FatalError("Unknown key type");
}
PORT_Assert(alg != SEC_OID_UNKNOWN);
rv = SECOID_SetAlgorithmID (cert->arena, &cert->signature, alg, 0);

View File

@ -101,7 +101,6 @@ CERT_VerifySignedDataWithPublicKey(CERTSignedData *sd,
void *wincx)
{
SECStatus rv;
SECOidTag algid;
SECItem sig;
if ( !pubKey || !sd ) {
@ -114,9 +113,8 @@ CERT_VerifySignedDataWithPublicKey(CERTSignedData *sd,
/* convert sig->len from bit counts to byte count. */
DER_ConvertBitString(&sig);
algid = SECOID_GetAlgorithmTag(&sd->signatureAlgorithm);
rv = VFY_VerifyData(sd->data.data, sd->data.len, pubKey, &sig,
algid, wincx);
rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey,
&sig, &sd->signatureAlgorithm, NULL, wincx);
return rv ? SECFailure : SECSuccess;
}

View File

@ -38,7 +38,7 @@
* Implementation of OCSP services, for both client and server.
* (XXX, really, mostly just for client right now, but intended to do both.)
*
* $Id: ocsp.c,v 1.22 2006/02/03 18:13:04 kaie%kuix.de Exp $
* $Id: ocsp.c,v 1.23 2006/02/08 06:13:57 rrelyea%redhat.com Exp $
*/
#include "prerror.h"
@ -2678,10 +2678,9 @@ ocsp_CheckSignature(ocspSignature *signature, void *tbs,
*/
DER_ConvertBitString(&rawSignature);
rv = VFY_VerifyData(encodedTBS->data, encodedTBS->len, signerKey,
&rawSignature,
SECOID_GetAlgorithmTag(&signature->signatureAlgorithm),
pwArg);
rv = VFY_VerifyDataWithAlgorithmID(encodedTBS->data, encodedTBS->len,
signerKey, &rawSignature,
&signature->signatureAlgorithm, NULL, pwArg);
finish:
if (signature->wasChecked)

View File

@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: cryptohi.h,v 1.9 2005/03/08 07:08:48 julien.pierre.bugs%sun.com Exp $ */
/* $Id: cryptohi.h,v 1.10 2006/02/08 06:14:07 rrelyea%redhat.com Exp $ */
#ifndef _CRYPTOHI_H_
#define _CRYPTOHI_H_
@ -65,7 +65,7 @@ SEC_BEGIN_PROTOS
* functions convert between formats.
*/
extern SECStatus DSAU_EncodeDerSig(SECItem *dest, SECItem *src);
extern SECItem *DSAU_DecodeDerSig(SECItem *item);
extern SECItem *DSAU_DecodeDerSig(const SECItem *item);
/*
* Unlike DSA, raw ECDSA signatures do not have a fixed length.
@ -81,7 +81,7 @@ extern SECItem *DSAU_DecodeDerSig(SECItem *item);
*/
extern SECStatus DSAU_EncodeDerSigWithLen(SECItem *dest, SECItem *src,
unsigned int len);
extern SECItem *DSAU_DecodeDerSigToLen(SECItem *item, unsigned int len);
extern SECItem *DSAU_DecodeDerSigToLen(const SECItem *item, unsigned int len);
/****************************************/
/*
@ -186,18 +186,60 @@ extern SECOidTag SEC_GetSignatureAlgorithmOidTag(KeyType keyType,
** Signature verification operations
*/
/*
** Create a signature verification context. This version is deprecated,
** This function is deprecated. Use VFY_CreateContextDirect or
** VFY_CreateContextWithAlgorithmID instead.
** "key" the public key to verify with
** "sig" the encrypted signature data if sig is NULL then
** VFY_EndWithSignature must be called with the correct signature at
** the end of the processing.
** "sigAlg" specifies the signing algorithm to use (including the
** hash algorthim). This must match the key type.
** "wincx" void pointer to the window context
*/
extern VFYContext *VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig,
SECOidTag sigAlg, void *wincx);
/*
** Create a signature verification context.
** "key" the public key to verify with
** "sig" the encrypted signature data if sig is NULL then
** VFY_EndWithSignature must be called with the correct signature at
** the end of the processing.
** "algid" specifies the signing algorithm to use. This must match
** the key type.
** "pubkAlg" specifies the cryptographic signing algorithm to use (the
** raw algorithm without any hash specified. This must match the key
** type.
** "hashAlg" specifies the hashing algorithm used. If the key is an
** RSA key, and sig is not NULL, then hashAlg can be SEC_OID_UNKNOWN.
** the hash is selected from data in the sig.
** "hash" optional pointer to return the actual hash algorithm used.
** in practice this should always match the passed in hashAlg (the
** exception is the case where hashAlg is SEC_OID_UNKNOWN above).
** If this value is NULL no, hash oid is returned.
** "wincx" void pointer to the window context
*/
extern VFYContext *VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig,
SECOidTag algid, void *wincx);
extern VFYContext *VFY_CreateContextDirect(const SECKEYPublicKey *key,
const SECItem *sig,
SECOidTag pubkAlg,
SECOidTag hashAlg,
SECOidTag *hash, void *wincx);
/*
** Create a signature verification context from a algorithm ID.
** "key" the public key to verify with
** "sig" the encrypted signature data if sig is NULL then
** VFY_EndWithSignature must be called with the correct signature at
** the end of the processing.
** "algid" specifies the signing algorithm and parameters to use.
** This must match the key type.
** "hash" optional pointer to return the oid of the actual hash used in
** the signature. If this value is NULL no, hash oid is returned.
** "wincx" void pointer to the window context
*/
extern VFYContext *VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key,
const SECItem *sig,
const SECAlgorithmID *algid,
SECOidTag *hash,
void *wincx);
/*
** Destroy a verification-context object.
@ -216,7 +258,7 @@ extern SECStatus VFY_Begin(VFYContext *cx);
** "input" the input data
** "inputLen" the amount of input data
*/
extern SECStatus VFY_Update(VFYContext *cx, unsigned char *input,
extern SECStatus VFY_Update(VFYContext *cx, const unsigned char *input,
unsigned int inputLen);
/*
@ -246,14 +288,93 @@ extern SECStatus VFY_EndWithSignature(VFYContext *cx, SECItem *sig);
** Verify the signature on a block of data for which we already have
** the digest. The signature data is an RSA private key encrypted
** block of data formatted according to PKCS#1.
** This function is deprecated. Use VFY_VerifyDigestDirect or
** VFY_VerifyDigestWithAlgorithmID instead.
** "dig" the digest
** "key" the public key to check the signature with
** "sig" the encrypted signature data
** "algid" specifies the signing algorithm to use. This must match
** "sigAlg" specifies the signing algorithm to use. This must match
** the key type.
** "wincx" void pointer to the window context
**/
extern SECStatus VFY_VerifyDigest(SECItem *dig, SECKEYPublicKey *key,
SECItem *sig, SECOidTag algid, void *wincx);
SECItem *sig, SECOidTag sigAlg, void *wincx);
/*
** Verify the signature on a block of data for which we already have
** the digest. The signature data is an RSA private key encrypted
** block of data formatted according to PKCS#1.
** "dig" the digest
** "key" the public key to check the signature with
** "sig" the encrypted signature data
** "pubkAlg" specifies the cryptographic signing algorithm to use (the
** raw algorithm without any hash specified. This must match the key
** type.
** "hashAlg" specifies the hashing algorithm used.
** "wincx" void pointer to the window context
**/
extern SECStatus VFY_VerifyDigestDirect(const SECItem *dig,
const SECKEYPublicKey *key,
const SECItem *sig, SECOidTag pubkAlg,
SECOidTag hashAlg, void *wincx);
/*
** Verify the signature on a block of data for which we already have
** the digest. The signature data is an RSA private key encrypted
** block of data formatted according to PKCS#1.
** "key" the public key to verify with
** "sig" the encrypted signature data if sig is NULL then
** VFY_EndWithSignature must be called with the correct signature at
** the end of the processing.
** "algid" specifies the signing algorithm and parameters to use.
** This must match the key type.
** "hash" oid of the actual hash used to create digest. If this value is
** not set to SEC_OID_UNKNOWN, it must match the hash of the signature.
** "wincx" void pointer to the window context
*/
extern SECStatus VFY_VerifyDigestWithAlgorithmID(const SECItem *dig,
const SECKEYPublicKey *key, const SECItem *sig,
const SECAlgorithmID *algid, SECOidTag hash,
void *wincx);
/*
** Verify the signature on a block of data. The signature data is an RSA
** private key encrypted block of data formatted according to PKCS#1.
** This function is deprecated. Use VFY_VerifyDataDirect or
** VFY_VerifyDataWithAlgorithmID instead.
** "buf" the input data
** "len" the length of the input data
** "key" the public key to check the signature with
** "sig" the encrypted signature data
** "sigAlg" specifies the signing algorithm to use. This must match
** the key type.
** "wincx" void pointer to the window context
*/
extern SECStatus VFY_VerifyData(unsigned char *buf, int len,
SECKEYPublicKey *key, SECItem *sig,
SECOidTag sigAlg, void *wincx);
/*
** Verify the signature on a block of data. The signature data is an RSA
** private key encrypted block of data formatted according to PKCS#1.
** "buf" the input data
** "len" the length of the input data
** "key" the public key to check the signature with
** "sig" the encrypted signature data
** "pubkAlg" specifies the cryptographic signing algorithm to use (the
** raw algorithm without any hash specified. This must match the key
** type.
** "hashAlg" specifies the hashing algorithm used. If the key is an
** RSA key, and sig is not NULL, then hashAlg can be SEC_OID_UNKNOWN.
** the hash is selected from data in the sig.
** "hash" optional pointer to return the actual hash algorithm used.
** in practice this should always match the passed in hashAlg (the
** exception is the case where hashAlg is SEC_OID_UNKNOWN above).
** If this value is NULL no, hash oid is returned.
** "wincx" void pointer to the window context
*/
extern SECStatus VFY_VerifyDataDirect(const unsigned char *buf, int len,
const SECKEYPublicKey *key,
const SECItem *sig,
SECOidTag pubkAlg, SECOidTag hashAlg,
SECOidTag *hash, void *wincx);
/*
** Verify the signature on a block of data. The signature data is an RSA
@ -262,12 +383,17 @@ extern SECStatus VFY_VerifyDigest(SECItem *dig, SECKEYPublicKey *key,
** "len" the length of the input data
** "key" the public key to check the signature with
** "sig" the encrypted signature data
** "algid" specifies the signing algorithm to use. This must match
** the key type.
** "algid" specifies the signing algorithm and parameters to use.
** This must match the key type.
** "hash" optional pointer to return the oid of the actual hash used in
** the signature. If this value is NULL no, hash oid is returned.
** "wincx" void pointer to the window context
*/
extern SECStatus VFY_VerifyData(unsigned char *buf, int len,
SECKEYPublicKey *key, SECItem *sig,
SECOidTag algid, void *wincx);
extern SECStatus VFY_VerifyDataWithAlgorithmID(const unsigned char *buf,
int len, const SECKEYPublicKey *key,
const SECItem *sig,
const SECAlgorithmID *algid, SECOidTag *hash,
void *wincx);
SEC_END_PROTOS

View File

@ -192,7 +192,7 @@ common_EncodeDerSig(SECItem *dest, SECItem *src)
** For ECDSA, len depends on the key size used to create the signature.
*/
static SECItem *
common_DecodeDerSig(SECItem *item, unsigned int len)
common_DecodeDerSig(const SECItem *item, unsigned int len)
{
SECItem * result = NULL;
SECStatus status;
@ -283,7 +283,7 @@ DSAU_EncodeDerSigWithLen(SECItem *dest, SECItem *src, unsigned int len)
** followed by 20 bytes of s.
*/
SECItem *
DSAU_DecodeDerSig(SECItem *item)
DSAU_DecodeDerSig(const SECItem *item)
{
return common_DecodeDerSig(item, DSA_SUBPRIME_LEN);
}
@ -294,7 +294,7 @@ DSAU_DecodeDerSig(SECItem *item)
** r followed by s (both padded to take up exactly len/2 bytes).
*/
SECItem *
DSAU_DecodeDerSigToLen(SECItem *item, unsigned int len)
DSAU_DecodeDerSigToLen(const SECItem *item, unsigned int len)
{
return common_DecodeDerSig(item, len/2);
}

View File

@ -35,7 +35,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: keyhi.h,v 1.13 2005/09/02 01:24:42 wtchang%redhat.com Exp $ */
/* $Id: keyhi.h,v 1.14 2006/02/08 06:14:07 rrelyea%redhat.com Exp $ */
#ifndef _KEYHI_H_
#define _KEYHI_H_
@ -82,22 +82,22 @@ SECKEY_KEAParamCompare(CERTCertificate *cert1,CERTCertificate *cert2);
/*
** Return the strength of the public key in bytes
*/
extern unsigned SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk);
extern unsigned SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk);
/*
** Return the strength of the public key in bits
*/
extern unsigned SECKEY_PublicKeyStrengthInBits(SECKEYPublicKey *pubk);
extern unsigned SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk);
/*
** Make a copy of the private key "privKey"
*/
extern SECKEYPrivateKey *SECKEY_CopyPrivateKey(SECKEYPrivateKey *privKey);
extern SECKEYPrivateKey *SECKEY_CopyPrivateKey(const SECKEYPrivateKey *privKey);
/*
** Make a copy of the public key "pubKey"
*/
extern SECKEYPublicKey *SECKEY_CopyPublicKey(SECKEYPublicKey *pubKey);
extern SECKEYPublicKey *SECKEY_CopyPublicKey(const SECKEYPublicKey *pubKey);
/*
** Convert a private key "privateKey" into a public key

View File

@ -0,0 +1,57 @@
/* ***** 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
* Red Hat, Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bob Relyea, Red Hat
*
* 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 ***** */
/* $Id: keyi.h,v 1.1 2006/02/08 06:14:07 rrelyea%redhat.com Exp $ */
#ifndef _KEYI_H_
#define _KEYI_H_
SEC_BEGIN_PROTOS
/* NSS private functions */
/* map an oid to a keytype... actually this function and it's converse
* are good candidates for public functions.. */
KeyType seckey_GetKeyType(SECOidTag pubKeyOid);
/* extract the 'encryption' (could be signing) and hash oids from and
* algorithm, key and parameters (parameters is the parameters field
* of a algorithm ID structure (SECAlgorithmID)*/
SECStatus sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg);
SEC_END_PROTOS
#endif /* _KEYHI_H_ */

View File

@ -48,6 +48,7 @@
#include "secdig.h"
#include "prtime.h"
#include "ec.h"
#include "keyi.h"
const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE,
@ -939,13 +940,11 @@ done:
}
/* Function used to determine what kind of cert we are dealing with. */
/* Function used to make an oid tag to a key type */
KeyType
CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki) {
int tag;
seckey_GetKeyType (SECOidTag tag) {
KeyType keyType;
tag = SECOID_GetAlgorithmTag(&spki->algorithm);
switch (tag) {
case SEC_OID_X500_RSA_ENCRYPTION:
case SEC_OID_PKCS1_RSA_ENCRYPTION:
@ -976,6 +975,13 @@ CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki) {
return keyType;
}
/* Function used to determine what kind of cert we are dealing with. */
KeyType
CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki)
{
return seckey_GetKeyType(SECOID_GetAlgorithmTag(&spki->algorithm));
}
static SECKEYPublicKey *
seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
{
@ -1290,9 +1296,10 @@ SECKEY_ECParamsToKeySize(const SECItem *encodedParams)
/* returns key strength in bytes (not bits) */
unsigned
SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk)
SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
{
unsigned char b0;
unsigned size;
/* interpret modulus length as key strength... in
* fortezza that's the public key length */
@ -1313,11 +1320,8 @@ SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk)
return PR_MAX(pubk->u.fortezza.KEAKey.len, pubk->u.fortezza.DSSKey.len);
case ecKey:
/* Get the key size in bits and adjust */
if (pubk->u.ec.size == 0) {
pubk->u.ec.size =
SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
}
return (pubk->u.ec.size + 7)/8;
size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
return (size + 7)/8;
default:
break;
}
@ -1326,8 +1330,9 @@ SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk)
/* returns key strength in bits */
unsigned
SECKEY_PublicKeyStrengthInBits(SECKEYPublicKey *pubk)
SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk)
{
unsigned size;
switch (pubk->keyType) {
case rsaKey:
case dsaKey:
@ -1335,11 +1340,8 @@ SECKEY_PublicKeyStrengthInBits(SECKEYPublicKey *pubk)
case fortezzaKey:
return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */
case ecKey:
if (pubk->u.ec.size == 0) {
pubk->u.ec.size =
SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
}
return pubk->u.ec.size;
size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
return size;
default:
break;
}
@ -1347,7 +1349,7 @@ SECKEY_PublicKeyStrengthInBits(SECKEYPublicKey *pubk)
}
SECKEYPrivateKey *
SECKEY_CopyPrivateKey(SECKEYPrivateKey *privk)
SECKEY_CopyPrivateKey(const SECKEYPrivateKey *privk)
{
SECKEYPrivateKey *copyk;
PRArenaPool *arena;
@ -1393,7 +1395,7 @@ fail:
}
SECKEYPublicKey *
SECKEY_CopyPublicKey(SECKEYPublicKey *pubk)
SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk)
{
SECKEYPublicKey *copyk;
PRArenaPool *arena;
@ -1944,8 +1946,8 @@ SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge,
/* check the signature */
sig = sd.signature;
DER_ConvertBitString(&sig);
rv = VFY_VerifyData(sd.data.data, sd.data.len, pubKey, &sig,
SECOID_GetAlgorithmTag(&(sd.signatureAlgorithm)), wincx);
rv = VFY_VerifyDataWithAlgorithmID(sd.data.data, sd.data.len, pubKey, &sig,
&(sd.signatureAlgorithm), NULL, wincx);
if ( rv != SECSuccess ) {
goto loser;
}

View File

@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: secsign.c,v 1.14 2005/09/02 01:24:44 wtchang%redhat.com Exp $ */
/* $Id: secsign.c,v 1.15 2006/02/08 06:14:07 rrelyea%redhat.com Exp $ */
#include <stdio.h>
#include "cryptohi.h"
@ -48,6 +48,7 @@
#include "secdig.h"
#include "pk11func.h"
#include "secerr.h"
#include "keyi.h"
struct SGNContextStr {
SECOidTag signalg;
@ -63,6 +64,7 @@ SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key)
SGNContext *cx;
SECOidTag hashalg, signalg;
KeyType keyType;
SECStatus rv;
/* OK, map a PKCS #7 hash and encrypt algorithm into
* a standard hashing algorithm. Why did we pass in the whole
@ -71,68 +73,13 @@ SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key)
* hashing on card. It may not support CKM_RSA_PKCS sign algorithm,
* it may just support CKM_RSA_PKCS_WITH_SHA1 and/or CKM_RSA_PKCS_WITH_MD5.
*/
switch (alg) {
/* We probably shouldn't be generating MD2 signatures either */
case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
hashalg = SEC_OID_MD2;
signalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
keyType = rsaKey;
break;
case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
hashalg = SEC_OID_MD5;
signalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
keyType = rsaKey;
break;
case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
hashalg = SEC_OID_SHA1;
signalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
keyType = rsaKey;
break;
case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
hashalg = SEC_OID_SHA256;
signalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
keyType = rsaKey;
break;
case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
hashalg = SEC_OID_SHA384;
signalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
keyType = rsaKey;
break;
case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
hashalg = SEC_OID_SHA512;
signalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
keyType = rsaKey;
break;
/* what about normal DSA? */
case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
hashalg = SEC_OID_SHA1;
signalg = SEC_OID_ANSIX9_DSA_SIGNATURE;
keyType = dsaKey;
break;
case SEC_OID_MISSI_DSS:
case SEC_OID_MISSI_KEA_DSS:
case SEC_OID_MISSI_KEA_DSS_OLD:
case SEC_OID_MISSI_DSS_OLD:
hashalg = SEC_OID_SHA1;
signalg = SEC_OID_MISSI_DSS; /* XXX Is there a better algid? */
keyType = fortezzaKey;
break;
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST:
hashalg = SEC_OID_SHA1;
signalg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
keyType = ecKey;
break;
/* we don't implement MD4 hashes.
* we *CERTAINLY* don't want to sign one! */
case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
default:
/* we have a private key, not a public key, so don't pass it in */
rv = sec_DecodeSigAlg(NULL, alg, NULL, &signalg, &hashalg);
if (rv != SECSuccess) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return 0;
}
keyType = seckey_GetKeyType(signalg);
/* verify our key type */
if (key->keyType != keyType &&
@ -503,9 +450,19 @@ SEC_GetSignatureAlgorithmOidTag(KeyType keyType, SECOidTag hashAlgTag)
}
break;
case ecKey:
/* XXX For now only ECDSA with SHA1 is supported */
sigTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
switch (hashAlgTag) {
case SEC_OID_UNKNOWN: /* default for ECDSA if not specified */
case SEC_OID_SHA1:
sigTag = SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE; break;
case SEC_OID_SHA256:
sigTag = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE; break;
case SEC_OID_SHA384:
sigTag = SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE; break;
case SEC_OID_SHA512:
sigTag = SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE; break;
default:
break;
}
default:
break;
}

View File

@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: secvfy.c,v 1.16 2005/08/24 23:05:39 wtchang%redhat.com Exp $ */
/* $Id: secvfy.c,v 1.17 2006/02/08 06:14:07 rrelyea%redhat.com Exp $ */
#include <stdio.h>
#include "cryptohi.h"
@ -48,6 +48,7 @@
#include "pk11func.h"
#include "secdig.h"
#include "secerr.h"
#include "keyi.h"
/*
** Decrypt signature block using public key
@ -57,7 +58,7 @@
*/
static SECStatus
DecryptSigBlock(SECOidTag *tagp, unsigned char *digest, unsigned int len,
SECKEYPublicKey *key, SECItem *sig, char *wincx)
SECKEYPublicKey *key, const SECItem *sig, char *wincx)
{
SGNDigestInfo *di = NULL;
unsigned char *buf = NULL;
@ -73,7 +74,7 @@ DecryptSigBlock(SECOidTag *tagp, unsigned char *digest, unsigned int len,
if (!buf) goto loser;
/* decrypt the block */
rv = PK11_VerifyRecover(key, sig, &it, wincx);
rv = PK11_VerifyRecover(key, (SECItem *)sig, &it, wincx);
if (rv != SECSuccess) goto loser;
di = SGN_DecodeDigestInfo(&it);
@ -106,11 +107,10 @@ DecryptSigBlock(SECOidTag *tagp, unsigned char *digest, unsigned int len,
return rv;
}
typedef enum { VFY_RSA, VFY_DSA, VFY_ECDSA } VerifyType;
struct VFYContextStr {
SECOidTag alg; /* the hash algorithm */
VerifyType type;
KeyType type;
SECKEYPublicKey *key;
/*
* This buffer holds either the digest or the full signature
@ -134,7 +134,7 @@ struct VFYContextStr {
void * wincx;
void *hashcx;
const SECHashObject *hashobj;
SECOidTag sigAlg; /* the (composite) signature algorithm */
SECOidTag encAlg; /* enc alg */
PRBool hasSignature; /* true if the signature was provided in the
* VFY_CreateContext call. If false, the
* signature must be provided with a
@ -147,65 +147,73 @@ struct VFYContextStr {
* to by dsig and has enough room for len bytes.
*/
static SECStatus
decodeECorDSASignature(SECOidTag algid, SECItem *sig, unsigned char *dsig,
decodeECorDSASignature(SECOidTag algid, const SECItem *sig, unsigned char *dsig,
unsigned int len) {
SECItem *dsasig = NULL; /* also used for ECDSA */
SECStatus rv=SECSuccess;
switch (algid) {
case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_ANSIX9_DSA_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST:
if (algid == SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST) {
if ((algid != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
(algid != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) {
if (sig->len != len) {
PORT_SetError(SEC_ERROR_BAD_DER);
return SECFailure;
}
PORT_Memcpy(dsig, sig->data, sig->len);
return SECSuccess;
}
if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
if (len > MAX_ECKEY_LEN * 2) {
PORT_SetError(SEC_ERROR_BAD_DER);
return SECFailure;
}
dsasig = DSAU_DecodeDerSigToLen(sig, len);
} else {
dsasig = DSAU_DecodeDerSig(sig);
}
dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len);
if ((dsasig == NULL) || (dsasig->len != len)) {
rv = SECFailure;
} else {
PORT_Memcpy(dsig, dsasig->data, dsasig->len);
}
break;
default:
if (sig->len != len) {
rv = SECFailure;
} else {
PORT_Memcpy(dsig, sig->data, sig->len);
}
break;
}
if (dsasig != NULL) SECITEM_FreeItem(dsasig, PR_TRUE);
if (rv == SECFailure) PORT_SetError(SEC_ERROR_BAD_DER);
return rv;
}
const SEC_ASN1Template hashParameterTemplate[] =
{
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECItem) },
{ SEC_ASN1_OBJECT_ID, 0 },
{ SEC_ASN1_SKIP_REST },
{ 0, }
};
/*
* Pulls the hash algorithm, signing algorithm, and key type out of a
* composite algorithm.
*
* alg: the composite algorithm to dissect.
* hashalg: address of a SECOidTag which will be set with the hash algorithm.
* signalg: address of a SECOidTag which will be set with the signing alg.
* (not implemented)
* keyType: address of a KeyType which will be set with the key type.
* (not implemented)
* encalg: address of a SECOidTag which will be set with the signing alg.
*
* Returns: SECSuccess if the algorithm was acceptable, SECFailure if the
* algorithm was not found or was not a signing algorithm.
*/
static SECStatus
decodeSigAlg(SECOidTag alg, SECOidTag *hashalg)
SECStatus
sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
const SECItem *param, SECOidTag *encalg, SECOidTag *hashalg)
{
PR_ASSERT(hashalg!=NULL);
int len;
PRArenaPool *arena;
SECStatus rv;
SECItem oid;
switch (alg) {
PR_ASSERT(hashalg!=NULL);
PR_ASSERT(encalg!=NULL);
switch (sigAlg) {
/* We probably shouldn't be generating MD2 signatures either */
case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
*hashalg = SEC_OID_MD2;
@ -217,13 +225,19 @@ decodeSigAlg(SECOidTag alg, SECOidTag *hashalg)
case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
*hashalg = SEC_OID_SHA1;
break;
case SEC_OID_PKCS1_RSA_ENCRYPTION:
*hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */
break;
case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
*hashalg = SEC_OID_SHA256;
break;
case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
*hashalg = SEC_OID_SHA384;
break;
case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
*hashalg = SEC_OID_SHA512;
break;
@ -231,7 +245,7 @@ decodeSigAlg(SECOidTag alg, SECOidTag *hashalg)
/* what about normal DSA? */
case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
*hashalg = SEC_OID_SHA1;
break;
case SEC_OID_MISSI_DSS:
@ -240,85 +254,217 @@ decodeSigAlg(SECOidTag alg, SECOidTag *hashalg)
case SEC_OID_MISSI_DSS_OLD:
*hashalg = SEC_OID_SHA1;
break;
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
/* This is an EC algorithm. Recommended means the largest
* hash algorithm that is not reduced by the keysize of
* the EC algorithm. Note that key strength is in bytes and
* algorithms are specified in bits. Never use an algorithm
* weaker than sha1. */
len = SECKEY_PublicKeyStrength(key);
if (len < 28) { /* 28 bytes == 224 bits */
*hashalg = SEC_OID_SHA1;
} else if (len < 32) { /* 32 bytes == 256 bits */
/* SHA 224 not supported in NSS */
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
} else if (len < 48) { /* 48 bytes == 384 bits */
*hashalg = SEC_OID_SHA256;
} else if (len < 64) { /* 48 bytes == 512 bits */
*hashalg = SEC_OID_SHA384;
} else {
/* use the largest in this case */
*hashalg = SEC_OID_SHA512;
}
break;
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
if (param == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
}
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
return SECFailure;
}
rv = SEC_QuickDERDecodeItem(arena, &oid, hashParameterTemplate, param);
if (rv != SECSuccess) {
PORT_FreeArena(arena, PR_FALSE);
return rv;
}
*hashalg = SECOID_FindOIDTag(&oid);
/* only accept hash algorithms */
if (HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) {
/* error set by HASH_GetHashTypeByOidTag */
return SECFailure;
}
break;
/* we don't implement MD4 hashes */
case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
default:
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
}
/* get the "encryption" algorithm */
switch (sigAlg) {
case SEC_OID_PKCS1_RSA_ENCRYPTION:
case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
*encalg = SEC_OID_PKCS1_RSA_ENCRYPTION;
break;
/* what about normal DSA? */
case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
*encalg = SEC_OID_ANSIX9_DSA_SIGNATURE;
break;
case SEC_OID_MISSI_DSS:
case SEC_OID_MISSI_KEA_DSS:
case SEC_OID_MISSI_KEA_DSS_OLD:
case SEC_OID_MISSI_DSS_OLD:
*encalg = SEC_OID_MISSI_DSS;
break;
case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
*encalg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
break;
/* we don't implement MD4 hashes */
case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
default:
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
}
return SECSuccess;
}
VFYContext *
VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag algid,
void *wincx)
/*
* we can verify signatures that come from 2 different sources:
* one in with the signature contains a signature oid, and the other
* in which the signature is managed by a Public key (encAlg) oid
* and a hash oid. The latter is the more basic, so that's what
* our base vfyCreate function takes.
*
* There is one noteworthy corner case, if we are using an RSA key, and the
* signature block is provided, then the hashAlg can be specified as
* SEC_OID_UNKNOWN. In this case, verify will use the hash oid supplied
* in the RSA signature block.
*/
static VFYContext *
vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
SECOidTag encAlg, SECOidTag hashAlg, SECOidTag *hash, void *wincx)
{
VFYContext *cx;
SECStatus rv;
unsigned int sigLen;
SECOidTag hashid = SEC_OID_UNKNOWN;
KeyType type;
/* make sure the encryption algorithm matches the key type */
type = seckey_GetKeyType(encAlg);
if (key->keyType != type) {
PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH);
return NULL;
}
cx = (VFYContext*) PORT_ZAlloc(sizeof(VFYContext));
if (cx) {
if (cx == NULL) {
goto loser;
}
cx->wincx = wincx;
cx->hasSignature = (sig != NULL);
cx->sigAlg = algid;
cx->encAlg = encAlg;
cx->alg = hashAlg;
cx->key = SECKEY_CopyPublicKey(key);
cx->type = key->keyType;
rv = SECSuccess;
if (sig) {
switch (key->keyType) {
case rsaKey:
cx->type = VFY_RSA;
cx->key = SECKEY_CopyPublicKey(key); /* extra safety precautions */
if (sig) {
SECOidTag hashid = SEC_OID_UNKNOWN;
rv = DecryptSigBlock(&hashid, cx->u.buffer,
HASH_LENGTH_MAX, cx->key, sig, (char*)wincx);
cx->alg = hashid;
} else {
rv = decodeSigAlg(algid,&cx->alg);
}
break;
case fortezzaKey:
case dsaKey:
case ecKey:
if (key->keyType == ecKey) {
cx->type = VFY_ECDSA;
/* Unlike DSA, EDSA does not have a fixed signature length
* (it depends on the key size)
*/
sigLen = SECKEY_PublicKeyStrength(key) * 2;
} else {
cx->type = VFY_DSA;
sigLen = DSA_SIGNATURE_LEN;
}
cx->alg = SEC_OID_SHA1;
cx->key = SECKEY_CopyPublicKey(key);
if (sig) {
rv = decodeECorDSASignature(algid,sig,cx->u.buffer,sigLen);
}
break;
default:
if (cx->alg != SEC_OID_UNKNOWN && cx->alg != hashid) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
rv = SECFailure;
break;
}
if (rv) goto loser;
switch (cx->alg) {
case SEC_OID_MD2:
case SEC_OID_MD5:
case SEC_OID_SHA1:
case SEC_OID_SHA256:
case SEC_OID_SHA384:
case SEC_OID_SHA512:
cx->alg = hashid;
break;
case dsaKey:
case ecKey:
sigLen = (key->keyType == ecKey) ?
SECKEY_PublicKeyStrength(key) * 2 :
DSA_SIGNATURE_LEN;
rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen);
break;
default:
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
goto loser;
rv = SECFailure;
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
break;
}
}
if (rv) goto loser;
/* check hash alg again, RSA may have changed it.*/
if (HASH_GetHashTypeByOidTag(cx->alg) == HASH_AlgNULL) {
/* error set by HASH_GetHashTypeByOidTag */
return NULL;
}
if (hash) {
*hash = cx->alg;
}
return cx;
loser:
if (cx) {
VFY_DestroyContext(cx, PR_TRUE);
}
return 0;
}
VFYContext *
VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag sigAlg,
void *wincx)
{
SECOidTag encAlg, hashAlg;
SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg);
if (rv != SECSuccess) {
return NULL;
}
return vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
}
VFYContext *
VFY_CreateContextDirect(const SECKEYPublicKey *key, const SECItem *sig,
SECOidTag encAlg, SECOidTag hashAlg,
SECOidTag *hash, void *wincx)
{
return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
}
VFYContext *
VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key, const SECItem *sig,
const SECAlgorithmID *sigAlgorithm, SECOidTag *hash, void *wincx)
{
SECOidTag encAlg, hashAlg;
SECStatus rv = sec_DecodeSigAlg(key,
SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
&sigAlgorithm->parameters, &encAlg, &hashAlg);
if (rv != SECSuccess) {
return NULL;
}
return vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
}
void
VFY_DestroyContext(VFYContext *cx, PRBool freeit)
{
@ -357,7 +503,7 @@ VFY_Begin(VFYContext *cx)
}
SECStatus
VFY_Update(VFYContext *cx, unsigned char *input, unsigned inputLen)
VFY_Update(VFYContext *cx, const unsigned char *input, unsigned inputLen)
{
if (cx->hashcx == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@ -386,16 +532,14 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
}
(*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));
switch (cx->type) {
case VFY_DSA:
case VFY_ECDSA:
case ecKey:
case dsaKey:
dsasig.data = cx->u.buffer;
if (cx->type == VFY_DSA) {
dsasig.len = DSA_SIGNATURE_LEN;
} else {
dsasig.len = SECKEY_PublicKeyStrength(cx->key) * 2;
}
dsasig.len = (cx->type == ecKey) ?
SECKEY_PublicKeyStrength(cx->key) * 2 :
DSA_SIGNATURE_LEN;
if (sig) {
rv = decodeECorDSASignature(cx->sigAlg,sig,dsasig.data,
rv = decodeECorDSASignature(cx->encAlg, sig, dsasig.data,
dsasig.len);
if (rv != SECSuccess) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
@ -409,7 +553,7 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
return SECFailure;
}
break;
case VFY_RSA:
case rsaKey:
if (sig) {
SECOidTag hashid = SEC_OID_UNKNOWN;
rv = DecryptSigBlock(&hashid, cx->u.buffer,
@ -440,13 +584,11 @@ VFY_End(VFYContext *cx)
/************************************************************************/
/*
* Verify that a previously-computed digest matches a signature.
* XXX This should take a parameter that specifies the digest algorithm,
* and we should compare that the algorithm found in the DigestInfo
* matches it!
*/
SECStatus
VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
SECOidTag algid, void *wincx)
static SECStatus
vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key,
const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
void *wincx)
{
SECStatus rv;
VFYContext *cx;
@ -454,7 +596,7 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
rv = SECFailure;
cx = VFY_CreateContext(key, sig, algid, wincx);
cx = vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
if (cx != NULL) {
switch (key->keyType) {
case rsaKey:
@ -464,7 +606,6 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
rv = SECSuccess;
}
break;
case fortezzaKey:
case dsaKey:
case ecKey:
dsasig.data = cx->u.buffer;
@ -474,7 +615,7 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
/* magic size of dsa signature */
dsasig.len = DSA_SIGNATURE_LEN;
}
if (PK11_Verify(cx->key, &dsasig, digest, cx->wincx)
if (PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx)
!= SECSuccess) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
} else {
@ -490,19 +631,66 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
}
SECStatus
VFY_VerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
SECItem *sig, SECOidTag algid, void *wincx)
VFY_VerifyDigestDirect(const SECItem *digest, const SECKEYPublicKey *key,
const SECItem *sig, SECOidTag encAlg,
SECOidTag hashAlg, void *wincx)
{
return VFY_VerifyDigestDirect(digest, key, sig, encAlg, hashAlg, wincx);
}
SECStatus
VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
SECOidTag algid, void *wincx)
{
SECOidTag encAlg, hashAlg;
SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
if (rv != SECSuccess) {
return SECFailure;
}
return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
}
/*
* this function takes an optional hash oid, which the digest function
* will be compared with our target hash value.
*/
SECStatus
VFY_VerifyDigestWithAlgorithmID(const SECItem *digest,
const SECKEYPublicKey *key, const SECItem *sig,
const SECAlgorithmID *sigAlgorithm,
SECOidTag hashCmp, void *wincx)
{
SECOidTag encAlg, hashAlg;
SECStatus rv = sec_DecodeSigAlg(key,
SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
&sigAlgorithm->parameters, &encAlg, &hashAlg);
if (rv != SECSuccess) {
return rv;
}
if ( hashCmp != SEC_OID_UNKNOWN &&
hashAlg != SEC_OID_UNKNOWN &&
hashCmp != hashAlg) {
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
return SECFailure;
}
return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, wincx);
}
static SECStatus
vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
SECOidTag *hash, void *wincx)
{
SECStatus rv;
VFYContext *cx;
cx = VFY_CreateContext(key, sig, algid, wincx);
cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
if (cx == NULL)
return SECFailure;
rv = VFY_Begin(cx);
if (rv == SECSuccess) {
rv = VFY_Update(cx, buf, len);
rv = VFY_Update(cx, (unsigned char *)buf, len);
if (rv == SECSuccess)
rv = VFY_End(cx);
}
@ -510,3 +698,41 @@ VFY_VerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
VFY_DestroyContext(cx, PR_TRUE);
return rv;
}
SECStatus
VFY_VerifyDataDirect(const unsigned char *buf, int len,
const SECKEYPublicKey *key, const SECItem *sig,
SECOidTag encAlg, SECOidTag hashAlg,
SECOidTag *hash, void *wincx)
{
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx);
}
SECStatus
VFY_VerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
SECItem *sig, SECOidTag algid, void *wincx)
{
SECOidTag encAlg, hashAlg;
SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg);
if (rv != SECSuccess) {
return rv;
}
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, NULL, wincx);
}
SECStatus
VFY_VerifyDataWithAlgorithmID(const unsigned char *buf, int len,
const SECKEYPublicKey *key,
const SECItem *sig,
const SECAlgorithmID *sigAlgorithm,
SECOidTag *hash, void *wincx)
{
SECOidTag encAlg, hashAlg;
SECStatus rv = sec_DecodeSigAlg(key,
SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
&sigAlgorithm->parameters, &encAlg, &hashAlg);
if (rv != SECSuccess) {
return rv;
}
return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, hash, wincx);
}

View File

@ -875,6 +875,12 @@ SECMOD_OpenUserDB;
;+NSS_3.12 { # NSS 3.12 release
;+ global:
PK11_GetAllSlotsForCert;
VFY_CreateContextDirect;
VFY_CreateContextWithAlgorithmID;
VFY_VerifyDataDirect;
VFY_VerifyDataWithAlgorithmID;
VFY_VerifyDigestDirect;
VFY_VerifyDigestWithAlgorithmID;
;+ local:
;+ *;
;+};

View File

@ -38,7 +38,7 @@
/*
* PKCS7 decoding, verification.
*
* $Id: p7decode.c,v 1.20 2005/10/03 22:01:56 relyea%netscape.com Exp $
* $Id: p7decode.c,v 1.21 2006/02/08 06:14:18 rrelyea%redhat.com Exp $
*/
#include "nssrenam.h"
@ -1436,7 +1436,8 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
CERTCertificate *cert, **certs;
PRBool goodsig;
CERTCertDBHandle *certdb, *defaultdb;
SECOidData *algiddata;
SECOidTag encTag,digestTag;
HASH_HashType found_type;
int i, certcount;
SECKEYPublicKey *publickey;
SECItem *content_type;
@ -1615,14 +1616,19 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
/*
* Find and confirm digest algorithm.
*/
algiddata = SECOID_FindOID (&(signerinfo->digestAlg.algorithm));
digestTag = SECOID_FindOIDTag(&(signerinfo->digestAlg.algorithm));
/* make sure we understand the digest type first */
found_type = HASH_GetHashTypeByOidTag(digestTag);
if ((digestTag == SEC_OID_UNKNOWN) || (found_type == HASH_AlgNULL)) {
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
goto done;
}
if (detached_digest != NULL) {
HASH_HashType found_type = HASH_GetHashTypeByOidTag(algiddata->offset);
unsigned int hashLen = HASH_ResultLen(digest_type);
unsigned int hashLen = HASH_ResultLen(found_type);
if (digest_type != found_type ||
digest_type == HASH_AlgNULL ||
detached_digest->len != hashLen) {
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
goto done;
@ -1638,12 +1644,8 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
/*
* pick digest matching signerinfo->digestAlg from digests
*/
if (algiddata == NULL) {
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
goto done;
}
for (i = 0; digestalgs[i] != NULL; i++) {
if (SECOID_FindOID (&(digestalgs[i]->algorithm)) == algiddata)
if (SECOID_FindOIDTag(&(digestalgs[i]->algorithm)) == digestTag)
break;
}
if (digestalgs[i] == NULL) {
@ -1654,19 +1656,8 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
digest = digests[i];
}
/*
* XXX This may not be the right set of algorithms to check.
* I'd prefer to trust that just calling VFY_Verify{Data,Digest}
* would do the right thing (and set an error if it could not);
* then additional algorithms could be handled by that code
* and we would Just Work. So this check should just be removed,
* but not until the VFY code is better at setting errors.
*/
algiddata = SECOID_FindOID (&(signerinfo->digestEncAlg.algorithm));
if (algiddata == NULL ||
((algiddata->offset != SEC_OID_PKCS1_RSA_ENCRYPTION) &&
(algiddata->offset != SEC_OID_ANSIX962_EC_PUBLIC_KEY) &&
(algiddata->offset != SEC_OID_ANSIX9_DSA_SIGNATURE))) {
encTag = SECOID_FindOIDTag(&(signerinfo->digestEncAlg.algorithm));
if (encTag == SEC_OID_UNKNOWN) {
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
goto done;
}
@ -1735,14 +1726,10 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
goto done;
}
/*
* XXX the 5th (algid) argument should be the signature algorithm.
* See sec_pkcs7_pick_sign_alg in p7encode.c.
*/
goodsig = (PRBool)(VFY_VerifyData (encoded_attrs.data,
goodsig = (PRBool)(VFY_VerifyDataDirect(encoded_attrs.data,
encoded_attrs.len,
publickey, &(signerinfo->encDigest),
SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)),
encTag, digestTag, NULL,
cinfo->pwfn_arg) == SECSuccess);
PORT_Free (encoded_attrs.data);
} else {
@ -1797,13 +1784,8 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
sig = &holder;
}
/*
* XXX the 4th (algid) argument should be the signature algorithm.
* See sec_pkcs7_pick_sign_alg in p7encode.c.
*/
goodsig = (PRBool)(VFY_VerifyDigest (digest, publickey, sig,
SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)),
cinfo->pwfn_arg)
goodsig = (PRBool)(VFY_VerifyDigestDirect(digest, publickey, sig,
encTag, digestTag, cinfo->pwfn_arg)
== SECSuccess);
if (sigkey != NULL) {

View File

@ -38,7 +38,7 @@
/*
* PKCS7 encoding.
*
* $Id: p7encode.c,v 1.11 2005/09/02 01:24:56 wtchang%redhat.com Exp $
* $Id: p7encode.c,v 1.12 2006/02/08 06:14:19 rrelyea%redhat.com Exp $
*/
#include "nssrenam.h"
@ -835,56 +835,6 @@ SEC_PKCS7EncoderUpdate (SEC_PKCS7EncoderContext *p7ecx,
PR_FALSE);
}
/*
* XXX I would *really* like to not have to do this, but the current
* signing interface gives me little choice.
*/
static SECOidTag
sec_pkcs7_pick_sign_alg (SECOidTag hashalg, SECOidTag encalg)
{
switch (encalg) {
case SEC_OID_PKCS1_RSA_ENCRYPTION:
switch (hashalg) {
case SEC_OID_MD2:
return SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
case SEC_OID_MD5:
return SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
case SEC_OID_SHA1:
return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
case SEC_OID_SHA256:
return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
case SEC_OID_SHA384:
return SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
case SEC_OID_SHA512:
return SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
default:
return SEC_OID_UNKNOWN;
}
case SEC_OID_ANSIX9_DSA_SIGNATURE:
case SEC_OID_MISSI_KEA_DSS:
case SEC_OID_MISSI_DSS:
switch (hashalg) {
case SEC_OID_SHA1:
return SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
default:
return SEC_OID_UNKNOWN;
}
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
switch (hashalg) {
case SEC_OID_SHA1:
return SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
default:
return SEC_OID_UNKNOWN;
}
default:
break;
}
return encalg; /* maybe it is already the right algid */
}
static SECStatus
sec_pkcs7_encoder_sig_and_certs (SEC_PKCS7ContentInfo *cinfo,
SECKEYGetPasswordKey pwfn, void *pwfnarg)
@ -1000,6 +950,7 @@ sec_pkcs7_encoder_sig_and_certs (SEC_PKCS7ContentInfo *cinfo,
SEC_PKCS7Attribute *attr;
SECItem encoded_attrs;
SECItem *dummy;
SECOidTag algid;
/*
* First, find and fill in the message digest attribute.
@ -1050,11 +1001,17 @@ sec_pkcs7_encoder_sig_and_certs (SEC_PKCS7ContentInfo *cinfo,
return SECFailure;
}
algid = SEC_GetSignatureAlgorithmOidTag(privkey->keyType,
digestalgtag);
if (algid == SEC_OID_UNKNOWN) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
SECKEY_DestroyPrivateKey (privkey);
return SECFailure;
}
rv = SEC_SignData (&signature,
encoded_attrs.data, encoded_attrs.len,
privkey,
sec_pkcs7_pick_sign_alg (digestalgtag,
signalgtag));
algid);
SECITEM_FreeItem (&encoded_attrs, PR_FALSE);
} else {
rv = SGN_Digest (privkey, digestalgtag, &signature,

View File

@ -37,7 +37,7 @@
/*
* Interfaces of the CMS implementation.
*
* $Id: cms.h,v 1.20 2004/04/25 15:03:15 gerv%gerv.net Exp $
* $Id: cms.h,v 1.21 2006/02/08 06:13:43 rrelyea%redhat.com Exp $
*/
#ifndef _CMS_H_
@ -410,13 +410,6 @@ NSS_CMSAlgArray_GetIndexByAlgTag(SECAlgorithmID **algorithmArray, SECOidTag algt
extern const SECHashObject *
NSS_CMSUtil_GetHashObjByAlgID(SECAlgorithmID *algid);
/*
* XXX I would *really* like to not have to do this, but the current
* signing interface gives me little choice.
*/
extern SECOidTag
NSS_CMSUtil_MakeSignatureAlgorithm(SECOidTag hashalg, SECOidTag encalg);
extern const SEC_ASN1Template *
NSS_CMSUtil_GetTemplateByTypeTag(SECOidTag type);

View File

@ -38,7 +38,7 @@
/*
* CMS signerInfo methods.
*
* $Id: cmssiginfo.c,v 1.29 2005/09/02 01:24:56 wtchang%redhat.com Exp $
* $Id: cmssiginfo.c,v 1.30 2006/02/08 06:13:43 rrelyea%redhat.com Exp $
*/
#include "cmslocal.h"
@ -262,7 +262,13 @@ NSS_CMSSignerInfo_Sign(NSSCMSSignerInfo *signerinfo, SECItem *digest, SECItem *c
&encoded_attrs) == NULL)
goto loser;
signAlgTag = NSS_CMSUtil_MakeSignatureAlgorithm(digestalgtag, pubkAlgTag);
signAlgTag = SEC_GetSignatureAlgorithmOidTag(privkey->keyType,
digestalgtag);
if (signAlgTag == SEC_OID_UNKNOWN) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
goto loser;
}
rv = SEC_SignData(&signature, encoded_attrs.data, encoded_attrs.len,
privkey, signAlgTag);
PORT_FreeArena(tmppoolp, PR_FALSE); /* awkward memory management :-( */
@ -350,7 +356,6 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo,
PLArenaPool *poolp;
SECOidTag digestalgtag;
SECOidTag pubkAlgTag;
SECOidTag signAlgTag;
if (signerinfo == NULL)
return SECFailure;
@ -370,35 +375,12 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo,
}
digestalgtag = NSS_CMSSignerInfo_GetDigestAlgTag(signerinfo);
/*
* XXX This may not be the right set of algorithms to check.
* I'd prefer to trust that just calling VFY_Verify{Data,Digest}
* would do the right thing (and set an error if it could not);
* then additional algorithms could be handled by that code
* and we would Just Work. So this check should just be removed,
* but not until the VFY code is better at setting errors.
*/
pubkAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg));
switch (pubkAlgTag) {
case SEC_OID_PKCS1_RSA_ENCRYPTION:
case SEC_OID_ANSIX9_DSA_SIGNATURE:
case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
/* ok */
break;
case SEC_OID_UNKNOWN:
if ((pubkAlgTag == SEC_OID_UNKNOWN) || (digestalgtag == SEC_OID_UNKNOWN)) {
vs = NSSCMSVS_SignatureAlgorithmUnknown;
goto loser;
default:
vs = NSSCMSVS_SignatureAlgorithmUnsupported;
goto loser;
}
signAlgTag = NSS_CMSUtil_MakeSignatureAlgorithm(digestalgtag, pubkAlgTag);
if (!NSS_CMSArray_IsEmpty((void **)signerinfo->authAttr)) {
if (contentType) {
/*
@ -461,9 +443,9 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo,
goto loser;
}
vs = (VFY_VerifyData (encoded_attrs.data, encoded_attrs.len,
publickey, &(signerinfo->encDigest), signAlgTag,
signerinfo->cmsg->pwfn_arg) != SECSuccess)
vs = (VFY_VerifyDataDirect(encoded_attrs.data, encoded_attrs.len,
publickey, &(signerinfo->encDigest), pubkAlgTag,
digestalgtag, NULL, signerinfo->cmsg->pwfn_arg) != SECSuccess)
? NSSCMSVS_BadSignature : NSSCMSVS_GoodSignature;
PORT_FreeArena(poolp, PR_FALSE); /* awkward memory management :-( */
@ -479,16 +461,17 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo,
goto loser;
vs = (!digest ||
VFY_VerifyDigest(digest, publickey, sig, signAlgTag,
signerinfo->cmsg->pwfn_arg) != SECSuccess)
VFY_VerifyDigestDirect(digest, publickey, sig, pubkAlgTag,
digestalgtag, signerinfo->cmsg->pwfn_arg) != SECSuccess)
? NSSCMSVS_BadSignature : NSSCMSVS_GoodSignature;
}
if (vs == NSSCMSVS_BadSignature) {
int error = PORT_GetError();
/*
* XXX Change the generic error into our specific one, because
* in that case we get a better explanation out of the Security
* Advisor. This is really a bug in our error strings (the
* Advisor. This is really a bug in the PSM error strings (the
* "generic" error has a lousy/wrong message associated with it
* which assumes the signature verification was done for the
* purposes of checking the issuer signature on a certificate)
@ -501,8 +484,17 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo,
* certificate signature check that failed during the cert
* verification done above. Our error handling is really a mess.
*/
if (PORT_GetError() == SEC_ERROR_BAD_SIGNATURE)
if (error == SEC_ERROR_BAD_SIGNATURE)
PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE);
/*
* map algorithm failures to NSSCMSVS values
*/
if ((error == SEC_ERROR_PKCS7_KEYALG_MISMATCH) ||
(error == SEC_ERROR_INVALID_ALGORITHM)) {
/* keep the same error code as 3.11 and before */
PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE);
vs = NSSCMSVS_SignatureAlgorithmUnsupported;
}
}
if (publickey != NULL)

View File

@ -38,7 +38,7 @@
/*
* CMS miscellaneous utility functions.
*
* $Id: cmsutil.c,v 1.13 2005/09/02 01:24:56 wtchang%redhat.com Exp $
* $Id: cmsutil.c,v 1.14 2006/02/08 06:13:43 rrelyea%redhat.com Exp $
*/
#include "nssrenam.h"
@ -222,54 +222,6 @@ NSS_CMSUtil_GetHashObjByAlgID(SECAlgorithmID *algid)
return digobj;
}
/*
* XXX I would *really* like to not have to do this, but the current
* signing interface gives me little choice.
*/
SECOidTag
NSS_CMSUtil_MakeSignatureAlgorithm(SECOidTag hashalg, SECOidTag encalg)
{
switch (encalg) {
case SEC_OID_PKCS1_RSA_ENCRYPTION:
switch (hashalg) {
case SEC_OID_MD2:
return SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
case SEC_OID_MD5:
return SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
case SEC_OID_SHA1:
return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
case SEC_OID_SHA256:
return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
case SEC_OID_SHA384:
return SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
case SEC_OID_SHA512:
return SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
default:
return SEC_OID_UNKNOWN;
}
case SEC_OID_ANSIX9_DSA_SIGNATURE:
case SEC_OID_MISSI_KEA_DSS:
case SEC_OID_MISSI_DSS:
switch (hashalg) {
case SEC_OID_SHA1:
return SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
default:
return SEC_OID_UNKNOWN;
}
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
switch (hashalg) {
case SEC_OID_SHA1:
return SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
default:
return SEC_OID_UNKNOWN;
}
default:
break;
}
return encalg; /* maybe it is already the right algid */
}
const SEC_ASN1Template *
NSS_CMSUtil_GetTemplateByTypeTag(SECOidTag type)
{

View File

@ -166,6 +166,8 @@
#define ANSI_X962_CURVE_OID ANSI_X962_OID, 0x03
#define ANSI_X962_GF2m_OID ANSI_X962_CURVE_OID, 0x00
#define ANSI_X962_GFp_OID ANSI_X962_CURVE_OID, 0x01
#define ANSI_X962_SIGNATURE_OID ANSI_X962_OID, 0x04
#define ANSI_X962_SPECIFY_OID ANSI_X962_SIGNATURE_OID, 0x03
#define CONST_OID static const unsigned char
@ -454,7 +456,13 @@ CONST_OID sha384[] = { SHAXXX, 2 };
CONST_OID sha512[] = { SHAXXX, 3 };
CONST_OID ansix962ECPublicKey[] = { ANSI_X962_OID, 0x02, 0x01 };
CONST_OID ansix962ECDSASignaturewithSHA1Digest[] = { ANSI_X962_OID, 0x04, 0x01 };
CONST_OID ansix962SignaturewithSHA1Digest[] = { ANSI_X962_SIGNATURE_OID, 0x01 };
CONST_OID ansix962SignatureRecommended[] = { ANSI_X962_SIGNATURE_OID, 0x02 };
CONST_OID ansix962SignatureSpecified[] = { ANSI_X962_SPECIFY_OID };
CONST_OID ansix962SignaturewithSHA224Digest[] = { ANSI_X962_SPECIFY_OID, 0x01 };
CONST_OID ansix962SignaturewithSHA256Digest[] = { ANSI_X962_SPECIFY_OID, 0x02 };
CONST_OID ansix962SignaturewithSHA384Digest[] = { ANSI_X962_SPECIFY_OID, 0x03 };
CONST_OID ansix962SignaturewithSHA512Digest[] = { ANSI_X962_SPECIFY_OID, 0x04 };
/* ANSI X9.62 prime curve OIDs */
/* NOTE: prime192v1 is the same as secp192r1, prime256v1 is the
@ -1150,8 +1158,8 @@ const static SECOidData oids[] = {
OD( ansix962ECPublicKey, SEC_OID_ANSIX962_EC_PUBLIC_KEY,
"X9.62 elliptic curve public key", CKM_ECDH1_DERIVE,
INVALID_CERT_EXTENSION ),
OD( ansix962ECDSASignaturewithSHA1Digest,
SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST,
OD( ansix962SignaturewithSHA1Digest,
SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE,
"X9.62 ECDSA signature with SHA1", CKM_ECDSA_SHA1,
INVALID_CERT_EXTENSION ),
@ -1435,6 +1443,32 @@ const static SECOidData oids[] = {
OD( pkcs9ExtensionRequest, SEC_OID_PKCS9_EXTENSION_REQUEST,
"PKCS #9 Extension Request",
CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
/* more ECC Signature Oids */
OD( ansix962SignatureRecommended,
SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST,
"X9.62 ECDSA signature with recommended digest", CKM_INVALID_MECHANISM,
INVALID_CERT_EXTENSION ),
OD( ansix962SignatureSpecified,
SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST,
"X9.62 ECDSA signature with specified digest", CKM_ECDSA,
INVALID_CERT_EXTENSION ),
OD( ansix962SignaturewithSHA224Digest,
SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE,
"X9.62 ECDSA signature with SHA224", CKM_INVALID_MECHANISM,
INVALID_CERT_EXTENSION ),
OD( ansix962SignaturewithSHA256Digest,
SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE,
"X9.62 ECDSA signature with SHA256", CKM_INVALID_MECHANISM,
INVALID_CERT_EXTENSION ),
OD( ansix962SignaturewithSHA384Digest,
SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE,
"X9.62 ECDSA signature with SHA384", CKM_INVALID_MECHANISM,
INVALID_CERT_EXTENSION ),
OD( ansix962SignaturewithSHA512Digest,
SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE,
"X9.62 ECDSA signature with SHA512", CKM_INVALID_MECHANISM,
INVALID_CERT_EXTENSION ),
};
/*

View File

@ -40,7 +40,7 @@
/*
* secoidt.h - public data structures for ASN.1 OID functions
*
* $Id: secoidt.h,v 1.19 2005/03/07 18:34:48 wtchang%redhat.com Exp $
* $Id: secoidt.h,v 1.20 2006/02/08 06:14:31 rrelyea%redhat.com Exp $
*/
#include "secitem.h"
@ -314,7 +314,10 @@ typedef enum {
/* Elliptic Curve Cryptography (ECC) OIDs */
SEC_OID_ANSIX962_EC_PUBLIC_KEY = 200,
SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST = 201,
SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE = 201,
#define SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST \
SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE
/* ANSI X9.62 named elliptic curves (prime field) */
SEC_OID_ANSIX962_EC_PRIME192V1 = 202,
@ -403,6 +406,13 @@ typedef enum {
SEC_OID_PKIX_CA_ISSUERS = 273,
SEC_OID_PKCS9_EXTENSION_REQUEST = 274,
/* new EC Signature oids */
SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST = 275,
SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST = 276,
SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE = 277,
SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE = 278,
SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE = 279,
SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE = 280,
SEC_OID_TOTAL
} SECOidTag;