📄 crmfres.c
字号:
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- *//* * 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. *//* PSM Server specific includes */#include "serv.h"#include "crmfres.h"#include "kgenctxt.h"#include "p12res.h"#include "newproto.h"#include "messages.h"#include "certres.h"#include "oldfunc.h"/* NSS include files */#include "base64.h"#include "crmfi.h"#include "cmmfi.h"#include "cert.h"#include "secmod.h"#include "secasn1.h"/* * These defines are used for setting the keyUsage extensions in * the requests. */#define DIGITAL_SIGNATURE KU_DIGITAL_SIGNATURE#define NON_REPUDIATION KU_NON_REPUDIATION#define KEY_ENCIPHERMENT KU_KEY_ENCIPHERMENT#define KEY_AGREEMENT KU_KEY_AGREEMENT/* I can use this for both SSMKeyPair and SSMCRMFRequest because they * both inherit directly from SSMResource * * A simple macro for an object that inherits from SSMResource that will * convert the object pointer into a SSMResource pointer. */#define SSMRESOURCE(object) (&(object)->super)/* * This structure is used for callbacks passed to the ASN1 encoder. */typedef struct CRMFASN1ArgStr { SECItem buffer; long allocatedLen;} CRMFASN1Arg;/* * Default allocation size for a DER chunk that will be passed to the * ASN1 parser. */#define DEFAULT_ASN1_CHUNK_SIZE 1024typedef struct CMMFResponseArgStr { SECItem *msg; SSMControlConnection *connection;} CMMFResponseArg;/* Forward decls */voidSSMCRMFRequest_PrepareBitStringForEncoding (SECItem *bitsmap, SECItem *value);SSMStatusSSMCRMFRequest_SetKeyUsageExtension(SSMCRMFRequest *crmfReq, unsigned char keyUsage);SSMStatusSSMCRMFRequest_SetRSADualUse(SSMCRMFRequest *crmfReq);SSMStatusSSMCRMFRequest_SetRSAKeyEx(SSMCRMFRequest *crmfReq);SSMStatusSSMCRMFRequest_SetRSASign(SSMCRMFRequest *crmfReq);SSMStatusSSMCRMFRequest_SetRSANonRepudiation(SSMCRMFRequest *crmfReq);SSMStatusSSMCRMFRequest_SetRSASignNonRepudiation(SSMCRMFRequest *crmfReq);SSMStatusSSMCRMFRequest_SetDH(SSMCRMFRequest *crmfReq);SSMStatusSSMCRMFRequest_SetDSASign(SSMCRMFRequest *crmfReq);SSMStatusSSMCRMFRequest_SetDSANonRepudiation(SSMCRMFRequest *crmfReq);SSMStatusSSMCRMFRequest_SetDSASignNonRepudiation(SSMCRMFRequest *crmfReq);SSMStatusSSMCRMFRequest_SetKeyGenType(SSMCRMFRequest *crmfReq, SSMKeyGenType keyGenType);SSMStatusSSMCRMFRequest_SetDN(SSMCRMFRequest *crmfReq, char *data);SSMStatusSSMCRMFRequest_SetRegToken(SSMCRMFRequest *crmfReq, char *value);SSMStatusSSMCRMFRequest_SetAuthenticator(SSMCRMFRequest *crmfReq, char *value);PRBoolSSMCRMFRequest_HasEscrowAuthority(SSMCRMFRequest *currReq);SSMStatusSSMCRMFRequest_SetKeyEnciphermentPOP(CRMFCertReqMsg *certReqMsg, SSMCRMFRequest *curReq);SSMStatusSSMCRMFRequest_SetProofOfPossession(CRMFCertReqMsg *certReqMsg, SSMCRMFRequest *curReq);SECKEYPrivateKey*SSM_FindPrivKeyFromKeyID(SECItem *keyID, SECMODModule *currMod, SSMControlConnection *ctrl);SECKEYPrivateKey*SSM_FindPrivKeyFromPubValue(SECItem *publicValue, SECMODModuleList *modList, SSMControlConnection *ctrl);SSMStatusSSM_InitCRMFASN1Arg(CRMFASN1Arg *arg);voidSSM_GenericASN1Callback(void *arg, const char *buf, unsigned long len);SSMStatusSSM_CreateNewCRMFRequest(SECItem *msg, SSMControlConnection *connection, SSMResourceID *destID){ SSMStatus prv; SSMResource *keyPairRes=NULL, *crmfReqRes=NULL; SSMCRMFRequestArg arg; SingleNumMessage request; if (CMT_DecodeMessage(SingleNumMessageTemplate, &request, (CMTItem*)msg) != CMTSuccess) { goto loser; } prv = SSMControlConnection_GetResource(connection, (SSMResourceID)request.value, &keyPairRes); if (prv != PR_SUCCESS || keyPairRes == NULL) { goto loser; } /* Let's ge a reference for ourselves. * The new SSMCRMFRequest will get a new reference as well, * but we don't want the keyPair to somehow disappear from underneath us. */ SSM_GetResourceReference(keyPairRes); if (!SSM_IsAKindOf(keyPairRes, SSM_RESTYPE_KEY_PAIR)) { goto loser; } arg.keyPair = (SSMKeyPair*)keyPairRes; arg.connection = connection; prv = SSM_CreateResource(SSM_RESTYPE_CRMF_REQUEST, (void*)&arg, connection, destID, &crmfReqRes); if (prv != PR_SUCCESS || crmfReqRes == NULL) { goto loser; }#if 0 /* Give up our references. Now only the Hash table has a reference to * the newly created SSMCRMFRequest structure. The new SSMCRMFRequest * also obtained its own reference to the key pair, so we can * release the reference obtained for the key pair by this function. */ SSM_FreeResource(crmfReqRes); SSM_FreeResource(keyPairRes);#endif crmfReqRes->m_clientCount++; return PR_SUCCESS; loser: if (keyPairRes != NULL) { SSM_FreeResource(keyPairRes); } if (crmfReqRes != NULL) { SSM_FreeResource(crmfReqRes); } return PR_FAILURE;}SSMStatusSSMCRMFRequest_Create(void *arg, SSMControlConnection * connection, SSMResource **res){ SSMCRMFRequest *crmfReq; SSMStatus rv; SSMCRMFRequestArg *createArg = (SSMCRMFRequestArg*)arg; crmfReq = SSM_ZNEW(SSMCRMFRequest); if (crmfReq == NULL) { goto loser; } rv = SSMCRMFRequest_Init(crmfReq, connection, SSM_RESTYPE_CRMF_REQUEST, createArg->keyPair, createArg->connection); if (rv != PR_SUCCESS) { goto loser; } *res = SSMRESOURCE(crmfReq); return PR_SUCCESS; loser: if (crmfReq != NULL) { SSM_FreeResource(SSMRESOURCE(crmfReq)); } *res = NULL; return PR_FAILURE;}SSMStatusSSMCRMFRequest_Init(SSMCRMFRequest *inCRMFReq, SSMControlConnection * conn, SSMResourceType type, SSMKeyPair *inKeyPair, SSMControlConnection *inConnection){ CRMFCertRequest *certReq = NULL; CERTSubjectPublicKeyInfo *spki = NULL; SSMStatus rv; SECStatus srv; long version = SEC_CERTIFICATE_VERSION_3 ; /* Version passed in is the value * to be encoded for the version * of the certificate. */ if (inKeyPair == NULL || inConnection == NULL) { goto loser; } rv = SSMResource_Init(conn, SSMRESOURCE(inCRMFReq), type); if (rv != PR_SUCCESS) { goto loser; } /* This reference will be inherited by the SSMCRMFRequest * structure being initialized. */ SSM_GetResourceReference(SSMRESOURCE(inKeyPair)); if (inKeyPair->m_PubKey == NULL || inKeyPair->m_PrivKey == NULL) { goto loser; } inCRMFReq->m_KeyPair = inKeyPair; inCRMFReq->m_KeyGenType = invalidKeyGen; inCRMFReq->m_Connection = inConnection; /* How do I remember that request number? */ certReq = CRMF_CreateCertRequest(rand()); if (certReq == NULL) { goto loser; } srv = CRMF_CertRequestSetTemplateField(certReq, crmfVersion, &version); if (srv != SECSuccess) { goto loser; } spki = SECKEY_CreateSubjectPublicKeyInfo(inKeyPair->m_PubKey); if(spki == NULL) { goto loser; } srv = CRMF_CertRequestSetTemplateField(certReq, crmfPublicKey, spki); SECKEY_DestroySubjectPublicKeyInfo(spki); if (srv != SECSuccess) { goto loser; } inCRMFReq->m_CRMFRequest = certReq; if (inKeyPair->m_KeyGenContext->m_eaCert != NULL && inKeyPair->m_KeyGenType == rsaEnc) { rv = SSMCRMFRequest_SetEscrowAuthority(inCRMFReq, inKeyPair->m_KeyGenContext->m_eaCert); if (rv != PR_SUCCESS) { goto loser; } } return PR_SUCCESS; loser: /* We only obtain a reference to the key pair in this function, so * that's the only reference we need to free in here. */ if (inKeyPair != NULL) { SSM_FreeResource(SSMRESOURCE(inKeyPair)); } if (certReq != NULL) { CRMF_DestroyCertRequest(certReq); } return PR_FAILURE;}SSMStatusSSMCRMFRequest_Destroy(SSMResource *inRequest, PRBool doFree){ SSMCRMFRequest *crmfReq = (SSMCRMFRequest*)inRequest; if (crmfReq->m_KeyPair != NULL) { SSM_FreeResource(SSMRESOURCE(crmfReq->m_KeyPair)); crmfReq->m_KeyPair = NULL; } if (crmfReq->m_CRMFRequest != NULL) { CRMF_DestroyCertRequest(crmfReq->m_CRMFRequest); crmfReq->m_CRMFRequest = NULL; } SSMResource_Destroy(SSMRESOURCE(crmfReq), PR_FALSE); if (doFree) { PR_Free(crmfReq); } return PR_SUCCESS;}voidSSMCRMFRequest_PrepareBitStringForEncoding (SECItem *bitsmap, SECItem *value){ unsigned char onebyte; unsigned int i, len = 0; /* to prevent warning on some platform at compile time */ onebyte = '\0'; /* Get the position of the right-most turn-on bit */ for (i = 0; i < (value->len ) * 8; ++i) { if (i % 8 == 0) onebyte = value->data[i/8]; if (onebyte & 0x80) len = i; onebyte <<= 1; } bitsmap->data = value->data; /* Add one here since we work with base 1 */ bitsmap->len = len + 1;}/* * Below is the set of functions that set the keyUsage extension in the * request. Each different type of key generation has a different * value that gets set for keyUsage. So each one defines the * value and just calls SSMCRMFRequest_SetKeyUsageExtension. */SSMStatusSSMCRMFRequest_SetKeyUsageExtension(SSMCRMFRequest *crmfReq, unsigned char keyUsage){ SECItem *encodedExt= NULL; SECItem keyUsageValue = { (SECItemType) 0, NULL, 0 }; SECItem bitsmap = { (SECItemType) 0, NULL, 0 }; SECStatus srv; CRMFCertExtension *ext = NULL; CRMFCertExtCreationInfo extAddParams; SEC_ASN1Template bitStrTemplate = {SEC_ASN1_BIT_STRING, 0, NULL, sizeof(SECItem)}; keyUsageValue.data = &keyUsage; keyUsageValue.len = 1; SSMCRMFRequest_PrepareBitStringForEncoding(&bitsmap, &keyUsageValue); encodedExt = SEC_ASN1EncodeItem(NULL, NULL, &bitsmap,&bitStrTemplate); if (encodedExt == NULL) { goto loser; } ext = CRMF_CreateCertExtension(SEC_OID_X509_KEY_USAGE, PR_TRUE, encodedExt); if (ext == NULL) { goto loser; } extAddParams.numExtensions = 1; extAddParams.extensions = &ext; srv = CRMF_CertRequestSetTemplateField(crmfReq->m_CRMFRequest, crmfExtension, &extAddParams); CRMF_DestroyCertExtension(ext); if (srv != SECSuccess) { goto loser; } return PR_SUCCESS; loser: if (encodedExt != NULL) { SECITEM_FreeItem(encodedExt, PR_TRUE); } return PR_FAILURE;}SSMStatusSSMCRMFRequest_SetRSADualUse(SSMCRMFRequest *crmfReq){ unsigned char keyUsage = DIGITAL_SIGNATURE | NON_REPUDIATION | KEY_ENCIPHERMENT; crmfReq->m_KeyGenType = rsaDualUse; return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);}SSMStatusSSMCRMFRequest_SetRSAKeyEx(SSMCRMFRequest *crmfReq){ unsigned char keyUsage = KEY_ENCIPHERMENT; crmfReq->m_KeyGenType = rsaEnc; return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);}SSMStatusSSMCRMFRequest_SetRSASign(SSMCRMFRequest *crmfReq){ unsigned char keyUsage = DIGITAL_SIGNATURE; crmfReq->m_KeyGenType = rsaSign; return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);}SSMStatusSSMCRMFRequest_SetRSANonRepudiation(SSMCRMFRequest *crmfReq){ unsigned char keyUsage = NON_REPUDIATION; crmfReq->m_KeyGenType = rsaNonrepudiation; return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);}SSMStatusSSMCRMFRequest_SetRSASignNonRepudiation(SSMCRMFRequest *crmfReq){ unsigned char keyUsage = DIGITAL_SIGNATURE | NON_REPUDIATION; crmfReq->m_KeyGenType = rsaSignNonrepudiation; return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);}SSMStatus
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -