~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/fortcrypt/swfort/swflib.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 * 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
 
39
 * support.
 
40
 */
 
41
 
 
42
#include "prtypes.h"
 
43
#include "prio.h"
 
44
 
 
45
#include "swforti.h"
 
46
/*#include "keytlow.h"*/
 
47
/* #include "dh.h" */
 
48
#include "blapi.h"
 
49
#include "maci.h"
 
50
/* #include "dsa.h" */
 
51
/* #include "hasht.h" */
 
52
#include "secitem.h"
 
53
#include "secrng.h"
 
54
/*#include "keylow.h" */
 
55
#include "secder.h"
 
56
 
 
57
#if defined(XP_UNIX) || defined(XP_BEOS)
 
58
#include <unistd.h>
 
59
#endif
 
60
 
 
61
#ifndef O_BINARY
 
62
#define O_BINARY 0
 
63
#endif
 
64
 
 
65
 
 
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
 
69
 * target.
 
70
 */
 
71
static FORTSWToken *swtoken = NULL;
 
72
 
 
73
#define SOCKET_ID 1
 
74
 
 
75
 
 
76
/* can't change the pin on SW fortezza for now */
 
77
int
 
78
MACI_ChangePIN(HSESSION session, int PINType, CI_PIN CI_FAR pOldPIN,
 
79
                                                 CI_PIN CI_FAR pNewPin)
 
80
{
 
81
    return CI_INV_STATE;
 
82
}
 
83
 
 
84
 
 
85
/*
 
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'.
 
90
 */
 
91
int
 
92
MACI_CheckPIN(HSESSION session, int PINType, CI_PIN CI_FAR pin)
 
93
{
 
94
    FORTSkipjackKeyPtr Ks;
 
95
    FORTSWFile *config_file = NULL;
 
96
    FORTSkipjackKey seed;
 
97
    unsigned char pinArea[13];
 
98
    unsigned char *padPin = NULL;
 
99
 
 
100
    /* This SW module can only log in as USER */
 
101
    if (PINType != CI_USER_PIN) return CI_INV_TYPE;
 
102
 
 
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;
 
107
 
 
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));
 
112
        pinArea[12] = 0;
 
113
        padPin = pinArea;
 
114
    }
 
115
 
 
116
    /* get the Ks by unwrapping it from the memphrase with the pbe generated
 
117
     * from the pin */
 
118
    Ks = fort_CalculateKMemPhrase(config_file, 
 
119
                        &config_file->fortezzaPhrase, (char *)pin, NULL);
 
120
 
 
121
    if (Ks == 0) {
 
122
        Ks = fort_CalculateKMemPhrase(config_file, 
 
123
                &config_file->fortezzaPhrase, (char *)padPin, NULL);
 
124
        if (Ks == 0) {
 
125
            PORT_Memset(pinArea, 0, sizeof(pinArea));
 
126
            fort_Logout(swtoken);
 
127
            return CI_FAIL;
 
128
        }
 
129
    }
 
130
 
 
131
    /* use Ks and hash to verify that pin is correct */
 
132
    if (! fort_CheckMemPhrase(config_file, &config_file->fortezzaPhrase, 
 
133
                                                (char *)pin, Ks) ) {
 
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);
 
139
            return CI_FAIL;
 
140
        }
 
141
    }
 
142
 
 
143
    PORT_Memset(pinArea, 0, sizeof(pinArea));
 
144
 
 
145
 
 
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));
 
150
 
 
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));
 
157
    PORT_Free(Ks);
 
158
 
 
159
 
 
160
    return CI_OK;
 
161
}
 
162
 
 
163
/*
 
164
 * close an open socket. Power_Down flag is set when we want to reset the
 
165
 * cards complete state.
 
166
 */
 
167
int
 
168
MACI_Close(HSESSION session, unsigned int flags, int socket)
 
169
{
 
170
    if (socket != SOCKET_ID) return CI_BAD_CARD;
 
171
    if (swtoken == NULL) return CI_BAD_CARD;
 
172
 
 
173
    if (flags == CI_POWER_DOWN_FLAG) {
 
174
        fort_Logout(swtoken);
 
175
    }
 
176
    return CI_OK;
 
177
}
 
178
 
 
179
/*
 
180
 * Decrypt keeps track of it's own IV.
 
181
 */
 
182
int
 
