cmmfchal.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 "cmmf.h"
  35. #include "cmmfi.h"
  36. #include "sechash.h"
  37. #include "genname.h"
  38. #include "pk11func.h"
  39. #include "cert.h"
  40. #include "secitem.h"
  41. #include "secmod.h"
  42. #include "secmodi.h"
  43. #include "keyhi.h"
  44. static SECStatus
  45. cmmf_create_witness_and_challenge(PRArenaPool     *poolp,
  46.   CMMFChallenge   *challenge,
  47.   long             inRandom,
  48.   SECItem         *senderDER,
  49.   SECKEYPublicKey *inPubKey,
  50.   void            *passwdArg)
  51. {
  52.     SECItem       *encodedRandNum;
  53.     SECItem        encodedRandStr = {siBuffer, NULL, 0};
  54.     SECItem        encryptBlock   = {siBuffer, NULL, 0};
  55.     SECItem       *dummy;
  56.     unsigned char *randHash, *senderHash, *encChal=NULL;
  57.     unsigned       modulusLen = 0;
  58.     SECStatus      rv = SECFailure;
  59.     CMMFRand       randStr= { {siBuffer, NULL, 0}, {siBuffer, NULL, 0}};
  60.     PK11SlotInfo  *slot;
  61.     PK11SymKey    *symKey = NULL;
  62.     CK_OBJECT_HANDLE id;
  63.     CERTSubjectPublicKeyInfo *spki = NULL;
  64.     
  65.     encodedRandNum = SEC_ASN1EncodeInteger(poolp, &challenge->randomNumber,
  66.    inRandom);
  67.     encodedRandNum = &challenge->randomNumber;
  68.     randHash   = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH);
  69.     senderHash = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH);
  70.     if (randHash == NULL) {
  71.         goto loser;
  72.     }
  73.     rv = PK11_HashBuf(SEC_OID_SHA1, randHash, encodedRandNum->data, 
  74.       (uint32)encodedRandNum->len);
  75.     if (rv != SECSuccess) {
  76.         goto loser;
  77.     }
  78.     rv = PK11_HashBuf(SEC_OID_SHA1, senderHash, senderDER->data,
  79.       (uint32)senderDER->len);
  80.     if (rv != SECSuccess) {
  81.         goto loser;
  82.     }
  83.     challenge->witness.data = randHash;
  84.     challenge->witness.len  = SHA1_LENGTH;
  85.     randStr.integer    = *encodedRandNum;
  86.     randStr.senderHash.data = senderHash;
  87.     randStr.senderHash.len  = SHA1_LENGTH;
  88.     dummy = SEC_ASN1EncodeItem(NULL, &encodedRandStr, &randStr, 
  89.        CMMFRandTemplate);
  90.     if (dummy != &encodedRandStr) {
  91.         rv = SECFailure;
  92.         goto loser;
  93.     }
  94.     /* XXXX Now I have to encrypt encodedRandStr and stash it away. */
  95.     modulusLen = SECKEY_PublicKeyStrength(inPubKey);
  96.     encChal = PORT_ArenaNewArray(poolp, unsigned char, modulusLen);
  97.     if (encChal == NULL) {
  98.         rv = SECFailure;
  99.         goto loser;
  100.     }
  101.     slot =PK11_GetBestSlot(CKM_RSA_PKCS, passwdArg);
  102.     if (slot == NULL) {
  103.         rv = SECFailure;
  104.         goto loser;
  105.     }
  106.     id = PK11_ImportPublicKey(slot, inPubKey, PR_FALSE);
  107.     /* In order to properly encrypt the data, we import as a symmetric
  108.      * key, and then wrap that key.  That in essence encrypts the data.
  109.      * This is the method recommended in the PK11 world in order
  110.      * to prevent threading issues as well as breaking any other semantics
  111.      * the PK11 libraries depend on.
  112.      */
  113.     symKey = PK11_ImportSymKey(slot, CKM_RSA_PKCS, PK11_OriginGenerated,
  114.        CKA_VALUE, &encodedRandStr, passwdArg);
  115.     if (symKey == NULL) {
  116.         rv = SECFailure;
  117. goto loser;
  118.     }
  119.     challenge->challenge.data = encChal;
  120.     challenge->challenge.len  = modulusLen;
  121.     rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, inPubKey, symKey, 
  122.     &challenge->challenge);
  123.     PK11_FreeSlot(slot);
  124.     if (rv != SECSuccess) {
  125. goto loser;
  126.     }
  127.     rv = SECITEM_CopyItem(poolp, &challenge->senderDER, senderDER);
  128.     crmf_get_public_value(inPubKey, &challenge->key);
  129.     /* Fall through */
  130.  loser:
  131.     if (spki != NULL) {
  132.         SECKEY_DestroySubjectPublicKeyInfo(spki);
  133.     }
  134.     if (encodedRandStr.data != NULL) {
  135.         PORT_Free(encodedRandStr.data);
  136.     }
  137.     if (encodedRandNum != NULL) {
  138.         SECITEM_FreeItem(encodedRandNum, PR_TRUE);
  139.     }
  140.     if (symKey != NULL) {
  141.         PK11_FreeSymKey(symKey);
  142.     }
  143.     return rv;
  144. }
  145. static SECStatus
  146. cmmf_create_first_challenge(CMMFPOPODecKeyChallContent *challContent, 
  147.     long                        inRandom, 
  148.     SECItem                    *senderDER, 
  149.     SECKEYPublicKey            *inPubKey,
  150.     void                       *passwdArg)
  151. {
  152.     SECOidData     *oidData;
  153.     CMMFChallenge  *challenge;
  154.     SECAlgorithmID *algId;
  155.     PRArenaPool    *poolp;
  156.     SECStatus       rv;
  157.     oidData = SECOID_FindOIDByTag(SEC_OID_SHA1);
  158.     if (oidData == NULL) {
  159.         return SECFailure;
  160.     }
  161.     poolp = challContent->poolp;
  162.     challenge = PORT_ArenaZNew(poolp, CMMFChallenge);
  163.     if (challenge == NULL) {
  164.         return SECFailure;
  165.     }
  166.     algId = challenge->owf = PORT_ArenaZNew(poolp, SECAlgorithmID);
  167.     if (algId == NULL) {
  168.         return SECFailure;
  169.     }
  170.     rv = SECITEM_CopyItem(poolp, &algId->algorithm, &oidData->oid);
  171.     if (rv != SECSuccess) {
  172.         return SECFailure;
  173.     }
  174.     rv = cmmf_create_witness_and_challenge(poolp, challenge, inRandom, 
  175.    senderDER, inPubKey, passwdArg);
  176.     challContent->challenges[0] = (rv == SECSuccess) ? challenge : NULL;
  177.     challContent->numChallenges++;
  178.     return rv ;
  179. }
  180. CMMFPOPODecKeyChallContent*
  181. CMMF_CreatePOPODecKeyChallContent (void)
  182. {
  183.     PRArenaPool *poolp;
  184.     CMMFPOPODecKeyChallContent *challContent;
  185.     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
  186.     if (poolp == NULL) {
  187.         return NULL;
  188.     }
  189.     challContent = PORT_ArenaZNew(poolp, CMMFPOPODecKeyChallContent);
  190.     if (challContent == NULL) {
  191.         PORT_FreeArena(poolp, PR_FALSE);
  192. return NULL;
  193.     }
  194.     challContent->poolp = poolp;
  195.     return challContent;
  196. }
  197. SECStatus
  198. CMMF_POPODecKeyChallContentSetNextChallenge
  199.                                     (CMMFPOPODecKeyChallContent *inDecKeyChall,
  200.      long                        inRandom,
  201.      CERTGeneralName            *inSender,
  202.      SECKEYPublicKey            *inPubKey,
  203.      void                       *passwdArg)
  204. {
  205.     CMMFChallenge               *curChallenge;
  206.     PRArenaPool                 *genNamePool = NULL, *poolp;
  207.     SECStatus                    rv;
  208.     SECItem                     *genNameDER;
  209.     void                        *mark;
  210.     SECItem                      senderDER = {siBuffer, NULL, 0};
  211.     PORT_Assert (inDecKeyChall != NULL &&
  212.  inSender      != NULL &&
  213.  inPubKey      != NULL);
  214.     if (inDecKeyChall == NULL || 
  215. inSender      == NULL || inPubKey == NULL) {
  216.         return SECFailure;
  217.     }
  218.     poolp = inDecKeyChall->poolp;
  219.     mark = PORT_ArenaMark(poolp);
  220.     genNamePool = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
  221.     genNameDER = cert_EncodeGeneralName(inSender, NULL, genNamePool);
  222.     if (genNameDER == NULL) {
  223.         rv = SECFailure;
  224.         goto loser;
  225.     }
  226.     if (inDecKeyChall->challenges == NULL) {
  227.         inDecKeyChall->challenges =
  228.     PORT_ArenaZNewArray(poolp, CMMFChallenge*,(CMMF_MAX_CHALLENGES+1));
  229. inDecKeyChall->numAllocated = CMMF_MAX_CHALLENGES;
  230.     }
  231.     if (inDecKeyChall->numChallenges >= inDecKeyChall->numAllocated) {
  232.         rv = SECFailure;
  233.         goto loser;
  234.     }
  235.     if (inDecKeyChall->numChallenges == 0) {
  236.         rv = cmmf_create_first_challenge(inDecKeyChall, inRandom, 
  237.  genNameDER, inPubKey, passwdArg);
  238.     } else {
  239.         curChallenge = PORT_ArenaZNew(poolp, CMMFChallenge);
  240. if (curChallenge == NULL) {
  241.     rv = SECFailure;
  242.     goto loser;
  243. }
  244. rv = cmmf_create_witness_and_challenge(poolp, curChallenge, inRandom, 
  245.        genNameDER, inPubKey, 
  246.        passwdArg);
  247. if (rv == SECSuccess) {
  248.     inDecKeyChall->challenges[inDecKeyChall->numChallenges] =
  249.         curChallenge;
  250.     inDecKeyChall->numChallenges++;
  251. }
  252.     }
  253.     if (rv != SECSuccess) {
  254.         goto loser;
  255.     }
  256.     PORT_ArenaUnmark(poolp, mark);
  257.     PORT_FreeArena(genNamePool, PR_FALSE);
  258.     return SECSuccess;
  259.  loser:
  260.     PORT_ArenaRelease(poolp, mark);
  261.     if (genNamePool != NULL) {
  262.         PORT_FreeArena(genNamePool, PR_FALSE);
  263.     }
  264.     PORT_Assert(rv != SECSuccess);
  265.     return rv;
  266. }
  267. SECStatus
  268. CMMF_DestroyPOPODecKeyRespContent(CMMFPOPODecKeyRespContent *inDecKeyResp)
  269. {
  270.     PORT_Assert(inDecKeyResp != NULL);
  271.     if (inDecKeyResp != NULL && inDecKeyResp->poolp != NULL) {
  272.         PORT_FreeArena(inDecKeyResp->poolp, PR_FALSE);
  273.     }
  274.     return SECSuccess;
  275. }
  276. int 
  277. CMMF_POPODecKeyRespContentGetNumResponses(CMMFPOPODecKeyRespContent *inRespCont)
  278. {
  279.     int numResponses = 0;
  280.     PORT_Assert(inRespCont != NULL);
  281.     if (inRespCont == NULL) {
  282.         return 0;
  283.     }
  284.     while (inRespCont->responses[numResponses] != NULL) {
  285.         numResponses ++;
  286.     }
  287.     return numResponses;
  288. }
  289. SECStatus
  290. CMMF_POPODecKeyRespContentGetResponse (CMMFPOPODecKeyRespContent *inRespCont,
  291.        int                        inIndex,
  292.        long                      *inDest)
  293. {
  294.     PORT_Assert(inRespCont != NULL);
  295.     
  296.     if (inRespCont == NULL || inIndex < 0 || 
  297. inIndex >= CMMF_POPODecKeyRespContentGetNumResponses(inRespCont)) {
  298.         return SECFailure;
  299.     }
  300.     *inDest = DER_GetInteger(inRespCont->responses[inIndex]);
  301.     return (*inDest == -1) ? SECFailure : SECSuccess;
  302. }