crmfdec.c

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

C
381
字号
/* -*- 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 "secitem.h"static CRMFPOPChoicecrmf_get_popchoice_from_der(SECItem *derPOP){    CRMFPOPChoice retChoice;    switch (derPOP->data[0] & 0x0f) {    case 0:        retChoice = crmfRAVerified;	break;    case 1:        retChoice = crmfSignature;	break;    case 2:        retChoice = crmfKeyEncipherment;	break;    case 3:        retChoice = crmfKeyAgreement;	break;    default:        retChoice = crmfNoPOPChoice;	break;    }    return retChoice;}static SECStatuscrmf_decode_process_raverified(CRMFCertReqMsg *inCertReqMsg){       CRMFProofOfPossession *pop;    /* Just set up the structure so that the message structure     * looks like one that was created using the API     */    pop = inCertReqMsg->pop;    pop->popChoice.raVerified.data = NULL;    pop->popChoice.raVerified.len  = 0;    return SECSuccess;}static SECStatuscrmf_decode_process_signature(CRMFCertReqMsg *inCertReqMsg){    return SEC_ASN1Decode(inCertReqMsg->poolp,			  &inCertReqMsg->pop->popChoice.signature,			  CRMFPOPOSigningKeyTemplate, 			  (const char*)inCertReqMsg->derPOP.data,			  inCertReqMsg->derPOP.len);}static CRMFPOPOPrivKeyChoicecrmf_get_messagechoice_from_der(SECItem *derPOP){    CRMFPOPOPrivKeyChoice retChoice;    switch (derPOP->data[2] & 0x0f) {    case 0:        retChoice = crmfThisMessage;	break;    case 1:        retChoice = crmfSubsequentMessage;	break;    case 2:        retChoice = crmfDHMAC;	break;    default:        retChoice = crmfNoMessage;    }    return retChoice;}static SECStatuscrmf_decode_process_popoprivkey(CRMFCertReqMsg *inCertReqMsg){    /* We've got a union, so a pointer to one POPOPrivKey     * struct is the same as having a pointer to the other      * one.     */    CRMFPOPOPrivKey *popoPrivKey =                     &inCertReqMsg->pop->popChoice.keyEncipherment;    SECItem         *derPOP, privKeyDer;    SECStatus        rv;    derPOP = &inCertReqMsg->derPOP;    popoPrivKey->messageChoice = crmf_get_messagechoice_from_der(derPOP);    if (popoPrivKey->messageChoice == crmfNoMessage) {        return SECFailure;    }    /* If we ever encounter BER encodings of this, we'll get in trouble*/    switch (popoPrivKey->messageChoice) {    case crmfThisMessage:    case crmfDHMAC:        privKeyDer.data = &derPOP->data[5];	privKeyDer.len  = derPOP->len - 5;	break;    case crmfSubsequentMessage:        privKeyDer.data = &derPOP->data[4];	privKeyDer.len  = derPOP->len - 4;	break;    default:        rv = SECFailure;    }    rv = SECITEM_CopyItem(inCertReqMsg->poolp, 			  &popoPrivKey->message.subsequentMessage,			  &privKeyDer);    if (rv != SECSuccess) {        return rv;    }    if (popoPrivKey->messageChoice == crmfThisMessage ||	popoPrivKey->messageChoice == crmfDHMAC) {        popoPrivKey->message.thisMessage.len = 	    CRMF_BYTES_TO_BITS(privKeyDer.len) - (int)derPOP->data[4];            }    return SECSuccess;    }static SECStatuscrmf_decode_process_keyagreement(CRMFCertReqMsg *inCertReqMsg){    return crmf_decode_process_popoprivkey(inCertReqMsg);}static SECStatuscrmf_decode_process_keyencipherment(CRMFCertReqMsg *inCertReqMsg){    SECStatus rv;    rv = crmf_decode_process_popoprivkey(inCertReqMsg);    if (rv != SECSuccess) {        return rv;    }    if (inCertReqMsg->pop->popChoice.keyEncipherment.messageChoice == 	crmfDHMAC) {        /* Key Encipherment can not use the dhMAC option for	 * POPOPrivKey. 	 */        return SECFailure;    }    return SECSuccess;}static SECStatuscrmf_decode_process_pop(CRMFCertReqMsg *inCertReqMsg){     SECItem               *derPOP;     PRArenaPool           *poolp;     CRMFProofOfPossession *pop;     void                  *mark;     SECStatus              rv;     derPOP = &inCertReqMsg->derPOP;     poolp  = inCertReqMsg->poolp;     if (derPOP->data == NULL) {         /* There is no Proof of Possession field in this message. */         return SECSuccess;     }     mark = PORT_ArenaMark(poolp);     pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);     if (pop == NULL) {         goto loser;     }     pop->popUsed = crmf_get_popchoice_from_der(derPOP);     if (pop->popUsed == crmfNoPOPChoice) {         /* A bad encoding of CRMF.  Not a valid tag was given to the	  * Proof Of Possession field.	  */         goto loser;     }     inCertReqMsg->pop = pop;     switch (pop->popUsed) {     case crmfRAVerified:         rv = crmf_decode_process_raverified(inCertReqMsg);	 break;     case crmfSignature:         rv = crmf_decode_process_signature(inCertReqMsg);	 break;     case crmfKeyEncipherment:         rv = crmf_decode_process_keyencipherment(inCertReqMsg);	 break;     case crmfKeyAgreement:         rv = crmf_decode_process_keyagreement(inCertReqMsg);	 break;     default:         rv = SECFailure;     }     if (rv != SECSuccess) {         goto loser;     }     PORT_ArenaUnmark(poolp, mark);     return SECSuccess; loser:     PORT_ArenaRelease(poolp, mark);     inCertReqMsg->pop = NULL;     return SECFailure;     }static SECStatuscrmf_decode_process_single_control(PRArenaPool *poolp, 				   CRMFControl *inControl){    const SEC_ASN1Template *asn1Template = NULL;    inControl->tag = SECOID_FindOIDTag(&inControl->derTag);    asn1Template = crmf_get_pkiarchiveoptions_subtemplate(inControl);    PORT_Assert (asn1Template != NULL);    /* We've got a union, so passing a pointer to one element of the     * union is the same as passing a pointer to any of the other     * members of the union.     */    return SEC_ASN1Decode(poolp, &inControl->value.archiveOptions, 			  asn1Template, (const char*)inControl->derValue.data,			  inControl->derValue.len);}static SECStatus crmf_decode_process_controls(CRMFCertReqMsg *inCertReqMsg){    int           i, numControls;    SECStatus     rv;    PRArenaPool  *poolp;    CRMFControl **controls;        numControls = CRMF_CertRequestGetNumControls(inCertReqMsg->certReq);    controls = inCertReqMsg->certReq->controls;    poolp    = inCertReqMsg->poolp;    for (i=0; i < numControls; i++) {        rv = crmf_decode_process_single_control(poolp, controls[i]);	if (rv != SECSuccess) {	    return SECFailure;	}    }    return SECSuccess;}static SECStatuscrmf_decode_process_single_reqmsg(CRMFCertReqMsg *inCertReqMsg){    SECStatus rv;    rv = crmf_decode_process_pop(inCertReqMsg);    if (rv != SECSuccess) {        goto loser;    }    rv = crmf_decode_process_controls(inCertReqMsg);    if (rv != SECSuccess) {        goto loser;    }    inCertReqMsg->certReq->certTemplate.numExtensions =         CRMF_CertRequestGetNumberOfExtensions(inCertReqMsg->certReq);    inCertReqMsg->isDecoded = PR_TRUE;    rv = SECSuccess; loser:    return rv;}CRMFCertReqMsg*CRMF_CreateCertReqMsgFromDER (const char * buf, long len){    PRArenaPool    *poolp;    CRMFCertReqMsg *certReqMsg;    SECStatus       rv;    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);    if (poolp == NULL) {        goto loser;    }    certReqMsg = PORT_ArenaZNew (poolp, CRMFCertReqMsg);    if (certReqMsg == NULL) {        goto loser;    }    certReqMsg->poolp = poolp;    rv = SEC_ASN1Decode(poolp, certReqMsg, CRMFCertReqMsgTemplate, buf, len);    if (rv != SECSuccess) {        goto loser;    }    rv = crmf_decode_process_single_reqmsg(certReqMsg);    if (rv != SECSuccess) {        goto loser;    }    return certReqMsg; loser:    if (poolp != NULL) {        PORT_FreeArena(poolp, PR_FALSE);    }    return NULL;}CRMFCertReqMessages*CRMF_CreateCertReqMessagesFromDER(const char *buf, long len){    long                 arenaSize;    int                  i;    SECStatus            rv;    PRArenaPool         *poolp;    CRMFCertReqMessages *certReqMsgs;    PORT_Assert (buf != NULL);    /* Wanna make sure the arena is big enough to store all of the requests     * coming in.  We'll guestimate according to the length of the buffer.     */    arenaSize = len * 1.5;    poolp = PORT_NewArena(arenaSize);    if (poolp == NULL) {        return NULL;    }    certReqMsgs = PORT_ArenaZNew(poolp, CRMFCertReqMessages);    if (certReqMsgs == NULL) {        goto loser;    }    certReqMsgs->poolp = poolp;    rv = SEC_ASN1Decode(poolp, certReqMsgs, CRMFCertReqMessagesTemplate,			buf, len);    if (rv != SECSuccess) {        goto loser;    }    for (i=0; certReqMsgs->messages[i] != NULL; i++) {        /* The sub-routines expect the individual messages to have 	 * an arena.  We'll give them one temporarily.	 */        certReqMsgs->messages[i]->poolp = poolp;        rv = crmf_decode_process_single_reqmsg(certReqMsgs->messages[i]);	if (rv != SECSuccess) {	    goto loser;	}        certReqMsgs->messages[i]->poolp = NULL;    }    return certReqMsgs; loser:    PORT_FreeArena(poolp, PR_FALSE);    return NULL;}

⌨️ 快捷键说明

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