183
MACI_Decrypt(HSESSION session, unsigned int size, CI_DATA cipherIn,
 
184
                                                        CI_DATA plainOut)
 
185
{
 
186
    int ret;
 
187
    unsigned char IV[SKIPJACK_BLOCK_SIZE];
 
188
 
 
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;
 
191
 
 
192
    /*fort_AddNoise();*/
 
193
 
 
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.
 
197
     */
 
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);
 
202
}
 
203
 
 
204
/*
 
205
 * Clear a key from one of the key registers (indicated by index).
 
206
 * return an error if no key exists.
 
207
 */
 
208
int
 
209
MACI_DeleteKey(HSESSION session, int index)
 
210
{
 
211
    int ret;
 
212
    if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
 
213
 
 
214
    /* can't delete Ks */
 
215
    if (index == 0) return CI_INV_KEY_INDEX;
 
216
 
 
217
    if ((ret = fort_KeyOK(swtoken,index,PR_TRUE)) != CI_OK)  return ret;
 
218
    fort_ClearKey(&swtoken->keyReg[index]);
 
219
    return CI_OK;
 
220
}
 
221
 
 
222
 
 
223
/*
 
224
 * encrypt  some blocks of data and update the IV.
 
225
 */ 
 
226
int
 
227
MACI_Encrypt(HSESSION session, unsigned int size, CI_DATA plainIn,
 
228
                                                        CI_DATA cipherOut)
 
229
{
 
230
    int ret;
 
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;
 
233
 
 
234
    /*fort_AddNoise();*/
 
235
 
 
236
    ret = fort_skipjackEncrypt(swtoken->keyReg[swtoken->key].data,
 
237
                                swtoken->IV,size,plainIn,cipherOut);
 
238
    fort_UpdateIV(cipherOut,size,swtoken->IV);
 
239
 
 
240
    return ret;
 
241
 
 
242
}
 
243
 
 
244
/*
 
245
 * create a new IV and encode it.
 
246
 */
 
247
 
 
248
static char *leafbits="THIS IS NOT LEAF";
 
249
 
 
250
int
 
251
MACI_GenerateIV(HSESSION Session, CI_IV CI_FAR pIV)
 
252
{
 
253
    int ret;
 
254
 
 
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;
 
257
 
 
258
    ret = fort_GenerateRandom(swtoken->IV,SKIPJACK_BLOCK_SIZE);
 
259
    if (ret != CI_OK) return ret;
 
260
 
 
261
    PORT_Memcpy(pIV,leafbits,SKIPJACK_LEAF_SIZE);
 
262
    PORT_Memcpy(&pIV[SKIPJACK_LEAF_SIZE],swtoken->IV,SKIPJACK_BLOCK_SIZE);
 
263
   
 
264
    return CI_OK;
 
265
}
 
266
 
 
267
 
 
268
/*
 
269
 * create a new Key
 
270
 */
 
271
int
 
272
MACI_GenerateMEK(HSESSION session, int index, int reserved)
 
273
{
 
274
    int ret;
 
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;
 
277
 
 
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;
 
281
 
 
282
    return ret;
 
283
}
 
284
 
 
285
/*
 
286
 * build a new Ra/ra pair for a KEA exchange.
 
287
 */
 
288
int
 
289
MACI_GenerateRa(HSESSION session, CI_RA CI_FAR pRa)
 
290
{
 
291
    int ret;
 
292
    int counter;
 
293
    int RaLen,raLen;
 
294
    DSAPrivateKey *privKey = NULL;
 
295
    PQGParams params;
 
296
    SECStatus rv;
 
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;
 
302
        
 
303
 
 
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;
 
307
 
 
308
    /* pick next Ra circular buffer */
 
309
    counter = swtoken->nextRa;
 
310
    swtoken->nextRa++;
 
311
    if (swtoken->nextRa >= MAX_RA_SLOTS) swtoken->nextRa = 0;
 
312
 
 
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;
 
318
    } else {
 
319
        key_info = certEntry->signatureKeyInformation;
 
320
    }
 
321
    if (key_info == NULL) return CI_NO_X;
 
322
   
 
323
    /* Generate Diffie Helman key Pair -- but we use DSA key gen to do it */
 
324
    rv = SECITEM_CopyItem(NULL,&params.prime,&key_info->p);
 
325
    if (rv != SECSuccess) return CI_EXEC_FAIL;
 
326
    rv = SECITEM_CopyItem(NULL,&params.subPrime,&key_info->q);
 
