crmfres.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:41k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /*
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  * 
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  * 
  13.  * The Original Code is the Netscape security libraries.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation.  Portions created by Netscape are 
  17.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s):
  21.  * 
  22.  * Alternatively, the contents of this file may be used under the
  23.  * terms of the GNU General Public License Version 2 or later (the
  24.  * "GPL"), in which case the provisions of the GPL are applicable 
  25.  * instead of those above.  If you wish to allow use of your 
  26.  * version of this file only under the terms of the GPL and not to
  27.  * allow others to use your version of this file under the MPL,
  28.  * indicate your decision by deleting the provisions above and
  29.  * replace them with the notice and other provisions required by
  30.  * the GPL.  If you do not delete the provisions above, a recipient
  31.  * may use your version of this file under either the MPL or the
  32.  * GPL.
  33.  */
  34. /* Cartman Server specific includes */
  35. #include "serv.h"
  36. #include "crmfres.h"
  37. #include "kgenctxt.h"
  38. #include "p12res.h"
  39. #include "newproto.h"
  40. #include "messages.h"
  41. #include "certres.h"
  42. #include "oldfunc.h"
  43. /* NSS include files */
  44. #include "base64.h"
  45. #include "crmfi.h"
  46. #include "cmmfi.h"
  47. #include "cert.h"
  48. #include "secmod.h"
  49. #include "secasn1.h"
  50. /*
  51.  * These defines are used for setting the keyUsage extensions in 
  52.  * the requests.
  53.  */
  54. #define DIGITAL_SIGNATURE KU_DIGITAL_SIGNATURE
  55. #define NON_REPUDIATION   KU_NON_REPUDIATION
  56. #define KEY_ENCIPHERMENT  KU_KEY_ENCIPHERMENT
  57. #define KEY_AGREEMENT     KU_KEY_AGREEMENT
  58. /* I can use this for both SSMKeyPair and SSMCRMFRequest because they
  59.  * both inherit directly from SSMResource
  60.  *
  61.  * A simple macro for an object that inherits from SSMResource that will
  62.  * convert the object pointer into a SSMResource pointer.
  63.  */
  64. #define SSMRESOURCE(object) (&(object)->super)
  65. /*
  66.  * This structure is used for callbacks passed to the ASN1 encoder.
  67.  */
  68. typedef struct CRMFASN1ArgStr {
  69.     SECItem buffer;
  70.     long    allocatedLen;
  71. } CRMFASN1Arg;
  72. /*
  73.  * Default allocation size for a DER chunk that will be passed to the 
  74.  * ASN1 parser.
  75.  */
  76. #define DEFAULT_ASN1_CHUNK_SIZE 1024
  77. typedef struct CMMFResponseArgStr {
  78.     SECItem *msg;
  79.     SSMControlConnection *connection;
  80. } CMMFResponseArg;
  81. /* Forward decls */
  82. void
  83. SSMCRMFRequest_PrepareBitStringForEncoding (SECItem *bitsmap, SECItem *value);
  84. SSMStatus
  85. SSMCRMFRequest_SetKeyUsageExtension(SSMCRMFRequest *crmfReq,
  86.                                     unsigned char   keyUsage);
  87. SSMStatus
  88. SSMCRMFRequest_SetRSADualUse(SSMCRMFRequest *crmfReq);
  89. SSMStatus
  90. SSMCRMFRequest_SetRSAKeyEx(SSMCRMFRequest *crmfReq);
  91. SSMStatus
  92. SSMCRMFRequest_SetRSASign(SSMCRMFRequest *crmfReq);
  93. SSMStatus
  94. SSMCRMFRequest_SetRSANonRepudiation(SSMCRMFRequest *crmfReq);
  95. SSMStatus
  96. SSMCRMFRequest_SetRSASignNonRepudiation(SSMCRMFRequest *crmfReq);
  97. SSMStatus
  98. SSMCRMFRequest_SetDH(SSMCRMFRequest *crmfReq);
  99. SSMStatus
  100. SSMCRMFRequest_SetDSASign(SSMCRMFRequest *crmfReq);
  101. SSMStatus
  102. SSMCRMFRequest_SetDSANonRepudiation(SSMCRMFRequest *crmfReq);
  103. SSMStatus
  104. SSMCRMFRequest_SetDSASignNonRepudiation(SSMCRMFRequest *crmfReq);
  105. SSMStatus
  106. SSMCRMFRequest_SetKeyGenType(SSMCRMFRequest *crmfReq, SSMKeyGenType keyGenType);
  107. SSMStatus
  108. SSMCRMFRequest_SetDN(SSMCRMFRequest *crmfReq, 
  109.                      char           *data);
  110. SSMStatus
  111. SSMCRMFRequest_SetRegToken(SSMCRMFRequest *crmfReq,
  112.    char           *value);
  113. SSMStatus
  114. SSMCRMFRequest_SetAuthenticator(SSMCRMFRequest *crmfReq,
  115.  char           *value);
  116. PRBool
  117. SSMCRMFRequest_HasEscrowAuthority(SSMCRMFRequest *currReq);
  118. SSMStatus
  119. SSMCRMFRequest_SetKeyEnciphermentPOP(CRMFCertReqMsg *certReqMsg,
  120.                                      SSMCRMFRequest *curReq);
  121. SSMStatus
  122. SSMCRMFRequest_SetProofOfPossession(CRMFCertReqMsg *certReqMsg, 
  123.     SSMCRMFRequest *curReq);
  124. SECKEYPrivateKey*
  125. SSM_FindPrivKeyFromKeyID(SECItem *keyID, SECMODModule *currMod,
  126.                          SSMControlConnection *ctrl);
  127. SECKEYPrivateKey*
  128. SSM_FindPrivKeyFromPubValue(SECItem *publicValue, SECMODModuleList *modList,
  129.                             SSMControlConnection *ctrl);
  130. SSMStatus
  131. SSM_InitCRMFASN1Arg(CRMFASN1Arg *arg);
  132. void
  133. SSM_GenericASN1Callback(void *arg, const char *buf, unsigned long len);
  134. SSMStatus
  135. SSM_CreateNewCRMFRequest(SECItem *msg, SSMControlConnection *connection,
  136.                          SSMResourceID *destID)
  137. {
  138.   SSMStatus     prv;
  139.   SSMResource *keyPairRes=NULL, *crmfReqRes=NULL;
  140.   SSMCRMFRequestArg arg;
  141.   SingleNumMessage request;
  142.   if (CMT_DecodeMessage(SingleNumMessageTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
  143.       goto loser;
  144.   }
  145.   prv = SSMControlConnection_GetResource(connection, (SSMResourceID)request.value, 
  146.                                          &keyPairRes);
  147.   if (prv != PR_SUCCESS || keyPairRes == NULL) {
  148.     goto loser;
  149.   }
  150.   if (!SSM_IsAKindOf(keyPairRes, SSM_RESTYPE_KEY_PAIR)) {
  151.     goto loser;
  152.   }
  153.   arg.keyPair    = (SSMKeyPair*)keyPairRes;
  154.   arg.connection = connection;
  155.   prv = SSM_CreateResource(SSM_RESTYPE_CRMF_REQUEST, (void*)&arg, connection,
  156.                            destID, &crmfReqRes);
  157.   if (prv != PR_SUCCESS || crmfReqRes == NULL) {
  158.     goto loser;
  159.   }
  160.   SSM_FreeResource(keyPairRes);
  161.   crmfReqRes->m_clientCount++;
  162.   return PR_SUCCESS;
  163.  loser:
  164.   if (keyPairRes != NULL) {
  165.     SSM_FreeResource(keyPairRes);
  166.   }
  167.   if (crmfReqRes != NULL) {
  168.     SSM_FreeResource(crmfReqRes);
  169.   }
  170.   return PR_FAILURE;
  171. }
  172. SSMStatus
  173. SSMCRMFRequest_Create(void *arg, SSMControlConnection * connection, 
  174.                       SSMResource **res)
  175. {
  176.   SSMCRMFRequest    *crmfReq;
  177.   SSMStatus           rv;
  178.   SSMCRMFRequestArg *createArg = (SSMCRMFRequestArg*)arg;
  179.   crmfReq = SSM_ZNEW(SSMCRMFRequest);
  180.   if (crmfReq == NULL) {
  181.     goto loser;
  182.   }
  183.   rv = SSMCRMFRequest_Init(crmfReq, connection, SSM_RESTYPE_CRMF_REQUEST, 
  184.                            createArg->keyPair, createArg->connection);
  185.   
  186.   if (rv != PR_SUCCESS) {
  187.     goto loser;
  188.   }
  189.   *res = SSMRESOURCE(crmfReq);
  190.   return PR_SUCCESS;
  191.   
  192.  loser:
  193.   if (crmfReq != NULL) {
  194.     SSM_FreeResource(SSMRESOURCE(crmfReq));
  195.   }
  196.   *res = NULL;
  197.   return PR_FAILURE;
  198. }
  199. SSMStatus
  200. SSMCRMFRequest_Init(SSMCRMFRequest       *inCRMFReq,
  201.     SSMControlConnection * conn,
  202.                     SSMResourceType       type,
  203.                     SSMKeyPair           *inKeyPair,
  204.                     SSMControlConnection *inConnection)
  205. {
  206.   CRMFCertRequest          *certReq = NULL;
  207.   CERTSubjectPublicKeyInfo *spki    = NULL;
  208.   SSMStatus                  rv;
  209.   SECStatus                 srv;
  210.   long                      version = SEC_CERTIFICATE_VERSION_3 ; 
  211.                                          /* Version passed in is the value 
  212.                                           * to be encoded for the version
  213.                                           * of the certificate.
  214.                                           */
  215.   if (inKeyPair == NULL || inConnection == NULL) {
  216.       goto loser;
  217.   }
  218.   rv = SSMResource_Init(conn, SSMRESOURCE(inCRMFReq), type);
  219.   if (rv != PR_SUCCESS) {
  220.     goto loser;
  221.   }
  222.   /* This reference will be inherited by the SSMCRMFRequest
  223.    * structure being initialized.
  224.    */
  225.   SSM_GetResourceReference(SSMRESOURCE(inKeyPair));
  226.   if (inKeyPair->m_PubKey  == NULL || 
  227.       inKeyPair->m_PrivKey == NULL) {
  228.     goto loser;
  229.   }
  230.   inCRMFReq->m_KeyPair    = inKeyPair;
  231.   inCRMFReq->m_KeyGenType = invalidKeyGen;
  232.   inCRMFReq->m_Connection = inConnection;
  233.   /* How do I remember that request number? */
  234.   certReq = CRMF_CreateCertRequest(rand());
  235.   if (certReq == NULL) {
  236.     goto loser;
  237.   }
  238.   srv = CRMF_CertRequestSetTemplateField(certReq, crmfVersion, &version);
  239.   if (srv != SECSuccess) {
  240.     goto loser;
  241.   }
  242.   spki = SECKEY_CreateSubjectPublicKeyInfo(inKeyPair->m_PubKey);
  243.   if(spki == NULL) {
  244.     goto loser;
  245.   }
  246.   srv = CRMF_CertRequestSetTemplateField(certReq, crmfPublicKey, spki);
  247.   SECKEY_DestroySubjectPublicKeyInfo(spki);
  248.   if (srv != SECSuccess) {
  249.     goto loser;
  250.   }
  251.   inCRMFReq->m_CRMFRequest = certReq;
  252.   if (inKeyPair->m_KeyGenContext->m_eaCert != NULL &&
  253.       inKeyPair->m_KeyGenType == rsaEnc) {
  254.       rv = SSMCRMFRequest_SetEscrowAuthority(inCRMFReq,
  255.                                         inKeyPair->m_KeyGenContext->m_eaCert);
  256.       if (rv != PR_SUCCESS) {
  257.         goto loser;
  258.       }
  259.   }
  260.   return PR_SUCCESS;
  261.  loser:
  262.   /* We only obtain a reference to the key pair in this function, so 
  263.    * that's the only reference we need to free in here.
  264.    */
  265.   if (inKeyPair != NULL) {
  266.     SSM_FreeResource(SSMRESOURCE(inKeyPair));
  267.   }
  268.   if (certReq != NULL) {
  269.     CRMF_DestroyCertRequest(certReq);
  270.   }
  271.   return PR_FAILURE;
  272. }
  273. SSMStatus
  274. SSMCRMFRequest_Destroy(SSMResource *inRequest, PRBool doFree)
  275. {
  276.   SSMCRMFRequest *crmfReq = (SSMCRMFRequest*)inRequest;
  277.   if (crmfReq->m_KeyPair != NULL) {
  278.     SSM_FreeResource(SSMRESOURCE(crmfReq->m_KeyPair));
  279.     crmfReq->m_KeyPair = NULL;
  280.   }
  281.   if (crmfReq->m_CRMFRequest != NULL) {
  282.     CRMF_DestroyCertRequest(crmfReq->m_CRMFRequest);
  283.     crmfReq->m_CRMFRequest = NULL;
  284.   }
  285.   SSMResource_Destroy(SSMRESOURCE(crmfReq), PR_FALSE);
  286.   if (doFree) {
  287.     PR_Free(crmfReq);
  288.   }
  289.   return PR_SUCCESS;
  290. }
  291. void
  292. SSMCRMFRequest_PrepareBitStringForEncoding (SECItem *bitsmap, SECItem *value)
  293. {
  294.   unsigned char onebyte;
  295.   unsigned int i, len = 0;
  296.   /* to prevent warning on some platform at compile time */
  297.   onebyte = '';
  298.   /* Get the position of the right-most turn-on bit */
  299.   for (i = 0; i < (value->len ) * 8; ++i) {
  300.       if (i % 8 == 0)
  301.           onebyte = value->data[i/8];
  302.       if (onebyte & 0x80)
  303.           len = i;
  304.       onebyte <<= 1;
  305.   }
  306.   bitsmap->data = value->data;
  307.   /* Add one here since we work with base 1 */
  308.   bitsmap->len = len + 1;
  309. }
  310. /*
  311.  * Below is the set of functions that set the keyUsage extension in the
  312.  * request.  Each different type of key generation has a different
  313.  * value that gets set for keyUsage.  So each one defines the 
  314.  * value and just calls SSMCRMFRequest_SetKeyUsageExtension.
  315.  */
  316. SSMStatus
  317. SSMCRMFRequest_SetKeyUsageExtension(SSMCRMFRequest *crmfReq,
  318.                                     unsigned char   keyUsage)
  319. {
  320.   SECItem                 *encodedExt= NULL;
  321.   SECItem                  keyUsageValue = { (SECItemType) 0, NULL, 0 };
  322.   SECItem                  bitsmap = { (SECItemType) 0, NULL, 0 };
  323.   SECStatus                srv;
  324.   CRMFCertExtension       *ext = NULL;
  325.   CRMFCertExtCreationInfo  extAddParams;
  326.   SEC_ASN1Template         bitStrTemplate = {SEC_ASN1_BIT_STRING, 0, NULL,
  327.                                              sizeof(SECItem)};
  328.   keyUsageValue.data = &keyUsage;
  329.   keyUsageValue.len  = 1;
  330.   SSMCRMFRequest_PrepareBitStringForEncoding(&bitsmap, &keyUsageValue);
  331.   encodedExt = SEC_ASN1EncodeItem(NULL, NULL, &bitsmap,&bitStrTemplate);
  332.   if (encodedExt == NULL) {
  333.       goto loser;
  334.   }
  335.   ext = CRMF_CreateCertExtension(SEC_OID_X509_KEY_USAGE, PR_TRUE, encodedExt);
  336.   if (ext == NULL) {
  337.       goto loser;
  338.   }
  339.   extAddParams.numExtensions = 1;
  340.   extAddParams.extensions = &ext;
  341.   srv = CRMF_CertRequestSetTemplateField(crmfReq->m_CRMFRequest, crmfExtension,
  342.                                          &extAddParams);
  343.   CRMF_DestroyCertExtension(ext);
  344.   if (srv != SECSuccess) {
  345.       goto loser;
  346.   }
  347.   return PR_SUCCESS;
  348.  loser:
  349.   if (encodedExt != NULL) {
  350.       SECITEM_FreeItem(encodedExt, PR_TRUE);
  351.   }
  352.   return PR_FAILURE;
  353. }
  354. SSMStatus
  355. SSMCRMFRequest_SetRSADualUse(SSMCRMFRequest *crmfReq)
  356. {
  357.   unsigned char keyUsage =   DIGITAL_SIGNATURE
  358.                            | NON_REPUDIATION
  359.                            | KEY_ENCIPHERMENT;
  360.   crmfReq->m_KeyGenType = rsaDualUse;
  361.   return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);
  362. }
  363. SSMStatus
  364. SSMCRMFRequest_SetRSAKeyEx(SSMCRMFRequest *crmfReq)
  365. {
  366.   unsigned char keyUsage = KEY_ENCIPHERMENT;
  367.      
  368.   crmfReq->m_KeyGenType = rsaEnc;
  369.   return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);
  370. }
  371. SSMStatus
  372. SSMCRMFRequest_SetRSASign(SSMCRMFRequest *crmfReq)
  373. {
  374.   unsigned char keyUsage = DIGITAL_SIGNATURE;
  375.                          
  376.   crmfReq->m_KeyGenType = rsaSign;
  377.   return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);
  378. }
  379. SSMStatus
  380. SSMCRMFRequest_SetRSANonRepudiation(SSMCRMFRequest *crmfReq)
  381. {
  382.   unsigned char keyUsage = NON_REPUDIATION;
  383.   crmfReq->m_KeyGenType = rsaNonrepudiation;
  384.   return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);
  385. }
  386. SSMStatus
  387. SSMCRMFRequest_SetRSASignNonRepudiation(SSMCRMFRequest *crmfReq)
  388. {
  389.   unsigned char keyUsage = DIGITAL_SIGNATURE |
  390.                            NON_REPUDIATION;
  391.   crmfReq->m_KeyGenType = rsaSignNonrepudiation;
  392.   return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);
  393. }
  394. SSMStatus
  395. SSMCRMFRequest_SetDH(SSMCRMFRequest *crmfReq)
  396. {
  397.   unsigned char keyUsage = KEY_AGREEMENT;
  398.   
  399.   crmfReq->m_KeyGenType = dhEx;
  400.   return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);
  401. }
  402. SSMStatus
  403. SSMCRMFRequest_SetDSASign(SSMCRMFRequest *crmfReq)
  404. {
  405.   unsigned char keyUsage = DIGITAL_SIGNATURE;
  406.   crmfReq->m_KeyGenType = dsaSign;
  407.   return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);
  408. }
  409. SSMStatus
  410. SSMCRMFRequest_SetDSANonRepudiation(SSMCRMFRequest *crmfReq)
  411. {
  412.   unsigned char keyUsage = NON_REPUDIATION;
  413.   crmfReq->m_KeyGenType = dsaNonrepudiation;
  414.   return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);
  415. }
  416. SSMStatus
  417. SSMCRMFRequest_SetDSASignNonRepudiation(SSMCRMFRequest *crmfReq)
  418. {
  419.   unsigned char keyUsage = DIGITAL_SIGNATURE |
  420.                            NON_REPUDIATION;
  421.   crmfReq->m_KeyGenType = dsaSignNonrepudiation;
  422.   return SSMCRMFRequest_SetKeyUsageExtension(crmfReq, keyUsage);
  423. }
  424. SSMStatus
  425. SSMCRMFRequest_SetKeyGenType(SSMCRMFRequest *crmfReq, SSMKeyGenType keyGenType)
  426. {
  427.   SSMStatus rv;
  428.   if (crmfReq->m_KeyGenType != invalidKeyGen) {
  429.     return PR_FAILURE;
  430.   }
  431.   switch (keyGenType) {
  432.   case rsaDualUse:
  433.     rv = SSMCRMFRequest_SetRSADualUse(crmfReq);
  434.     break;
  435.   case rsaEnc:
  436.     rv = SSMCRMFRequest_SetRSAKeyEx(crmfReq);
  437.     break;
  438.   case rsaSign:
  439.     rv = SSMCRMFRequest_SetRSASign(crmfReq);
  440.     break;
  441.   case rsaNonrepudiation:
  442.     rv = SSMCRMFRequest_SetRSANonRepudiation(crmfReq);
  443.     break;
  444.   case rsaSignNonrepudiation:
  445.     rv = SSMCRMFRequest_SetRSASignNonRepudiation(crmfReq);
  446.     break;
  447.   case dhEx:
  448.     rv = SSMCRMFRequest_SetDH(crmfReq);
  449.     break;
  450.   case dsaSign:
  451.     rv = SSMCRMFRequest_SetDSASign(crmfReq);
  452.     break;
  453.   case dsaNonrepudiation:
  454.     rv = SSMCRMFRequest_SetDSANonRepudiation(crmfReq);
  455.     break;
  456.   case dsaSignNonrepudiation:
  457.     rv = SSMCRMFRequest_SetDSASignNonRepudiation(crmfReq);
  458.     break;
  459.   default:
  460.     SSM_DEBUG("Unknown KeyGenType %dn", keyGenType);
  461.     rv = PR_FAILURE;
  462.     break;
  463.   }
  464.   return rv;
  465. }
  466. /*
  467.  * This function takes an ASCII string in RFC1485 format and converts it
  468.  * to a CERTName, then sets that names as the subjectName for the request
  469.  * passed in.
  470.  */
  471. SSMStatus
  472. SSMCRMFRequest_SetDN(SSMCRMFRequest *crmfReq, 
  473.                      char           *data)
  474. {
  475.   SECStatus    srv;
  476.   CERTName    *subjectName;
  477.   if (data == NULL || CRMF_CertRequestIsFieldPresent(crmfReq->m_CRMFRequest,
  478.                                                      crmfSubject)) {
  479.     return PR_FAILURE;
  480.   }
  481.   subjectName = CERT_AsciiToName(data);
  482.   if (subjectName == NULL) {
  483.     return PR_FAILURE;
  484.   }
  485.   srv = CRMF_CertRequestSetTemplateField (crmfReq->m_CRMFRequest, crmfSubject, 
  486.                                           (void*)subjectName);
  487.   CERT_DestroyName(subjectName);
  488.   return (srv == SECSuccess) ? PR_SUCCESS : PR_FAILURE;
  489. }
  490. /*
  491.  * This function will set the Registration Token Control in 
  492.  * the certificate request passed in.  We only allow one registration
  493.  * token control per request in Cartman.
  494.  */
  495. SSMStatus
  496. SSMCRMFRequest_SetRegToken(SSMCRMFRequest *crmfReq,
  497.    char           *value)
  498. {
  499.   SECItem   src, *derEncoded;
  500.   SECStatus rv;
  501.   if (CRMF_CertRequestIsControlPresent(crmfReq->m_CRMFRequest, 
  502.                                        crmfRegTokenControl)) {
  503.     return PR_FAILURE;
  504.   }
  505.   src.data = (unsigned char*)value;
  506.   src.len  = strlen(value)+1;
  507.   derEncoded = SEC_ASN1EncodeItem(NULL, NULL, &src, SEC_UTF8StringTemplate);
  508.   if (derEncoded == NULL) {
  509.     return PR_FAILURE;
  510.   }
  511.   rv = CRMF_CertRequestSetRegTokenControl(crmfReq->m_CRMFRequest, derEncoded);
  512.   SECITEM_FreeItem(derEncoded, PR_TRUE);
  513.   if (rv != SECSuccess) {
  514.     return PR_FAILURE;
  515.   }
  516.   return PR_SUCCESS;
  517. }
  518. /*
  519.  * This function sets the authenticator control in the certificate request.
  520.  * The string passed in is an ASCII string.  The CRMF libraries encode that
  521.  * string as a UTF8 string and then include it in the request.  Cartman will
  522.  * only allow one Authenticator control per request.
  523.  */
  524. SSMStatus
  525. SSMCRMFRequest_SetAuthenticator(SSMCRMFRequest *crmfReq,
  526.  char           *value)
  527. {
  528.   SECItem   src, *derEncoded;
  529.   SECStatus rv;
  530.   if (CRMF_CertRequestIsControlPresent(crmfReq->m_CRMFRequest,
  531.                                        crmfAuthenticatorControl)) {
  532.     return PR_FAILURE;
  533.   }
  534.   src.data = (unsigned char*)value;
  535.   src.len  = strlen(value)+1;
  536.   derEncoded = SEC_ASN1EncodeItem(NULL, NULL, &src, SEC_UTF8StringTemplate);
  537.   if (derEncoded == NULL) {
  538.     return PR_FAILURE;
  539.   }
  540.   rv = CRMF_CertRequestSetAuthenticatorControl(crmfReq->m_CRMFRequest, 
  541.                                                derEncoded);
  542.   SECITEM_FreeItem(derEncoded, PR_TRUE);
  543.   if (rv != SECSuccess) {
  544.     return PR_FAILURE;
  545.   }
  546.   return PR_SUCCESS;
  547. }
  548. SSMStatus
  549. SSMCRMFRequest_SetEscrowAuthority(SSMCRMFRequest  *crmfReq,
  550.                                   CERTCertificate *eaCert)
  551. {
  552.   CRMFEncryptedKey      *encrKey   = NULL;
  553.   CRMFPKIArchiveOptions *archOpt   = NULL;
  554.   SECStatus              rv;
  555.   PR_ASSERT(eaCert!= NULL);
  556.   if (eaCert == NULL || 
  557.       CRMF_CertRequestIsControlPresent(crmfReq->m_CRMFRequest, 
  558.                                        crmfPKIArchiveOptionsControl)) {
  559.     return PR_FAILURE;
  560.   }
  561.   /*
  562.    * CRMF_CreatePKIArchiveOptions checks to see if the value passed in,
  563.    * in this case encrKey, is NULL.  So passing in the value without 
  564.    * checking the contents first is OK in this case.  Really.
  565.    */
  566.   encrKey = 
  567.     CRMF_CreateEncryptedKeyWithEncryptedValue(crmfReq->m_KeyPair->m_PrivKey,
  568.                                               eaCert);
  569.   archOpt = CRMF_CreatePKIArchiveOptions(crmfEncryptedPrivateKey, 
  570.                                          (void*)encrKey);
  571.   if (archOpt == NULL) {
  572.     goto loser;
  573.   }
  574.   rv = CRMF_CertRequestSetPKIArchiveOptions(crmfReq->m_CRMFRequest, archOpt);
  575.   if (rv != SECSuccess) {
  576.     goto loser;
  577.   }
  578.   CRMF_DestroyEncryptedKey(encrKey);
  579.   CRMF_DestroyPKIArchiveOptions(archOpt);
  580.   return PR_SUCCESS;
  581.  loser:
  582.   /* Free up all the memory here. */
  583.   if (encrKey != NULL) {
  584.     CRMF_DestroyEncryptedKey(encrKey);
  585.   }
  586.   if (archOpt != NULL) {
  587.     CRMF_DestroyPKIArchiveOptions(archOpt);
  588.   }
  589.   return PR_FAILURE;
  590. }
  591. SSMStatus
  592. SSMCRMFRequest_SetAttr(SSMResource         *res,
  593.                        SSMAttributeID      attrID,
  594.                        SSMAttributeValue   *value)
  595. {
  596.   SSMCRMFRequest *crmfReq = (SSMCRMFRequest*)res;
  597.   SSMStatus        rv;
  598.   SSM_DEBUG("Calling SSMCRMFRequest_SetAttrn");
  599.   switch (attrID) {
  600.   case SSM_FID_CRMFREQ_KEY_TYPE:
  601.     SSM_DEBUG("Setting SSMKeyGenType to %dn", value->u.numeric);
  602.     if (value->type != SSM_NUMERIC_ATTRIBUTE) {
  603.       rv = PR_FAILURE;
  604.       break;
  605.     }
  606.     rv = SSMCRMFRequest_SetKeyGenType(crmfReq, (SSMKeyGenType) value->u.numeric);
  607.     break;
  608.   case SSM_FID_CRMFREQ_DN:
  609.     SSM_DEBUG("Setting the DN to %sn", value->u.string.data);
  610.     if (value->type != SSM_STRING_ATTRIBUTE) {
  611.       rv = PR_FAILURE;
  612.       break;
  613.     }
  614.     rv = SSMCRMFRequest_SetDN(crmfReq, (char *) value->u.string.data);
  615.     break;
  616.   case SSM_FID_CRMFREQ_REGTOKEN:
  617.     SSM_DEBUG("Setting the regToken to %sn", value->u.string.data);
  618.     if (value->type != SSM_STRING_ATTRIBUTE) {
  619.       rv = PR_FAILURE;
  620.       break;
  621.     }
  622.     rv = SSMCRMFRequest_SetRegToken(crmfReq, (char *) value->u.string.data);
  623.     break;
  624.   case SSM_FID_CRMFREQ_AUTHENTICATOR:
  625.     SSM_DEBUG("Setting the authenticator to %sn", value->u.string.data);
  626.     rv = SSMCRMFRequest_SetAuthenticator(crmfReq, (char *) value->u.string.data);
  627.     break;
  628.   default:
  629.     SSM_DEBUG("Got unknown CRMF Set Attribute request %dn", attrID);
  630.     rv = PR_FAILURE;
  631.     break;
  632.   }
  633.   return rv;
  634. }
  635. /*
  636.  * This function checks to see if a CRMF request has the PKIArchiveOptions
  637.  * control already set.
  638.  */
  639. PRBool
  640. SSMCRMFRequest_HasEscrowAuthority(SSMCRMFRequest *currReq)
  641. {
  642.   return CRMF_CertRequestIsControlPresent(currReq->m_CRMFRequest,
  643.                                           crmfPKIArchiveOptionsControl);
  644. }
  645. /*
  646.  * This function will set the Proof Of Possession (POP) for a request
  647.  * associated with a key pair intended to do Key Encipherment.  Currently
  648.  * this means encryption only keys.
  649.  */
  650. SSMStatus
  651. SSMCRMFRequest_SetKeyEnciphermentPOP(CRMFCertReqMsg *certReqMsg,
  652.                                      SSMCRMFRequest *curReq)
  653. {
  654.   SECItem       bitString;
  655.   unsigned char der[2];
  656.   SECStatus     rv;
  657.   if (SSMCRMFRequest_HasEscrowAuthority(curReq)) { 
  658.     /* For proof of possession on escrowed keys, we use the
  659.      * this Message option of POPOPrivKey and include a zero
  660.      * length bit string in the POP field.  This is OK because the encrypted
  661.      * private key already exists as part of the PKIArchiveOptions
  662.      * Control and that for all intents and purposes proves that
  663.      * we do own the private key.
  664.      */
  665.     der[0] = 0x03; /*We've got a bit string          */
  666.     der[1] = 0x00; /*We've got a 0 length bit string */
  667.     bitString.data = der;
  668.     bitString.len  = 2;
  669.     rv = CRMF_CertReqMsgSetKeyEnciphermentPOP(certReqMsg, crmfThisMessage,
  670.                                               crmfNoSubseqMess, &bitString);
  671.   } else {
  672.     /* If the encryption key is not being escrowed, then we set the 
  673.      * Proof Of Possession to be a Challenge Response mechanism.
  674.      */
  675.     rv = CRMF_CertReqMsgSetKeyEnciphermentPOP(certReqMsg, 
  676.                                               crmfSubsequentMessage,
  677.                                               crmfChallengeResp, NULL); 
  678.   }
  679.   return (rv == SECSuccess) ? PR_SUCCESS : PR_FAILURE; 
  680. }
  681. /*
  682.  * This function sets the Proof Of Possession(POP) for a requests.
  683.  * All requests except for those associated with encryption only keys
  684.  * sign the request as their form of POP.  Encryption only keys require
  685.  * extra logic in determining the type of POP to use, that is why encryption
  686.  * only keys have an extra layer for setting the POP instead of calling into
  687.  * the CRMF libraries directly from within this function.
  688.  */
  689. SSMStatus
  690. SSMCRMFRequest_SetProofOfPossession(CRMFCertReqMsg *certReqMsg, 
  691.     SSMCRMFRequest *curReq)
  692. {
  693.   SSMStatus  rv;
  694.   SECStatus srv;
  695.   switch (curReq->m_KeyGenType) {
  696.   case rsaSign:
  697.   case rsaDualUse:
  698.   case rsaNonrepudiation:
  699.   case rsaSignNonrepudiation:
  700.   case dsaSign:
  701.   case dsaNonrepudiation:
  702.   case dsaSignNonrepudiation:
  703.     srv = CRMF_CertReqMsgSetSignaturePOP(certReqMsg, 
  704.                                          curReq->m_KeyPair->m_PrivKey, 
  705.                                          curReq->m_KeyPair->m_PubKey, NULL,
  706.                                          NULL, NULL);
  707.     rv = (srv == SECSuccess) ? PR_SUCCESS : PR_FAILURE;
  708.     break;
  709.   case rsaEnc:
  710.     rv = SSMCRMFRequest_SetKeyEnciphermentPOP(certReqMsg, curReq);
  711.     break;
  712.   case dhEx:
  713.     /* This case may be supported in the future, but for now, we just fall 
  714.      * though to the default case and return an error for diffie-hellman keys.
  715.      */
  716.   default:
  717.     rv = PR_FAILURE;
  718.     break;
  719.   }
  720.   return rv;
  721. }
  722. SSMStatus
  723. SSM_EncodeCRMFRequests(SSMControlConnection * ctrl,SECItem *msg, 
  724.                        char **destDER, SSMPRUint32 *destLen)
  725. {
  726.   PRInt32               i;
  727.   SSMStatus              rv;
  728.   SECStatus             srv;
  729.   CRMFCertReqMsg      **certReqMsgs = NULL;
  730.   SSMCRMFRequest       *curReq;
  731.   SSMResource          *res;
  732.   SECItem              *encodedReq;
  733.   CRMFCertReqMessages   messages;
  734.   EncodeCRMFReqRequest request;
  735.   if (CMT_DecodeMessage(EncodeCRMFReqRequestTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
  736.       goto loser;
  737.   }
  738.   certReqMsgs = SSM_ZNEW_ARRAY(CRMFCertReqMsg*, (request.numRequests+1));
  739.   for (i=0; i<request.numRequests; i++) {
  740.     rv = SSMControlConnection_GetResource(ctrl, (SSMResourceID)request.reqIDs[i],
  741.                                           &res);
  742.     if (rv != PR_SUCCESS) {
  743.       goto loser;
  744.     }
  745.     if (!SSM_IsAKindOf(res, SSM_RESTYPE_CRMF_REQUEST)) {
  746.       rv = PR_FAILURE;
  747.       goto loser;
  748.     }
  749.     curReq = (SSMCRMFRequest*)res;
  750.     certReqMsgs[i] = CRMF_CreateCertReqMsg();
  751.     srv = CRMF_CertReqMsgSetCertRequest(certReqMsgs[i], curReq->m_CRMFRequest);
  752.     if (srv != SECSuccess) {
  753.       rv = PR_FAILURE;
  754.       goto loser;
  755.     }
  756.     rv = SSMCRMFRequest_SetProofOfPossession(certReqMsgs[i], curReq);
  757.     if (rv != PR_SUCCESS) {
  758.       goto loser;
  759.     }
  760.     
  761.   }
  762.   /* Now we're ready to encode */
  763.   messages.messages = certReqMsgs;
  764.   encodedReq = SEC_ASN1EncodeItem(NULL, NULL, &messages,
  765.                                   CRMFCertReqMessagesTemplate);
  766.   if (encodedReq == NULL) {
  767.     rv = PR_FAILURE;
  768.     goto loser;
  769.   }
  770.   *destDER = BTOA_DataToAscii(encodedReq->data, encodedReq->len);
  771.   *destLen = (*destDER == NULL) ? 0 : strlen(*destDER) + 1;
  772.   SECITEM_FreeItem(encodedReq, PR_TRUE);
  773.   rv = (*destDER == NULL) ? PR_FAILURE : PR_SUCCESS;
  774.  loser:
  775.   /* Do some massive memory clean-up in here. */
  776.   if (certReqMsgs != NULL) {
  777.     for (i=0; certReqMsgs[i] != NULL; i++){
  778.       CRMF_DestroyCertReqMsg(certReqMsgs[i]);
  779.     }
  780.     PR_Free(certReqMsgs);
  781.   }
  782.   return rv;
  783. }
  784. void
  785. ssm_processcmmfresponse_thread(void *arg)
  786. {
  787.   CMMFResponseArg *inArg = (CMMFResponseArg*)arg;
  788.   SECItem *msg = inArg->msg;
  789.   SSMControlConnection *connection = inArg->connection;
  790.   SECStatus    srv;
  791.   SSMStatus    rv;
  792.   char        *nickname=NULL;
  793.   int          numResponses, i;
  794.   SECItem      cmmfDer = {siBuffer, NULL, 0};
  795.   PRArenaPool *ourPool  = NULL;
  796.   SECItem     *derCerts = NULL;
  797.   SSMPKCS12CreateArg p12Create;
  798.   SSMResourceID      p12RID;
  799.   PRBool             freeLocalNickname = PR_FALSE;
  800.   SSMPKCS12Context   *p12Cxt         = NULL;
  801.   CERTCertList       *caPubs         = NULL;
  802.   CERTCertificate    *currCert       = NULL;
  803.   CERTCertificate    *dbCert         = NULL;
  804.   CMMFCertRepContent *certRepContent = NULL;
  805.   CMMFCertResponse   *currResponse   = NULL;
  806.   PK11SlotInfo       *slot           = NULL;
  807.   CERTCertificate   **certArr        = NULL;
  808.   CMMFPKIStatus       reqStatus;
  809.   PRBool              certAlreadyExisted = PR_FALSE;
  810.   CMMFCertResponseRequest request;
  811.   if (CMT_DecodeMessage(CMMFCertResponseRequestTemplate, &request, 
  812.                         (CMTItem*)msg) != CMTSuccess) {
  813.       goto loser;
  814.   }
  815.   srv = ATOB_ConvertAsciiToItem(&cmmfDer, request.base64Der);
  816.   if (srv != SECSuccess || cmmfDer.data == NULL) {
  817.       goto loser;
  818.   }
  819.   certRepContent = CMMF_CreateCertRepContentFromDER(connection->m_certdb,
  820.                                                     (const char*)cmmfDer.data,
  821.                                                     cmmfDer.len);
  822.   if (certRepContent == NULL) {
  823.       /* This could be a key recovery response, but fail for now. */
  824.       goto loser;
  825.   }
  826.   numResponses = CMMF_CertRepContentGetNumResponses(certRepContent);
  827.   if (request.doBackup) {
  828.       certArr = SSM_ZNEW_ARRAY(CERTCertificate*, numResponses);
  829.       if (certArr == NULL) {
  830.           /* Let's not do back up in this case. */
  831.           request.doBackup = (CMBool) PR_FALSE;
  832.       }
  833.   }
  834.   for (i=0; i<numResponses; i++) {
  835.       currResponse = CMMF_CertRepContentGetResponseAtIndex(certRepContent, i);
  836.       if (currResponse == NULL) {
  837.           goto loser;
  838.       }
  839.       /* Need to make sure the ID corresponds to a request Cartman actually
  840.        * made.  Figure out how you're gonna do this.
  841.        */
  842.       reqStatus = CMMF_CertResponseGetPKIStatusInfoStatus(currResponse);
  843.       if (!(reqStatus == cmmfGranted || reqStatus == cmmfGrantedWithMods)) {
  844.           /* The CA didn't give us the cert as we requested. */
  845.           goto loser;
  846.       }
  847.       currCert = CMMF_CertResponseGetCertificate(currResponse, 
  848.  connection->m_certdb);
  849.       if (currCert == NULL) {
  850.           goto loser;
  851.       }
  852.       if (!certificate_conflict(connection, &currCert->derCert,
  853.                                connection->m_certdb, !certAlreadyExisted)) {
  854.           /* This certificate already exists in the permanent
  855.            * database.  Let's not add it and continue on 
  856.            * processing responses.
  857.            */
  858.           if (request.doBackup) {
  859.               certArr[i] = currCert;
  860.           } else {
  861.               CERT_DestroyCertificate(currCert);
  862.           }
  863.           CMMF_DestroyCertResponse(currResponse);
  864.           certAlreadyExisted = PR_TRUE;
  865.           continue;
  866.       }
  867.       
  868.       if (currCert->subjectList && currCert->subjectList->entry && 
  869.           currCert->subjectList->entry->nickname) {
  870.           nickname = currCert->subjectList->entry->nickname;
  871.       } else if (request.nickname == NULL || request.nickname[0] == '') {
  872.           nickname = default_nickname(currCert, connection);
  873.           freeLocalNickname = PR_TRUE; 
  874.       } else {
  875.           nickname = request.nickname;
  876.       }
  877.       slot = PK11_ImportCertForKey(currCert, nickname, connection);
  878.       if (freeLocalNickname) {
  879.           PR_Free(nickname);
  880.           freeLocalNickname = PR_FALSE;
  881.       }
  882.       if (slot == NULL) {
  883.           goto loser;
  884.       }
  885.       SSM_UseAsDefaultEmailIfNoneSet(connection, currCert, PR_TRUE);
  886.       if (request.doBackup) {
  887.           certArr[i] = currCert;
  888.       } else {
  889.           CERT_DestroyCertificate(currCert);
  890.       }
  891.       PK11_FreeSlot(slot);
  892.       CMMF_DestroyCertResponse(currResponse);
  893.   }
  894.   caPubs = CMMF_CertRepContentGetCAPubs(certRepContent);
  895.   if (caPubs != NULL) {
  896.       CERTCertListNode *node;
  897.       /* We got some CA certs to install in the database */
  898.       ourPool = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
  899.       if (ourPool == NULL) {
  900.           goto loser;
  901.       }
  902.       derCerts = PORT_ArenaNewArray(ourPool, SECItem, 
  903.                                     SSM_CertListCount(caPubs));
  904.       if (derCerts == NULL) {
  905.           goto loser;
  906.       }
  907.       for (node = CERT_LIST_HEAD(caPubs), i=0; 
  908.            !CERT_LIST_END(node, caPubs);
  909.            node = CERT_LIST_NEXT(node), i++) {
  910.           srv = SECITEM_CopyItem(ourPool, &derCerts[i], &node->cert->derCert);
  911.           if (srv != SECSuccess) {
  912.               goto loser;
  913.           }
  914.       }
  915.       srv = CERT_ImportCAChain(derCerts, SSM_CertListCount(caPubs),
  916.                                certUsageUserCertImport);
  917.       if (srv != SECSuccess) {
  918.           goto loser;
  919.       }
  920.       PORT_FreeArena(ourPool, PR_FALSE);
  921.   }
  922.   CMMF_DestroyCertRepContent(certRepContent);
  923.   if (request.doBackup) {
  924.       p12Create.isExportContext = PR_TRUE;
  925.       rv = SSM_CreateResource(SSM_RESTYPE_PKCS12_CONTEXT, 
  926.                               (void*)&p12Create,
  927.                               connection, &p12RID,
  928.                               (SSMResource**)(&p12Cxt));
  929.       p12Cxt->arg = SSM_ZNEW(SSMPKCS12BackupThreadArg);
  930.       if (p12Cxt->arg == NULL) {
  931.           goto loser;
  932.       }
  933.       p12Cxt->arg->certs = certArr;
  934.       p12Cxt->arg->numCerts = numResponses;
  935.       p12Cxt->super.m_clientContext = request.clientContext;
  936.       p12Cxt->m_thread = SSM_CreateThread(&p12Cxt->super,
  937.                                   SSMPKCS12Context_BackupMultipleCertsThread);
  938.                                           
  939.   }
  940.   PR_Free(request.base64Der);
  941.   PR_Free(request.nickname);
  942.   PR_FREEIF(msg->data);
  943.   msg->data = NULL;
  944.   msg->len = 0;
  945.   msg->type = (SECItemType)(SSM_REPLY_OK_MESSAGE | SSM_CRMF_ACTION | 
  946.                             SSM_PROCESS_CMMF_RESP);
  947.   if (ssmcontrolconnection_send_message_to_client(connection, msg) 
  948.       != SSM_SUCCESS){
  949.       goto loser;
  950.   }
  951.   SSM_FreeResource(&connection->super.super);
  952.   SECITEM_FreeItem(msg, PR_TRUE);
  953.   return;
  954.  loser:
  955.   if (connection != NULL) {
  956.       SSM_FreeResource(&connection->super.super);
  957.   }
  958.   if (ourPool != NULL) {
  959.       PORT_FreeArena(ourPool, PR_FALSE);
  960.   }
  961.   if (certRepContent != NULL) {
  962.       CMMF_DestroyCertRepContent(certRepContent);
  963.   }
  964.   if (request.base64Der != NULL) {
  965.       PR_Free(request.base64Der);
  966.   }
  967.   if (request.nickname != NULL) {
  968.       PR_Free(request.nickname);
  969.   }
  970.   rv = ssmcontrolconnection_encode_err_reply(msg, SSM_FAILURE);
  971.   PR_ASSERT(rv == SSM_SUCCESS);
  972.   rv = ssmcontrolconnection_send_message_to_client(connection, msg);
  973.   PR_ASSERT(rv == SSM_SUCCESS);
  974. }
  975. SSMStatus 
  976. SSM_ProcessCMMFCertResponse(SECItem *msg, SSMControlConnection *connection)
  977. {
  978.     CMMFResponseArg *arg=NULL;
  979.     arg = SSM_NEW(CMMFResponseArg);
  980.     if (arg == NULL) {
  981.         goto loser;
  982.     }
  983.     arg->msg = SECITEM_DupItem(msg);
  984.     arg->connection = connection;
  985.     SSM_GetResourceReference(&connection->super.super);
  986.     if (SSM_CreateAndRegisterThread(PR_USER_THREAD, 
  987.                                     ssm_processcmmfresponse_thread,
  988.                                     (void *)arg, PR_PRIORITY_NORMAL, 
  989.                                     PR_LOCAL_THREAD,
  990.                                     PR_UNJOINABLE_THREAD, 0) == NULL) {
  991.         SSM_FreeResource(&connection->super.super);
  992.         goto loser;
  993.     }
  994.     return SSM_ERR_DEFER_RESPONSE;    
  995.  loser:
  996.     PR_FREEIF(arg);
  997.     return SSM_FAILURE;
  998. }
  999. SECKEYPrivateKey*
  1000. SSM_FindPrivKeyFromKeyID(SECItem *keyID, SECMODModule *currMod,
  1001.                          SSMControlConnection *ctrl)
  1002. {
  1003.     PK11SlotInfo     *currSlot;
  1004.     SECKEYPrivateKey *privKey = NULL;
  1005.     int               i;
  1006.     for (i=0; i<currMod->slotCount; i++) {
  1007.         currSlot = currMod->slots[i];
  1008.         privKey = PK11_FindKeyByKeyID(currSlot, keyID, (void*)ctrl);
  1009.         if (privKey != NULL) {
  1010.             break;
  1011.         }
  1012.     }
  1013.     return privKey;
  1014. }
  1015. SECKEYPrivateKey*
  1016. SSM_FindPrivKeyFromPubValue(SECItem *publicValue, SECMODModuleList *modList,
  1017.                             SSMControlConnection *ctrl)
  1018. {
  1019.     SECItem          *keyID = NULL;
  1020.     SECMODModuleList *currMod;
  1021.     SECKEYPrivateKey *privKey = NULL;
  1022.     keyID = PK11_MakeIDFromPubKey(publicValue);
  1023.     if (keyID == NULL) {
  1024.         return NULL;
  1025.     }
  1026.     /* Iterate through the slots looking for the slot where the private 
  1027.      * key lives.
  1028.      */
  1029.     currMod = modList;
  1030.     while (currMod != NULL && currMod->module != NULL) {
  1031.         privKey = SSM_FindPrivKeyFromKeyID(keyID, currMod->module, ctrl);
  1032.         if (privKey != NULL) {
  1033.             break;
  1034.         }
  1035.         currMod = currMod->next;
  1036.     }
  1037.     SECITEM_FreeItem(keyID, PR_TRUE);
  1038.     return privKey;
  1039. }
  1040. SSMStatus
  1041. SSM_InitCRMFASN1Arg(CRMFASN1Arg *arg)
  1042. {
  1043.     arg->buffer.data = SSM_NEW_ARRAY(unsigned char, DEFAULT_ASN1_CHUNK_SIZE);
  1044.     if (arg->buffer.data == NULL) {
  1045.         return PR_FAILURE;
  1046.     }
  1047.     arg->buffer.len   = 0;
  1048.     arg->allocatedLen = DEFAULT_ASN1_CHUNK_SIZE;
  1049.     return PR_FAILURE;
  1050. }
  1051. void
  1052. SSM_GenericASN1Callback(void *arg, const char *buf, unsigned long len)
  1053. {
  1054.     CRMFASN1Arg   *encoderArg = (CRMFASN1Arg*)arg;
  1055.     unsigned char *cursor;
  1056.     
  1057.     if ((encoderArg->buffer.len + len) > encoderArg->allocatedLen) {
  1058.         int newSize = encoderArg->buffer.len + DEFAULT_ASN1_CHUNK_SIZE;
  1059.         void *dummy = PR_Realloc(encoderArg->buffer.data, newSize);
  1060.         if (dummy == NULL) {
  1061.             PR_ASSERT(0);
  1062.             return;
  1063.         }
  1064.         encoderArg->buffer.data  = (unsigned char *) dummy;
  1065.         encoderArg->allocatedLen = newSize;
  1066.     }
  1067.     cursor = &(encoderArg->buffer.data[encoderArg->buffer.len]);
  1068.     memcpy(cursor, buf, len);
  1069.     encoderArg->buffer.len += len;
  1070. }
  1071. SSMStatus
  1072. SSM_RespondToPOPChallenge(SECItem                *msg, 
  1073.                           SSMControlConnection   *ctrl,
  1074.                           char                  **challengeResponse, 
  1075.                           PRUint32               *responseLen)
  1076. {
  1077.     SSMStatus   rv;
  1078.     SECStatus  srv;
  1079.     SECItem    challengeDER = {siBuffer, NULL, 0}, *publicValue=NULL;
  1080.     int        i, numChallenges;
  1081.     long      *decryptedChallenges=NULL;
  1082.     CMMFPOPODecKeyChallContent *challContent = NULL;
  1083.     SECMODModuleList           *modList = NULL;
  1084.     SECKEYPrivateKey           *privKey = NULL;
  1085.     CRMFASN1Arg                 asn1Arg = {{(SECItemType) 0, NULL, 0}, 0};
  1086.     SingleStringMessage request;
  1087.     if (CMT_DecodeMessage(SingleStringMessageTemplate, &request, (CMTItem*)msg) != CMTSuccess) {
  1088.         goto loser;
  1089.     }
  1090.     srv = ATOB_ConvertAsciiToItem(&challengeDER, request.string);
  1091.     if (srv != SECSuccess) {
  1092.         goto loser;
  1093.     }
  1094.     challContent = CMMF_CreatePOPODecKeyChallContentFromDER((char *) challengeDER.data,
  1095.                                                             (unsigned int) challengeDER.len);
  1096.     if (challContent == NULL) {
  1097.         goto loser;
  1098.     }
  1099.     numChallenges = CMMF_POPODecKeyChallContentGetNumChallenges(challContent);
  1100.     if (numChallenges <= 0) {
  1101.         /* There weren't any challenges in the challenge string. */
  1102.         goto loser;
  1103.     }
  1104.     modList = SECMOD_GetDefaultModuleList();
  1105.     if (modList == NULL) {
  1106.         goto loser;
  1107.     }
  1108.     decryptedChallenges = SSM_ZNEW_ARRAY(long, (numChallenges+1));
  1109.     if (decryptedChallenges == NULL) {
  1110.         goto loser;
  1111.     }
  1112.     for (i=0; i<numChallenges; i++) {
  1113.         publicValue = 
  1114.             CMMF_POPODecKeyChallContentGetPublicValue(challContent, i);
  1115.         if (publicValue == NULL) {
  1116.             goto loser;
  1117.         }
  1118.         privKey = SSM_FindPrivKeyFromPubValue(publicValue, modList, ctrl);
  1119.         if (privKey == NULL) {
  1120.             goto loser;
  1121.         }
  1122.         SECITEM_FreeItem(publicValue, PR_TRUE);
  1123.         publicValue = NULL;
  1124.         srv = CMMF_POPODecKeyChallContDecryptChallenge(challContent, i,
  1125.                                                        privKey);
  1126.         if (srv != SECSuccess) {
  1127.             goto loser;
  1128.         }
  1129.         srv = CMMF_POPODecKeyChallContentGetRandomNumber(challContent, i,
  1130.                                                      &decryptedChallenges[i]);
  1131.         if (srv != SECSuccess) {
  1132.             goto loser;
  1133.         }
  1134.     }
  1135.     modList = NULL;
  1136.     CMMF_DestroyPOPODecKeyChallContent(challContent);
  1137.     challContent = NULL;
  1138.     rv = SSM_InitCRMFASN1Arg(&asn1Arg);
  1139.     srv = CMMF_EncodePOPODecKeyRespContent(decryptedChallenges, numChallenges,
  1140.                                            SSM_GenericASN1Callback, &asn1Arg);
  1141.     if (srv != SECSuccess) {
  1142.         goto loser;
  1143.     }
  1144.     *challengeResponse = BTOA_DataToAscii(asn1Arg.buffer.data, 
  1145.                                           asn1Arg.buffer.len);
  1146.     PR_Free(asn1Arg.buffer.data);
  1147.     *responseLen = (*challengeResponse == NULL) ? 0 : 
  1148.                                                   strlen(*challengeResponse)+1;
  1149.     PR_Free(decryptedChallenges);
  1150.     PR_Free(request.string);
  1151.     return PR_SUCCESS;
  1152.  loser:
  1153.     if (asn1Arg.buffer.data != NULL) {
  1154.         PR_Free(asn1Arg.buffer.data);
  1155.     }
  1156.     if (decryptedChallenges != NULL) {
  1157.         PR_Free(decryptedChallenges);
  1158.     }
  1159.     if (request.string != NULL) {
  1160.         PR_Free(request.string);
  1161.     }
  1162.     if (challContent != NULL) {
  1163.         CMMF_DestroyPOPODecKeyChallContent(challContent);
  1164.     }
  1165.     if (publicValue != NULL) {
  1166.         SECITEM_FreeItem(publicValue, PR_TRUE);
  1167.     }
  1168.     if (modList != NULL) {
  1169.         SECMOD_DestroyModuleList(modList);
  1170.     }
  1171.     return PR_FAILURE;
  1172. }
  1173. void SSM_CRMFEncodeThread(void *arg)
  1174. {
  1175.    SSMCRMFThreadArg     *encArg = (SSMCRMFThreadArg*)arg; 
  1176.    SSMControlConnection *ctrl   = encArg->ctrl;
  1177.    SECItem              *msg    = encArg->msg;
  1178.    char                 *encodedReq = NULL;
  1179.    PRUint32              derLen;
  1180.    SingleItemMessage reply;
  1181.    SSMStatus rv;
  1182.    SSM_RegisterThread("CRMF Encode", NULL);
  1183.    SSM_DEBUG("Encoding CRMF request(s)n");
  1184.    rv = SSM_EncodeCRMFRequests(ctrl, msg, &encodedReq, &derLen);
  1185.    if (rv != PR_SUCCESS) {
  1186.        goto loser;
  1187.    }
  1188.    msg->data = NULL;
  1189.    msg->len  = 0;
  1190.    msg->type = (SECItemType) (SSM_REPLY_OK_MESSAGE | 
  1191.                               SSM_CRMF_ACTION      |
  1192.                               SSM_DER_ENCODE_REQ);
  1193.    reply.item.len = derLen;
  1194.    reply.item.data = (unsigned char *) encodedReq;
  1195.    if (CMT_EncodeMessage(SingleItemMessageTemplate, 
  1196.                          (CMTItem*)msg, &reply) != CMTSuccess) {
  1197.        goto loser;
  1198.    }
  1199.    SSM_DEBUG("Created the following request: n");
  1200.    SSM_DEBUG("n%sn",encodedReq);
  1201.    PR_Free(encodedReq);
  1202.    SSM_DEBUG("queueing reply: type %lx, len %ld.n", msg->type, msg->len);
  1203.    SSM_SendQMessage(ctrl->m_controlOutQ,
  1204.                     SSM_PRIORITY_NORMAL,
  1205.                     msg->type, msg->len,
  1206.                     (char *)msg->data, PR_TRUE);
  1207.    goto done;
  1208.  loser:
  1209.   {
  1210.     SingleNumMessage reply;
  1211.     msg->type = (SECItemType) SSM_REPLY_ERR_MESSAGE;
  1212.     reply.value = rv;
  1213.     CMT_EncodeMessage(SingleNumMessageTemplate, (CMTItem*)msg, &reply);
  1214.   }
  1215.   SSM_DEBUG("queueing reply: type %lx, len %ld.n", msg->type, msg->len);
  1216.   SSM_SendQMessage(ctrl->m_controlOutQ,
  1217.                    SSM_PRIORITY_NORMAL,
  1218.                    msg->type, msg->len,
  1219.                    (char *)msg->data, PR_TRUE);
  1220.  done:
  1221.   SSM_FreeResource(&ctrl->super.super);
  1222.   SECITEM_FreeItem(msg, PR_TRUE);
  1223.   PR_Free(arg);
  1224. }