swflib.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,029 行 · 第 1/2 页
C
1,029 行
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//* * implement the MACI calls as Software Fortezza Calls. * only do the ones Nescape Needs. This provides a single software slot, * with 100 key registers, and 50 backup Ra private registers. Since we only * create one session per slot, this implementation only uses one session. * One future enhancement may be to try to improve on this for better threading * support. */#include "prtypes.h"#include "prio.h"#include "swforti.h"#include "keytlow.h"/* #include "dh.h" */#include "blapi.h"#include "maci.h"/* #include "dsa.h" *//* #include "hasht.h" */#include "secitem.h"#include "secrng.h"#include "keylow.h"#include "secder.h"#ifdef XP_UNIX#include <unistd.h>#endif#ifndef O_BINARY#define O_BINARY 0#endif/* currently we only support one software token. In the future we can use the * session to determin which of many possible tokens we are talking about. * all the calls which need tokens take a pointer to the software token as a * target. */static FORTSWToken *swtoken = NULL;#define SOCKET_ID 1/* can't change the pin on SW fortezza for now */intMACI_ChangePIN(HSESSION session, int PINType, CI_PIN CI_FAR pOldPIN, CI_PIN CI_FAR pNewPin){ return CI_INV_STATE;}/* * Check pin checks the pin, then logs the user in or out depending on if * the pin succedes. The General implementation would support both SSO and * User mode our's only needs User mode. Pins are checked by whether or not * they can produce our valid Ks for this 'card'. */intMACI_CheckPIN(HSESSION session, int PINType, CI_PIN CI_FAR pin){ FORTSkipjackKeyPtr Ks; FORTSWFile *config_file = NULL; FORTSkipjackKey seed; unsigned char pinArea[13]; unsigned char *padPin = NULL; /* This SW module can only log in as USER */ if (PINType != CI_USER_PIN) return CI_INV_TYPE; if (swtoken == NULL) return CI_NO_CARD; /* we can't check a pin if we haven't been initialized yet */ if (swtoken->config_file == NULL) return CI_NO_CARD; config_file = swtoken->config_file; /* Make sure the pin value meets minimum lengths */ if (PORT_Strlen((char *)pin) < 12) { PORT_Memset(pinArea, ' ', sizeof(pinArea)); PORT_Memcpy(pinArea,pin,PORT_Strlen((char *)pin)); pinArea[12] = 0; padPin = pinArea; } /* get the Ks by unwrapping it from the memphrase with the pbe generated * from the pin */ Ks = fort_CalculateKMemPhrase(config_file, &config_file->fortezzaPhrase, (char *)pin, NULL); if (Ks == 0) { Ks = fort_CalculateKMemPhrase(config_file, &config_file->fortezzaPhrase, (char *)padPin, NULL); if (Ks == 0) { PORT_Memset(pinArea, 0, sizeof(pinArea)); fort_Logout(swtoken); return CI_FAIL; } } /* use Ks and hash to verify that pin is correct */ if (! fort_CheckMemPhrase(config_file, &config_file->fortezzaPhrase, (char *)pin, Ks) ) { if ((padPin == NULL) || ! fort_CheckMemPhrase(config_file, &config_file->fortezzaPhrase, (char *)padPin, Ks) ) { PORT_Memset(pinArea, 0, sizeof(pinArea)); fort_Logout(swtoken); return CI_FAIL; } } PORT_Memset(pinArea, 0, sizeof(pinArea)); /* OK, add the random Seed value into the random number generator */ fort_skipjackUnwrap(Ks,config_file->wrappedRandomSeed.len, config_file->wrappedRandomSeed.data,seed); RNG_RandomUpdate(seed,sizeof(seed)); /* it is, go ahead and log in */ swtoken->login = PR_TRUE; /* Ks is always stored in keyReg[0] when we log in */ PORT_Memcpy(swtoken->keyReg[0].data, Ks, sizeof (FORTSkipjackKey)); swtoken->keyReg[0].present = PR_TRUE; PORT_Memset(Ks, 0, sizeof(FORTSkipjackKey)); PORT_Free(Ks); return CI_OK;}/* * close an open socket. Power_Down flag is set when we want to reset the * cards complete state. */intMACI_Close(HSESSION session, unsigned int flags, int socket){ if (socket != SOCKET_ID) return CI_BAD_CARD; if (swtoken == NULL) return CI_BAD_CARD; if (flags == CI_POWER_DOWN_FLAG) { fort_Logout(swtoken); } return CI_OK;}/* * Decrypt keeps track of it's own IV. */intMACI_Decrypt(HSESSION session, unsigned int size, CI_DATA cipherIn, CI_DATA plainOut){ int ret; unsigned char IV[SKIPJACK_BLOCK_SIZE]; if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; if ((ret = fort_KeyOK(swtoken,swtoken->key,PR_TRUE)) != CI_OK) return ret; /*fort_AddNoise();*/ /* save the IV, before we potentially trash the new one when we decrypt. * (it's permissible to decrypt into the cipher text buffer by passing the * same buffers for both cipherIn and plainOut. */ PORT_Memcpy(IV,swtoken->IV, sizeof(IV)); fort_UpdateIV(cipherIn,size,swtoken->IV); return fort_skipjackDecrypt(swtoken->keyReg[swtoken->key].data, IV,size,cipherIn,plainOut);}/* * Clear a key from one of the key registers (indicated by index). * return an error if no key exists. */intMACI_DeleteKey(HSESSION session, int index){ int ret; if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; /* can't delete Ks */ if (index == 0) return CI_INV_KEY_INDEX; if ((ret = fort_KeyOK(swtoken,index,PR_TRUE)) != CI_OK) return ret; fort_ClearKey(&swtoken->keyReg[index]); return CI_OK;}/* * encrypt some blocks of data and update the IV. */ intMACI_Encrypt(HSESSION session, unsigned int size, CI_DATA plainIn, CI_DATA cipherOut){ int ret; if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; if ((ret = fort_KeyOK(swtoken,swtoken->key,PR_TRUE)) != CI_OK) return ret; /*fort_AddNoise();*/ ret = fort_skipjackEncrypt(swtoken->keyReg[swtoken->key].data, swtoken->IV,size,plainIn,cipherOut); fort_UpdateIV(cipherOut,size,swtoken->IV); return ret;}/* * create a new IV and encode it. */static char *leafbits="THIS IS NOT LEAF";intMACI_GenerateIV(HSESSION Session, CI_IV CI_FAR pIV){ int ret; if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; if ((ret = fort_KeyOK(swtoken,swtoken->key,PR_TRUE)) != CI_OK) return ret; ret = fort_GenerateRandom(swtoken->IV,SKIPJACK_BLOCK_SIZE); if (ret != CI_OK) return ret; PORT_Memcpy(pIV,leafbits,SKIPJACK_LEAF_SIZE); PORT_Memcpy(&pIV[SKIPJACK_LEAF_SIZE],swtoken->IV,SKIPJACK_BLOCK_SIZE); return CI_OK;}/* * create a new Key */intMACI_GenerateMEK(HSESSION session, int index, int reserved){ int ret; if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; if ((ret = fort_KeyOK(swtoken,index,PR_FALSE)) != CI_OK) return ret; ret = fort_GenerateRandom(swtoken->keyReg[index].data, sizeof (swtoken->keyReg[index].data)); if (ret == CI_OK) swtoken->keyReg[index].present = PR_TRUE; return ret;}/* * build a new Ra/ra pair for a KEA exchange. */intMACI_GenerateRa(HSESSION session, CI_RA CI_FAR pRa){ int ret; int counter; int RaLen,raLen; DSAPrivateKey *privKey = NULL; PQGParams params; SECStatus rv; int crv = CI_EXEC_FAIL; fortSlotEntry *certEntry = NULL; unsigned char *unsignedRa = NULL; unsigned char *unsignedra = NULL; fortKeyInformation *key_info = NULL; if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; /* make sure the personality is set */ if (swtoken->certIndex == 0) return CI_INV_STATE; /* pick next Ra circular buffer */ counter = swtoken->nextRa; swtoken->nextRa++; if (swtoken->nextRa >= MAX_RA_SLOTS) swtoken->nextRa = 0; /* now get the params for diffie -helman key gen */ certEntry = fort_GetCertEntry(swtoken->config_file,swtoken->certIndex); if (certEntry == NULL) return CI_INV_CERT_INDEX; if (certEntry->exchangeKeyInformation) { key_info = certEntry->exchangeKeyInformation; } else { key_info = certEntry->signatureKeyInformation; } if (key_info == NULL) return CI_NO_X; /* Generate Diffie Helman key Pair -- but we use DSA key gen to do it */ rv = SECITEM_CopyItem(NULL,¶ms.prime,&key_info->p); if (rv != SECSuccess) return CI_EXEC_FAIL; rv = SECITEM_CopyItem(NULL,¶ms.subPrime,&key_info->q); if (rv != SECSuccess) return CI_EXEC_FAIL; rv = SECITEM_CopyItem(NULL,¶ms.base,&key_info->g); if (rv != SECSuccess) return CI_EXEC_FAIL; /* KEA uses DSA like key generation with short DSA keys that have to * maintain a relationship to q */ rv = DSA_NewKey(¶ms, &privKey); SECITEM_FreeItem(¶ms.prime,PR_FALSE); SECITEM_FreeItem(¶ms.subPrime,PR_FALSE); SECITEM_FreeItem(¶ms.base,PR_FALSE); if (rv != SECSuccess) return CI_EXEC_FAIL; /* save private key, public key, and param in Ra Circular buffer */ unsignedRa = privKey->publicValue.data; RaLen = privKey->publicValue.len; while ((unsignedRa[0] == 0) && (RaLen > CI_RA_SIZE)) { unsignedRa++; RaLen--; } if (RaLen > CI_RA_SIZE) goto loser; unsignedra = privKey->privateValue.data; raLen = privKey->privateValue.len; while ((unsignedra[0] == 0) && (raLen > sizeof(fortRaPrivate))) { unsignedra++; raLen--; } if (raLen > sizeof(fortRaPrivate)) goto loser; PORT_Memset(swtoken->RaValues[counter].private, 0, sizeof(fortRaPrivate)); PORT_Memcpy( &swtoken->RaValues[counter].private[sizeof(fortRaPrivate) - raLen], unsignedra, raLen); PORT_Memset(pRa, 0, CI_RA_SIZE); PORT_Memcpy(&pRa[CI_RA_SIZE-RaLen], unsignedRa, RaLen); PORT_Memcpy(swtoken->RaValues[counter].public, pRa, CI_RA_SIZE); crv = CI_OK;loser: PORT_FreeArena(privKey->params.arena, PR_TRUE); return crv;}/* * return some random data. */intMACI_GenerateRandom(HSESSION session, CI_RANDOM CI_FAR random){ int ret; if ((ret = fort_CardExists(swtoken,PR_FALSE)) != CI_OK) return ret; return fort_GenerateRandom(random,sizeof (CI_RANDOM));}static CI_RA Remail = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};/* * build a new Token exchange key using KEA. */intMACI_GenerateTEK(HSESSION hSession, int flags, int target, CI_RA CI_FAR Ra, CI_RA CI_FAR Rb, unsigned int YSize, CI_Y CI_FAR pY ){ SECKEYLowPrivateKey *key = NULL; fortSlotEntry * certEntry; unsigned char * w = NULL; SECItem *q; SECStatus rv; int ret,i; PRBool email = PR_TRUE; SECItem R; /* public */ SECItem Y; /* public */ SECItem r; /* private */ SECItem x; /* private */ SECItem wItem; /* derived secret */ fortRaPrivatePtr ra; FORTSkipjackKey cover_key; unsigned char pad[10] = { 0x72, 0xf1, 0xa8, 0x7e, 0x92, 0x82, 0x41, 0x98, 0xab, 0x0b }; /* verify that everything is ok with the token, keys and certs */ if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret; /* make sure the personality is set */ if (swtoken->certIndex == 0) return CI_INV_STATE; if ((ret = fort_KeyOK(swtoken,target,PR_FALSE)) != CI_OK) return ret; /* get the cert from the entry, then look up the key from that cert */ certEntry = fort_GetCertEntry(swtoken->config_file,swtoken->certIndex); if (certEntry == NULL) return CI_INV_CERT_INDEX; key = fort_GetPrivKey(swtoken,dhKey,certEntry); if (key == NULL) return CI_NO_X; if (certEntry->exchangeKeyInformation) { q = &certEntry->exchangeKeyInformation->q; } else { q = &certEntry->signatureKeyInformation->q; } email = (PORT_Memcmp(Rb,Remail,sizeof(Rb)) == 0) ? PR_TRUE: PR_FALSE; /* load the common elements */ Y.data = pY; Y.len = YSize; x.data = key->u.dh.privateValue.data; x.len = key->u.dh.privateValue.len; /* now initialize the rest of the values */ if (flags == CI_INITIATOR_FLAG) { if (email) { R.data = Y.data; R.len = Y.len; } else { R.data = Rb; R.len = sizeof(CI_RA); } ra = fort_LookupPrivR(swtoken,Ra); if (ra == NULL) { ret = CI_EXEC_FAIL; goto loser; } r.data = ra; r.len = sizeof(fortRaPrivate); } else { R.data = Ra; R.len = sizeof(CI_RA); if (email) { r.data = x.data; r.len = x.len; } else { ra = fort_LookupPrivR(swtoken,Rb); if (ra == NULL) { ret = CI_EXEC_FAIL; goto loser; } r.data = ra; r.len = sizeof(fortRaPrivate); } } if (!KEA_Verify(&Y,&key->u.dh.prime,q)) { ret = CI_EXEC_FAIL; goto loser; } if (!KEA_Verify(&R,&key->u.dh.prime,q)) { ret = CI_EXEC_FAIL; goto loser; } /* calculate the base key */ rv = KEA_Derive(&key->u.dh.prime, &Y, &R, &r, &x, &wItem); if (rv != SECSuccess) { ret = CI_EXEC_FAIL; goto loser; } w = wItem.data; /* use the skipjack wrapping function to 'mix' the key up */ for (i=0; i < sizeof(FORTSkipjackKey); i++) cover_key[i] = pad[i] ^ w[i]; ret = fort_skipjackWrap(cover_key,sizeof(FORTSkipjackKey), &w[sizeof(FORTSkipjackKey)],swtoken->keyReg[target].data); if (ret != CI_OK) goto loser; swtoken->keyReg[target].present = PR_TRUE; ret = CI_OK;loser: if (w) PORT_Free(w); if (key) SECKEY_LowDestroyPrivateKey(key);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?