327
    if (rv != SECSuccess) return CI_EXEC_FAIL;
 
328
    rv = SECITEM_CopyItem(NULL,&params.base,&key_info->g);
 
329
    if (rv != SECSuccess) return CI_EXEC_FAIL;
 
330
 
 
331
    /* KEA uses DSA like key generation with short DSA keys that have to
 
332
     * maintain a relationship to q */
 
333
    rv = DSA_NewKey(&params, &privKey);
 
334
    SECITEM_FreeItem(&params.prime,PR_FALSE);
 
335
    SECITEM_FreeItem(&params.subPrime,PR_FALSE);
 
336
    SECITEM_FreeItem(&params.base,PR_FALSE);
 
337
    if (rv != SECSuccess) return CI_EXEC_FAIL;
 
338
    
 
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)) {
 
343
        unsignedRa++;
 
344
        RaLen--;
 
345
    }
 
346
    if (RaLen > CI_RA_SIZE) goto loser;
 
347
 
 
348
    unsignedra = privKey->privateValue.data;
 
349
    raLen      = privKey->privateValue.len;
 
350
    while ((unsignedra[0] == 0) && (raLen > sizeof(fortRaPrivate))) {
 
351
        unsignedra++;
 
352
        raLen--;
 
353
    }
 
354
 
 
355
    if (raLen > sizeof(fortRaPrivate)) goto loser;
 
356
 
 
357
    PORT_Memset(swtoken->RaValues[counter].private, 0, sizeof(fortRaPrivate));
 
358
    PORT_Memcpy(
 
359
        &swtoken->RaValues[counter].private[sizeof(fortRaPrivate) - raLen],
 
360
                                                        unsignedra, 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);
 
364
    crv = CI_OK;
 
365
 
 
366
loser:
 
367
    PORT_FreeArena(privKey->params.arena, PR_TRUE);
 
368
 
 
369
    return crv;
 
370
}
 
371
 
 
372
 
 
373
/*
 
374
 * return some random data.
 
375
 */
 
376
int
 
377
MACI_GenerateRandom(HSESSION session, CI_RANDOM CI_FAR random)
 
378
{
 
379
    int ret;
 
380
    if ((ret = fort_CardExists(swtoken,PR_FALSE)) != CI_OK) return ret;
 
381
    return fort_GenerateRandom(random,sizeof (CI_RANDOM));
 
382
}
 
383
 
 
384
 
 
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,
 
388
 
 
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,
 
391
 
 
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,
 
394
 
 
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
 
397
};
 
398
 
 
399
/*
 
400
 * build a new Token exchange key using KEA.
 
401
 */
 
402
int
 
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 )
 
405
{
 
406
    FORTEZZAPrivateKey *key             = NULL;
 
407
    fortSlotEntry *      certEntry;
 
408
    unsigned char *      w              = NULL;
 
409
    SECItem              *q;
 
410
    SECStatus            rv;
 
411
    int                  ret,i;
 
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 */
 
418
    fortRaPrivatePtr     ra;
 
419
    FORTSkipjackKey      cover_key;
 
420
 
 
421
    unsigned char pad[10] = { 0x72, 0xf1, 0xa8, 0x7e, 0x92,
 
422
                              0x82, 0x41, 0x98, 0xab, 0x0b };
 
423
 
 
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;
 
429
 
 
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; 
 
435
 
 
436
    if (certEntry->exchangeKeyInformation) {
 
437
        q = &certEntry->exchangeKeyInformation->q;
 
438
    } else {
 
439
        q = &certEntry->signatureKeyInformation->q;
 
440
    }
 
441
 
 
442
    email = (PORT_Memcmp(Rb,Remail,sizeof(Rb)) == 0) ? PR_TRUE: PR_FALSE;
 
443
 
 
444
 
 
445
    /* load the common elements */
 
446
    Y.data = pY;
 
447
    Y.len = YSize;
 
448
    x.data = key->u.dh.privateValue.data;
 
449
    x.len = key->u.dh.privateValue.len;
 
450
 
 
451
    /* now initialize the rest of the values */
 
452
    if (flags == CI_INITIATOR_FLAG) {
 
453
        if (email) { 
 
454
            R.data = Y.data;
 
455
            R.len = Y.len;
 
456
        } else {
 
457
            R.data = Rb;
 
458
            R.len = sizeof(CI_RA);
 
459
        }
 
460
        ra = fort_LookupPrivR(swtoken,Ra);
 
461
        if (ra == NULL) {
 
462
            ret = CI_EXEC_FAIL;
 
463
            goto loser;
 
464
        }
 
465
        r.data = ra;
 
466
        r.len = sizeof(fortRaPrivate);
 
467
    } else {
 
468
        R.data = Ra;
 
469
        R.len = sizeof(CI_RA);
 
470
        if (email) {
 
471
            r.data = x.data;
 
472
            r.len = x.len;
 
473
        } else {
 
474
            ra = fort_LookupPrivR(swtoken,Rb);
 
475
            if (ra == NULL) {
 
476
                ret = CI_EXEC_FAIL;
 
477
                goto loser;
 
478
            }
 
479
            r.data = ra;
 
480
            r.len = sizeof(fortRaPrivate);
 
481
        }
 
482
    }
 
483
 
 
484
 
 
485
    if (!KEA_Verify(&Y,&key->u.dh.prime,q)) {
 
486
        ret = CI_EXEC_FAIL;
 
487
        goto loser;
 
488
    }
 
489
    if (!KEA_Verify(&R,&key->u.dh.prime,q)) {
 
490
        ret = CI_EXEC_FAIL;
 
491
        goto loser;
 
492
    }
 
493
 
 
494
    /* calculate the base key */
 
495
    rv = KEA_Derive(&key->u.dh.prime, &Y, &R, &r, &x, &wItem);
 
496
    if (rv != SECSuccess) {
 
497
        ret = CI_EXEC_FAIL;
 
498
        goto loser;
 
499
    }
 
500
 
 
501
    w = wItem.data;
 
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];
 
