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

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. #if defined(XP_UNIX) || defined(XP_BEOS) || defined(XP_OS2)
  35. #include <sys/types.h>
  36. #include <sys/socket.h>
  37. #include <netinet/in.h>
  38. #include <sys/time.h>
  39. #else
  40. #ifdef XP_MAC
  41. #include "macsocket.h"
  42. #else /* Windows */
  43. #include <windows.h>
  44. #include <winsock.h>
  45. #endif
  46. #endif
  47. #include <errno.h>
  48. #include "cmtcmn.h"
  49. #include "cmtutils.h"
  50. #include "messages.h"
  51. #include "rsrcids.h"
  52. typedef struct _CMTP7Private {
  53.     CMTPrivate priv;
  54.     CMTP7ContentCallback cb;
  55.     void *cb_arg;
  56. } CMTP7Private;
  57. CMTStatus CMT_PKCS7DecoderStart(PCMT_CONTROL control, void* clientContext, CMUint32 * connectionID, CMInt32 * result,
  58.                                 CMTP7ContentCallback cb, void *cb_arg)
  59. {
  60.     CMTItem message;
  61.     CMTStatus rv;
  62.     CMTP7Private *priv=NULL;
  63.     SingleItemMessage request;
  64.     DataConnectionReply reply;
  65.     /* Check passed in parameters */
  66.     if (!control) {
  67.         goto loser;
  68.     }
  69.     request.item = CMT_CopyPtrToItem(clientContext);
  70.     /* Encode message */
  71.     if (CMT_EncodeMessage(SingleItemMessageTemplate, &message, &request) != CMTSuccess) {
  72.         goto loser;
  73.     }
  74.     /* Set the message request type */
  75.     message.type = SSM_REQUEST_MESSAGE | SSM_DATA_CONNECTION | SSM_PKCS7DECODE_STREAM;
  76.     /* Send the message. */
  77.     if (CMT_SendMessage(control, &message) == CMTFailure) {
  78.         goto loser;
  79.     }
  80.     /* Validate the message reply type */
  81.     if (message.type != (SSM_REPLY_OK_MESSAGE | SSM_DATA_CONNECTION | SSM_PKCS7DECODE_STREAM)) {
  82.         goto loser;
  83.     }
  84.     /* Decode the reply */
  85.     if (CMT_DecodeMessage(DataConnectionReplyTemplate, &reply, &message) != CMTSuccess) {
  86.         goto loser;
  87.     }
  88.     /* Success */
  89.     if (reply.result == 0) {
  90.         CMTSocket sock;
  91.         priv = (CMTP7Private *)malloc(sizeof(CMTP7Private));
  92.         if (priv == NULL)
  93.             goto loser;
  94.         priv->priv.dest = (CMTReclaimFunc) free;
  95.         priv->cb = cb;
  96.         priv->cb_arg = cb_arg;
  97.         sock = control->sockFuncs.socket(0);
  98.         if (sock == NULL) {
  99.             goto loser;
  100.         }
  101.  
  102.        if (control->sockFuncs.connect(sock, (short)reply.port, 
  103.                                       NULL) != CMTSuccess) {
  104.             goto loser;
  105.         }
  106.  
  107.         if (control->sockFuncs.send(sock, control->nonce.data, 
  108.                                     control->nonce.len) != control->nonce.len){
  109.             goto loser;
  110.         }
  111.         /* Save connection info */
  112.         if (CMT_AddDataConnection(control, sock, reply.connID)
  113.             != CMTSuccess) {
  114.             goto loser;
  115.         }
  116.         *connectionID = reply.connID;
  117.         rv = CMT_SetPrivate(control, reply.connID, &priv->priv);
  118.         if (rv != CMTSuccess)
  119.             goto loser;
  120.         return CMTSuccess;
  121.     } 
  122. loser:
  123.     if (priv) {
  124.         free(priv);
  125.     }
  126. *result = reply.result;
  127.     return CMTFailure;
  128. }
  129. CMTStatus CMT_PKCS7DecoderUpdate(PCMT_CONTROL control, CMUint32 connectionID, const char * buf, CMUint32 len)
  130. {
  131.     CMUint32 sent;
  132.     CMTP7Private *priv;
  133.     unsigned long nbytes;
  134.     char read_buf[128];
  135.     CMTSocket sock, ctrlsock, selSock, sockArr[2];
  136.     /* Do some parameter checking */
  137.     if (!control || !buf) {
  138.         goto loser;
  139.     }
  140.     /* Get the data socket */
  141.     if (CMT_GetDataSocket(control, connectionID, &sock) == CMTFailure) {
  142.         goto loser;
  143.     }
  144.     priv = (CMTP7Private *)CMT_GetPrivate(control, connectionID);
  145.     if (priv == NULL)
  146.         goto loser;
  147.     /* Write the data to the socket */
  148.     sent = CMT_WriteThisMany(control, sock, (void*)buf, len);
  149.     if (sent != len) {
  150.         goto loser;
  151.     }
  152. ctrlsock = control->sock;
  153. sockArr[0] = ctrlsock;
  154. sockArr[1] = sock;
  155.     while ((selSock = control->sockFuncs.select(sockArr,2,1))) 
  156.     {
  157. if (selSock == ctrlsock) {
  158. CMT_ProcessEvent(control);
  159. } else {
  160.         nbytes = control->sockFuncs.recv(sock, read_buf, sizeof(read_buf));
  161.     if (nbytes == -1) {
  162.     goto loser;
  163. }
  164. if (nbytes == 0) {
  165.             break;
  166.     }
  167. priv->cb(priv->cb_arg, read_buf, nbytes);
  168. }
  169.     }
  170.     return CMTSuccess;
  171. loser:
  172.     return CMTFailure;
  173. }
  174.                                                                                 
  175. CMTStatus CMT_PKCS7DecoderFinish(PCMT_CONTROL control, CMUint32 connectionID, 
  176.                                  CMUint32 * resourceID)
  177. {
  178.     CMTP7Private *priv;
  179.     long nbytes;
  180.     char buf[128];
  181.     CMTSocket sock, ctrlsock, selSock, sockArr[2];
  182. #ifndef XP_MAC
  183.     int numTries = 0;
  184. #endif
  185.     /* Do some parameter checking */
  186.     if (!control) {
  187.         goto loser;
  188.     }
  189.     priv = (CMTP7Private *)CMT_GetPrivate(control, connectionID);
  190.     if (priv == NULL)
  191.         goto loser;
  192.     if (CMT_GetDataSocket(control, connectionID, &sock) == CMTFailure) {
  193.         goto loser;
  194.     }
  195.     ctrlsock = control->sock;
  196.     /* drain socket before we close it */
  197.     control->sockFuncs.shutdown(sock);
  198.     sockArr[0] = sock;
  199.     sockArr[1] = ctrlsock;
  200.     /* Let's see if doing a poll first gets rid of a weird bug where we
  201.      * lock up the client.
  202.      * There are some cases where the server doesn't put up data fast 
  203.      * enough, so we should loop on this poll instead of just trying it
  204.      * once.
  205.      */
  206. #ifndef XP_MAC
  207.  poll_sockets:
  208.     if (control->sockFuncs.select(sockArr,2,1) != NULL)
  209. #endif
  210. {
  211.         while (1) {
  212.             selSock = control->sockFuncs.select(sockArr,2,0);
  213.             if (selSock == ctrlsock) {
  214.                 CMT_ProcessEvent(control);
  215.             } else if (selSock == sock) {
  216.                 nbytes = control->sockFuncs.recv(sock, buf, sizeof(buf));
  217.                 if (nbytes < 0) {
  218.                     goto loser;
  219.                 } else if (nbytes == 0) {
  220.                     break;
  221.                 }
  222.                 if (priv->cb)
  223.                     priv->cb(priv->cb_arg, buf, nbytes);
  224.             }
  225.         }
  226.     }
  227. #ifndef XP_MAC
  228.     else {
  229. #ifdef WIN32
  230.         if (numTries < 20) {
  231.             Sleep(100);
  232.             numTries++;
  233.             goto poll_sockets;
  234.         }
  235. #endif
  236. #ifdef XP_UNIX
  237. if (numTries < 25) {
  238.   numTries += sleep(1);
  239.   goto poll_sockets;
  240. }
  241. #endif
  242.     }
  243. #endif
  244.     
  245.     if (CMT_CloseDataConnection(control, connectionID) == CMTFailure) {
  246.         goto loser;
  247.     }
  248.     /* Get the PKCS7 content info */
  249.     if (CMT_GetRIDAttribute(control, connectionID, SSM_FID_P7CONN_CONTENT_INFO,
  250.                             resourceID) == CMTFailure) {
  251.         goto loser;
  252.     }
  253.     return CMTSuccess;
  254. loser:
  255.     if (control) {
  256.         CMT_CloseDataConnection(control, connectionID);
  257.     }
  258.     
  259.     return CMTFailure;
  260. }
  261. CMTStatus CMT_PKCS7DestroyContentInfo(PCMT_CONTROL control, CMUint32 resourceID)
  262. {
  263.     if (!control) {
  264.         goto loser;
  265.     }
  266.     /* Delete the resource */
  267.     if (CMT_DestroyResource(control, resourceID, SSM_FID_P7CONN_CONTENT_INFO) == CMTFailure) {
  268.         goto loser;
  269.     }
  270.     return CMTSuccess;
  271. loser:
  272.     return CMTFailure;
  273. }
  274. CMTStatus CMT_PKCS7VerifyDetachedSignature(PCMT_CONTROL control, CMUint32 resourceID, CMUint32 certUsage, CMUint32 hashAlgID, CMUint32 keepCerts, CMTItem* digest, CMInt32 * result)
  275. {
  276.     CMTItem message;
  277.     VerifyDetachedSigRequest request;
  278.     SingleNumMessage reply;
  279.     /* Do some parameter checking */
  280.     if (!control || !digest || !result) {
  281.         goto loser;
  282.     }
  283.     /* Set the request */
  284.     request.pkcs7ContentID = resourceID;
  285.     request.certUsage = certUsage;
  286.     request.hashAlgID = hashAlgID;
  287.     request.keepCert = (CMBool) keepCerts;
  288.     request.hash = *digest;
  289.     /* Encode the request */
  290.     if (CMT_EncodeMessage(VerifyDetachedSigRequestTemplate, &message, &request) != CMTSuccess) {
  291.         goto loser;
  292.     }
  293.     /* Set the message request type */
  294.     message.type = SSM_REQUEST_MESSAGE | SSM_OBJECT_SIGNING | SSM_VERIFY_DETACHED_SIG;
  295.     /* Send the message */
  296.     if (CMT_SendMessage(control, &message) == CMTFailure) {
  297.         goto loser;
  298.     }
  299.     /* Validate the message reply type */
  300.     if (message.type != (SSM_REPLY_OK_MESSAGE | SSM_OBJECT_SIGNING |SSM_VERIFY_DETACHED_SIG)) {
  301.         goto loser;
  302.     }
  303.     /* Decode the reply */
  304.     if (CMT_DecodeMessage(SingleNumMessageTemplate, &reply, &message) != CMTSuccess) {
  305.         goto loser;
  306.     }
  307.     *result = reply.value;
  308.     return CMTSuccess;
  309. loser:
  310. *result = reply.value;
  311. return CMTFailure;
  312. }
  313. CMTStatus CMT_PKCS7VerifySignature(PCMT_CONTROL control, CMUint32 pubKeyAlgID,
  314.                                    CMTItem *pubKeyParams, CMTItem *signerPubKey,
  315.                                    CMTItem *computedHash, CMTItem *signature,
  316.                                    CMInt32 *result)
  317. {
  318. return CMTFailure;
  319. }
  320. CMTStatus CMT_CreateSigned(PCMT_CONTROL control, CMUint32 scertRID,
  321.                            CMUint32 ecertRID, CMUint32 dig_alg,
  322.                            CMTItem *digest, CMUint32 *ciRID, CMInt32 *errCode)
  323. {
  324.     CMTItem message;
  325.     CreateSignedRequest request;
  326.     CreateContentInfoReply reply;
  327.     char checkMessageForError = 0;
  328.     /* Do some parameter checking */
  329.     if (!control || !scertRID || !digest || !ciRID) {
  330.         goto loser;
  331.     }
  332.     /* Set the request */
  333.     request.scertRID = scertRID;
  334.     request.ecertRID = ecertRID;
  335.     request.dig_alg = dig_alg;
  336.     request.digest = *digest;
  337.     /* Encode the request */
  338.     if (CMT_EncodeMessage(CreateSignedRequestTemplate, &message, &request) != CMTSuccess) {
  339.         goto loser;
  340.     }
  341.     /* Set the message request type */
  342.     message.type = SSM_REQUEST_MESSAGE | SSM_OBJECT_SIGNING | SSM_CREATE_SIGNED;
  343.     /* Send the message */
  344.     if (CMT_SendMessage(control, &message) == CMTFailure) {
  345.         goto loser;
  346.     }
  347.     checkMessageForError = 1;
  348.     /* Validate the message reply type */
  349.     if (message.type != (SSM_REPLY_OK_MESSAGE | SSM_OBJECT_SIGNING | SSM_CREATE_SIGNED)) {
  350.         goto loser;
  351.     }
  352.     /* Decode the reply */
  353.     if (CMT_DecodeMessage(CreateContentInfoReplyTemplate, &reply, &message) != CMTSuccess) {
  354.         goto loser;
  355.     }
  356.     *ciRID = reply.ciRID;
  357.     if (reply.result == 0) {
  358. return CMTSuccess;
  359. loser:
  360.     if (checkMessageForError && 
  361. CMT_DecodeMessage(SingleNumMessageTemplate, 
  362.   &reply, &message) == CMTSuccess) {
  363.         *errCode = reply.errorCode;
  364.     } else {
  365.         *errCode = 0;
  366.     }
  367. return CMTFailure;
  368. }
  369. CMTStatus CMT_CreateEncrypted(PCMT_CONTROL control, CMUint32 scertRID,
  370.                               CMUint32 *rcertRIDs, CMUint32 *ciRID)
  371. {
  372.     CMTItem message;
  373.     CMInt32 nrcerts;
  374.     CreateEncryptedRequest request;
  375.     CreateContentInfoReply reply;
  376.     /* Do some parameter checking */
  377.     if (!control || !scertRID || !rcertRIDs || !ciRID) {
  378.         goto loser;
  379.     }
  380.     /* Calculate the number of certs */
  381.     for (nrcerts =0; rcertRIDs[nrcerts] != 0; nrcerts++) {
  382.         /* Nothing */
  383.         ;
  384.     }
  385.     /* Set up the request */
  386.     request.scertRID = scertRID;
  387.     request.nrcerts = nrcerts;
  388.     request.rcertRIDs = (long *) rcertRIDs;
  389.     /* Encode the request */
  390.     if (CMT_EncodeMessage(CreateEncryptedRequestTemplate, &message, &request) != CMTSuccess) {
  391.         goto loser;
  392.     }
  393.     /* Set the message request type */
  394.     message.type = SSM_REQUEST_MESSAGE | SSM_OBJECT_SIGNING | SSM_CREATE_ENCRYPTED;
  395.     /* Send the message */
  396.     if (CMT_SendMessage(control, &message) == CMTFailure) {
  397.         goto loser;
  398.     }
  399.     /* Validate the message response type */
  400.     if (message.type != (SSM_REPLY_OK_MESSAGE | SSM_OBJECT_SIGNING | SSM_CREATE_ENCRYPTED)) {
  401.         goto loser;
  402.     }
  403.     /* Decode the reply */
  404.     if (CMT_DecodeMessage(CreateContentInfoReplyTemplate, &reply, &message) != CMTSuccess) {
  405.         goto loser;
  406.     }
  407.     *ciRID = reply.ciRID;
  408.     if (reply.result == 0) {
  409. return CMTSuccess;
  410. loser:
  411. return CMTFailure;
  412. }
  413. CMTStatus CMT_PKCS7EncoderStart(PCMT_CONTROL control, CMUint32 ciRID,
  414.                                 CMUint32 *connectionID, CMTP7ContentCallback cb,
  415.                                 void *cb_arg)
  416. {
  417.     CMTItem message;
  418.     CMTStatus rv;
  419.     CMTP7Private *priv;
  420.     PKCS7DataConnectionRequest request;
  421.     DataConnectionReply reply;
  422.     /* Check passed in parameters */
  423.     if (!control || !ciRID) {
  424.         goto loser;
  425.     }
  426.     /* Set up the request */
  427.     request.resID = ciRID;
  428.     request.clientContext.len = 0;
  429.     request.clientContext.data = NULL;
  430.     /* Encode the request */
  431.     if (CMT_EncodeMessage(PKCS7DataConnectionRequestTemplate, &message, &request) != CMTSuccess) {
  432.         goto loser;
  433.     }
  434.     /* Set the message request type */
  435.     message.type = SSM_REQUEST_MESSAGE | SSM_DATA_CONNECTION | SSM_PKCS7ENCODE_STREAM;
  436.     /* Send the message */
  437.     if (CMT_SendMessage(control, &message) == CMTFailure) {
  438.         goto loser;
  439.     }
  440.     /* Validate the message reply type */
  441.     if (message.type != (SSM_REPLY_OK_MESSAGE | SSM_DATA_CONNECTION | SSM_PKCS7ENCODE_STREAM)) {
  442.         goto loser;
  443.     }
  444.     /* Decode the reply */
  445.     if (CMT_DecodeMessage(DataConnectionReplyTemplate, &reply, &message) != CMTSuccess) {
  446.         goto loser;
  447.     }
  448.     /* Success */
  449.     if (reply.result == 0) {
  450.         CMTSocket sock;
  451.         priv = (CMTP7Private *)malloc(sizeof(CMTP7Private));
  452.         if (priv == NULL)
  453.             goto loser;
  454.         priv->priv.dest = (CMTReclaimFunc) free;
  455.         priv->cb = cb;
  456.         priv->cb_arg = cb_arg;
  457.         sock = control->sockFuncs.socket(0);
  458.         if (sock == NULL) {
  459.             goto loser;
  460.         }
  461.         if (control->sockFuncs.connect(sock, (short)reply.port, 
  462.                                        NULL) != CMTSuccess) {
  463.             goto loser;
  464.         }
  465.         if (control->sockFuncs.send(sock, control->nonce.data, 
  466.                                    control->nonce.len) != control->nonce.len) {
  467.             goto loser;
  468.         }
  469.         /* Save connection info */
  470.         if (CMT_AddDataConnection(control, sock, reply.connID)
  471.             != CMTSuccess) {
  472.             goto loser;
  473.         }
  474.         *connectionID = reply.connID;
  475.         rv = CMT_SetPrivate(control, reply.connID, &priv->priv);
  476.         if (rv != CMTSuccess)
  477.             goto loser;
  478.         return CMTSuccess;
  479.     } 
  480. loser:
  481.     return CMTFailure;
  482. }
  483. CMTStatus CMT_PKCS7EncoderUpdate(PCMT_CONTROL control, CMUint32 connectionID,
  484.                                  const char *buf, CMUint32 len)
  485. {
  486.     CMUint32 sent;
  487.     CMTP7Private *priv;
  488.     unsigned long nbytes;
  489.     char read_buf[128];
  490.     CMTSocket sock, ctrlsock, sockArr[2], selSock;
  491.     /* Do some parameter checking */
  492.     if (!control || !connectionID || !buf) {
  493.         goto loser;
  494.     }
  495.     /* Get the data socket */
  496.     if (CMT_GetDataSocket(control, connectionID, &sock) == CMTFailure) {
  497.         goto loser;
  498.     }
  499.     priv = (CMTP7Private *)CMT_GetPrivate(control, connectionID);
  500.     if (priv == NULL)
  501.         goto loser;
  502.     /* Write the data to the socket */
  503.     sent = CMT_WriteThisMany(control, sock, (void*)buf, len);
  504.     if (sent != len) {
  505.         goto loser;
  506.     }
  507. ctrlsock = control->sock;
  508. sockArr[0] = ctrlsock;
  509. sockArr[1] = sock;
  510.     while ((selSock = control->sockFuncs.select(sockArr, 2, 1)) != NULL) 
  511.     {
  512. if (selSock == ctrlsock) {
  513. CMT_ProcessEvent(control);
  514. } else {
  515.         nbytes = control->sockFuncs.recv(sock, read_buf, sizeof(read_buf));
  516.     if (nbytes == -1) {
  517.     goto loser;
  518. } else if (nbytes == 0) {
  519.             break;
  520.     } else {
  521.     priv->cb(priv->cb_arg, read_buf, nbytes);
  522. }
  523. }
  524.     }
  525.     return CMTSuccess;
  526. loser:
  527.     return CMTFailure;
  528. }
  529. CMTStatus CMT_PKCS7EncoderFinish(PCMT_CONTROL control, CMUint32 connectionID)
  530. {
  531.     CMTP7Private *priv;
  532.     CMInt32 nbytes;
  533.     char buf[128];
  534.     CMTSocket sock, ctrlsock, sockArr[2], selSock;
  535.     /* Do some parameter checking */
  536.     if (!control) {
  537.         goto loser;
  538.     }
  539.     priv = (CMTP7Private *)CMT_GetPrivate(control, connectionID);
  540.     if (priv == NULL)
  541.         goto loser;
  542.     if (CMT_GetDataSocket(control, connectionID, &sock) == CMTFailure) {
  543.         goto loser;
  544.     }
  545.     ctrlsock = control->sock;
  546.     sockArr[0] = ctrlsock;
  547.     sockArr[1] = sock;
  548.     control->sockFuncs.shutdown(sock);
  549.     while (1) {
  550.         selSock = control->sockFuncs.select(sockArr, 2, 0);
  551.         if (selSock == ctrlsock) {
  552.             CMT_ProcessEvent(control);
  553.         } else if (selSock == sock) {
  554.             nbytes = control->sockFuncs.recv(sock, buf, sizeof(buf));
  555.             if (nbytes < 0) {
  556.                 goto loser;
  557.             } else if (nbytes == 0) {
  558.                 break;
  559.             } else {
  560.                 priv->cb(priv->cb_arg, buf, nbytes);
  561.             }
  562.         }
  563.     }
  564.     if (CMT_CloseDataConnection(control, connectionID) == CMTFailure) {
  565.         goto loser;
  566.     }
  567.     return CMTSuccess;
  568. loser:
  569.     if (control) {
  570.         CMT_CloseDataConnection(control, connectionID);
  571.     }
  572.     
  573.     return CMTFailure;
  574. }