Bug 320583 Support for SHA256/384/512 with ECC signing
This commit is contained in:
Родитель
f215fa13a0
Коммит
a855b8fda9
|
@ -2153,17 +2153,11 @@ SignCert(CERTCertificate *cert,
|
||||||
|
|
||||||
arena = cert->arena;
|
arena = cert->arena;
|
||||||
|
|
||||||
switch(caPrivateKey->keyType) {
|
algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType,
|
||||||
case rsaKey:
|
SEC_OID_UNKNOWN);
|
||||||
algID = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
|
if (algID == SEC_OID_UNKNOWN) {
|
||||||
break;
|
|
||||||
case dsaKey:
|
|
||||||
algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error_out("ERROR: Unknown key type for issuer.");
|
error_out("ERROR: Unknown key type for issuer.");
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0);
|
rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0);
|
||||||
|
|
|
@ -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
|
static
|
||||||
SECStatus
|
SECStatus
|
||||||
OurVerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
|
OurVerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
|
||||||
|
@ -200,8 +158,8 @@ OurVerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
|
||||||
int hashAlgTag;
|
int hashAlgTag;
|
||||||
int showDigestOid=0;
|
int showDigestOid=0;
|
||||||
|
|
||||||
cx = VFY_CreateContext(key, sig, SECOID_GetAlgorithmTag(sigAlgorithm),
|
cx = VFY_CreateContextWithAlgorithmID(key, sig, sigAlgorithm, &hashAlgTag,
|
||||||
NULL);
|
NULL);
|
||||||
if (cx == NULL)
|
if (cx == NULL)
|
||||||
return SECFailure;
|
return SECFailure;
|
||||||
|
|
||||||
|
@ -210,18 +168,9 @@ OurVerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
|
||||||
return SECFailure;
|
return SECFailure;
|
||||||
sigAlgTag = sigAlgOid->offset;
|
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) {
|
if (showDigestOid) {
|
||||||
oiddata = SECOID_FindOIDByTag(cx->alg);
|
oiddata = SECOID_FindOIDByTag(hashAlgTag);
|
||||||
if ( oiddata ) {
|
if ( oiddata ) {
|
||||||
printf("PROBLEM: (cont) Digest OID is %s\n", oiddata->desc);
|
printf("PROBLEM: (cont) Digest OID is %s\n", oiddata->desc);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -414,14 +414,9 @@ createNewCert(CERTCertificate**issuedCert,CERTCertificateRequest *oldCertReq,
|
||||||
if (issuerPrivKey == NULL) {
|
if (issuerPrivKey == NULL) {
|
||||||
rv = COULD_NOT_FIND_ISSUER_PRIVATE_KEY;
|
rv = COULD_NOT_FIND_ISSUER_PRIVATE_KEY;
|
||||||
}
|
}
|
||||||
switch(issuerPrivKey->keyType) {
|
signTag = SEC_GetSignatureAlgorithmOidTag(issuerPrivatekey->keytype,
|
||||||
case rsaKey:
|
SEC_OID_UNKNOWN);
|
||||||
signTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
|
if (signTag == SEC_OID_UNKNOWN) {
|
||||||
break;
|
|
||||||
case dsaKey:
|
|
||||||
signTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rv = UNSUPPORTED_SIGN_OPERATION_FOR_ISSUER;
|
rv = UNSUPPORTED_SIGN_OPERATION_FOR_ISSUER;
|
||||||
goto loser;
|
goto loser;
|
||||||
}
|
}
|
||||||
|
@ -644,8 +639,8 @@ verifySignature(CGIVarTable *varTable, CRMFCertReqMsg *currReq,
|
||||||
rv = ERROR_ENCODING_CERT_REQ_FOR_POP;
|
rv = ERROR_ENCODING_CERT_REQ_FOR_POP;
|
||||||
goto loser;
|
goto loser;
|
||||||
}
|
}
|
||||||
srv = VFY_VerifyData(reqDER->data, reqDER->len, pubKey, signature,
|
srv = VFY_VerifyDataWithAlgorithmID(reqDER->data, reqDER->len, pubKey,
|
||||||
SECOID_FindOIDTag(&algID->algorithm), varTable);
|
signature, &algID->algorithm, NULL, varTable);
|
||||||
if (srv != SECSuccess) {
|
if (srv != SECSuccess) {
|
||||||
rv = ERROR_VERIFYING_SIGNATURE_POP;
|
rv = ERROR_VERIFYING_SIGNATURE_POP;
|
||||||
goto loser;
|
goto loser;
|
||||||
|
|
|
@ -455,18 +455,10 @@ sign_cert(CERTCertificate *cert, SECKEYPrivateKey *privk)
|
||||||
void *dummy;
|
void *dummy;
|
||||||
SECOidTag alg = SEC_OID_UNKNOWN;
|
SECOidTag alg = SEC_OID_UNKNOWN;
|
||||||
|
|
||||||
switch (privk->keyType) {
|
alg = SEC_GetSignatureAlgorithmOidTag(privk->keyType, SEC_OID_UNKNOWN);
|
||||||
case rsaKey:
|
if (alg == SEC_OID_UNKNOWN) {
|
||||||
alg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case dsaKey:
|
|
||||||
alg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
FatalError("Unknown key type");
|
FatalError("Unknown key type");
|
||||||
}
|
}
|
||||||
PORT_Assert(alg != SEC_OID_UNKNOWN);
|
|
||||||
|
|
||||||
rv = SECOID_SetAlgorithmID (cert->arena, &cert->signature, alg, 0);
|
rv = SECOID_SetAlgorithmID (cert->arena, &cert->signature, alg, 0);
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,6 @@ CERT_VerifySignedDataWithPublicKey(CERTSignedData *sd,
|
||||||
void *wincx)
|
void *wincx)
|
||||||
{
|
{
|
||||||
SECStatus rv;
|
SECStatus rv;
|
||||||
SECOidTag algid;
|
|
||||||
SECItem sig;
|
SECItem sig;
|
||||||
|
|
||||||
if ( !pubKey || !sd ) {
|
if ( !pubKey || !sd ) {
|
||||||
|
@ -114,9 +113,8 @@ CERT_VerifySignedDataWithPublicKey(CERTSignedData *sd,
|
||||||
/* convert sig->len from bit counts to byte count. */
|
/* convert sig->len from bit counts to byte count. */
|
||||||
DER_ConvertBitString(&sig);
|
DER_ConvertBitString(&sig);
|
||||||
|
|
||||||
algid = SECOID_GetAlgorithmTag(&sd->signatureAlgorithm);
|
rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey,
|
||||||
rv = VFY_VerifyData(sd->data.data, sd->data.len, pubKey, &sig,
|
&sig, &sd->signatureAlgorithm, NULL, wincx);
|
||||||
algid, wincx);
|
|
||||||
|
|
||||||
return rv ? SECFailure : SECSuccess;
|
return rv ? SECFailure : SECSuccess;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
* Implementation of OCSP services, for both client and server.
|
* Implementation of OCSP services, for both client and server.
|
||||||
* (XXX, really, mostly just for client right now, but intended to do both.)
|
* (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"
|
#include "prerror.h"
|
||||||
|
@ -2678,10 +2678,9 @@ ocsp_CheckSignature(ocspSignature *signature, void *tbs,
|
||||||
*/
|
*/
|
||||||
DER_ConvertBitString(&rawSignature);
|
DER_ConvertBitString(&rawSignature);
|
||||||
|
|
||||||
rv = VFY_VerifyData(encodedTBS->data, encodedTBS->len, signerKey,
|
rv = VFY_VerifyDataWithAlgorithmID(encodedTBS->data, encodedTBS->len,
|
||||||
&rawSignature,
|
signerKey, &rawSignature,
|
||||||
SECOID_GetAlgorithmTag(&signature->signatureAlgorithm),
|
&signature->signatureAlgorithm, NULL, pwArg);
|
||||||
pwArg);
|
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
if (signature->wasChecked)
|
if (signature->wasChecked)
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** 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_
|
#ifndef _CRYPTOHI_H_
|
||||||
#define _CRYPTOHI_H_
|
#define _CRYPTOHI_H_
|
||||||
|
@ -65,7 +65,7 @@ SEC_BEGIN_PROTOS
|
||||||
* functions convert between formats.
|
* functions convert between formats.
|
||||||
*/
|
*/
|
||||||
extern SECStatus DSAU_EncodeDerSig(SECItem *dest, SECItem *src);
|
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.
|
* 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,
|
extern SECStatus DSAU_EncodeDerSigWithLen(SECItem *dest, SECItem *src,
|
||||||
unsigned int len);
|
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
|
** 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.
|
** Create a signature verification context.
|
||||||
** "key" the public key to verify with
|
** "key" the public key to verify with
|
||||||
** "sig" the encrypted signature data if sig is NULL then
|
** "sig" the encrypted signature data if sig is NULL then
|
||||||
** VFY_EndWithSignature must be called with the correct signature at
|
** VFY_EndWithSignature must be called with the correct signature at
|
||||||
** the end of the processing.
|
** the end of the processing.
|
||||||
** "algid" specifies the signing algorithm to use. This must match
|
** "pubkAlg" specifies the cryptographic signing algorithm to use (the
|
||||||
** the key type.
|
** 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
|
** "wincx" void pointer to the window context
|
||||||
*/
|
*/
|
||||||
extern VFYContext *VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig,
|
extern VFYContext *VFY_CreateContextDirect(const SECKEYPublicKey *key,
|
||||||
SECOidTag algid, void *wincx);
|
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.
|
** Destroy a verification-context object.
|
||||||
|
@ -216,7 +258,7 @@ extern SECStatus VFY_Begin(VFYContext *cx);
|
||||||
** "input" the input data
|
** "input" the input data
|
||||||
** "inputLen" the amount of 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);
|
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
|
** Verify the signature on a block of data for which we already have
|
||||||
** the digest. The signature data is an RSA private key encrypted
|
** the digest. The signature data is an RSA private key encrypted
|
||||||
** block of data formatted according to PKCS#1.
|
** block of data formatted according to PKCS#1.
|
||||||
|
** This function is deprecated. Use VFY_VerifyDigestDirect or
|
||||||
|
** VFY_VerifyDigestWithAlgorithmID instead.
|
||||||
** "dig" the digest
|
** "dig" the digest
|
||||||
** "key" the public key to check the signature with
|
** "key" the public key to check the signature with
|
||||||
** "sig" the encrypted signature data
|
** "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.
|
** the key type.
|
||||||
|
** "wincx" void pointer to the window context
|
||||||
**/
|
**/
|
||||||
extern SECStatus VFY_VerifyDigest(SECItem *dig, SECKEYPublicKey *key,
|
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
|
** 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
|
** "len" the length of the input data
|
||||||
** "key" the public key to check the signature with
|
** "key" the public key to check the signature with
|
||||||
** "sig" the encrypted signature data
|
** "sig" the encrypted signature data
|
||||||
** "algid" specifies the signing algorithm to use. This must match
|
** "algid" specifies the signing algorithm and parameters to use.
|
||||||
** the key type.
|
** 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,
|
extern SECStatus VFY_VerifyDataWithAlgorithmID(const unsigned char *buf,
|
||||||
SECKEYPublicKey *key, SECItem *sig,
|
int len, const SECKEYPublicKey *key,
|
||||||
SECOidTag algid, void *wincx);
|
const SECItem *sig,
|
||||||
|
const SECAlgorithmID *algid, SECOidTag *hash,
|
||||||
|
void *wincx);
|
||||||
|
|
||||||
|
|
||||||
SEC_END_PROTOS
|
SEC_END_PROTOS
|
||||||
|
|
|
@ -192,7 +192,7 @@ common_EncodeDerSig(SECItem *dest, SECItem *src)
|
||||||
** For ECDSA, len depends on the key size used to create the signature.
|
** For ECDSA, len depends on the key size used to create the signature.
|
||||||
*/
|
*/
|
||||||
static SECItem *
|
static SECItem *
|
||||||
common_DecodeDerSig(SECItem *item, unsigned int len)
|
common_DecodeDerSig(const SECItem *item, unsigned int len)
|
||||||
{
|
{
|
||||||
SECItem * result = NULL;
|
SECItem * result = NULL;
|
||||||
SECStatus status;
|
SECStatus status;
|
||||||
|
@ -283,7 +283,7 @@ DSAU_EncodeDerSigWithLen(SECItem *dest, SECItem *src, unsigned int len)
|
||||||
** followed by 20 bytes of s.
|
** followed by 20 bytes of s.
|
||||||
*/
|
*/
|
||||||
SECItem *
|
SECItem *
|
||||||
DSAU_DecodeDerSig(SECItem *item)
|
DSAU_DecodeDerSig(const SECItem *item)
|
||||||
{
|
{
|
||||||
return common_DecodeDerSig(item, DSA_SUBPRIME_LEN);
|
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).
|
** r followed by s (both padded to take up exactly len/2 bytes).
|
||||||
*/
|
*/
|
||||||
SECItem *
|
SECItem *
|
||||||
DSAU_DecodeDerSigToLen(SECItem *item, unsigned int len)
|
DSAU_DecodeDerSigToLen(const SECItem *item, unsigned int len)
|
||||||
{
|
{
|
||||||
return common_DecodeDerSig(item, len/2);
|
return common_DecodeDerSig(item, len/2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** 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_
|
#ifndef _KEYHI_H_
|
||||||
#define _KEYHI_H_
|
#define _KEYHI_H_
|
||||||
|
@ -82,22 +82,22 @@ SECKEY_KEAParamCompare(CERTCertificate *cert1,CERTCertificate *cert2);
|
||||||
/*
|
/*
|
||||||
** Return the strength of the public key in bytes
|
** 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
|
** 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"
|
** 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"
|
** 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
|
** Convert a private key "privateKey" into a public key
|
||||||
|
|
|
@ -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_ */
|
|
@ -48,6 +48,7 @@
|
||||||
#include "secdig.h"
|
#include "secdig.h"
|
||||||
#include "prtime.h"
|
#include "prtime.h"
|
||||||
#include "ec.h"
|
#include "ec.h"
|
||||||
|
#include "keyi.h"
|
||||||
|
|
||||||
const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {
|
const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {
|
||||||
{ SEC_ASN1_SEQUENCE,
|
{ 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
|
KeyType
|
||||||
CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki) {
|
seckey_GetKeyType (SECOidTag tag) {
|
||||||
int tag;
|
|
||||||
KeyType keyType;
|
KeyType keyType;
|
||||||
|
|
||||||
tag = SECOID_GetAlgorithmTag(&spki->algorithm);
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case SEC_OID_X500_RSA_ENCRYPTION:
|
case SEC_OID_X500_RSA_ENCRYPTION:
|
||||||
case SEC_OID_PKCS1_RSA_ENCRYPTION:
|
case SEC_OID_PKCS1_RSA_ENCRYPTION:
|
||||||
|
@ -976,6 +975,13 @@ CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki) {
|
||||||
return keyType;
|
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 *
|
static SECKEYPublicKey *
|
||||||
seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
|
seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki)
|
||||||
{
|
{
|
||||||
|
@ -1290,9 +1296,10 @@ SECKEY_ECParamsToKeySize(const SECItem *encodedParams)
|
||||||
|
|
||||||
/* returns key strength in bytes (not bits) */
|
/* returns key strength in bytes (not bits) */
|
||||||
unsigned
|
unsigned
|
||||||
SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk)
|
SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
|
||||||
{
|
{
|
||||||
unsigned char b0;
|
unsigned char b0;
|
||||||
|
unsigned size;
|
||||||
|
|
||||||
/* interpret modulus length as key strength... in
|
/* interpret modulus length as key strength... in
|
||||||
* fortezza that's the public key length */
|
* 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);
|
return PR_MAX(pubk->u.fortezza.KEAKey.len, pubk->u.fortezza.DSSKey.len);
|
||||||
case ecKey:
|
case ecKey:
|
||||||
/* Get the key size in bits and adjust */
|
/* Get the key size in bits and adjust */
|
||||||
if (pubk->u.ec.size == 0) {
|
size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
|
||||||
pubk->u.ec.size =
|
return (size + 7)/8;
|
||||||
SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
|
|
||||||
}
|
|
||||||
return (pubk->u.ec.size + 7)/8;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1326,8 +1330,9 @@ SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk)
|
||||||
|
|
||||||
/* returns key strength in bits */
|
/* returns key strength in bits */
|
||||||
unsigned
|
unsigned
|
||||||
SECKEY_PublicKeyStrengthInBits(SECKEYPublicKey *pubk)
|
SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk)
|
||||||
{
|
{
|
||||||
|
unsigned size;
|
||||||
switch (pubk->keyType) {
|
switch (pubk->keyType) {
|
||||||
case rsaKey:
|
case rsaKey:
|
||||||
case dsaKey:
|
case dsaKey:
|
||||||
|
@ -1335,11 +1340,8 @@ SECKEY_PublicKeyStrengthInBits(SECKEYPublicKey *pubk)
|
||||||
case fortezzaKey:
|
case fortezzaKey:
|
||||||
return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */
|
return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */
|
||||||
case ecKey:
|
case ecKey:
|
||||||
if (pubk->u.ec.size == 0) {
|
size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
|
||||||
pubk->u.ec.size =
|
return size;
|
||||||
SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
|
|
||||||
}
|
|
||||||
return pubk->u.ec.size;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1347,7 +1349,7 @@ SECKEY_PublicKeyStrengthInBits(SECKEYPublicKey *pubk)
|
||||||
}
|
}
|
||||||
|
|
||||||
SECKEYPrivateKey *
|
SECKEYPrivateKey *
|
||||||
SECKEY_CopyPrivateKey(SECKEYPrivateKey *privk)
|
SECKEY_CopyPrivateKey(const SECKEYPrivateKey *privk)
|
||||||
{
|
{
|
||||||
SECKEYPrivateKey *copyk;
|
SECKEYPrivateKey *copyk;
|
||||||
PRArenaPool *arena;
|
PRArenaPool *arena;
|
||||||
|
@ -1393,7 +1395,7 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
SECKEYPublicKey *
|
SECKEYPublicKey *
|
||||||
SECKEY_CopyPublicKey(SECKEYPublicKey *pubk)
|
SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk)
|
||||||
{
|
{
|
||||||
SECKEYPublicKey *copyk;
|
SECKEYPublicKey *copyk;
|
||||||
PRArenaPool *arena;
|
PRArenaPool *arena;
|
||||||
|
@ -1944,8 +1946,8 @@ SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge,
|
||||||
/* check the signature */
|
/* check the signature */
|
||||||
sig = sd.signature;
|
sig = sd.signature;
|
||||||
DER_ConvertBitString(&sig);
|
DER_ConvertBitString(&sig);
|
||||||
rv = VFY_VerifyData(sd.data.data, sd.data.len, pubKey, &sig,
|
rv = VFY_VerifyDataWithAlgorithmID(sd.data.data, sd.data.len, pubKey, &sig,
|
||||||
SECOID_GetAlgorithmTag(&(sd.signatureAlgorithm)), wincx);
|
&(sd.signatureAlgorithm), NULL, wincx);
|
||||||
if ( rv != SECSuccess ) {
|
if ( rv != SECSuccess ) {
|
||||||
goto loser;
|
goto loser;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** 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 <stdio.h>
|
||||||
#include "cryptohi.h"
|
#include "cryptohi.h"
|
||||||
|
@ -48,6 +48,7 @@
|
||||||
#include "secdig.h"
|
#include "secdig.h"
|
||||||
#include "pk11func.h"
|
#include "pk11func.h"
|
||||||
#include "secerr.h"
|
#include "secerr.h"
|
||||||
|
#include "keyi.h"
|
||||||
|
|
||||||
struct SGNContextStr {
|
struct SGNContextStr {
|
||||||
SECOidTag signalg;
|
SECOidTag signalg;
|
||||||
|
@ -63,6 +64,7 @@ SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key)
|
||||||
SGNContext *cx;
|
SGNContext *cx;
|
||||||
SECOidTag hashalg, signalg;
|
SECOidTag hashalg, signalg;
|
||||||
KeyType keyType;
|
KeyType keyType;
|
||||||
|
SECStatus rv;
|
||||||
|
|
||||||
/* OK, map a PKCS #7 hash and encrypt algorithm into
|
/* OK, map a PKCS #7 hash and encrypt algorithm into
|
||||||
* a standard hashing algorithm. Why did we pass in the whole
|
* 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,
|
* 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.
|
* it may just support CKM_RSA_PKCS_WITH_SHA1 and/or CKM_RSA_PKCS_WITH_MD5.
|
||||||
*/
|
*/
|
||||||
switch (alg) {
|
/* we have a private key, not a public key, so don't pass it in */
|
||||||
/* We probably shouldn't be generating MD2 signatures either */
|
rv = sec_DecodeSigAlg(NULL, alg, NULL, &signalg, &hashalg);
|
||||||
case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
|
if (rv != SECSuccess) {
|
||||||
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:
|
|
||||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
keyType = seckey_GetKeyType(signalg);
|
||||||
|
|
||||||
/* verify our key type */
|
/* verify our key type */
|
||||||
if (key->keyType != keyType &&
|
if (key->keyType != keyType &&
|
||||||
|
@ -503,9 +450,19 @@ SEC_GetSignatureAlgorithmOidTag(KeyType keyType, SECOidTag hashAlgTag)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ecKey:
|
case ecKey:
|
||||||
/* XXX For now only ECDSA with SHA1 is supported */
|
switch (hashAlgTag) {
|
||||||
sigTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
|
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;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** 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 <stdio.h>
|
||||||
#include "cryptohi.h"
|
#include "cryptohi.h"
|
||||||
|
@ -48,6 +48,7 @@
|
||||||
#include "pk11func.h"
|
#include "pk11func.h"
|
||||||
#include "secdig.h"
|
#include "secdig.h"
|
||||||
#include "secerr.h"
|
#include "secerr.h"
|
||||||
|
#include "keyi.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Decrypt signature block using public key
|
** Decrypt signature block using public key
|
||||||
|
@ -57,7 +58,7 @@
|
||||||
*/
|
*/
|
||||||
static SECStatus
|
static SECStatus
|
||||||
DecryptSigBlock(SECOidTag *tagp, unsigned char *digest, unsigned int len,
|
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;
|
SGNDigestInfo *di = NULL;
|
||||||
unsigned char *buf = NULL;
|
unsigned char *buf = NULL;
|
||||||
|
@ -73,7 +74,7 @@ DecryptSigBlock(SECOidTag *tagp, unsigned char *digest, unsigned int len,
|
||||||
if (!buf) goto loser;
|
if (!buf) goto loser;
|
||||||
|
|
||||||
/* decrypt the block */
|
/* decrypt the block */
|
||||||
rv = PK11_VerifyRecover(key, sig, &it, wincx);
|
rv = PK11_VerifyRecover(key, (SECItem *)sig, &it, wincx);
|
||||||
if (rv != SECSuccess) goto loser;
|
if (rv != SECSuccess) goto loser;
|
||||||
|
|
||||||
di = SGN_DecodeDigestInfo(&it);
|
di = SGN_DecodeDigestInfo(&it);
|
||||||
|
@ -106,11 +107,10 @@ DecryptSigBlock(SECOidTag *tagp, unsigned char *digest, unsigned int len,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum { VFY_RSA, VFY_DSA, VFY_ECDSA } VerifyType;
|
|
||||||
|
|
||||||
struct VFYContextStr {
|
struct VFYContextStr {
|
||||||
SECOidTag alg; /* the hash algorithm */
|
SECOidTag alg; /* the hash algorithm */
|
||||||
VerifyType type;
|
KeyType type;
|
||||||
SECKEYPublicKey *key;
|
SECKEYPublicKey *key;
|
||||||
/*
|
/*
|
||||||
* This buffer holds either the digest or the full signature
|
* This buffer holds either the digest or the full signature
|
||||||
|
@ -134,7 +134,7 @@ struct VFYContextStr {
|
||||||
void * wincx;
|
void * wincx;
|
||||||
void *hashcx;
|
void *hashcx;
|
||||||
const SECHashObject *hashobj;
|
const SECHashObject *hashobj;
|
||||||
SECOidTag sigAlg; /* the (composite) signature algorithm */
|
SECOidTag encAlg; /* enc alg */
|
||||||
PRBool hasSignature; /* true if the signature was provided in the
|
PRBool hasSignature; /* true if the signature was provided in the
|
||||||
* VFY_CreateContext call. If false, the
|
* VFY_CreateContext call. If false, the
|
||||||
* signature must be provided with a
|
* signature must be provided with a
|
||||||
|
@ -147,39 +147,34 @@ struct VFYContextStr {
|
||||||
* to by dsig and has enough room for len bytes.
|
* to by dsig and has enough room for len bytes.
|
||||||
*/
|
*/
|
||||||
static SECStatus
|
static SECStatus
|
||||||
decodeECorDSASignature(SECOidTag algid, SECItem *sig, unsigned char *dsig,
|
decodeECorDSASignature(SECOidTag algid, const SECItem *sig, unsigned char *dsig,
|
||||||
unsigned int len) {
|
unsigned int len) {
|
||||||
SECItem *dsasig = NULL; /* also used for ECDSA */
|
SECItem *dsasig = NULL; /* also used for ECDSA */
|
||||||
SECStatus rv=SECSuccess;
|
SECStatus rv=SECSuccess;
|
||||||
|
|
||||||
switch (algid) {
|
if ((algid != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
|
||||||
case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
|
(algid != SEC_OID_ANSIX962_EC_PUBLIC_KEY) ) {
|
||||||
case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
|
if (sig->len != len) {
|
||||||
case SEC_OID_ANSIX9_DSA_SIGNATURE:
|
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||||
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST:
|
return SECFailure;
|
||||||
if (algid == SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST) {
|
|
||||||
if (len > MAX_ECKEY_LEN * 2) {
|
|
||||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
|
||||||
return SECFailure;
|
|
||||||
}
|
|
||||||
dsasig = DSAU_DecodeDerSigToLen(sig, len);
|
|
||||||
} else {
|
|
||||||
dsasig = DSAU_DecodeDerSig(sig);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dsasig == NULL) || (dsasig->len != len)) {
|
PORT_Memcpy(dsig, sig->data, sig->len);
|
||||||
rv = SECFailure;
|
return SECSuccess;
|
||||||
} else {
|
}
|
||||||
PORT_Memcpy(dsig, dsasig->data, dsasig->len);
|
|
||||||
|
if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
|
||||||
|
if (len > MAX_ECKEY_LEN * 2) {
|
||||||
|
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||||
|
return SECFailure;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
default:
|
dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len);
|
||||||
if (sig->len != len) {
|
|
||||||
rv = SECFailure;
|
if ((dsasig == NULL) || (dsasig->len != len)) {
|
||||||
} else {
|
rv = SECFailure;
|
||||||
PORT_Memcpy(dsig, sig->data, sig->len);
|
} else {
|
||||||
}
|
PORT_Memcpy(dsig, dsasig->data, dsasig->len);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dsasig != NULL) SECITEM_FreeItem(dsasig, PR_TRUE);
|
if (dsasig != NULL) SECITEM_FreeItem(dsasig, PR_TRUE);
|
||||||
|
@ -187,25 +182,38 @@ decodeECorDSASignature(SECOidTag algid, SECItem *sig, unsigned char *dsig,
|
||||||
return rv;
|
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
|
* Pulls the hash algorithm, signing algorithm, and key type out of a
|
||||||
* composite algorithm.
|
* composite algorithm.
|
||||||
*
|
*
|
||||||
* alg: the composite algorithm to dissect.
|
* alg: the composite algorithm to dissect.
|
||||||
* hashalg: address of a SECOidTag which will be set with the hash algorithm.
|
* 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.
|
* encalg: 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)
|
|
||||||
* Returns: SECSuccess if the algorithm was acceptable, SECFailure if the
|
* Returns: SECSuccess if the algorithm was acceptable, SECFailure if the
|
||||||
* algorithm was not found or was not a signing algorithm.
|
* algorithm was not found or was not a signing algorithm.
|
||||||
*/
|
*/
|
||||||
static SECStatus
|
SECStatus
|
||||||
decodeSigAlg(SECOidTag alg, SECOidTag *hashalg)
|
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 */
|
/* We probably shouldn't be generating MD2 signatures either */
|
||||||
case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
|
case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
|
||||||
*hashalg = SEC_OID_MD2;
|
*hashalg = SEC_OID_MD2;
|
||||||
|
@ -217,13 +225,19 @@ decodeSigAlg(SECOidTag alg, SECOidTag *hashalg)
|
||||||
case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
|
case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
|
||||||
*hashalg = SEC_OID_SHA1;
|
*hashalg = SEC_OID_SHA1;
|
||||||
break;
|
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:
|
case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
|
||||||
*hashalg = SEC_OID_SHA256;
|
*hashalg = SEC_OID_SHA256;
|
||||||
break;
|
break;
|
||||||
|
case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
|
||||||
case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
|
case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
|
||||||
*hashalg = SEC_OID_SHA384;
|
*hashalg = SEC_OID_SHA384;
|
||||||
break;
|
break;
|
||||||
|
case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
|
||||||
case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
|
case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
|
||||||
*hashalg = SEC_OID_SHA512;
|
*hashalg = SEC_OID_SHA512;
|
||||||
break;
|
break;
|
||||||
|
@ -231,7 +245,7 @@ decodeSigAlg(SECOidTag alg, SECOidTag *hashalg)
|
||||||
/* what about normal DSA? */
|
/* what about normal DSA? */
|
||||||
case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
|
case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
|
||||||
case SEC_OID_BOGUS_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;
|
*hashalg = SEC_OID_SHA1;
|
||||||
break;
|
break;
|
||||||
case SEC_OID_MISSI_DSS:
|
case SEC_OID_MISSI_DSS:
|
||||||
|
@ -240,85 +254,217 @@ decodeSigAlg(SECOidTag alg, SECOidTag *hashalg)
|
||||||
case SEC_OID_MISSI_DSS_OLD:
|
case SEC_OID_MISSI_DSS_OLD:
|
||||||
*hashalg = SEC_OID_SHA1;
|
*hashalg = SEC_OID_SHA1;
|
||||||
break;
|
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 */
|
/* we don't implement MD4 hashes */
|
||||||
case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
|
case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
|
||||||
default:
|
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 SECFailure;
|
||||||
}
|
}
|
||||||
return SECSuccess;
|
return SECSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
VFYContext *
|
/*
|
||||||
VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag algid,
|
* we can verify signatures that come from 2 different sources:
|
||||||
void *wincx)
|
* 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;
|
VFYContext *cx;
|
||||||
SECStatus rv;
|
SECStatus rv;
|
||||||
unsigned int sigLen;
|
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));
|
cx = (VFYContext*) PORT_ZAlloc(sizeof(VFYContext));
|
||||||
if (cx) {
|
if (cx == NULL) {
|
||||||
cx->wincx = wincx;
|
goto loser;
|
||||||
cx->hasSignature = (sig != NULL);
|
}
|
||||||
cx->sigAlg = algid;
|
|
||||||
rv = SECSuccess;
|
cx->wincx = wincx;
|
||||||
|
cx->hasSignature = (sig != NULL);
|
||||||
|
cx->encAlg = encAlg;
|
||||||
|
cx->alg = hashAlg;
|
||||||
|
cx->key = SECKEY_CopyPublicKey(key);
|
||||||
|
cx->type = key->keyType;
|
||||||
|
rv = SECSuccess;
|
||||||
|
if (sig) {
|
||||||
switch (key->keyType) {
|
switch (key->keyType) {
|
||||||
case rsaKey:
|
case rsaKey:
|
||||||
cx->type = VFY_RSA;
|
rv = DecryptSigBlock(&hashid, cx->u.buffer,
|
||||||
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);
|
HASH_LENGTH_MAX, cx->key, sig, (char*)wincx);
|
||||||
cx->alg = hashid;
|
if (cx->alg != SEC_OID_UNKNOWN && cx->alg != hashid) {
|
||||||
} else {
|
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||||
rv = decodeSigAlg(algid,&cx->alg);
|
rv = SECFailure;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
cx->alg = hashid;
|
||||||
break;
|
break;
|
||||||
case fortezzaKey:
|
|
||||||
case dsaKey:
|
case dsaKey:
|
||||||
case ecKey:
|
case ecKey:
|
||||||
if (key->keyType == ecKey) {
|
sigLen = (key->keyType == ecKey) ?
|
||||||
cx->type = VFY_ECDSA;
|
SECKEY_PublicKeyStrength(key) * 2 :
|
||||||
/* Unlike DSA, EDSA does not have a fixed signature length
|
DSA_SIGNATURE_LEN;
|
||||||
* (it depends on the key size)
|
rv = decodeECorDSASignature(encAlg, sig, cx->u.buffer, sigLen);
|
||||||
*/
|
break;
|
||||||
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:
|
default:
|
||||||
rv = SECFailure;
|
rv = SECFailure;
|
||||||
|
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (rv) goto loser;
|
}
|
||||||
switch (cx->alg) {
|
|
||||||
case SEC_OID_MD2:
|
if (rv) goto loser;
|
||||||
case SEC_OID_MD5:
|
|
||||||
case SEC_OID_SHA1:
|
/* check hash alg again, RSA may have changed it.*/
|
||||||
case SEC_OID_SHA256:
|
if (HASH_GetHashTypeByOidTag(cx->alg) == HASH_AlgNULL) {
|
||||||
case SEC_OID_SHA384:
|
/* error set by HASH_GetHashTypeByOidTag */
|
||||||
case SEC_OID_SHA512:
|
return NULL;
|
||||||
break;
|
}
|
||||||
default:
|
|
||||||
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
|
if (hash) {
|
||||||
goto loser;
|
*hash = cx->alg;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return cx;
|
return cx;
|
||||||
|
|
||||||
loser:
|
loser:
|
||||||
VFY_DestroyContext(cx, PR_TRUE);
|
if (cx) {
|
||||||
|
VFY_DestroyContext(cx, PR_TRUE);
|
||||||
|
}
|
||||||
return 0;
|
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
|
void
|
||||||
VFY_DestroyContext(VFYContext *cx, PRBool freeit)
|
VFY_DestroyContext(VFYContext *cx, PRBool freeit)
|
||||||
{
|
{
|
||||||
|
@ -357,7 +503,7 @@ VFY_Begin(VFYContext *cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
SECStatus
|
SECStatus
|
||||||
VFY_Update(VFYContext *cx, unsigned char *input, unsigned inputLen)
|
VFY_Update(VFYContext *cx, const unsigned char *input, unsigned inputLen)
|
||||||
{
|
{
|
||||||
if (cx->hashcx == NULL) {
|
if (cx->hashcx == NULL) {
|
||||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
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));
|
(*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));
|
||||||
switch (cx->type) {
|
switch (cx->type) {
|
||||||
case VFY_DSA:
|
case ecKey:
|
||||||
case VFY_ECDSA:
|
case dsaKey:
|
||||||
dsasig.data = cx->u.buffer;
|
dsasig.data = cx->u.buffer;
|
||||||
if (cx->type == VFY_DSA) {
|
dsasig.len = (cx->type == ecKey) ?
|
||||||
dsasig.len = DSA_SIGNATURE_LEN;
|
SECKEY_PublicKeyStrength(cx->key) * 2 :
|
||||||
} else {
|
DSA_SIGNATURE_LEN;
|
||||||
dsasig.len = SECKEY_PublicKeyStrength(cx->key) * 2;
|
|
||||||
}
|
|
||||||
if (sig) {
|
if (sig) {
|
||||||
rv = decodeECorDSASignature(cx->sigAlg,sig,dsasig.data,
|
rv = decodeECorDSASignature(cx->encAlg, sig, dsasig.data,
|
||||||
dsasig.len);
|
dsasig.len);
|
||||||
if (rv != SECSuccess) {
|
if (rv != SECSuccess) {
|
||||||
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||||
|
@ -409,7 +553,7 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
|
||||||
return SECFailure;
|
return SECFailure;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case VFY_RSA:
|
case rsaKey:
|
||||||
if (sig) {
|
if (sig) {
|
||||||
SECOidTag hashid = SEC_OID_UNKNOWN;
|
SECOidTag hashid = SEC_OID_UNKNOWN;
|
||||||
rv = DecryptSigBlock(&hashid, cx->u.buffer,
|
rv = DecryptSigBlock(&hashid, cx->u.buffer,
|
||||||
|
@ -440,13 +584,11 @@ VFY_End(VFYContext *cx)
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/*
|
/*
|
||||||
* Verify that a previously-computed digest matches a signature.
|
* 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
|
static SECStatus
|
||||||
VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
|
vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key,
|
||||||
SECOidTag algid, void *wincx)
|
const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
|
||||||
|
void *wincx)
|
||||||
{
|
{
|
||||||
SECStatus rv;
|
SECStatus rv;
|
||||||
VFYContext *cx;
|
VFYContext *cx;
|
||||||
|
@ -454,7 +596,7 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
|
||||||
|
|
||||||
rv = SECFailure;
|
rv = SECFailure;
|
||||||
|
|
||||||
cx = VFY_CreateContext(key, sig, algid, wincx);
|
cx = vfy_CreateContext(key, sig, encAlg, hashAlg, NULL, wincx);
|
||||||
if (cx != NULL) {
|
if (cx != NULL) {
|
||||||
switch (key->keyType) {
|
switch (key->keyType) {
|
||||||
case rsaKey:
|
case rsaKey:
|
||||||
|
@ -464,7 +606,6 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
|
||||||
rv = SECSuccess;
|
rv = SECSuccess;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case fortezzaKey:
|
|
||||||
case dsaKey:
|
case dsaKey:
|
||||||
case ecKey:
|
case ecKey:
|
||||||
dsasig.data = cx->u.buffer;
|
dsasig.data = cx->u.buffer;
|
||||||
|
@ -474,7 +615,7 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
|
||||||
/* magic size of dsa signature */
|
/* magic size of dsa signature */
|
||||||
dsasig.len = DSA_SIGNATURE_LEN;
|
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) {
|
!= SECSuccess) {
|
||||||
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
|
||||||
} else {
|
} else {
|
||||||
|
@ -490,19 +631,66 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
|
||||||
}
|
}
|
||||||
|
|
||||||
SECStatus
|
SECStatus
|
||||||
VFY_VerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
|
VFY_VerifyDigestDirect(const SECItem *digest, const SECKEYPublicKey *key,
|
||||||
SECItem *sig, SECOidTag algid, void *wincx)
|
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;
|
SECStatus rv;
|
||||||
VFYContext *cx;
|
VFYContext *cx;
|
||||||
|
|
||||||
cx = VFY_CreateContext(key, sig, algid, wincx);
|
cx = vfy_CreateContext(key, sig, encAlg, hashAlg, hash, wincx);
|
||||||
if (cx == NULL)
|
if (cx == NULL)
|
||||||
return SECFailure;
|
return SECFailure;
|
||||||
|
|
||||||
rv = VFY_Begin(cx);
|
rv = VFY_Begin(cx);
|
||||||
if (rv == SECSuccess) {
|
if (rv == SECSuccess) {
|
||||||
rv = VFY_Update(cx, buf, len);
|
rv = VFY_Update(cx, (unsigned char *)buf, len);
|
||||||
if (rv == SECSuccess)
|
if (rv == SECSuccess)
|
||||||
rv = VFY_End(cx);
|
rv = VFY_End(cx);
|
||||||
}
|
}
|
||||||
|
@ -510,3 +698,41 @@ VFY_VerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,
|
||||||
VFY_DestroyContext(cx, PR_TRUE);
|
VFY_DestroyContext(cx, PR_TRUE);
|
||||||
return rv;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -875,6 +875,12 @@ SECMOD_OpenUserDB;
|
||||||
;+NSS_3.12 { # NSS 3.12 release
|
;+NSS_3.12 { # NSS 3.12 release
|
||||||
;+ global:
|
;+ global:
|
||||||
PK11_GetAllSlotsForCert;
|
PK11_GetAllSlotsForCert;
|
||||||
|
VFY_CreateContextDirect;
|
||||||
|
VFY_CreateContextWithAlgorithmID;
|
||||||
|
VFY_VerifyDataDirect;
|
||||||
|
VFY_VerifyDataWithAlgorithmID;
|
||||||
|
VFY_VerifyDigestDirect;
|
||||||
|
VFY_VerifyDigestWithAlgorithmID;
|
||||||
;+ local:
|
;+ local:
|
||||||
;+ *;
|
;+ *;
|
||||||
;+};
|
;+};
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
/*
|
/*
|
||||||
* PKCS7 decoding, verification.
|
* 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"
|
#include "nssrenam.h"
|
||||||
|
@ -1436,7 +1436,8 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
|
||||||
CERTCertificate *cert, **certs;
|
CERTCertificate *cert, **certs;
|
||||||
PRBool goodsig;
|
PRBool goodsig;
|
||||||
CERTCertDBHandle *certdb, *defaultdb;
|
CERTCertDBHandle *certdb, *defaultdb;
|
||||||
SECOidData *algiddata;
|
SECOidTag encTag,digestTag;
|
||||||
|
HASH_HashType found_type;
|
||||||
int i, certcount;
|
int i, certcount;
|
||||||
SECKEYPublicKey *publickey;
|
SECKEYPublicKey *publickey;
|
||||||
SECItem *content_type;
|
SECItem *content_type;
|
||||||
|
@ -1615,14 +1616,19 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
|
||||||
/*
|
/*
|
||||||
* Find and confirm digest algorithm.
|
* 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) {
|
if (detached_digest != NULL) {
|
||||||
HASH_HashType found_type = HASH_GetHashTypeByOidTag(algiddata->offset);
|
unsigned int hashLen = HASH_ResultLen(found_type);
|
||||||
unsigned int hashLen = HASH_ResultLen(digest_type);
|
|
||||||
|
|
||||||
if (digest_type != found_type ||
|
if (digest_type != found_type ||
|
||||||
digest_type == HASH_AlgNULL ||
|
|
||||||
detached_digest->len != hashLen) {
|
detached_digest->len != hashLen) {
|
||||||
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
|
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -1638,12 +1644,8 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
|
||||||
/*
|
/*
|
||||||
* pick digest matching signerinfo->digestAlg from digests
|
* 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++) {
|
for (i = 0; digestalgs[i] != NULL; i++) {
|
||||||
if (SECOID_FindOID (&(digestalgs[i]->algorithm)) == algiddata)
|
if (SECOID_FindOIDTag(&(digestalgs[i]->algorithm)) == digestTag)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (digestalgs[i] == NULL) {
|
if (digestalgs[i] == NULL) {
|
||||||
|
@ -1654,19 +1656,8 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
|
||||||
digest = digests[i];
|
digest = digests[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
encTag = SECOID_FindOIDTag(&(signerinfo->digestEncAlg.algorithm));
|
||||||
* XXX This may not be the right set of algorithms to check.
|
if (encTag == SEC_OID_UNKNOWN) {
|
||||||
* 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))) {
|
|
||||||
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
|
PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -1735,14 +1726,10 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
goodsig = (PRBool)(VFY_VerifyDataDirect(encoded_attrs.data,
|
||||||
* 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,
|
|
||||||
encoded_attrs.len,
|
encoded_attrs.len,
|
||||||
publickey, &(signerinfo->encDigest),
|
publickey, &(signerinfo->encDigest),
|
||||||
SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)),
|
encTag, digestTag, NULL,
|
||||||
cinfo->pwfn_arg) == SECSuccess);
|
cinfo->pwfn_arg) == SECSuccess);
|
||||||
PORT_Free (encoded_attrs.data);
|
PORT_Free (encoded_attrs.data);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1797,14 +1784,9 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo,
|
||||||
sig = &holder;
|
sig = &holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
goodsig = (PRBool)(VFY_VerifyDigestDirect(digest, publickey, sig,
|
||||||
* XXX the 4th (algid) argument should be the signature algorithm.
|
encTag, digestTag, cinfo->pwfn_arg)
|
||||||
* See sec_pkcs7_pick_sign_alg in p7encode.c.
|
== SECSuccess);
|
||||||
*/
|
|
||||||
goodsig = (PRBool)(VFY_VerifyDigest (digest, publickey, sig,
|
|
||||||
SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)),
|
|
||||||
cinfo->pwfn_arg)
|
|
||||||
== SECSuccess);
|
|
||||||
|
|
||||||
if (sigkey != NULL) {
|
if (sigkey != NULL) {
|
||||||
PORT_Assert (sig == &holder);
|
PORT_Assert (sig == &holder);
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
/*
|
/*
|
||||||
* PKCS7 encoding.
|
* 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"
|
#include "nssrenam.h"
|
||||||
|
@ -835,56 +835,6 @@ SEC_PKCS7EncoderUpdate (SEC_PKCS7EncoderContext *p7ecx,
|
||||||
PR_FALSE);
|
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
|
static SECStatus
|
||||||
sec_pkcs7_encoder_sig_and_certs (SEC_PKCS7ContentInfo *cinfo,
|
sec_pkcs7_encoder_sig_and_certs (SEC_PKCS7ContentInfo *cinfo,
|
||||||
SECKEYGetPasswordKey pwfn, void *pwfnarg)
|
SECKEYGetPasswordKey pwfn, void *pwfnarg)
|
||||||
|
@ -1000,6 +950,7 @@ sec_pkcs7_encoder_sig_and_certs (SEC_PKCS7ContentInfo *cinfo,
|
||||||
SEC_PKCS7Attribute *attr;
|
SEC_PKCS7Attribute *attr;
|
||||||
SECItem encoded_attrs;
|
SECItem encoded_attrs;
|
||||||
SECItem *dummy;
|
SECItem *dummy;
|
||||||
|
SECOidTag algid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First, find and fill in the message digest attribute.
|
* First, find and fill in the message digest attribute.
|
||||||
|
@ -1050,11 +1001,17 @@ sec_pkcs7_encoder_sig_and_certs (SEC_PKCS7ContentInfo *cinfo,
|
||||||
return SECFailure;
|
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,
|
rv = SEC_SignData (&signature,
|
||||||
encoded_attrs.data, encoded_attrs.len,
|
encoded_attrs.data, encoded_attrs.len,
|
||||||
privkey,
|
privkey,
|
||||||
sec_pkcs7_pick_sign_alg (digestalgtag,
|
algid);
|
||||||
signalgtag));
|
|
||||||
SECITEM_FreeItem (&encoded_attrs, PR_FALSE);
|
SECITEM_FreeItem (&encoded_attrs, PR_FALSE);
|
||||||
} else {
|
} else {
|
||||||
rv = SGN_Digest (privkey, digestalgtag, &signature,
|
rv = SGN_Digest (privkey, digestalgtag, &signature,
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
/*
|
/*
|
||||||
* Interfaces of the CMS implementation.
|
* 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_
|
#ifndef _CMS_H_
|
||||||
|
@ -410,13 +410,6 @@ NSS_CMSAlgArray_GetIndexByAlgTag(SECAlgorithmID **algorithmArray, SECOidTag algt
|
||||||
extern const SECHashObject *
|
extern const SECHashObject *
|
||||||
NSS_CMSUtil_GetHashObjByAlgID(SECAlgorithmID *algid);
|
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 *
|
extern const SEC_ASN1Template *
|
||||||
NSS_CMSUtil_GetTemplateByTypeTag(SECOidTag type);
|
NSS_CMSUtil_GetTemplateByTypeTag(SECOidTag type);
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
/*
|
/*
|
||||||
* CMS signerInfo methods.
|
* 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"
|
#include "cmslocal.h"
|
||||||
|
@ -262,7 +262,13 @@ NSS_CMSSignerInfo_Sign(NSSCMSSignerInfo *signerinfo, SECItem *digest, SECItem *c
|
||||||
&encoded_attrs) == NULL)
|
&encoded_attrs) == NULL)
|
||||||
goto loser;
|
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,
|
rv = SEC_SignData(&signature, encoded_attrs.data, encoded_attrs.len,
|
||||||
privkey, signAlgTag);
|
privkey, signAlgTag);
|
||||||
PORT_FreeArena(tmppoolp, PR_FALSE); /* awkward memory management :-( */
|
PORT_FreeArena(tmppoolp, PR_FALSE); /* awkward memory management :-( */
|
||||||
|
@ -350,7 +356,6 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo,
|
||||||
PLArenaPool *poolp;
|
PLArenaPool *poolp;
|
||||||
SECOidTag digestalgtag;
|
SECOidTag digestalgtag;
|
||||||
SECOidTag pubkAlgTag;
|
SECOidTag pubkAlgTag;
|
||||||
SECOidTag signAlgTag;
|
|
||||||
|
|
||||||
if (signerinfo == NULL)
|
if (signerinfo == NULL)
|
||||||
return SECFailure;
|
return SECFailure;
|
||||||
|
@ -370,35 +375,12 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
digestalgtag = NSS_CMSSignerInfo_GetDigestAlgTag(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));
|
pubkAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg));
|
||||||
switch (pubkAlgTag) {
|
if ((pubkAlgTag == SEC_OID_UNKNOWN) || (digestalgtag == SEC_OID_UNKNOWN)) {
|
||||||
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:
|
|
||||||
vs = NSSCMSVS_SignatureAlgorithmUnknown;
|
vs = NSSCMSVS_SignatureAlgorithmUnknown;
|
||||||
goto loser;
|
goto loser;
|
||||||
default:
|
|
||||||
vs = NSSCMSVS_SignatureAlgorithmUnsupported;
|
|
||||||
goto loser;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
signAlgTag = NSS_CMSUtil_MakeSignatureAlgorithm(digestalgtag, pubkAlgTag);
|
|
||||||
|
|
||||||
if (!NSS_CMSArray_IsEmpty((void **)signerinfo->authAttr)) {
|
if (!NSS_CMSArray_IsEmpty((void **)signerinfo->authAttr)) {
|
||||||
if (contentType) {
|
if (contentType) {
|
||||||
/*
|
/*
|
||||||
|
@ -461,10 +443,10 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo,
|
||||||
goto loser;
|
goto loser;
|
||||||
}
|
}
|
||||||
|
|
||||||
vs = (VFY_VerifyData (encoded_attrs.data, encoded_attrs.len,
|
vs = (VFY_VerifyDataDirect(encoded_attrs.data, encoded_attrs.len,
|
||||||
publickey, &(signerinfo->encDigest), signAlgTag,
|
publickey, &(signerinfo->encDigest), pubkAlgTag,
|
||||||
signerinfo->cmsg->pwfn_arg) != SECSuccess)
|
digestalgtag, NULL, signerinfo->cmsg->pwfn_arg) != SECSuccess)
|
||||||
? NSSCMSVS_BadSignature : NSSCMSVS_GoodSignature;
|
? NSSCMSVS_BadSignature : NSSCMSVS_GoodSignature;
|
||||||
|
|
||||||
PORT_FreeArena(poolp, PR_FALSE); /* awkward memory management :-( */
|
PORT_FreeArena(poolp, PR_FALSE); /* awkward memory management :-( */
|
||||||
|
|
||||||
|
@ -479,16 +461,17 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo,
|
||||||
goto loser;
|
goto loser;
|
||||||
|
|
||||||
vs = (!digest ||
|
vs = (!digest ||
|
||||||
VFY_VerifyDigest(digest, publickey, sig, signAlgTag,
|
VFY_VerifyDigestDirect(digest, publickey, sig, pubkAlgTag,
|
||||||
signerinfo->cmsg->pwfn_arg) != SECSuccess)
|
digestalgtag, signerinfo->cmsg->pwfn_arg) != SECSuccess)
|
||||||
? NSSCMSVS_BadSignature : NSSCMSVS_GoodSignature;
|
? NSSCMSVS_BadSignature : NSSCMSVS_GoodSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vs == NSSCMSVS_BadSignature) {
|
if (vs == NSSCMSVS_BadSignature) {
|
||||||
|
int error = PORT_GetError();
|
||||||
/*
|
/*
|
||||||
* XXX Change the generic error into our specific one, because
|
* XXX Change the generic error into our specific one, because
|
||||||
* in that case we get a better explanation out of the Security
|
* 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
|
* "generic" error has a lousy/wrong message associated with it
|
||||||
* which assumes the signature verification was done for the
|
* which assumes the signature verification was done for the
|
||||||
* purposes of checking the issuer signature on a certificate)
|
* 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
|
* certificate signature check that failed during the cert
|
||||||
* verification done above. Our error handling is really a mess.
|
* 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);
|
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)
|
if (publickey != NULL)
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
/*
|
/*
|
||||||
* CMS miscellaneous utility functions.
|
* 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"
|
#include "nssrenam.h"
|
||||||
|
@ -222,54 +222,6 @@ NSS_CMSUtil_GetHashObjByAlgID(SECAlgorithmID *algid)
|
||||||
return digobj;
|
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 *
|
const SEC_ASN1Template *
|
||||||
NSS_CMSUtil_GetTemplateByTypeTag(SECOidTag type)
|
NSS_CMSUtil_GetTemplateByTypeTag(SECOidTag type)
|
||||||
{
|
{
|
||||||
|
|
|
@ -166,6 +166,8 @@
|
||||||
#define ANSI_X962_CURVE_OID ANSI_X962_OID, 0x03
|
#define ANSI_X962_CURVE_OID ANSI_X962_OID, 0x03
|
||||||
#define ANSI_X962_GF2m_OID ANSI_X962_CURVE_OID, 0x00
|
#define ANSI_X962_GF2m_OID ANSI_X962_CURVE_OID, 0x00
|
||||||
#define ANSI_X962_GFp_OID ANSI_X962_CURVE_OID, 0x01
|
#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
|
#define CONST_OID static const unsigned char
|
||||||
|
|
||||||
|
@ -453,8 +455,14 @@ CONST_OID sha256[] = { SHAXXX, 1 };
|
||||||
CONST_OID sha384[] = { SHAXXX, 2 };
|
CONST_OID sha384[] = { SHAXXX, 2 };
|
||||||
CONST_OID sha512[] = { SHAXXX, 3 };
|
CONST_OID sha512[] = { SHAXXX, 3 };
|
||||||
|
|
||||||
CONST_OID ansix962ECPublicKey[] = { ANSI_X962_OID, 0x02, 0x01 };
|
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 */
|
/* ANSI X9.62 prime curve OIDs */
|
||||||
/* NOTE: prime192v1 is the same as secp192r1, prime256v1 is the
|
/* 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,
|
OD( ansix962ECPublicKey, SEC_OID_ANSIX962_EC_PUBLIC_KEY,
|
||||||
"X9.62 elliptic curve public key", CKM_ECDH1_DERIVE,
|
"X9.62 elliptic curve public key", CKM_ECDH1_DERIVE,
|
||||||
INVALID_CERT_EXTENSION ),
|
INVALID_CERT_EXTENSION ),
|
||||||
OD( ansix962ECDSASignaturewithSHA1Digest,
|
OD( ansix962SignaturewithSHA1Digest,
|
||||||
SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST,
|
SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE,
|
||||||
"X9.62 ECDSA signature with SHA1", CKM_ECDSA_SHA1,
|
"X9.62 ECDSA signature with SHA1", CKM_ECDSA_SHA1,
|
||||||
INVALID_CERT_EXTENSION ),
|
INVALID_CERT_EXTENSION ),
|
||||||
|
|
||||||
|
@ -1435,6 +1443,32 @@ const static SECOidData oids[] = {
|
||||||
OD( pkcs9ExtensionRequest, SEC_OID_PKCS9_EXTENSION_REQUEST,
|
OD( pkcs9ExtensionRequest, SEC_OID_PKCS9_EXTENSION_REQUEST,
|
||||||
"PKCS #9 Extension Request",
|
"PKCS #9 Extension Request",
|
||||||
CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
|
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 ),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
/*
|
/*
|
||||||
* secoidt.h - public data structures for ASN.1 OID functions
|
* 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"
|
#include "secitem.h"
|
||||||
|
@ -314,7 +314,10 @@ typedef enum {
|
||||||
|
|
||||||
/* Elliptic Curve Cryptography (ECC) OIDs */
|
/* Elliptic Curve Cryptography (ECC) OIDs */
|
||||||
SEC_OID_ANSIX962_EC_PUBLIC_KEY = 200,
|
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) */
|
/* ANSI X9.62 named elliptic curves (prime field) */
|
||||||
SEC_OID_ANSIX962_EC_PRIME192V1 = 202,
|
SEC_OID_ANSIX962_EC_PRIME192V1 = 202,
|
||||||
|
@ -403,6 +406,13 @@ typedef enum {
|
||||||
SEC_OID_PKIX_CA_ISSUERS = 273,
|
SEC_OID_PKIX_CA_ISSUERS = 273,
|
||||||
SEC_OID_PKCS9_EXTENSION_REQUEST = 274,
|
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
|
SEC_OID_TOTAL
|
||||||
} SECOidTag;
|
} SECOidTag;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче