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

CA认证

开发平台:

WINDOWS

  1. /* -*- Mode: C; tab-width: 8 -*-*/
  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. #include "crmf.h"
  35. #include "crmfi.h"
  36. #include "secitem.h"
  37. static CRMFPOPChoice
  38. crmf_get_popchoice_from_der(SECItem *derPOP)
  39. {
  40.     CRMFPOPChoice retChoice;
  41.     switch (derPOP->data[0] & 0x0f) {
  42.     case 0:
  43.         retChoice = crmfRAVerified;
  44. break;
  45.     case 1:
  46.         retChoice = crmfSignature;
  47. break;
  48.     case 2:
  49.         retChoice = crmfKeyEncipherment;
  50. break;
  51.     case 3:
  52.         retChoice = crmfKeyAgreement;
  53. break;
  54.     default:
  55.         retChoice = crmfNoPOPChoice;
  56. break;
  57.     }
  58.     return retChoice;
  59. }
  60. static SECStatus
  61. crmf_decode_process_raverified(CRMFCertReqMsg *inCertReqMsg)
  62. {   
  63.     CRMFProofOfPossession *pop;
  64.     /* Just set up the structure so that the message structure
  65.      * looks like one that was created using the API
  66.      */
  67.     pop = inCertReqMsg->pop;
  68.     pop->popChoice.raVerified.data = NULL;
  69.     pop->popChoice.raVerified.len  = 0;
  70.     return SECSuccess;
  71. }
  72. static SECStatus
  73. crmf_decode_process_signature(CRMFCertReqMsg *inCertReqMsg)
  74. {
  75.     return SEC_ASN1Decode(inCertReqMsg->poolp,
  76.   &inCertReqMsg->pop->popChoice.signature,
  77.   CRMFPOPOSigningKeyTemplate, 
  78.   (const char*)inCertReqMsg->derPOP.data,
  79.   inCertReqMsg->derPOP.len);
  80. }
  81. static CRMFPOPOPrivKeyChoice
  82. crmf_get_messagechoice_from_der(SECItem *derPOP)
  83. {
  84.     CRMFPOPOPrivKeyChoice retChoice;
  85.     switch (derPOP->data[2] & 0x0f) {
  86.     case 0:
  87.         retChoice = crmfThisMessage;
  88. break;
  89.     case 1:
  90.         retChoice = crmfSubsequentMessage;
  91. break;
  92.     case 2:
  93.         retChoice = crmfDHMAC;
  94. break;
  95.     default:
  96.         retChoice = crmfNoMessage;
  97.     }
  98.     return retChoice;
  99. }
  100. static SECStatus
  101. crmf_decode_process_popoprivkey(CRMFCertReqMsg *inCertReqMsg)
  102. {
  103.     /* We've got a union, so a pointer to one POPOPrivKey
  104.      * struct is the same as having a pointer to the other 
  105.      * one.
  106.      */
  107.     CRMFPOPOPrivKey *popoPrivKey = 
  108.                     &inCertReqMsg->pop->popChoice.keyEncipherment;
  109.     SECItem         *derPOP, privKeyDer;
  110.     SECStatus        rv;
  111.     derPOP = &inCertReqMsg->derPOP;
  112.     popoPrivKey->messageChoice = crmf_get_messagechoice_from_der(derPOP);
  113.     if (popoPrivKey->messageChoice == crmfNoMessage) {
  114.         return SECFailure;
  115.     }
  116.     /* If we ever encounter BER encodings of this, we'll get in trouble*/
  117.     switch (popoPrivKey->messageChoice) {
  118.     case crmfThisMessage:
  119.     case crmfDHMAC:
  120.         privKeyDer.data = &derPOP->data[5];
  121. privKeyDer.len  = derPOP->len - 5;
  122. break;
  123.     case crmfSubsequentMessage:
  124.         privKeyDer.data = &derPOP->data[4];
  125. privKeyDer.len  = derPOP->len - 4;
  126. break;
  127.     default:
  128.         rv = SECFailure;
  129.     }
  130.     rv = SECITEM_CopyItem(inCertReqMsg->poolp, 
  131.   &popoPrivKey->message.subsequentMessage,
  132.   &privKeyDer);
  133.     if (rv != SECSuccess) {
  134.         return rv;
  135.     }
  136.     if (popoPrivKey->messageChoice == crmfThisMessage ||
  137. popoPrivKey->messageChoice == crmfDHMAC) {
  138.         popoPrivKey->message.thisMessage.len = 
  139.     CRMF_BYTES_TO_BITS(privKeyDer.len) - (int)derPOP->data[4];
  140.         
  141.     }
  142.     return SECSuccess;    
  143. }
  144. static SECStatus
  145. crmf_decode_process_keyagreement(CRMFCertReqMsg *inCertReqMsg)
  146. {
  147.     return crmf_decode_process_popoprivkey(inCertReqMsg);
  148. }
  149. static SECStatus
  150. crmf_decode_process_keyencipherment(CRMFCertReqMsg *inCertReqMsg)
  151. {
  152.     SECStatus rv;
  153.     rv = crmf_decode_process_popoprivkey(inCertReqMsg);
  154.     if (rv != SECSuccess) {
  155.         return rv;
  156.     }
  157.     if (inCertReqMsg->pop->popChoice.keyEncipherment.messageChoice == 
  158. crmfDHMAC) {
  159.         /* Key Encipherment can not use the dhMAC option for
  160.  * POPOPrivKey. 
  161.  */
  162.         return SECFailure;
  163.     }
  164.     return SECSuccess;
  165. }
  166. static SECStatus
  167. crmf_decode_process_pop(CRMFCertReqMsg *inCertReqMsg)
  168. {
  169.      SECItem               *derPOP;
  170.      PRArenaPool           *poolp;
  171.      CRMFProofOfPossession *pop;
  172.      void                  *mark;
  173.      SECStatus              rv;
  174.      derPOP = &inCertReqMsg->derPOP;
  175.      poolp  = inCertReqMsg->poolp;
  176.      if (derPOP->data == NULL) {
  177.          /* There is no Proof of Possession field in this message. */
  178.          return SECSuccess;
  179.      }
  180.      mark = PORT_ArenaMark(poolp);
  181.      pop = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
  182.      if (pop == NULL) {
  183.          goto loser;
  184.      }
  185.      pop->popUsed = crmf_get_popchoice_from_der(derPOP);
  186.      if (pop->popUsed == crmfNoPOPChoice) {
  187.          /* A bad encoding of CRMF.  Not a valid tag was given to the
  188.   * Proof Of Possession field.
  189.   */
  190.          goto loser;
  191.      }
  192.      inCertReqMsg->pop = pop;
  193.      switch (pop->popUsed) {
  194.      case crmfRAVerified:
  195.          rv = crmf_decode_process_raverified(inCertReqMsg);
  196.  break;
  197.      case crmfSignature:
  198.          rv = crmf_decode_process_signature(inCertReqMsg);
  199.  break;
  200.      case crmfKeyEncipherment:
  201.          rv = crmf_decode_process_keyencipherment(inCertReqMsg);
  202.  break;
  203.      case crmfKeyAgreement:
  204.          rv = crmf_decode_process_keyagreement(inCertReqMsg);
  205.  break;
  206.      default:
  207.          rv = SECFailure;
  208.      }
  209.      if (rv != SECSuccess) {
  210.          goto loser;
  211.      }
  212.      PORT_ArenaUnmark(poolp, mark);
  213.      return SECSuccess;
  214.  loser:
  215.      PORT_ArenaRelease(poolp, mark);
  216.      inCertReqMsg->pop = NULL;
  217.      return SECFailure;
  218.      
  219. }
  220. static SECStatus
  221. crmf_decode_process_single_control(PRArenaPool *poolp, 
  222.    CRMFControl *inControl)
  223. {
  224.     const SEC_ASN1Template *asn1Template = NULL;
  225.     inControl->tag = SECOID_FindOIDTag(&inControl->derTag);
  226.     asn1Template = crmf_get_pkiarchiveoptions_subtemplate(inControl);
  227.     PORT_Assert (asn1Template != NULL);
  228.     /* We've got a union, so passing a pointer to one element of the
  229.      * union is the same as passing a pointer to any of the other
  230.      * members of the union.
  231.      */
  232.     return SEC_ASN1Decode(poolp, &inControl->value.archiveOptions, 
  233.   asn1Template, (const char*)inControl->derValue.data,
  234.   inControl->derValue.len);
  235. }
  236. static SECStatus 
  237. crmf_decode_process_controls(CRMFCertReqMsg *inCertReqMsg)
  238. {
  239.     int           i, numControls;
  240.     SECStatus     rv;
  241.     PRArenaPool  *poolp;
  242.     CRMFControl **controls;
  243.     
  244.     numControls = CRMF_CertRequestGetNumControls(inCertReqMsg->certReq);
  245.     controls = inCertReqMsg->certReq->controls;
  246.     poolp    = inCertReqMsg->poolp;
  247.     for (i=0; i < numControls; i++) {
  248.         rv = crmf_decode_process_single_control(poolp, controls[i]);
  249. if (rv != SECSuccess) {
  250.     return SECFailure;
  251. }
  252.     }
  253.     return SECSuccess;
  254. }
  255. static SECStatus
  256. crmf_decode_process_single_reqmsg(CRMFCertReqMsg *inCertReqMsg)
  257. {
  258.     SECStatus rv;
  259.     rv = crmf_decode_process_pop(inCertReqMsg);
  260.     if (rv != SECSuccess) {
  261.         goto loser;
  262.     }
  263.     rv = crmf_decode_process_controls(inCertReqMsg);
  264.     if (rv != SECSuccess) {
  265.         goto loser;
  266.     }
  267.     inCertReqMsg->certReq->certTemplate.numExtensions = 
  268.         CRMF_CertRequestGetNumberOfExtensions(inCertReqMsg->certReq);
  269.     inCertReqMsg->isDecoded = PR_TRUE;
  270.     rv = SECSuccess;
  271.  loser:
  272.     return rv;
  273. }
  274. CRMFCertReqMsg*
  275. CRMF_CreateCertReqMsgFromDER (const char * buf, long len)
  276. {
  277.     PRArenaPool    *poolp;
  278.     CRMFCertReqMsg *certReqMsg;
  279.     SECStatus       rv;
  280.     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
  281.     if (poolp == NULL) {
  282.         goto loser;
  283.     }
  284.     certReqMsg = PORT_ArenaZNew (poolp, CRMFCertReqMsg);
  285.     if (certReqMsg == NULL) {
  286.         goto loser;
  287.     }
  288.     certReqMsg->poolp = poolp;
  289.     rv = SEC_ASN1Decode(poolp, certReqMsg, CRMFCertReqMsgTemplate, buf, len);
  290.     if (rv != SECSuccess) {
  291.         goto loser;
  292.     }
  293.     rv = crmf_decode_process_single_reqmsg(certReqMsg);
  294.     if (rv != SECSuccess) {
  295.         goto loser;
  296.     }
  297.     return certReqMsg;
  298.  loser:
  299.     if (poolp != NULL) {
  300.         PORT_FreeArena(poolp, PR_FALSE);
  301.     }
  302.     return NULL;
  303. }
  304. CRMFCertReqMessages*
  305. CRMF_CreateCertReqMessagesFromDER(const char *buf, long len)
  306. {
  307.     long                 arenaSize;
  308.     int                  i;
  309.     SECStatus            rv;
  310.     PRArenaPool         *poolp;
  311.     CRMFCertReqMessages *certReqMsgs;
  312.     PORT_Assert (buf != NULL);
  313.     /* Wanna make sure the arena is big enough to store all of the requests
  314.      * coming in.  We'll guestimate according to the length of the buffer.
  315.      */
  316.     arenaSize = len * 1.5;
  317.     poolp = PORT_NewArena(arenaSize);
  318.     if (poolp == NULL) {
  319.         return NULL;
  320.     }
  321.     certReqMsgs = PORT_ArenaZNew(poolp, CRMFCertReqMessages);
  322.     if (certReqMsgs == NULL) {
  323.         goto loser;
  324.     }
  325.     certReqMsgs->poolp = poolp;
  326.     rv = SEC_ASN1Decode(poolp, certReqMsgs, CRMFCertReqMessagesTemplate,
  327. buf, len);
  328.     if (rv != SECSuccess) {
  329.         goto loser;
  330.     }
  331.     for (i=0; certReqMsgs->messages[i] != NULL; i++) {
  332.         /* The sub-routines expect the individual messages to have 
  333.  * an arena.  We'll give them one temporarily.
  334.  */
  335.         certReqMsgs->messages[i]->poolp = poolp;
  336.         rv = crmf_decode_process_single_reqmsg(certReqMsgs->messages[i]);
  337. if (rv != SECSuccess) {
  338.     goto loser;
  339. }
  340.         certReqMsgs->messages[i]->poolp = NULL;
  341.     }
  342.     return certReqMsgs;
  343.  loser:
  344.     PORT_FreeArena(poolp, PR_FALSE);
  345.     return NULL;
  346. }