505
 
 
506
    ret = fort_skipjackWrap(cover_key,sizeof(FORTSkipjackKey),
 
507
                &w[sizeof(FORTSkipjackKey)],swtoken->keyReg[target].data);
 
508
    if (ret != CI_OK) goto loser;
 
509
 
 
510
    swtoken->keyReg[target].present = PR_TRUE;
 
511
 
 
512
    ret = CI_OK;
 
513
loser:
 
514
    if (w) PORT_Free(w);
 
515
    if (key) fort_DestroyPrivateKey(key);
 
516
    
 
517
    return ret;
 
518
}
 
519
 
 
520
 
 
521
/*
 
522
 * return the bytes of a certificate.
 
523
 */
 
524
int
 
525
MACI_GetCertificate(HSESSION hSession, int certIndex,
 
526
                                                 CI_CERTIFICATE CI_FAR cert)
 
527
{
 
528
    int len;
 
529
    int ret;
 
530
    fortSlotEntry *certEntry = NULL;
 
531
 
 
532
    if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
 
533
 
 
534
    certEntry = fort_GetCertEntry(swtoken->config_file,certIndex);
 
535
    if (certEntry == NULL) return CI_INV_CERT_INDEX;
 
536
 
 
537
    len = certEntry->certificateData.dataEncryptedWithKs.len;
 
538
    PORT_Memset(cert,0,sizeof(CI_CERTIFICATE));
 
539
    PORT_Memcpy(cert, certEntry->certificateData.dataEncryptedWithKs.data,len);
 
540
 
 
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],
 
544
                                                len,cert,cert);
 
545
}
 
546
 
 
547
 
 
548
/*
 
549
 * return out sofware configuration bytes. Those field not used by the PKCS #11
 
550
 * module may not be filled in exactly.
 
551
 */
 
552
#define NETSCAPE "Netscape Communications Corp    "
 
553
#define PRODUCT  "Netscape Software FORTEZZA Lib  "
 
554
#define SOFTWARE "Software FORTEZZA Implementation"
 
555
 
 
556
int
 
557
MACI_GetConfiguration(HSESSION hSession, CI_CONFIG_PTR config)
 
558
{
 
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;
 
573
    return CI_OK;
 
574
}
 
575
 
 
576
/*
 
577
 * return a list of all the personalities (up to the value 'EntryCount')
 
578
 */
 
579
int
 
580
MACI_GetPersonalityList(HSESSION hSession, int EntryCount, 
 
581
                                                CI_PERSON CI_FAR personList[])
 
