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

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. /*
  34.  * The following program decodes the FORTEZZA Init File, and stores the result
  35.  * into the fortezza directory.
  36.  */
  37. #include "secasn1.h"
  38. #include "swforti.h"
  39. #include "blapi.h"
  40. #include "secoid.h"
  41. #include "secitem.h"
  42. #include "secder.h"
  43. /*
  44.  * templates for parsing the FORTEZZA Init File. These were taken from DER
  45.  * definitions on SWF Initialization File Format Version 1.0 pp1-3.
  46.  */
  47. /* Key info structure... There are up to two of these per slot entry  */
  48. static const SEC_ASN1Template fortKeyInfoTemplate[] = {
  49.     { SEC_ASN1_SEQUENCE,
  50.           0, NULL, sizeof(fortKeyInformation) },
  51.     { SEC_ASN1_INTEGER,
  52.           offsetof(fortKeyInformation,keyFlags) },
  53.     { SEC_ASN1_OCTET_STRING,
  54.           offsetof(fortKeyInformation,privateKeyWrappedWithKs) },
  55.     { SEC_ASN1_ANY ,
  56.           offsetof(fortKeyInformation, derPublicKey) },
  57.     { SEC_ASN1_OCTET_STRING, offsetof(fortKeyInformation,p) },
  58.     { SEC_ASN1_OCTET_STRING, offsetof(fortKeyInformation,g) },
  59.     { SEC_ASN1_OCTET_STRING, offsetof(fortKeyInformation,q) },
  60.     { 0 }
  61. }; 
  62. /* This is data that has been wrapped by Ks */
  63. static const SEC_ASN1Template fortProtDataTemplate[] = {
  64.     { SEC_ASN1_SEQUENCE,
  65.           0, NULL, sizeof(fortProtectedData) },
  66.     { SEC_ASN1_INTEGER,
  67.           offsetof(fortProtectedData,length) },
  68.     { SEC_ASN1_OCTET_STRING,
  69.           offsetof(fortProtectedData,dataIV) },
  70.     { SEC_ASN1_OCTET_STRING,
  71.           offsetof(fortProtectedData,dataEncryptedWithKs) },
  72.     { 0 }
  73. };
  74. /* DER to describe each Certificate Slot ... there are an arbitrary number */
  75. static const SEC_ASN1Template fortSlotEntryTemplate[] = {
  76.     { SEC_ASN1_SEQUENCE,
  77.           0, NULL, sizeof(fortSlotEntry) },
  78.     { SEC_ASN1_BOOLEAN,
  79.           offsetof(fortSlotEntry,trusted) },
  80.     { SEC_ASN1_INTEGER,
  81.           offsetof(fortSlotEntry,certificateIndex) },
  82.     { SEC_ASN1_INLINE,
  83.           offsetof(fortSlotEntry,certificateLabel), fortProtDataTemplate },
  84.     { SEC_ASN1_INLINE,
  85.           offsetof(fortSlotEntry,certificateData), fortProtDataTemplate },
  86.     { SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC |  
  87. SEC_ASN1_CONSTRUCTED | 0,
  88.           offsetof(fortSlotEntry, exchangeKeyInformation),
  89.  fortKeyInfoTemplate },
  90.     { SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 
  91. SEC_ASN1_CONSTRUCTED | 1,
  92.           offsetof(fortSlotEntry, signatureKeyInformation), 
  93.  fortKeyInfoTemplate },
  94.     { 0 }
  95. };
  96. /* This data is used to check MemPhrases, and to generate Ks
  97.  * each file has two mem phrases, one for SSO, one for User */
  98. static const SEC_ASN1Template fortProtectedMemPhrase[]  = {
  99.     { SEC_ASN1_SEQUENCE,
  100.           0, NULL, sizeof(fortProtectedPhrase) },
  101.     { SEC_ASN1_OCTET_STRING,
  102.           offsetof(fortProtectedPhrase,kValueIV) },
  103.     { SEC_ASN1_OCTET_STRING,
  104.           offsetof(fortProtectedPhrase,wrappedKValue) },
  105.     { SEC_ASN1_OCTET_STRING,
  106.           offsetof(fortProtectedPhrase,memPhraseIV) },
  107.     { SEC_ASN1_OCTET_STRING,
  108.           offsetof(fortProtectedPhrase,hashedEncryptedMemPhrase) },
  109.     { 0 }
  110. };
  111. /* This data is used to check the Mem Init Phrases, and to generate Kinit
  112.  * each file has one mem init phrase, which is used only in transport of
  113.  * this file */
  114. static const SEC_ASN1Template fortMemInitPhrase[]  = {
  115.     { SEC_ASN1_SEQUENCE,
  116.           0, NULL, sizeof(fortProtectedPhrase) },
  117.     { SEC_ASN1_OCTET_STRING,
  118.           offsetof(fortProtectedPhrase,wrappedKValue) },
  119.     { SEC_ASN1_OCTET_STRING,
  120.           offsetof(fortProtectedPhrase,memPhraseIV) },
  121.     { SEC_ASN1_OCTET_STRING,
  122.           offsetof(fortProtectedPhrase,hashedEncryptedMemPhrase) },
  123.     { 0 }
  124. };
  125. static const SEC_ASN1Template fortSlotEntriesTemplate[]  = {
  126.     { SEC_ASN1_SEQUENCE_OF, 0, fortSlotEntryTemplate }
  127. };
  128. /* This is the complete file with all it's data, but has not been signed
  129.  * yet. */
  130. static const SEC_ASN1Template fortSwFortezzaInitFileToSign[]  = {
  131.     { SEC_ASN1_SEQUENCE,
  132.           0, NULL, sizeof(FORTSWFile) },
  133.     { SEC_ASN1_INTEGER,
  134.           offsetof(FORTSWFile,version) },
  135.     { SEC_ASN1_ANY,
  136.           offsetof(FORTSWFile,derIssuer) },
  137.     { SEC_ASN1_OCTET_STRING,
  138.           offsetof(FORTSWFile,serialID) },
  139.     { SEC_ASN1_INLINE,
  140.           offsetof(FORTSWFile,initMemPhrase), fortMemInitPhrase },
  141.     { SEC_ASN1_INLINE,
  142.           offsetof(FORTSWFile,ssoMemPhrase), fortProtectedMemPhrase },
  143.     { SEC_ASN1_INLINE,
  144.           offsetof(FORTSWFile,userMemPhrase), fortProtectedMemPhrase },
  145.     { SEC_ASN1_INLINE,
  146.           offsetof(FORTSWFile,ssoPinPhrase), fortProtectedMemPhrase },
  147.     { SEC_ASN1_INLINE,
  148.           offsetof(FORTSWFile,userPinPhrase), fortProtectedMemPhrase },
  149.     { SEC_ASN1_OCTET_STRING,
  150.           offsetof(FORTSWFile,wrappedRandomSeed) },
  151.     { SEC_ASN1_SEQUENCE_OF, offsetof(FORTSWFile,slotEntries),
  152.  fortSlotEntryTemplate },
  153.     /* optional extentions to ignore here... */
  154.     { 0 }
  155. };
  156. /* The complete, signed init file */
  157. static const SEC_ASN1Template fortSwFortezzaInitFile[]  = {
  158.     { SEC_ASN1_SEQUENCE,
  159.           0, NULL, sizeof(FORTSignedSWFile) },
  160.     { SEC_ASN1_SAVE,
  161.           offsetof(FORTSignedSWFile,signatureWrap.data) },
  162.     { SEC_ASN1_INLINE,
  163.           offsetof(FORTSignedSWFile,file),
  164.           fortSwFortezzaInitFileToSign },
  165.     { SEC_ASN1_INLINE,
  166.           offsetof(FORTSignedSWFile,signatureWrap.signatureAlgorithm),
  167.           SECOID_AlgorithmIDTemplate },
  168.     { SEC_ASN1_BIT_STRING,
  169.           offsetof(FORTSignedSWFile,signatureWrap.signature) },
  170.     { 0 }
  171. };
  172. FORTSkipjackKeyPtr
  173. fort_CalculateKMemPhrase(FORTSWFile *file, 
  174.   fortProtectedPhrase * prot_phrase, char *phrase, FORTSkipjackKeyPtr wrapKey)
  175. {
  176.     unsigned char *data = NULL;
  177.     unsigned char hashout[SHA1_LENGTH];
  178.     int data_len = prot_phrase->wrappedKValue.len;
  179.     int ret;
  180.     unsigned int len;
  181.     unsigned int version;
  182.     unsigned char enc_version[2];
  183.     FORTSkipjackKeyPtr Kout = NULL;
  184.     FORTSkipjackKey Kfek;
  185.     SHA1Context *sha;
  186.     data = (unsigned char *) PORT_ZAlloc(data_len);
  187.     if (data == NULL) goto fail;
  188.     
  189.     PORT_Memcpy(data,prot_phrase->wrappedKValue.data,data_len);
  190.     /* if it's a real protected mem phrase, it's been wrapped by kinit, which
  191.      * was passed to us. */
  192.     if (wrapKey) {
  193. fort_skipjackDecrypt(wrapKey,
  194. &prot_phrase->kValueIV.data[SKIPJACK_LEAF_SIZE],data_len,
  195. data,data);
  196. data_len = sizeof(CI_KEY);
  197.     }
  198.     /* now calculate the PBE key for fortezza */
  199.     sha = SHA1_NewContext();
  200.     if (sha == NULL) goto fail;
  201.     SHA1_Begin(sha);
  202.     version = DER_GetUInteger(&file->version);
  203.     enc_version[0] = (version >> 8) & 0xff;
  204.     enc_version[1] = version & 0xff;
  205.     SHA1_Update(sha,enc_version,sizeof(enc_version));
  206.     SHA1_Update(sha,file->derIssuer.data, file->derIssuer.len);
  207.     SHA1_Update(sha,file->serialID.data, file->serialID.len);
  208.     SHA1_Update(sha,(unsigned char *)phrase,strlen(phrase));
  209.     SHA1_End(sha,hashout,&len,SHA1_LENGTH);
  210.     SHA1_DestroyContext(sha, PR_TRUE);
  211.     PORT_Memcpy(Kfek,hashout,sizeof(FORTSkipjackKey));
  212.     /* now use that key to unwrap */
  213.     Kout = (FORTSkipjackKeyPtr) PORT_Alloc(sizeof(FORTSkipjackKey));
  214.     ret = fort_skipjackUnwrap(Kfek,data_len,data,Kout);
  215.     if (ret != CI_OK) {
  216. PORT_Free(Kout);
  217. Kout = NULL;
  218.     }
  219. fail:
  220.     PORT_Memset(&Kfek, 0, sizeof(FORTSkipjackKey));
  221.     if (data) PORT_ZFree(data,data_len);
  222.     return Kout;
  223. }
  224. PRBool
  225. fort_CheckMemPhrase(FORTSWFile *file, 
  226.   fortProtectedPhrase * prot_phrase, char *phrase, FORTSkipjackKeyPtr wrapKey) 
  227. {
  228.     unsigned char *data = NULL;
  229.     unsigned char hashout[SHA1_LENGTH];
  230.     int data_len = prot_phrase->hashedEncryptedMemPhrase.len;
  231.     unsigned int len;
  232.     SHA1Context *sha;
  233.     PRBool pinOK = PR_FALSE;
  234.     unsigned char cw[4];
  235.     int i;
  236.     /* first, decrypt the hashed/Encrypted Memphrase */
  237.     data = (unsigned char *) PORT_ZAlloc(data_len);
  238.     if (data == NULL) goto failed;
  239.     PORT_Memcpy(data,prot_phrase->hashedEncryptedMemPhrase.data,data_len);
  240.     fort_skipjackDecrypt(wrapKey,
  241. &prot_phrase->memPhraseIV.data[SKIPJACK_LEAF_SIZE],data_len,
  242. data,data);
  243.     /* now build the hash for comparisons */
  244.     sha = SHA1_NewContext();
  245.     if (sha == NULL) goto failed;
  246.     SHA1_Begin(sha);
  247.     SHA1_Update(sha,(unsigned char *)phrase,strlen(phrase));
  248.     SHA1_End(sha,hashout,&len,SHA1_LENGTH);
  249.     SHA1_DestroyContext(sha, PR_TRUE);
  250.     /* hashes don't match... must not be the right pass mem */
  251.     if (PORT_Memcmp(data,hashout,len) != 0) goto failed;
  252.     /* now calcuate the checkword and compare it */
  253.     cw[0] = cw[1] = cw[2] = cw[3] = 0;
  254.     for (i=0; i <5 ; i++) {
  255. cw[0] = cw[0] ^ hashout[i*4];
  256. cw[1] = cw[1] ^ hashout[i*4+1];
  257. cw[2] = cw[2] ^ hashout[i*4+2];
  258. cw[3] = cw[3] ^ hashout[i*4+3];
  259.     }
  260.     /* checkword doesn't match, must not be the right pass mem */
  261.     if (PORT_Memcmp(data+len,cw,4) != 0) goto failed;
  262.     /* pased all our test, its OK */
  263.     pinOK = PR_TRUE;
  264. failed:
  265.     PORT_Free(data);
  266.     return pinOK;
  267. }
  268. /*
  269.  * walk through the list of memphrases. This function allows us to use a
  270.  * for loop to walk down them.
  271.  */
  272. fortProtectedPhrase *
  273. fort_getNextPhrase( FORTSWFile *file, fortProtectedPhrase *last)
  274. {
  275.     if (last == &file->userMemPhrase) {
  276. return &file->userPinPhrase;
  277.     }
  278.     /* we can add more test here if we want to support SSO mode someday. */
  279.     return NULL;
  280. }
  281. /*
  282.  * decode the DER file data into our nice data structures, including turning
  283.  * cert indexes into integers.
  284.  */
  285. FORTSignedSWFile *
  286. FORT_GetSWFile(SECItem *initBits)
  287. {
  288.     FORTSignedSWFile *sw_init_file;
  289.     PRArenaPool *arena = NULL;
  290.     SECStatus rv;
  291.     int i, count;
  292.     /* get the local arena... be sure to free this at the end */
  293.     /* get the local arena... be sure to free this at the end */
  294.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  295.     if (arena == NULL) goto fail;
  296.     sw_init_file = (FORTSignedSWFile *)
  297. PORT_ArenaZAlloc(arena,sizeof(FORTSignedSWFile));
  298.     if (sw_init_file == NULL) goto fail;
  299.     /* ANS1 decode the complete init file */
  300.     rv = SEC_ASN1DecodeItem(arena,sw_init_file,fortSwFortezzaInitFile,initBits);
  301.     if (rv != SECSuccess) {
  302. goto fail;
  303.     }
  304.     /* count the certs */
  305.     count = 0;
  306.     while (sw_init_file->file.slotEntries[count]) count++;
  307.     for (i=0; i < count; i++) {
  308. /* update the cert Index Pointers */
  309. sw_init_file->file.slotEntries[i]->certIndex =
  310. DER_GetInteger(&sw_init_file->
  311. file.slotEntries[i]->certificateIndex );
  312.     }
  313.     /* now start checking the mem phrases and pins, as well as calculating the
  314.      * file's 'K' values. First we start with K(init). */
  315.     sw_init_file->file.arena = arena; 
  316.     return sw_init_file;
  317.     /* OK now that we've read in the init file, and now have Kinit, Ks, and the
  318.      * appropriate Pin Phrase, we need to build our database file. */
  319.    
  320. fail: 
  321.     if (arena) PORT_FreeArena(arena,PR_TRUE);
  322.     return NULL;
  323. }
  324. /*
  325.  * Check the init memphrases and the user mem phrases. Remove all the init
  326.  * memphrase wrappings. Save the Kinit and Ks values for use.
  327.  */
  328. SECStatus
  329. FORT_CheckInitPhrase(FORTSignedSWFile *sw_init_file, char *initMemPhrase)
  330. {
  331.     SECStatus rv = SECFailure;
  332.     sw_init_file->Kinit = fort_CalculateKMemPhrase(&sw_init_file->file,
  333.  &sw_init_file->file.initMemPhrase, initMemPhrase, NULL);
  334.     if (sw_init_file->Kinit == NULL)  goto fail;
  335.     /* now check the init Mem phrase */
  336.     if (!fort_CheckMemPhrase(&sw_init_file->file,
  337. &sw_init_file->file.initMemPhrase, 
  338. initMemPhrase, sw_init_file->Kinit)) {
  339. goto fail;
  340.     }
  341.     rv = SECSuccess;
  342. fail:
  343.     return rv;
  344. }
  345.     /* now check user user mem phrase and calculate Ks */
  346. SECStatus
  347. FORT_CheckUserPhrase(FORTSignedSWFile *sw_init_file, char *userMemPhrase)
  348. {
  349.     SECStatus rv = SECFailure;
  350.     char tmp_data[13];
  351.     char *padMemPhrase = NULL;
  352.     fortProtectedPhrase *phrase_store;
  353.     if (strlen(userMemPhrase) < 12) {
  354. PORT_Memset(tmp_data, ' ', sizeof(tmp_data));
  355. PORT_Memcpy(tmp_data,userMemPhrase,strlen(userMemPhrase));
  356. tmp_data[12] = 0;
  357. padMemPhrase = tmp_data;
  358.     }
  359.     for (phrase_store = &sw_init_file->file.userMemPhrase; phrase_store;
  360.      phrase_store = fort_getNextPhrase(&sw_init_file->file,phrase_store)) {
  361. sw_init_file->Ks = fort_CalculateKMemPhrase(&sw_init_file->file,
  362.  phrase_store, userMemPhrase, sw_init_file->Kinit);
  363.  
  364. if ((sw_init_file->Ks == NULL) && (padMemPhrase != NULL)) {
  365. sw_init_file->Ks = fort_CalculateKMemPhrase(&sw_init_file->file,
  366.      phrase_store, padMemPhrase, sw_init_file->Kinit);
  367. userMemPhrase = padMemPhrase;
  368. }
  369. if (sw_init_file->Ks == NULL) {
  370.     continue;
  371. }
  372. /* now check the User Mem phrase */
  373. if (fort_CheckMemPhrase(&sw_init_file->file, phrase_store, 
  374. userMemPhrase, sw_init_file->Ks)) {
  375.     break;
  376. }
  377. PORT_Free(sw_init_file->Ks);
  378. sw_init_file->Ks = NULL;
  379.     }
  380.     if (phrase_store == NULL) goto fail;
  381.     /* strip the Kinit wrapping */
  382.     fort_skipjackDecrypt(sw_init_file->Kinit,
  383. &phrase_store->kValueIV.data[SKIPJACK_LEAF_SIZE],
  384. phrase_store->wrappedKValue.len, phrase_store->wrappedKValue.data,
  385. phrase_store->wrappedKValue.data);
  386.     phrase_store->wrappedKValue.len = 12;
  387.     PORT_Memset(phrase_store->kValueIV.data,0,phrase_store->kValueIV.len);
  388.     sw_init_file->file.initMemPhrase = *phrase_store;
  389.     sw_init_file->file.ssoMemPhrase = *phrase_store;
  390.     sw_init_file->file.ssoPinPhrase = *phrase_store;
  391.     sw_init_file->file.userMemPhrase = *phrase_store;
  392.     sw_init_file->file.userPinPhrase = *phrase_store;
  393.     rv = SECSuccess;
  394.    
  395. fail: 
  396.     /* don't keep the pin around */
  397.     PORT_Memset(tmp_data, 0, sizeof(tmp_data));
  398.     return rv;
  399. }
  400. void
  401. FORT_DestroySWFile(FORTSWFile *file)
  402. {
  403.     PORT_FreeArena(file->arena,PR_FALSE);
  404. }
  405. void
  406. FORT_DestroySignedSWFile(FORTSignedSWFile *swfile)
  407. {
  408.     FORT_DestroySWFile(&swfile->file);
  409. }
  410. SECItem *
  411. FORT_GetDERCert(FORTSignedSWFile *swfile,int index)
  412. {
  413.     SECItem *newItem = NULL;
  414.     unsigned char *cert = NULL;
  415.     int len,ret;
  416.     fortSlotEntry *certEntry = NULL;
  417.    
  418.     newItem = PORT_ZNew(SECItem);
  419.     if (newItem == NULL) return NULL;
  420.     certEntry = fort_GetCertEntry(&swfile->file,index);
  421.     if (certEntry == NULL) {
  422. PORT_Free(newItem);
  423. return NULL;
  424.     }
  425.     newItem->len = len = certEntry->certificateData.dataEncryptedWithKs.len;
  426.     newItem->data = cert = PORT_ZAlloc(len);
  427.     if (cert == NULL) {
  428. PORT_Free(newItem);
  429. return NULL;
  430.     }
  431.     newItem->len = DER_GetUInteger(&certEntry->certificateData.length);
  432.     
  433.     PORT_Memcpy(cert, certEntry->certificateData.dataEncryptedWithKs.data,len);
  434.     /* Ks is always stored in keyReg[0] when we log in */
  435.     ret = fort_skipjackDecrypt(swfile->Ks,
  436. &certEntry->certificateData.dataIV.data[SKIPJACK_LEAF_SIZE],
  437. len,cert,cert);
  438.     if (ret != CI_OK) {
  439. SECITEM_FreeItem(newItem,PR_TRUE);
  440. return NULL;
  441.     }
  442.     return newItem;
  443. }
  444. /*
  445.  * decode the DER file data into our nice data structures, including turning
  446.  * cert indexes into integers.
  447.  */
  448. SECItem *
  449. FORT_PutSWFile(FORTSignedSWFile *sw_init_file)
  450. {
  451.     SECItem *outBits, *tmpBits;
  452.     PRArenaPool *arena = NULL;
  453.     /* get the local arena... be sure to free this at the end */
  454.     /* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); */
  455.     /* if (arena == NULL) goto fail; */
  456.     /*outBits = (SECItem *) PORT_ArenaZAlloc(arena,sizeof(SECItem)); */
  457.     outBits = PORT_ZNew(SECItem);
  458.     if (outBits == NULL) goto fail;
  459.     /* ANS1 encode the complete init file */
  460.     tmpBits = SEC_ASN1EncodeItem(NULL,outBits,sw_init_file,fortSwFortezzaInitFile);
  461.     if (tmpBits == NULL) {
  462. goto fail;
  463.     }
  464.     return outBits;
  465.    
  466. fail: 
  467.     if (outBits) SECITEM_FreeItem(outBits,PR_TRUE);
  468.     return NULL;
  469. }