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,&params.prime,&key_info->p);    if (rv != SECSuccess) return CI_EXEC_FAIL;    rv = SECITEM_CopyItem(NULL,&params.subPrime,&key_info->q);    if (rv != SECSuccess) return CI_EXEC_FAIL;    rv = SECITEM_CopyItem(NULL,&params.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(&params, &privKey);    SECITEM_FreeItem(&params.prime,PR_FALSE);    SECITEM_FreeItem(&params.subPrime,PR_FALSE);    SECITEM_FreeItem(&params.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 + -
显示快捷键?