582
{
 
583
    int count;
 
584
    int i,ret;
 
585
    FORTSWFile *config_file = NULL;
 
586
    unsigned char tmp[32];
 
587
 
 
588
    if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
 
589
    config_file = swtoken->config_file;
 
590
 
 
591
    /* search for the index */
 
592
    count= fort_GetCertCount(config_file);
 
593
 
 
594
    /* don't return more than the user asked for */
 
595
    if (count > EntryCount) count = EntryCount;
 
596
    for (i=0; i < count ;i ++) {
 
597
        int len, dataLen;
 
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));
 
605
        PORT_Memcpy(tmp, 
 
606
             config_file->slotEntries[i]->
 
607
                        certificateLabel.dataEncryptedWithKs.data,
 
608
                                                                len);
 
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,
 
613
                        tmp,tmp);
 
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;
 
623
    }
 
624
    return CI_OK;
 
625
}
 
626
 
 
627
 
 
628
/*
 
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.
 
631
 */
 
632
int
 
633
MACI_GetSessionID(HSESSION *session)
 
634
{
 
635
    *session = 1;
 
636
    return CI_OK;
 
637
}
 
638
 
 
639
/*
 
640
 * return the current card state.
 
641
 */
 
642
int
 
643
MACI_GetState(HSESSION hSession, CI_STATE_PTR state)
 
644
{
 
645
    int ret;
 
646
    if ((ret = fort_CardExists(swtoken,PR_FALSE)) != CI_OK) return ret;
 
647
    *state = fort_GetState(swtoken);
 
648
    return CI_OK;
 
649
}
 
650
 
 
651
/*
 
652
 * return the status. NOTE that KeyRegisterFlags and CertificateFlags are never
 
653
 * really used by the PKCS #11 module, so they are not implemented.
 
654
 */
 
655
int
 
656
MACI_GetStatus(HSESSION hSession, CI_STATUS_PTR status)
 
657
{
 
658
    int ret;
 
659
    FORTSWFile *config_file = NULL;
 
660
 
 
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));
 
678
 
 
679
    return CI_OK;
 
680
}
 
681
 
 
682
/*
 
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.
 
685
 */
 
686
int
 
687
MACI_GetTime(HSESSION hSession, CI_TIME CI_FAR time)
 
688
{
 
689
   return CI_BAD_CLOCK;
 
690
}
 
691
 
 
692
 
 
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);
 
696
 
 
697
/*
 
698
 * initialize the SW module, and return the number of slots we support (1).
 
699
 */
 
700
int
 
701
MACI_Initialize(int CI_FAR *count)
 
702
{
 
703
    char *filename = NULL;
 
704
    SECItem file;
 
705
    FORTSignedSWFile *decode_file = NULL;
 
706
    PRFileInfo info;
 
707
    /*PRFileDesc *fd = NULL;*/
 
708
    int fd = -1;
 
709
    PRStatus err;
 
710
    int ret = CI_OK;
 
711
    int fcount;
 
712
 
 
713
    file.data = NULL;
 
714
    file.len = 0;
 
715
 
 
716
    *count = 1;
 
717
 
 
718
    /* allocate swtoken structure */
 
719
    swtoken = PORT_ZNew(FORTSWToken);
 
720
    if (swtoken == NULL) return CI_OUT_OF_MEMORY;
 
721
 
 
722
    filename = (char *)fort_LookupFORTEZZAInitFile();
 
723
    if (filename == NULL) {
 
724
        ret = CI_BAD_READ;
 
725
        goto failed;
 
726
    }
 
727
    
 
728
    fd = open(filename,O_RDONLY|O_BINARY,0);
 
729
    if (fd < 0) {
 
730
        ret = CI_BAD_READ;
 
731
        goto failed;
 
732
    }
 
733
 
 
734
    err = local_getFileInfo(filename,&info);
 
735
    if ((err != 0) || (info.size == 0)) {
 
736
        ret = CI_BAD_READ;
 
737
        goto failed;
 
738
    }
 
739
 
 
740
    file.data = PORT_ZAlloc(info.size);
 
741
    if (file.data == NULL) {
 
742
        ret = CI_OUT_OF_MEMORY;
 
743
        goto failed;
 
744
    }
 
745
 
 
746
    fcount = read(fd,file.data,info.size);
 
747
    close(fd);  fd = -1;
 
748
    if (fcount != (int)info.size) {
 
749
        ret = CI_BAD_READ;
 
750
        goto failed;
 
751
    }
 
752
 
 
753
    file.len = fcount;
 
754
 
 
755
    decode_file = FORT_GetSWFile(&file);
 
756
    if (decode_file == NULL) {
 
757
        ret = CI_BAD_READ;
 
758
        goto failed;
 
759
    }
 
760
    swtoken->config_file = &decode_file->file;
 
761
 
 
762
    RNG_SystemInfoForRNG();
 
763
    RNG_FileForRNG(filename);
 
764
 
 
765
 
 
766
failed:
 
767
    if (filename) PORT_Free(filename);
 
768
    if (fd != -1) close(fd);
 
769
    if (file.data) PORT_Free(file.data);
 
770
    if (ret != CI_OK) {
 
771
        if (decode_file) FORT_DestroySignedSWFile(decode_file);
 
772
        if (swtoken) PORT_Free(swtoken);
 
773
        swtoken = NULL;
 
774
    }
 
775
 
 
776
    return CI_OK;
 
777
}
 
