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

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 "secitem.h"
  37. #include "pk11func.h"
  38. CMMFPOPODecKeyChallContent*
  39. CMMF_CreatePOPODecKeyChallContentFromDER(const char *buf, long len)
  40. {
  41.     PRArenaPool                *poolp;
  42.     CMMFPOPODecKeyChallContent *challContent;
  43.     SECStatus                   rv;
  44.     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
  45.     if (poolp == NULL) {
  46.         return NULL;
  47.     }
  48.     challContent = PORT_ArenaZNew(poolp, CMMFPOPODecKeyChallContent);
  49.     if (challContent == NULL) {
  50.         goto loser;
  51.     }
  52.     challContent->poolp = poolp;
  53.     rv = SEC_ASN1Decode(poolp, challContent, 
  54. CMMFPOPODecKeyChallContentTemplate, buf, len);
  55.     if (rv != SECSuccess) {
  56.         goto loser;
  57.     }
  58.     if (challContent->challenges) {
  59.       while (challContent->challenges[challContent->numChallenges] != NULL) {
  60.   challContent->numChallenges++;
  61.       }
  62.       challContent->numAllocated = challContent->numChallenges;
  63.     }
  64.     return challContent;
  65.  loser:
  66.     if (poolp != NULL) {
  67.         PORT_FreeArena(poolp, PR_FALSE);
  68.     }
  69.     return NULL;
  70. }
  71. int
  72. CMMF_POPODecKeyChallContentGetNumChallenges 
  73.                               (CMMFPOPODecKeyChallContent *inKeyChallCont)
  74. {
  75.     PORT_Assert(inKeyChallCont != NULL);
  76.     if (inKeyChallCont == NULL) {
  77.         return 0;
  78.     }
  79.     return inKeyChallCont->numChallenges;
  80. }
  81. SECItem* 
  82. CMMF_POPODecKeyChallContentGetPublicValue
  83.                                    (CMMFPOPODecKeyChallContent *inKeyChallCont,
  84.     int                         inIndex)
  85. {
  86.     PORT_Assert(inKeyChallCont != NULL);
  87.     if (inKeyChallCont == NULL || (inIndex > inKeyChallCont->numChallenges-1)||
  88. inIndex < 0) {
  89.         return NULL;
  90.     }
  91.     return SECITEM_DupItem(&inKeyChallCont->challenges[inIndex]->key);
  92. }
  93. static SECAlgorithmID*
  94. cmmf_get_owf(CMMFPOPODecKeyChallContent *inChalCont, 
  95.      int                         inIndex)
  96. {
  97.    int i;
  98.    
  99.    for (i=inIndex; i >= 0; i--) {
  100.        if (inChalCont->challenges[i]->owf != NULL) {
  101.    return inChalCont->challenges[i]->owf;
  102.        }
  103.    }
  104.    return NULL;
  105. }
  106. SECStatus 
  107. CMMF_POPODecKeyChallContDecryptChallenge(CMMFPOPODecKeyChallContent *inChalCont,
  108.  int                         inIndex,
  109.  SECKEYPrivateKey           *inPrivKey)
  110. {
  111.     CMMFChallenge  *challenge;
  112.     SECItem        *decryptedRand=NULL;
  113.     SECStatus       rv = SECFailure;
  114.     PK11SlotInfo   *slot;
  115.     PK11SymKey     *symKey = NULL;
  116.     CMMFRand        randStr;
  117.     SECAlgorithmID *owf;
  118.     unsigned char   hash[SHA1_LENGTH]; /*SHA1 is the longest, so we'll use
  119. *it's length.
  120. */
  121.     SECItem         hashItem;
  122.     SECOidTag       tag;
  123.     PORT_Assert(inChalCont != NULL && inPrivKey != NULL);
  124.     if (inChalCont == NULL || inIndex <0 || inIndex > inChalCont->numChallenges
  125. || inPrivKey == NULL){
  126.         return SECFailure;
  127.     }
  128.     challenge = inChalCont->challenges[inIndex];
  129.     decryptedRand = PORT_ZNew(SECItem);
  130.     if (decryptedRand == NULL) {
  131.         goto loser;
  132.     }
  133.     decryptedRand->data = 
  134.         PORT_NewArray(unsigned char, challenge->challenge.len);
  135.     if (decryptedRand->data == NULL) {
  136.         goto loser;
  137.     }
  138.     slot = inPrivKey->pkcs11Slot;
  139.     symKey = PK11_PubUnwrapSymKey(inPrivKey, &challenge->challenge, 
  140.   CKM_RSA_PKCS, CKA_VALUE, 0);
  141.     if (symKey == NULL) {
  142.       rv = SECFailure;
  143.       goto loser;
  144.     }
  145.     rv = PK11_ExtractKeyValue(symKey);
  146.     if (rv != SECSuccess) {
  147.       goto loser;
  148.     }
  149.     decryptedRand = PK11_GetKeyData(symKey);
  150.     rv = SEC_ASN1DecodeItem(NULL, &randStr, CMMFRandTemplate,
  151.     decryptedRand); 
  152.     /* The decryptedRand returned points to a member within the symKey structure,
  153.      * so we don't want to free it. Let the symKey destruction function deal with
  154.      * freeing that memory.
  155.      */
  156.     if (rv != SECSuccess) {
  157.         goto loser;
  158.     }
  159.     rv = SECFailure; /* Just so that when we do go to loser,
  160.       * I won't have to set it again.
  161.       */
  162.     owf = cmmf_get_owf(inChalCont, inIndex);
  163.     if (owf == NULL) {
  164.         /* No hashing algorithm came with the challenges.  Can't verify */
  165.         goto loser;
  166.     }
  167.     /* Verify the hashes in the challenge */
  168.     tag = SECOID_FindOIDTag(&owf->algorithm);
  169.     switch (tag) {
  170.     case SEC_OID_MD2:
  171.         hashItem.len = MD2_LENGTH;
  172. break;
  173.     case SEC_OID_MD5:
  174.         hashItem.len = MD5_LENGTH;
  175. break;
  176.     case SEC_OID_SHA1:
  177.         hashItem.len = SHA1_LENGTH;
  178. break;
  179.     default:
  180.         goto loser;
  181.     }
  182.     rv = PK11_HashBuf(tag, hash, randStr.integer.data, randStr.integer.len);
  183.     if (rv != SECSuccess) {
  184.         goto loser;
  185.     }
  186.     hashItem.data = hash;
  187.     if (SECITEM_CompareItem(&hashItem, &challenge->witness) != SECEqual) {
  188.         /* The hash for the data we decrypted doesn't match the hash provided
  189.  * in the challenge.  Bail out.
  190.  */
  191.         rv = SECFailure;
  192. goto loser;
  193.     }
  194.     rv = PK11_HashBuf(tag, hash, challenge->senderDER.data, 
  195.       challenge->senderDER.len);
  196.     if (rv != SECSuccess) {
  197.         goto loser;
  198.     }
  199.     if (SECITEM_CompareItem(&hashItem, &randStr.senderHash) != SECEqual) {
  200.         /* The hash for the data we decrypted doesn't match the hash provided
  201.  * in the challenge.  Bail out.
  202.  */
  203.         rv = SECFailure;
  204. goto loser;
  205.     }
  206.     /* All of the hashes have verified, so we can now store the integer away.*/
  207.     rv = SECITEM_CopyItem(inChalCont->poolp, &challenge->randomNumber,
  208.   &randStr.integer);
  209.  loser:
  210.     if (symKey != NULL) {
  211.         PK11_FreeSymKey(symKey);
  212.     }
  213.     return rv;
  214. }
  215. SECStatus
  216. CMMF_POPODecKeyChallContentGetRandomNumber
  217.                                    (CMMFPOPODecKeyChallContent *inKeyChallCont,
  218.     int                          inIndex,
  219.     long                        *inDest)
  220. {
  221.     CMMFChallenge *challenge;
  222.     
  223.     PORT_Assert(inKeyChallCont != NULL);
  224.     if (inKeyChallCont == NULL || inIndex > 0 || inIndex >= 
  225. inKeyChallCont->numChallenges) {
  226.         return SECFailure;
  227.     }
  228.     challenge = inKeyChallCont->challenges[inIndex];
  229.     if (challenge->randomNumber.data == NULL) {
  230.         /* There is no random number here, nothing to see. */
  231.         return SECFailure;
  232.     }
  233.     *inDest = DER_GetInteger(&challenge->randomNumber);
  234.     return (*inDest == -1) ? SECFailure : SECSuccess;
  235. }
  236. SECStatus 
  237. CMMF_EncodePOPODecKeyRespContent(long                     *inDecodedRand,
  238.  int                       inNumRand,
  239.  CRMFEncoderOutputCallback inCallback,
  240.  void                     *inArg)
  241. {
  242.     PRArenaPool *poolp;
  243.     CMMFPOPODecKeyRespContent *response;
  244.     SECItem *currItem;
  245.     SECStatus rv=SECFailure;
  246.     int i;
  247.     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
  248.     if (poolp == NULL) {
  249.         return SECFailure;
  250.     }
  251.     response = PORT_ArenaZNew(poolp, CMMFPOPODecKeyRespContent);
  252.     if (response == NULL) {
  253.         goto loser;
  254.     }
  255.     response->responses = PORT_ArenaZNewArray(poolp, SECItem*, inNumRand+1);
  256.     if (response->responses == NULL) {
  257.         goto loser;
  258.     }
  259.     for (i=0; i<inNumRand; i++) {
  260.         currItem = response->responses[i] = PORT_ArenaZNew(poolp,SECItem);
  261. if (currItem == NULL) {
  262.     goto loser;
  263. }
  264. SEC_ASN1EncodeInteger(poolp, currItem,inDecodedRand[i]);
  265.     }
  266.     rv = cmmf_user_encode(response, inCallback, inArg,
  267.   CMMFPOPODecKeyRespContentTemplate);
  268.  loser:
  269.     if (poolp != NULL) {
  270.         PORT_FreeArena(poolp, PR_FALSE);
  271.     }
  272.     return rv;
  273. }