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/
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.
12
* The Original Code is the Netscape security libraries.
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
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
34
* implement the MACI calls as Software Fortezza Calls.
35
* only do the ones Nescape Needs. This provides a single software slot,
36
* with 100 key registers, and 50 backup Ra private registers. Since we only
37
* create one session per slot, this implementation only uses one session.
38
* One future enhancement may be to try to improve on this for better threading
46
/*#include "keytlow.h"*/
50
/* #include "dsa.h" */
51
/* #include "hasht.h" */
54
/*#include "keylow.h" */
57
#if defined(XP_UNIX) || defined(XP_BEOS)
66
/* currently we only support one software token. In the future we can use the
67
* session to determin which of many possible tokens we are talking about.
68
* all the calls which need tokens take a pointer to the software token as a
71
static FORTSWToken *swtoken = NULL;
76
/* can't change the pin on SW fortezza for now */
78
MACI_ChangePIN(HSESSION session, int PINType, CI_PIN CI_FAR pOldPIN,
79
CI_PIN CI_FAR pNewPin)
86
* Check pin checks the pin, then logs the user in or out depending on if
87
* the pin succedes. The General implementation would support both SSO and
88
* User mode our's only needs User mode. Pins are checked by whether or not
89
* they can produce our valid Ks for this 'card'.
92
MACI_CheckPIN(HSESSION session, int PINType, CI_PIN CI_FAR pin)
94
FORTSkipjackKeyPtr Ks;
95
FORTSWFile *config_file = NULL;
97
unsigned char pinArea[13];
98
unsigned char *padPin = NULL;
100
/* This SW module can only log in as USER */
101
if (PINType != CI_USER_PIN) return CI_INV_TYPE;
103
if (swtoken == NULL) return CI_NO_CARD;
104
/* we can't check a pin if we haven't been initialized yet */
105
if (swtoken->config_file == NULL) return CI_NO_CARD;
106
config_file = swtoken->config_file;
108
/* Make sure the pin value meets minimum lengths */
109
if (PORT_Strlen((char *)pin) < 12) {
110
PORT_Memset(pinArea, ' ', sizeof(pinArea));
111
PORT_Memcpy(pinArea,pin,PORT_Strlen((char *)pin));
116
/* get the Ks by unwrapping it from the memphrase with the pbe generated
118
Ks = fort_CalculateKMemPhrase(config_file,
119
&config_file->fortezzaPhrase, (char *)pin, NULL);
122
Ks = fort_CalculateKMemPhrase(config_file,
123
&config_file->fortezzaPhrase, (char *)padPin, NULL);
125
PORT_Memset(pinArea, 0, sizeof(pinArea));
126
fort_Logout(swtoken);
131
/* use Ks and hash to verify that pin is correct */
132
if (! fort_CheckMemPhrase(config_file, &config_file->fortezzaPhrase,
134
if ((padPin == NULL) ||
135
! fort_CheckMemPhrase(config_file, &config_file->fortezzaPhrase,
136
(char *)padPin, Ks) ) {
137
PORT_Memset(pinArea, 0, sizeof(pinArea));
138
fort_Logout(swtoken);
143
PORT_Memset(pinArea, 0, sizeof(pinArea));
146
/* OK, add the random Seed value into the random number generator */
147
fort_skipjackUnwrap(Ks,config_file->wrappedRandomSeed.len,
148
config_file->wrappedRandomSeed.data,seed);
149
RNG_RandomUpdate(seed,sizeof(seed));
151
/* it is, go ahead and log in */
152
swtoken->login = PR_TRUE;
153
/* Ks is always stored in keyReg[0] when we log in */
154
PORT_Memcpy(swtoken->keyReg[0].data, Ks, sizeof (FORTSkipjackKey));
155
swtoken->keyReg[0].present = PR_TRUE;
156
PORT_Memset(Ks, 0, sizeof(FORTSkipjackKey));
164
* close an open socket. Power_Down flag is set when we want to reset the
165
* cards complete state.
168
MACI_Close(HSESSION session, unsigned int flags, int socket)
170
if (socket != SOCKET_ID) return CI_BAD_CARD;
171
if (swtoken == NULL) return CI_BAD_CARD;
173
if (flags == CI_POWER_DOWN_FLAG) {
174
fort_Logout(swtoken);
180
* Decrypt keeps track of it's own IV.
183
MACI_Decrypt(HSESSION session, unsigned int size, CI_DATA cipherIn,
187
unsigned char IV[SKIPJACK_BLOCK_SIZE];
189
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
190
if ((ret = fort_KeyOK(swtoken,swtoken->key,PR_TRUE)) != CI_OK) return ret;
194
/* save the IV, before we potentially trash the new one when we decrypt.
195
* (it's permissible to decrypt into the cipher text buffer by passing the
196
* same buffers for both cipherIn and plainOut.
198
PORT_Memcpy(IV,swtoken->IV, sizeof(IV));
199
fort_UpdateIV(cipherIn,size,swtoken->IV);
200
return fort_skipjackDecrypt(swtoken->keyReg[swtoken->key].data,
201
IV,size,cipherIn,plainOut);
205
* Clear a key from one of the key registers (indicated by index).
206
* return an error if no key exists.
209
MACI_DeleteKey(HSESSION session, int index)
212
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
214
/* can't delete Ks */
215
if (index == 0) return CI_INV_KEY_INDEX;
217
if ((ret = fort_KeyOK(swtoken,index,PR_TRUE)) != CI_OK) return ret;
218
fort_ClearKey(&swtoken->keyReg[index]);
224
* encrypt some blocks of data and update the IV.
227
MACI_Encrypt(HSESSION session, unsigned int size, CI_DATA plainIn,
231
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
232
if ((ret = fort_KeyOK(swtoken,swtoken->key,PR_TRUE)) != CI_OK) return ret;
236
ret = fort_skipjackEncrypt(swtoken->keyReg[swtoken->key].data,
237
swtoken->IV,size,plainIn,cipherOut);
238
fort_UpdateIV(cipherOut,size,swtoken->IV);
245
* create a new IV and encode it.
248
static char *leafbits="THIS IS NOT LEAF";
251
MACI_GenerateIV(HSESSION Session, CI_IV CI_FAR pIV)
255
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
256
if ((ret = fort_KeyOK(swtoken,swtoken->key,PR_TRUE)) != CI_OK) return ret;
258
ret = fort_GenerateRandom(swtoken->IV,SKIPJACK_BLOCK_SIZE);
259
if (ret != CI_OK) return ret;
261
PORT_Memcpy(pIV,leafbits,SKIPJACK_LEAF_SIZE);
262
PORT_Memcpy(&pIV[SKIPJACK_LEAF_SIZE],swtoken->IV,SKIPJACK_BLOCK_SIZE);
272
MACI_GenerateMEK(HSESSION session, int index, int reserved)
275
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
276
if ((ret = fort_KeyOK(swtoken,index,PR_FALSE)) != CI_OK) return ret;
278
ret = fort_GenerateRandom(swtoken->keyReg[index].data,
279
sizeof (swtoken->keyReg[index].data));
280
if (ret == CI_OK) swtoken->keyReg[index].present = PR_TRUE;
286
* build a new Ra/ra pair for a KEA exchange.
289
MACI_GenerateRa(HSESSION session, CI_RA CI_FAR pRa)
294
DSAPrivateKey *privKey = NULL;
297
int crv = CI_EXEC_FAIL;
298
fortSlotEntry *certEntry = NULL;
299
unsigned char *unsignedRa = NULL;
300
unsigned char *unsignedra = NULL;
301
fortKeyInformation *key_info = NULL;
304
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
305
/* make sure the personality is set */
306
if (swtoken->certIndex == 0) return CI_INV_STATE;
308
/* pick next Ra circular buffer */
309
counter = swtoken->nextRa;
311
if (swtoken->nextRa >= MAX_RA_SLOTS) swtoken->nextRa = 0;
313
/* now get the params for diffie -helman key gen */
314
certEntry = fort_GetCertEntry(swtoken->config_file,swtoken->certIndex);
315
if (certEntry == NULL) return CI_INV_CERT_INDEX;
316
if (certEntry->exchangeKeyInformation) {
317
key_info = certEntry->exchangeKeyInformation;
319
key_info = certEntry->signatureKeyInformation;
321
if (key_info == NULL) return CI_NO_X;
323
/* Generate Diffie Helman key Pair -- but we use DSA key gen to do it */
324
rv = SECITEM_CopyItem(NULL,¶ms.prime,&key_info->p);
325
if (rv != SECSuccess) return CI_EXEC_FAIL;
326
rv = SECITEM_CopyItem(NULL,¶ms.subPrime,&key_info->q);
327
if (rv != SECSuccess) return CI_EXEC_FAIL;
328
rv = SECITEM_CopyItem(NULL,¶ms.base,&key_info->g);
329
if (rv != SECSuccess) return CI_EXEC_FAIL;
331
/* KEA uses DSA like key generation with short DSA keys that have to
332
* maintain a relationship to q */
333
rv = DSA_NewKey(¶ms, &privKey);
334
SECITEM_FreeItem(¶ms.prime,PR_FALSE);
335
SECITEM_FreeItem(¶ms.subPrime,PR_FALSE);
336
SECITEM_FreeItem(¶ms.base,PR_FALSE);
337
if (rv != SECSuccess) return CI_EXEC_FAIL;
339
/* save private key, public key, and param in Ra Circular buffer */
340
unsignedRa = privKey->publicValue.data;
341
RaLen = privKey->publicValue.len;
342
while ((unsignedRa[0] == 0) && (RaLen > CI_RA_SIZE)) {
346
if (RaLen > CI_RA_SIZE) goto loser;
348
unsignedra = privKey->privateValue.data;
349
raLen = privKey->privateValue.len;
350
while ((unsignedra[0] == 0) && (raLen > sizeof(fortRaPrivate))) {
355
if (raLen > sizeof(fortRaPrivate)) goto loser;
357
PORT_Memset(swtoken->RaValues[counter].private, 0, sizeof(fortRaPrivate));
359
&swtoken->RaValues[counter].private[sizeof(fortRaPrivate) - raLen],
361
PORT_Memset(pRa, 0, CI_RA_SIZE);
362
PORT_Memcpy(&pRa[CI_RA_SIZE-RaLen], unsignedRa, RaLen);
363
PORT_Memcpy(swtoken->RaValues[counter].public, pRa, CI_RA_SIZE);
367
PORT_FreeArena(privKey->params.arena, PR_TRUE);
374
* return some random data.
377
MACI_GenerateRandom(HSESSION session, CI_RANDOM CI_FAR random)
380
if ((ret = fort_CardExists(swtoken,PR_FALSE)) != CI_OK) return ret;
381
return fort_GenerateRandom(random,sizeof (CI_RANDOM));
385
static CI_RA Remail = {
386
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
387
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
389
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
390
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
392
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
393
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
395
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
396
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
400
* build a new Token exchange key using KEA.
403
MACI_GenerateTEK(HSESSION hSession, int flags, int target,
404
CI_RA CI_FAR Ra, CI_RA CI_FAR Rb, unsigned int YSize, CI_Y CI_FAR pY )
406
FORTEZZAPrivateKey *key = NULL;
407
fortSlotEntry * certEntry;
408
unsigned char * w = NULL;
412
PRBool email = PR_TRUE;
413
SECItem R; /* public */
414
SECItem Y; /* public */
415
SECItem r; /* private */
416
SECItem x; /* private */
417
SECItem wItem; /* derived secret */
419
FORTSkipjackKey cover_key;
421
unsigned char pad[10] = { 0x72, 0xf1, 0xa8, 0x7e, 0x92,
422
0x82, 0x41, 0x98, 0xab, 0x0b };
424
/* verify that everything is ok with the token, keys and certs */
425
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
426
/* make sure the personality is set */
427
if (swtoken->certIndex == 0) return CI_INV_STATE;
428
if ((ret = fort_KeyOK(swtoken,target,PR_FALSE)) != CI_OK) return ret;
430
/* get the cert from the entry, then look up the key from that cert */
431
certEntry = fort_GetCertEntry(swtoken->config_file,swtoken->certIndex);
432
if (certEntry == NULL) return CI_INV_CERT_INDEX;
433
key = fort_GetPrivKey(swtoken,fortezzaDHKey,certEntry);
434
if (key == NULL) return CI_NO_X;
436
if (certEntry->exchangeKeyInformation) {
437
q = &certEntry->exchangeKeyInformation->q;
439
q = &certEntry->signatureKeyInformation->q;
442
email = (PORT_Memcmp(Rb,Remail,sizeof(Rb)) == 0) ? PR_TRUE: PR_FALSE;
445
/* load the common elements */
448
x.data = key->u.dh.privateValue.data;
449
x.len = key->u.dh.privateValue.len;
451
/* now initialize the rest of the values */
452
if (flags == CI_INITIATOR_FLAG) {
458
R.len = sizeof(CI_RA);
460
ra = fort_LookupPrivR(swtoken,Ra);
466
r.len = sizeof(fortRaPrivate);
469
R.len = sizeof(CI_RA);
474
ra = fort_LookupPrivR(swtoken,Rb);
480
r.len = sizeof(fortRaPrivate);
485
if (!KEA_Verify(&Y,&key->u.dh.prime,q)) {
489
if (!KEA_Verify(&R,&key->u.dh.prime,q)) {
494
/* calculate the base key */
495
rv = KEA_Derive(&key->u.dh.prime, &Y, &R, &r, &x, &wItem);
496
if (rv != SECSuccess) {
502
/* use the skipjack wrapping function to 'mix' the key up */
503
for (i=0; i < sizeof(FORTSkipjackKey); i++)
504
cover_key[i] = pad[i] ^ w[i];
506
ret = fort_skipjackWrap(cover_key,sizeof(FORTSkipjackKey),
507
&w[sizeof(FORTSkipjackKey)],swtoken->keyReg[target].data);
508
if (ret != CI_OK) goto loser;
510
swtoken->keyReg[target].present = PR_TRUE;
515
if (key) fort_DestroyPrivateKey(key);
522
* return the bytes of a certificate.
525
MACI_GetCertificate(HSESSION hSession, int certIndex,
526
CI_CERTIFICATE CI_FAR cert)
530
fortSlotEntry *certEntry = NULL;
532
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
534
certEntry = fort_GetCertEntry(swtoken->config_file,certIndex);
535
if (certEntry == NULL) return CI_INV_CERT_INDEX;
537
len = certEntry->certificateData.dataEncryptedWithKs.len;
538
PORT_Memset(cert,0,sizeof(CI_CERTIFICATE));
539
PORT_Memcpy(cert, certEntry->certificateData.dataEncryptedWithKs.data,len);
541
/* Ks is always stored in keyReg[0] when we log in */
542
return fort_skipjackDecrypt(swtoken->keyReg[0].data,
543
&certEntry->certificateData.dataIV.data[SKIPJACK_LEAF_SIZE],
549
* return out sofware configuration bytes. Those field not used by the PKCS #11
550
* module may not be filled in exactly.
552
#define NETSCAPE "Netscape Communications Corp "
553
#define PRODUCT "Netscape Software FORTEZZA Lib "
554
#define SOFTWARE "Software FORTEZZA Implementation"
557
MACI_GetConfiguration(HSESSION hSession, CI_CONFIG_PTR config)
559
config->LibraryVersion = 0x0100;
560
config->ManufacturerVersion = 0x0100;
561
PORT_Memcpy(config->ManufacturerName,NETSCAPE,sizeof(NETSCAPE));
562
PORT_Memcpy(config->ProductName,PRODUCT,sizeof(PRODUCT));
563
PORT_Memcpy(config->ProcessorType,SOFTWARE,sizeof(SOFTWARE));
564
config->UserRAMSize = 0;
565
config->LargestBlockSize = 0x10000;
566
config->KeyRegisterCount = KEY_REGISTERS;
567
config->CertificateCount =
568
swtoken ? fort_GetCertCount(swtoken->config_file): 0;
569
config->CryptoCardFlag = 0;
570
config->ICDVersion = 0;
571
config->ManufacturerSWVer = 0x0100;
572
config->DriverVersion = 0x0100;
577
* return a list of all the personalities (up to the value 'EntryCount')
580
MACI_GetPersonalityList(HSESSION hSession, int EntryCount,
581
CI_PERSON CI_FAR personList[])
585
FORTSWFile *config_file = NULL;
586
unsigned char tmp[32];
588
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
589
config_file = swtoken->config_file;
591
/* search for the index */
592
count= fort_GetCertCount(config_file);
594
/* don't return more than the user asked for */
595
if (count > EntryCount) count = EntryCount;
596
for (i=0; i < count ;i ++) {
598
personList[i].CertificateIndex =
599
config_file->slotEntries[i]->certIndex;
600
len = config_file->slotEntries[i]->certificateLabel.
601
dataEncryptedWithKs.len;
602
if (len > sizeof(tmp)) len = sizeof(tmp);
603
PORT_Memset(personList[i].CertLabel, ' ',
604
sizeof(personList[i].CertLabel));
606
config_file->slotEntries[i]->
607
certificateLabel.dataEncryptedWithKs.data,
609
/* Ks is always stored in keyReg[0] when we log in */
610
ret = fort_skipjackDecrypt(swtoken->keyReg[0].data,
611
&config_file->slotEntries[i]->
612
certificateLabel.dataIV.data[SKIPJACK_LEAF_SIZE],len,
614
if (ret != CI_OK) return ret;
615
dataLen = DER_GetInteger(&config_file->slotEntries[i]->
616
certificateLabel.length);
617
if (dataLen > sizeof(tmp)) dataLen = sizeof(tmp);
618
PORT_Memcpy(personList[i].CertLabel, tmp, dataLen);
619
personList[i].CertLabel[32] = 0;
620
personList[i].CertLabel[33] = 0;
621
personList[i].CertLabel[34] = 0;
622
personList[i].CertLabel[35] = 0;
629
* get a new session ID. This function is only to make the interface happy,
630
* the PKCS #11 module only uses one session per token.
633
MACI_GetSessionID(HSESSION *session)
640
* return the current card state.
643
MACI_GetState(HSESSION hSession, CI_STATE_PTR state)
646
if ((ret = fort_CardExists(swtoken,PR_FALSE)) != CI_OK) return ret;
647
*state = fort_GetState(swtoken);
652
* return the status. NOTE that KeyRegisterFlags and CertificateFlags are never
653
* really used by the PKCS #11 module, so they are not implemented.
656
MACI_GetStatus(HSESSION hSession, CI_STATUS_PTR status)
659
FORTSWFile *config_file = NULL;
661
if ((ret = fort_CardExists(swtoken,PR_FALSE)) != CI_OK) return ret;
662
config_file = swtoken->config_file;
663
status->CurrentSocket = 1;
664
status->LockState = swtoken->lock;
665
PORT_Memcpy(status->SerialNumber,
666
config_file->serialID.data, config_file->serialID.len);
667
status->CurrentState = fort_GetState(swtoken);
668
status->DecryptionMode = CI_CBC64_MODE;
669
status->EncryptionMode = CI_CBC64_MODE;
670
status->CurrentPersonality = swtoken->certIndex;
671
status->KeyRegisterCount = KEY_REGISTERS;
672
/* our code doesn't use KeyRegisters, which is good, because there's not
673
* enough of them .... */
674
PORT_Memset(status->KeyRegisterFlags,0,sizeof(status->KeyRegisterFlags));
675
status->CertificateCount = fort_GetCertCount(config_file);
676
PORT_Memset(status->CertificateFlags,0,sizeof(status->CertificateFlags));
677
PORT_Memset(status->Flags,0,sizeof(status->Flags));
683
* add the time call because the PKCS #11 module calls it, but always pretend
684
* the clock is bad, so it never uses the returned time.
687
MACI_GetTime(HSESSION hSession, CI_TIME CI_FAR time)
693
/* This function is copied from NSPR so that the PKCS #11 module can be
694
* independent of NSPR */
695
PRInt32 local_getFileInfo(const char *fn, PRFileInfo *info);
698
* initialize the SW module, and return the number of slots we support (1).
701
MACI_Initialize(int CI_FAR *count)
703
char *filename = NULL;
705
FORTSignedSWFile *decode_file = NULL;
707
/*PRFileDesc *fd = NULL;*/
718
/* allocate swtoken structure */
719
swtoken = PORT_ZNew(FORTSWToken);
720
if (swtoken == NULL) return CI_OUT_OF_MEMORY;
722
filename = (char *)fort_LookupFORTEZZAInitFile();
723
if (filename == NULL) {
728
fd = open(filename,O_RDONLY|O_BINARY,0);
734
err = local_getFileInfo(filename,&info);
735
if ((err != 0) || (info.size == 0)) {
740
file.data = PORT_ZAlloc(info.size);
741
if (file.data == NULL) {
742
ret = CI_OUT_OF_MEMORY;
746
fcount = read(fd,file.data,info.size);
748
if (fcount != (int)info.size) {
755
decode_file = FORT_GetSWFile(&file);
756
if (decode_file == NULL) {
760
swtoken->config_file = &decode_file->file;
762
RNG_SystemInfoForRNG();
763
RNG_FileForRNG(filename);
767
if (filename) PORT_Free(filename);
768
if (fd != -1) close(fd);
769
if (file.data) PORT_Free(file.data);
771
if (decode_file) FORT_DestroySignedSWFile(decode_file);
772
if (swtoken) PORT_Free(swtoken);
780
* load an IV from an external source. We technically should check it with the
784
MACI_LoadIV(HSESSION session, CI_IV CI_FAR iv)
788
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
789
PORT_Memcpy(swtoken->IV,&iv[SKIPJACK_LEAF_SIZE],SKIPJACK_BLOCK_SIZE);
793
/* implement token lock (should call PR_Monitor here) */
795
MACI_Lock(HSESSION session, int flags)
798
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
804
/* open a token. For software there isn't much to do that hasn't already been
805
* done by initialize. */
807
MACI_Open(HSESSION session, unsigned int flags, int socket)
809
if (socket != SOCKET_ID) return CI_NO_CARD;
810
if (swtoken == NULL) return CI_NO_CARD;
815
* Reset logs out the token...
818
MACI_Reset(HSESSION session)
820
if (swtoken) fort_Logout(swtoken);
825
* restore and encrypt/decrypt state. NOTE: there is no error checking in this
826
* or the save function.
829
MACI_Restore(HSESSION session, int type, CI_SAVE_DATA CI_FAR data)
832
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
833
PORT_Memcpy(swtoken->IV,data, sizeof (swtoken->IV));
838
* save and encrypt/decrypt state. NOTE: there is no error checking in this
839
* or the restore function.
842
MACI_Save(HSESSION session, int type,CI_SAVE_DATA CI_FAR data)
845
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
846
PORT_Memcpy(data,swtoken->IV, sizeof (swtoken->IV));
851
* picks a token to operate against. In our case there can be only one.
854
MACI_Select(HSESSION session, int socket)
856
if (socket == SOCKET_ID) return CKR_OK;
861
* set a register as the key to use for encrypt/decrypt operations.
864
MACI_SetKey(HSESSION session, int index)
867
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
868
if ((ret = fort_KeyOK(swtoken,index,PR_TRUE)) != CI_OK) return ret;
870
swtoken->key = index;
875
* only CBC64 is supported. Keep setmode for compatibility */
877
MACI_SetMode(HSESSION session, int type, int mode)
879
if (mode != CI_CBC64_MODE) return CI_INV_MODE;
883
/* set the personality to use for sign/verify */
885
MACI_SetPersonality(HSESSION session, int cert)
888
fortSlotEntry *certEntry = NULL;
890
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
892
certEntry = fort_GetCertEntry(swtoken->config_file,cert);
893
if ((certEntry == NULL) ||
894
((certEntry->exchangeKeyInformation == NULL) &&
895
(certEntry->signatureKeyInformation == NULL)) )
896
return CI_INV_CERT_INDEX;
897
swtoken->certIndex = cert;
902
/* DSA sign some data */
904
MACI_Sign(HSESSION session, CI_HASHVALUE CI_FAR hash, CI_SIGNATURE CI_FAR sig)
906
FORTEZZAPrivateKey *key = NULL;
907
fortSlotEntry * certEntry = NULL;
912
unsigned char random[DSA_SUBPRIME_LEN];
914
/* standard checks */
915
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
916
/* make sure the personality is set */
917
if (swtoken->certIndex == 0) return CI_INV_STATE;
919
/* get the current personality */
920
certEntry = fort_GetCertEntry(swtoken->config_file,swtoken->certIndex);
921
if (certEntry == NULL) return CI_INV_CERT_INDEX;
923
/* extract the private key from the personality */
925
key = fort_GetPrivKey(swtoken,fortezzaDSAKey,certEntry);
931
/* create a random value for the signature */
932
ret = fort_GenerateRandom(random, sizeof(random));
933
if (ret != CI_OK) goto loser;
935
/* Sign with that private key */
937
signItem.len = DSA_SIGNATURE_LEN;
939
hashItem.data = hash;
940
hashItem.len = SHA1_LENGTH;
942
rv = DSA_SignDigestWithSeed(&key->u.dsa, &signItem, &hashItem, random);
943
if (rv != SECSuccess) {
949
if (key != NULL) fort_DestroyPrivateKey(key);
955
* clean up after ourselves.
958
MACI_Terminate(HSESSION session)
960
if (swtoken == NULL) return CI_OUT_OF_MEMORY;
962
/* clear all the keys */
963
fort_Logout(swtoken);
965
FORT_DestroySWFile(swtoken->config_file);
973
/* implement token unlock (should call PR_Monitor here) */
975
MACI_Unlock(HSESSION session)
978
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
984
* unwrap a key into our software token. NOTE: this function does not
985
* verify that the wrapping key is Ks or a TEK. This is because our higher
986
* level software doesn't try to wrap MEKs with MEKs. If this API was exposed
987
* generically, then we would have to worry about things like this.
990
MACI_UnwrapKey(HSESSION session, int wrapKey, int target,
991
CI_KEY CI_FAR keyData)
995
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
996
if ((ret = fort_KeyOK(swtoken,target,PR_FALSE)) != CI_OK) return ret;
997
if ((ret = fort_KeyOK(swtoken,wrapKey,PR_TRUE)) != CI_OK) return ret;
998
ret = fort_skipjackUnwrap(swtoken->keyReg[wrapKey].data,
999
sizeof(CI_KEY), keyData, swtoken->keyReg[target].data);
1000
if (ret != CI_OK) goto loser;
1002
swtoken->keyReg[target].present = PR_TRUE;
1009
* Wrap a key out of our software token. NOTE: this function does not
1010
* verify that the wrapping key is Ks or a TEK, or that the source key is
1011
* a MEK. This is because our higher level software doesn't try to wrap MEKs
1012
* with MEKs, or wrap out TEKS and Ks. If this API was exposed
1013
* generically, then we would have to worry about things like this.
1016
MACI_WrapKey(HSESSION session, int wrapKey, int source, CI_KEY CI_FAR keyData)
1020
if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
1021
if ((ret = fort_KeyOK(swtoken,source,PR_TRUE)) != CI_OK) return ret;
1022
if ((ret = fort_KeyOK(swtoken,wrapKey,PR_TRUE)) != CI_OK) return ret;
1023
ret = fort_skipjackWrap(swtoken->keyReg[wrapKey].data,
1024
sizeof(CI_KEY), swtoken->keyReg[source].data,keyData);