778
 
 
779
/*
 
780
 * load an IV from an external source. We technically should check it with the
 
781
 * key we received.
 
782
 */
 
783
int
 
784
MACI_LoadIV(HSESSION session, CI_IV CI_FAR iv)
 
785
{
 
786
    int ret;
 
787
 
 
788
    if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
 
789
    PORT_Memcpy(swtoken->IV,&iv[SKIPJACK_LEAF_SIZE],SKIPJACK_BLOCK_SIZE);
 
790
    return CI_OK;
 
791
}
 
792
 
 
793
/* implement token lock (should call PR_Monitor here) */
 
794
int
 
795
MACI_Lock(HSESSION session, int flags)
 
796
{
 
797
    int ret;
 
798
    if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
 
799
    swtoken->lock = 1;
 
800
 
 
801
    return CI_OK;
 
802
}
 
803
 
 
804
/* open a token. For software there isn't much to do that hasn't already been
 
805
 * done by initialize. */
 
806
int
 
807
MACI_Open(HSESSION session, unsigned int flags, int socket)
 
808
{
 
809
    if (socket != SOCKET_ID) return CI_NO_CARD;
 
810
    if (swtoken == NULL) return CI_NO_CARD;
 
811
    return CI_OK;
 
812
}
 
813
 
 
814
/*
 
815
 * Reset logs out the token...
 
816
 */
 
817
int
 
818
MACI_Reset(HSESSION session)
 
819
{
 
820
    if (swtoken) fort_Logout(swtoken);
 
821
    return CI_OK;
 
822
}
 
823
 
 
824
/*
 
825
 * restore and encrypt/decrypt state. NOTE: there is no error checking in this
 
826
 * or the save function.
 
827
 */
 
828
int
 
829
MACI_Restore(HSESSION session, int type, CI_SAVE_DATA CI_FAR data)
 
830
{
 
831
    int ret;
 
832
    if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
 
833
    PORT_Memcpy(swtoken->IV,data, sizeof (swtoken->IV));
 
834
    return CI_OK;
 
835
}
 
836
 
 
837
/*
 
838
 * save and encrypt/decrypt state. NOTE: there is no error checking in this
 
839
 * or the restore function.
 
840
 */
 
841
int
 
842
MACI_Save(HSESSION session, int type,CI_SAVE_DATA CI_FAR data)
 
843
{
 
844
    int ret;
 
845
    if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
 
846
    PORT_Memcpy(data,swtoken->IV, sizeof (swtoken->IV));
 
847
    return CI_OK;
 
848
}
 
849
 
 
850
/*
 
851
 * picks a token to operate against. In our case there can be only one.
 
852
 */
 
853
int
 
854
MACI_Select(HSESSION session, int socket)
 
855
{
 
856
    if (socket == SOCKET_ID) return CKR_OK;
 
857
    return CI_NO_CARD;
 
858
}
 
859
 
 
860
/*
 
861
 * set a register as the key to use for encrypt/decrypt operations.
 
862
 */
 
863
int
 
864
MACI_SetKey(HSESSION session, int index)
 
865
{
 
866
    int ret;
 
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;
 
869
 
 
870
    swtoken->key = index;
 
871
    return CI_OK;
 
872
}
 
873
 
 
874
/*
 
875
 * only CBC64 is supported. Keep setmode for compatibility */
 
876
int
 
877
MACI_SetMode(HSESSION session, int type, int mode)
 
878
{
 
879
    if (mode != CI_CBC64_MODE) return CI_INV_MODE;
 
880
    return CI_OK;
 
881
}
 
