secvfy.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 392 行

C
392
字号
/* * Verification stuff. * * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. * * $Id: secvfy.c,v 1.3 2000/06/13 21:56:22 chrisk%netscape.com Exp $ */#include <stdio.h>#include "cryptohi.h"#include "sechash.h"#include "keyhi.h"#include "secasn1.h"#include "secoid.h"#include "pk11func.h"#include "secdig.h"#include "secerr.h"/*** Decrypt signature block using public key (in place)** XXX this is assuming that the signature algorithm has WITH_RSA_ENCRYPTION*/static SECStatusDecryptSigBlock(int *tagp, unsigned char *digest, SECKEYPublicKey *key,		SECItem *sig, char *wincx){    SGNDigestInfo *di   = NULL;    unsigned char *dsig = NULL;    unsigned char *buf  = NULL;    SECStatus      rv;    SECOidTag      tag;    SECItem        it;    if (key == NULL) goto loser;    it.len  = SECKEY_PublicKeyStrength(key);    if (!it.len) goto loser;    it.data = buf = (unsigned char *)PORT_Alloc(it.len);    if (!buf) goto loser;    /* Decrypt signature block */    dsig = (unsigned char*) PORT_Alloc(sig->len);    if (dsig == NULL) goto loser;    /* decrypt the block */    rv = PK11_VerifyRecover(key, sig, &it, wincx);    if (rv != SECSuccess) goto loser;    di = SGN_DecodeDigestInfo(&it);    if (di == NULL) goto sigloser;    /*    ** Finally we have the digest info; now we can extract the algorithm    ** ID and the signature block    */    tag = SECOID_GetAlgorithmTag(&di->digestAlgorithm);    /* XXX Check that tag is an appropriate algorithm? */    if (di->digest.len > 32) {	PORT_SetError(SEC_ERROR_OUTPUT_LEN);	goto loser;    }    PORT_Memcpy(digest, di->digest.data, di->digest.len);    *tagp = tag;    goto done;  sigloser:    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);  loser:    rv = SECFailure;  done:    if (di   != NULL) SGN_DestroyDigestInfo(di);    if (dsig != NULL) PORT_Free(dsig);    if (buf  != NULL) PORT_Free(buf);        return rv;}typedef enum { VFY_RSA, VFY_DSA} VerifyType;struct VFYContextStr {    int alg;    VerifyType type;    SECKEYPublicKey *key;    /* digest holds the full dsa signature... 40 bytes */    unsigned char digest[DSA_SIGNATURE_LEN];    void * wincx;    void *hashcx;    SECHashObject *hashobj;};VFYContext *VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag algid,		  void *wincx){    VFYContext *cx;    SECStatus rv;    SECItem *dsasig = NULL;    cx = (VFYContext*) PORT_ZAlloc(sizeof(VFYContext));    if (cx) {        cx->wincx = cx;	switch (key->keyType) {	  case rsaKey:	    cx->type = VFY_RSA;	    cx->key = NULL; /* extra safety precautions */	    rv = DecryptSigBlock(&cx->alg, &cx->digest[0], key, sig, (char*)wincx);	    break;	  case fortezzaKey:	  case dsaKey:	    cx->type = VFY_DSA;	    cx->alg = SEC_OID_SHA1;	    cx->key = SECKEY_CopyPublicKey(key);	    /* if this is a DER encoded signature, decode it first */	    if ((algid == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) ||		(algid == SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) ||		(algid == SEC_OID_ANSIX9_DSA_SIGNATURE)) {		dsasig = DSAU_DecodeDerSig(sig);		if ((dsasig == NULL) || (dsasig->len != DSA_SIGNATURE_LEN)) {		    goto loser;		}		PORT_Memcpy(&cx->digest[0], dsasig->data, dsasig->len);	    } else {		if (sig->len != DSA_SIGNATURE_LEN) {		    goto loser;		}		PORT_Memcpy(&cx->digest[0], sig->data, sig->len);	    }	    rv = SECSuccess;	    break;	  default:	    rv = SECFailure;	    break;	}	if (rv) goto loser;	switch (cx->alg) {	  case SEC_OID_MD2:	  case SEC_OID_MD5:	  case SEC_OID_SHA1:	    break;	  default:	    PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);	    goto loser;	}    }    return cx;  loser:    if (dsasig != NULL)	SECITEM_FreeItem(dsasig, PR_TRUE);    VFY_DestroyContext(cx, PR_TRUE);    return 0;}voidVFY_DestroyContext(VFYContext *cx, PRBool freeit){    if (cx) {	if (cx->hashcx != NULL) {	    (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);	    cx->hashcx = NULL;	}	if (cx->key) {	    SECKEY_DestroyPublicKey(cx->key);	}	if (freeit) {	    PORT_ZFree(cx, sizeof(VFYContext));	}    }}SECStatusVFY_Begin(VFYContext *cx){    if (cx->hashcx != NULL) {	(*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);	cx->hashcx = NULL;    }    switch (cx->alg) {      case SEC_OID_MD2:	cx->hashobj = &SECHashObjects[HASH_AlgMD2];	break;      case SEC_OID_MD5:	cx->hashobj = &SECHashObjects[HASH_AlgMD5];	break;      case SEC_OID_SHA1:	cx->hashobj = &SECHashObjects[HASH_AlgSHA1];	break;      default:	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);	return SECFailure;    }    cx->hashcx = (*cx->hashobj->create)();    if (cx->hashcx == NULL)	return SECFailure;    (*cx->hashobj->begin)(cx->hashcx);    return SECSuccess;}SECStatusVFY_Update(VFYContext *cx, unsigned char *input, unsigned inputLen){    if (cx->hashcx == NULL) {	PORT_SetError(SEC_ERROR_INVALID_ARGS);	return SECFailure;    }    (*cx->hashobj->update)(cx->hashcx, input, inputLen);    return SECSuccess;}SECStatusVFY_End(VFYContext *cx){    unsigned char final[32];    unsigned part;    SECItem hash,sig;    if (cx->hashcx == NULL) {	PORT_SetError(SEC_ERROR_INVALID_ARGS);	return SECFailure;    }    (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));    switch (cx->type) {      case VFY_DSA:	sig.data = cx->digest;	sig.len = DSA_SIGNATURE_LEN; /* magic size of dsa signature */	hash.data = final;	hash.len = part;	if (PK11_Verify(cx->key,&sig,&hash,cx->wincx) != SECSuccess) {		PORT_SetError(SEC_ERROR_BAD_SIGNATURE);		return SECFailure;	}	break;      case VFY_RSA:	if (PORT_Memcmp(final, cx->digest, part)) {	    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);	    return SECFailure;	}	break;      default:	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);	return SECFailure; /* shouldn't happen */    }    return SECSuccess;}/************************************************************************//* * 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! */SECStatusVFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,		 SECOidTag algid, void *wincx){    SECStatus rv;    VFYContext *cx;    SECItem dsasig;    rv = SECFailure;    cx = VFY_CreateContext(key, sig, algid, wincx);    if (cx != NULL) {	switch (key->keyType) {	case rsaKey:	    if (PORT_Memcmp(digest->data, cx->digest, digest->len)) {		PORT_SetError(SEC_ERROR_BAD_SIGNATURE);	    } else {		rv = SECSuccess;	    }	    break;	case fortezzaKey:	case dsaKey:	    dsasig.data = &cx->digest[0];	    dsasig.len = DSA_SIGNATURE_LEN; /* magic size of dsa signature */	    if (PK11_Verify(cx->key, &dsasig, digest, cx->wincx) != SECSuccess) {		PORT_SetError(SEC_ERROR_BAD_SIGNATURE);	    } else {		rv = SECSuccess;	    }	    break;	default:	    break;	}	VFY_DestroyContext(cx, PR_TRUE);    }    return rv;}SECStatusVFY_VerifyData(unsigned char *buf, int len, SECKEYPublicKey *key,	       SECItem *sig, SECOidTag algid, void *wincx){    SECStatus rv;    VFYContext *cx;    cx = VFY_CreateContext(key, sig, algid, wincx);    if (cx == NULL)	return SECFailure;    rv = VFY_Begin(cx);    if (rv == SECSuccess) {	rv = VFY_Update(cx, buf, len);	if (rv == SECSuccess)	    rv = VFY_End(cx);    }    VFY_DestroyContext(cx, PR_TRUE);    return rv;}SECStatusSEC_VerifyFile(FILE *input, SECKEYPublicKey *key, SECItem *sig,	       SECOidTag algid, void *wincx){    unsigned char buf[1024];    SECStatus rv;    int nb;    VFYContext *cx;    cx = VFY_CreateContext(key, sig, algid, wincx);    if (cx == NULL)	rv = SECFailure;    rv = VFY_Begin(cx);    if (rv == SECSuccess) {	/*	 * Now feed the contents of the input file into the digest algorithm,	 * one chunk at a time, until we have exhausted the input.	 */	for (;;) {	    if (feof(input))		break;	    nb = fread(buf, 1, sizeof(buf), input);	    if (nb == 0) {		if (ferror(input)) {		    PORT_SetError(SEC_ERROR_IO);		    VFY_DestroyContext(cx, PR_TRUE);		    return SECFailure;		}		break;	    }	    rv = VFY_Update(cx, buf, nb);	    if (rv != SECSuccess)		goto loser;	}    }    /* Verify the digest */    rv = VFY_End(cx);    /* FALL THROUGH */  loser:    VFY_DestroyContext(cx, PR_TRUE);    return rv;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?