crmfpop.c

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

C
605
字号
/* -*- Mode: C; tab-width: 8 -*-*//* * 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. */#include "crmf.h"#include "crmfi.h"#include "secasn1.h"#include "keyhi.h"#include "cryptohi.h"#define CRMF_DEFAULT_ALLOC_SIZE 1024SECStatuscrmf_init_encoder_callback_arg (struct crmfEncoderArg *encoderArg, 				SECItem               *derDest) {    derDest->data = PORT_ZNewArray(unsigned char, CRMF_DEFAULT_ALLOC_SIZE);    if (derDest->data == NULL) {        return SECFailure;    }    derDest->len = 0;    encoderArg->allocatedLen = CRMF_DEFAULT_ALLOC_SIZE;    encoderArg->buffer = derDest;    return SECSuccess;}/* Caller should release or unmark the pool, instead of doing it here.** But there are NO callers of this function at present...*/SECStatus CRMF_CertReqMsgSetRAVerifiedPOP(CRMFCertReqMsg *inCertReqMsg){    SECItem               *dummy;    CRMFProofOfPossession *pop;    PRArenaPool           *poolp;    void                  *mark;    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->pop == NULL);    poolp = inCertReqMsg->poolp;    mark = PORT_ArenaMark(poolp);    if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice) {        return SECFailure;    }    pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);    if (pop == NULL) {        goto loser;    }    pop->popUsed = crmfRAVerified;    pop->popChoice.raVerified.data = NULL;    pop->popChoice.raVerified.len  = 0;    inCertReqMsg->pop = pop;    dummy = SEC_ASN1EncodeItem(poolp, &(inCertReqMsg->derPOP),			       &(pop->popChoice.raVerified),			       CRMFRAVerifiedTemplate);    return SECSuccess; loser:    PORT_ArenaRelease(poolp, mark);    return SECFailure;}SECOidTagcrmf_map_keytag_to_signtag(SECOidTag inTag){    switch (inTag) {    case SEC_OID_PKCS1_RSA_ENCRYPTION:        return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;    case SEC_OID_ANSIX9_DSA_SIGNATURE:    case SEC_OID_MISSI_KEA_DSS:    case SEC_OID_MISSI_DSS:        return SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;    default:        /* Put this in here to kill warnings. */        break;    }    return inTag;}SECOidTagcrmf_get_key_sign_tag(SECKEYPublicKey *inPubKey){    CERTSubjectPublicKeyInfo *spki;    SECOidTag                 tag;    spki = SECKEY_CreateSubjectPublicKeyInfo(inPubKey);    if (spki == NULL) {        return SEC_OID_UNKNOWN;    }    tag = SECOID_GetAlgorithmTag(&spki->algorithm);    SECKEY_DestroySubjectPublicKeyInfo(spki);    return crmf_map_keytag_to_signtag(tag);}SECAlgorithmID*crmf_create_poposignkey_algid(PRArenaPool      *poolp,			      SECKEYPublicKey  *inPubKey){    SECAlgorithmID *algID;    SECOidTag       tag;    SECStatus       rv;    void           *mark;    mark = PORT_ArenaMark(poolp);    algID = PORT_ArenaZNew(poolp, SECAlgorithmID);    if (algID == NULL) {        goto loser;    }    tag = crmf_get_key_sign_tag(inPubKey);    if (tag == SEC_OID_UNKNOWN) {        goto loser;    }    rv = SECOID_SetAlgorithmID(poolp, algID, tag, NULL);    if (rv != SECSuccess) {        goto loser;    }    PORT_ArenaUnmark(poolp, mark);    return algID; loser:    PORT_ArenaRelease(poolp, mark);    return NULL;}static CRMFPOPOSigningKeyInput*crmf_create_poposigningkeyinput(PRArenaPool *poolp, CERTCertificate *inCert,				CRMFMACPasswordCallback fn, void *arg){  /* PSM isn't going to do this, so we'll fail here for now.*/     return NULL;}voidcrmf_generic_encoder_callback(void *arg, const char* buf, unsigned long len,			      int depth, SEC_ASN1EncodingPart data_kind){    struct crmfEncoderArg *encoderArg = (struct crmfEncoderArg*)arg;    unsigned char *cursor;       if (encoderArg->buffer->len + len > encoderArg->allocatedLen) {        int newSize = encoderArg->buffer->len+CRMF_DEFAULT_ALLOC_SIZE;        void *dummy = PORT_Realloc(encoderArg->buffer->data, newSize);	if (dummy == NULL) {	    /* I really want to return an error code here */	    PORT_Assert(0);	    return;	}	encoderArg->buffer->data = dummy;	encoderArg->allocatedLen = newSize;    }    cursor = &(encoderArg->buffer->data[encoderArg->buffer->len]);    PORT_Memcpy (cursor, buf, len);    encoderArg->buffer->len += len;    }static SECStatuscrmf_encode_certreq(CRMFCertRequest *inCertReq, SECItem *derDest){    struct crmfEncoderArg encoderArg;    SECStatus             rv;      rv = crmf_init_encoder_callback_arg (&encoderArg, derDest);    if (rv != SECSuccess) {        return SECFailure;    }    return SEC_ASN1Encode(inCertReq, CRMFCertRequestTemplate, 			  crmf_generic_encoder_callback, &encoderArg);}static SECStatuscrmf_sign_certreq(PRArenaPool        *poolp, 		  CRMFPOPOSigningKey *crmfSignKey, 		  CRMFCertRequest    *certReq,		  SECKEYPrivateKey   *inKey,		  SECAlgorithmID     *inAlgId){    SECItem                      derCertReq;    SECItem                      certReqSig;    SECStatus                    rv = SECSuccess;    rv = crmf_encode_certreq(certReq, &derCertReq);    if (rv != SECSuccess) {       goto loser;    }    rv = SEC_SignData(&certReqSig, derCertReq.data, derCertReq.len,		      inKey,SECOID_GetAlgorithmTag(inAlgId));    if (rv != SECSuccess) {        goto loser;    }     /* Now make it a part of the POPOSigningKey */    rv = SECITEM_CopyItem(poolp, &(crmfSignKey->signature), &certReqSig);    /* Convert this length to number of bits */    crmfSignKey->signature.len <<= 3;     loser:    if (derCertReq.data != NULL) {        PORT_Free(derCertReq.data);    }    if (certReqSig.data != NULL) {        PORT_Free(certReqSig.data);    }    return rv;}static SECStatuscrmf_create_poposignkey(PRArenaPool             *poolp, 			CRMFCertReqMsg          *inCertReqMsg, 			CRMFPOPOSigningKeyInput *signKeyInput, 			SECKEYPrivateKey        *inPrivKey,			SECAlgorithmID          *inAlgID,			CRMFPOPOSigningKey      *signKey) {    CRMFCertRequest    *certReq;    void               *mark;    PRBool              useSignKeyInput;    SECStatus           rv;        PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL);    mark = PORT_ArenaMark(poolp);    if (signKey == NULL) {        goto loser;    }    certReq = inCertReqMsg->certReq;    useSignKeyInput = !(CRMF_DoesRequestHaveField(certReq,crmfSubject)  &&			CRMF_DoesRequestHaveField(certReq,crmfPublicKey));    if (useSignKeyInput) {        goto loser;     } else {        rv = crmf_sign_certreq(poolp, signKey, certReq,inPrivKey, inAlgID);	if (rv != SECSuccess) {	    goto loser;	}    }    PORT_ArenaUnmark(poolp,mark);    return SECSuccess; loser:    PORT_ArenaRelease(poolp,mark);    return SECFailure;}SECStatusCRMF_CertReqMsgSetSignaturePOP(CRMFCertReqMsg   *inCertReqMsg,			       SECKEYPrivateKey *inPrivKey,			       SECKEYPublicKey  *inPubKey,			       CERTCertificate  *inCertForInput,			       CRMFMACPasswordCallback  fn,			       void                    *arg){    SECAlgorithmID  *algID;    PRArenaPool     *poolp;    SECItem          derDest = {siBuffer, NULL, 0};    void            *mark;    SECStatus        rv;    CRMFPOPOSigningKeyInput *signKeyInput = NULL;    CRMFCertRequest         *certReq;    CRMFProofOfPossession   *pop;    struct crmfEncoderArg    encoderArg;    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->certReq != NULL &&		inCertReqMsg->pop == NULL);    certReq = inCertReqMsg->certReq;    if (CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfNoPOPChoice || 	!CRMF_DoesRequestHaveField(certReq, crmfPublicKey)) {        return SECFailure;    }     poolp = inCertReqMsg->poolp;    mark = PORT_ArenaMark(poolp);    algID = crmf_create_poposignkey_algid(poolp, inPubKey);    if(!CRMF_DoesRequestHaveField(certReq,crmfSubject)) {        signKeyInput = crmf_create_poposigningkeyinput(poolp, inCertForInput,						       fn, arg);

⌨️ 快捷键说明

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