882
 
 
883
/* set the personality to use for sign/verify */
 
884
int
 
885
MACI_SetPersonality(HSESSION session, int cert)
 
886
{
 
887
    int ret;
 
888
    fortSlotEntry *certEntry = NULL;
 
889
 
 
890
    if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
 
891
 
 
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;
 
898
    return CI_OK;
 
899
}
 
900
 
 
901
 
 
902
/* DSA sign some data */
 
903
int
 
904
MACI_Sign(HSESSION session, CI_HASHVALUE CI_FAR hash, CI_SIGNATURE CI_FAR sig)
 
905
{
 
906
    FORTEZZAPrivateKey *key             = NULL;
 
907
    fortSlotEntry *      certEntry      = NULL;
 
908
    int                  ret            = CI_OK;
 
909
    SECStatus            rv;
 
910
    SECItem              signItem;
 
911
    SECItem              hashItem;
 
912
    unsigned char        random[DSA_SUBPRIME_LEN];
 
913
 
 
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;
 
918
 
 
919
    /* get the current personality */
 
920
    certEntry = fort_GetCertEntry(swtoken->config_file,swtoken->certIndex);
 
921
    if (certEntry == NULL) return CI_INV_CERT_INDEX;
 
922
 
 
923
    /* extract the private key from the personality */
 
924
    ret = CI_OK;
 
925
    key = fort_GetPrivKey(swtoken,fortezzaDSAKey,certEntry);
 
926
    if (key == NULL) {
 
927
        ret = CI_NO_X;
 
928
        goto loser;
 
929
    }
 
930
 
 
931
    /* create a random value for the signature */
 
932
    ret = fort_GenerateRandom(random, sizeof(random));
 
933
    if (ret != CI_OK) goto loser;
 
934
 
 
935
    /* Sign with that private key */
 
936
    signItem.data = sig;
 
937
    signItem.len  = DSA_SIGNATURE_LEN;
 
938
 
 
939
    hashItem.data = hash;
 
940
    hashItem.len  = SHA1_LENGTH;
 
941
 
 
942
    rv = DSA_SignDigestWithSeed(&key->u.dsa, &signItem, &hashItem, random);
 
943
    if (rv != SECSuccess) {
 
944
        ret = CI_EXEC_FAIL;
 
945
    }
 
946
 
 
947
    /* clean up */
 
948
loser:
 
949
    if (key != NULL) fort_DestroyPrivateKey(key);
 
950
 
 
951
    return ret;
 
952
}
 
953
 
 
954
/*
 
955
 * clean up after ourselves.
 
956
 */
 
957
int
 
958
MACI_Terminate(HSESSION session)
 
959
{
 
960
    if (swtoken == NULL) return CI_OUT_OF_MEMORY;
 
961
 
 
962
    /* clear all the keys */
 
963
    fort_Logout(swtoken);
 
964
    
 
965
    FORT_DestroySWFile(swtoken->config_file);
 
966
    PORT_Free(swtoken);
 
967
    swtoken = NULL;
 
968
    return CI_OK;
 
969
}
 
970
 
 
971
 
 
972
 
 
973
/* implement token unlock (should call PR_Monitor here) */
 
974
int
 
975
MACI_Unlock(HSESSION session)
 
976
{
 
977
    int ret;
 
978
    if ((ret = fort_CardExists(swtoken,PR_TRUE)) != CI_OK) return ret;
 
979
    swtoken->lock = 0;
 
980
    return CI_OK;
 
981
}
 
982
 
 
983
/*
 
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.
 
988
 */
 
989
int
 
990
MACI_UnwrapKey(HSESSION session, int wrapKey, int target, 
 
991
                                                CI_KEY CI_FAR keyData)
 
992
{
 
993
    int ret = CI_OK;
 
994
 
 
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;
 
1001
 
 
1002
    swtoken->keyReg[target].present = PR_TRUE;
 
1003
 
 
1004
loser:
 
1005
    return ret;
 
1006
}
 
1007
 
 
1008
/*
 
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.
 
1014
 */
 
1015
int
 
1016
MACI_WrapKey(HSESSION session, int wrapKey, int source, CI_KEY CI_FAR keyData)
 
1017
{
 
1018
    int ret;
 
1019
 
 
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);
 
1025
 
 
1026
    return ret;
 
1027
}
 
1028