~ubuntu-branches/ubuntu/trusty/xulrunner/trusty

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/softoken/pkcs11u.c

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2008-08-25 13:04:18 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825130418-ck1i2ms384tzb9m0
Tags: 1.8.1.16+nobinonly-0ubuntu1
* New upstream release (taken from upstream CVS), LP: #254618.
* Fix MFSA 2008-35, MFSA 2008-34, MFSA 2008-33, MFSA 2008-32, MFSA 2008-31,
  MFSA 2008-30, MFSA 2008-29, MFSA 2008-28, MFSA 2008-27, MFSA 2008-25,
  MFSA 2008-24, MFSA 2008-23, MFSA 2008-22, MFSA 2008-21, MFSA 2008-26 also
  known as CVE-2008-2933, CVE-2008-2785, CVE-2008-2811, CVE-2008-2810,
  CVE-2008-2809, CVE-2008-2808, CVE-2008-2807, CVE-2008-2806, CVE-2008-2805,
  CVE-2008-2803, CVE-2008-2802, CVE-2008-2801, CVE-2008-2800, CVE-2008-2798.
* Drop 89_bz419350_attachment_306066 patch, merged upstream.
* Bump Standards-Version to 3.8.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
4
 * The contents of this file are subject to the Mozilla Public License Version
 
5
 * 1.1 (the "License"); you may not use this file except in compliance with
 
6
 * the License. You may obtain a copy of the License at
 
7
 * http://www.mozilla.org/MPL/
 
8
 *
 
9
 * Software distributed under the License is distributed on an "AS IS" basis,
 
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
11
 * for the specific language governing rights and limitations under the
 
12
 * License.
 
13
 *
 
14
 * The Original Code is the Netscape security libraries.
 
15
 *
 
16
 * The Initial Developer of the Original Code is
 
17
 * Netscape Communications Corporation.
 
18
 * Portions created by the Initial Developer are Copyright (C) 1994-2000
 
19
 * the Initial Developer. All Rights Reserved.
 
20
 *
 
21
 * Contributor(s):
 
22
 *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
 
23
 *
 
24
 * Alternatively, the contents of this file may be used under the terms of
 
25
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
26
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
27
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
28
 * of those above. If you wish to allow use of your version of this file only
 
29
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
30
 * use your version of this file under the terms of the MPL, indicate your
 
31
 * decision by deleting the provisions above and replace them with the notice
 
32
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
33
 * the provisions above, a recipient may use your version of this file under
 
34
 * the terms of any one of the MPL, the GPL or the LGPL.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
/*
 
38
 * Internal PKCS #11 functions. Should only be called by pkcs11.c
 
39
 */
 
40
#include "pkcs11.h"
 
41
#include "pkcs11i.h"
 
42
#include "pcertt.h"
 
43
#include "lowkeyi.h"
 
44
#include "pcert.h"
 
45
#include "secasn1.h"
 
46
#include "blapi.h"
 
47
#include "secerr.h"
 
48
#include "prnetdb.h" /* for PR_ntohl */
 
49
 
 
50
/*
 
51
 * ******************** Attribute Utilities *******************************
 
52
 */
 
53
 
 
54
/*
 
55
 * create a new attribute with type, value, and length. Space is allocated
 
56
 * to hold value.
 
57
 */
 
58
static SFTKAttribute *
 
59
sftk_NewAttribute(SFTKObject *object,
 
60
        CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value, CK_ULONG len)
 
61
{
 
62
    SFTKAttribute *attribute;
 
63
 
 
64
    SFTKSessionObject *so = sftk_narrowToSessionObject(object);
 
65
    int index;
 
66
 
 
67
    if (so == NULL)  {
 
68
        /* allocate new attribute in a buffer */
 
69
        PORT_Assert(0);
 
70
        return NULL;
 
71
    }
 
72
    /* 
 
73
     * We attempt to keep down contention on Malloc and Arena locks by
 
74
     * limiting the number of these calls on high traversed paths. This
 
75
     * is done for attributes by 'allocating' them from a pool already
 
76
     * allocated by the parent object.
 
77
     */
 
78
    PZ_Lock(so->attributeLock);
 
79
    index = so->nextAttr++;
 
80
    PZ_Unlock(so->attributeLock);
 
81
    PORT_Assert(index < MAX_OBJS_ATTRS);
 
82
    if (index >= MAX_OBJS_ATTRS) return NULL;
 
83
 
 
84
    attribute = &so->attrList[index];
 
85
    attribute->attrib.type = type;
 
86
    attribute->freeAttr = PR_FALSE;
 
87
    attribute->freeData = PR_FALSE;
 
88
    if (value) {
 
89
        if (len <= ATTR_SPACE) {
 
90
            attribute->attrib.pValue = attribute->space;
 
91
        } else {
 
92
            attribute->attrib.pValue = PORT_Alloc(len);
 
93
            attribute->freeData = PR_TRUE;
 
94
        }
 
95
        if (attribute->attrib.pValue == NULL) {
 
96
            return NULL;
 
97
        }
 
98
        PORT_Memcpy(attribute->attrib.pValue,value,len);
 
99
        attribute->attrib.ulValueLen = len;
 
100
    } else {
 
101
        attribute->attrib.pValue = NULL;
 
102
        attribute->attrib.ulValueLen = 0;
 
103
    }
 
104
    attribute->attrib.type = type;
 
105
    attribute->handle = type;
 
106
    attribute->next = attribute->prev = NULL;
 
107
    return attribute;
 
108
}
 
109
 
 
110
static SFTKAttribute *
 
111
sftk_NewTokenAttribute(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value,
 
112
                                                CK_ULONG len, PRBool copy)
 
113
{
 
114
    SFTKAttribute *attribute;
 
115
 
 
116
    attribute = (SFTKAttribute*)PORT_Alloc(sizeof(SFTKAttribute));
 
117
 
 
118
    if (attribute == NULL) return NULL;
 
119
    attribute->attrib.type = type;
 
120
    attribute->handle = type;
 
121
    attribute->next = attribute->prev = NULL;
 
122
    attribute->freeAttr = PR_TRUE;
 
123
    attribute->freeData = PR_FALSE;
 
124
    attribute->attrib.type = type;
 
125
    if (!copy) {
 
126
        attribute->attrib.pValue = value;
 
127
        attribute->attrib.ulValueLen = len;
 
128
        return attribute;
 
129
    }
 
130
 
 
131
    if (value) {
 
132
        if (len <= ATTR_SPACE) {
 
133
            attribute->attrib.pValue = attribute->space;
 
134
        } else {
 
135
            attribute->attrib.pValue = PORT_Alloc(len);
 
136
            attribute->freeData = PR_TRUE;
 
137
        }
 
138
        if (attribute->attrib.pValue == NULL) {
 
139
            PORT_Free(attribute);
 
140
            return NULL;
 
141
        }
 
142
        PORT_Memcpy(attribute->attrib.pValue,value,len);
 
143
        attribute->attrib.ulValueLen = len;
 
144
    } else {
 
145
        attribute->attrib.pValue = NULL;
 
146
        attribute->attrib.ulValueLen = 0;
 
147
    }
 
148
    return attribute;
 
149
}
 
150
 
 
151
static SFTKAttribute *
 
152
sftk_NewTokenAttributeSigned(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value, 
 
153
                                                CK_ULONG len, PRBool copy)
 
154
{
 
155
    unsigned char * dval = (unsigned char *)value;
 
156
    if (*dval == 0) {
 
157
        dval++;
 
158
        len--;
 
159
    }
 
160
    return sftk_NewTokenAttribute(type,dval,len,copy);
 
161
}
 
162
 
 
163
/*
 
164
 * Free up all the memory associated with an attribute. Reference count
 
165
 * must be zero to call this.
 
166
 */
 
167
static void
 
168
sftk_DestroyAttribute(SFTKAttribute *attribute)
 
169
{
 
170
    if (attribute->freeData) {
 
171
        if (attribute->attrib.pValue) {
 
172
            /* clear out the data in the attribute value... it may have been
 
173
             * sensitive data */
 
174
            PORT_Memset(attribute->attrib.pValue, 0,
 
175
                                                attribute->attrib.ulValueLen);
 
176
        }
 
177
        PORT_Free(attribute->attrib.pValue);
 
178
    }
 
179
    PORT_Free(attribute);
 
180
}
 
181
 
 
182
/*
 
183
 * release a reference to an attribute structure
 
184
 */
 
185
void
 
186
sftk_FreeAttribute(SFTKAttribute *attribute)
 
187
{
 
188
    if (attribute->freeAttr) {
 
189
        sftk_DestroyAttribute(attribute);
 
190
        return;
 
191
    }
 
192
}
 
193
 
 
194
#define SFTK_DEF_ATTRIBUTE(value,len) \
 
195
   { NULL, NULL, PR_FALSE, PR_FALSE, 0, { 0, value, len } }
 
196
 
 
197
#define SFTK_CLONE_ATTR(type, staticAttr) \
 
198
    sftk_NewTokenAttribute( type, staticAttr.attrib.pValue, \
 
199
    staticAttr.attrib.ulValueLen, PR_FALSE)
 
200
 
 
201
CK_BBOOL sftk_staticTrueValue = CK_TRUE;
 
202
CK_BBOOL sftk_staticFalseValue = CK_FALSE;
 
203
static const SFTKAttribute sftk_StaticTrueAttr = 
 
204
  SFTK_DEF_ATTRIBUTE(&sftk_staticTrueValue,sizeof(sftk_staticTrueValue));
 
205
static const SFTKAttribute sftk_StaticFalseAttr = 
 
206
  SFTK_DEF_ATTRIBUTE(&sftk_staticFalseValue,sizeof(sftk_staticFalseValue));
 
207
static const SFTKAttribute sftk_StaticNullAttr = SFTK_DEF_ATTRIBUTE(NULL,0);
 
208
char sftk_StaticOneValue = 1;
 
209
static const SFTKAttribute sftk_StaticOneAttr = 
 
210
  SFTK_DEF_ATTRIBUTE(&sftk_StaticOneValue,sizeof(sftk_StaticOneValue));
 
211
 
 
212
CK_CERTIFICATE_TYPE sftk_staticX509Value = CKC_X_509;
 
213
static const SFTKAttribute sftk_StaticX509Attr =
 
214
  SFTK_DEF_ATTRIBUTE(&sftk_staticX509Value, sizeof(sftk_staticX509Value));
 
215
CK_TRUST sftk_staticTrustedValue = CKT_NETSCAPE_TRUSTED;
 
216
CK_TRUST sftk_staticTrustedDelegatorValue = CKT_NETSCAPE_TRUSTED_DELEGATOR;
 
217
CK_TRUST sftk_staticValidDelegatorValue = CKT_NETSCAPE_VALID_DELEGATOR;
 
218
CK_TRUST sftk_staticUnTrustedValue = CKT_NETSCAPE_UNTRUSTED;
 
219
CK_TRUST sftk_staticTrustUnknownValue = CKT_NETSCAPE_TRUST_UNKNOWN;
 
220
CK_TRUST sftk_staticValidPeerValue = CKT_NETSCAPE_VALID;
 
221
CK_TRUST sftk_staticMustVerifyValue = CKT_NETSCAPE_MUST_VERIFY;
 
222
static const SFTKAttribute sftk_StaticTrustedAttr =
 
223
  SFTK_DEF_ATTRIBUTE(&sftk_staticTrustedValue,
 
224
                                sizeof(sftk_staticTrustedValue));
 
225
static const SFTKAttribute sftk_StaticTrustedDelegatorAttr =
 
226
  SFTK_DEF_ATTRIBUTE(&sftk_staticTrustedDelegatorValue,
 
227
                                sizeof(sftk_staticTrustedDelegatorValue));
 
228
static const SFTKAttribute sftk_StaticValidDelegatorAttr =
 
229
  SFTK_DEF_ATTRIBUTE(&sftk_staticValidDelegatorValue,
 
230
                                sizeof(sftk_staticValidDelegatorValue));
 
231
static const SFTKAttribute sftk_StaticUnTrustedAttr =
 
232
  SFTK_DEF_ATTRIBUTE(&sftk_staticUnTrustedValue,
 
233
                                sizeof(sftk_staticUnTrustedValue));
 
234
static const SFTKAttribute sftk_StaticTrustUnknownAttr =
 
235
  SFTK_DEF_ATTRIBUTE(&sftk_staticTrustUnknownValue,
 
236
                                sizeof(sftk_staticTrustUnknownValue));
 
237
static const SFTKAttribute sftk_StaticValidPeerAttr =
 
238
  SFTK_DEF_ATTRIBUTE(&sftk_staticValidPeerValue,
 
239
                                sizeof(sftk_staticValidPeerValue));
 
240
static const SFTKAttribute sftk_StaticMustVerifyAttr =
 
241
  SFTK_DEF_ATTRIBUTE(&sftk_staticMustVerifyValue,
 
242
                                sizeof(sftk_staticMustVerifyValue));
 
243
 
 
244
/*
 
245
 * helper functions which get the database and call the underlying 
 
246
 * low level database function.
 
247
 */
 
248
static char *
 
249
sftk_FindKeyNicknameByPublicKey(SFTKSlot *slot, SECItem *dbKey)
 
250
{
 
251
    NSSLOWKEYDBHandle *keyHandle;
 
252
    char * label;
 
253
 
 
254
    keyHandle = sftk_getKeyDB(slot);
 
255
    if (!keyHandle) {
 
256
        return NULL;
 
257
    }
 
258
 
 
259
    label = nsslowkey_FindKeyNicknameByPublicKey(keyHandle, dbKey, 
 
260
                                                 slot->password);
 
261
    sftk_freeKeyDB(keyHandle);
 
262
    return label;
 
263
}
 
264
 
 
265
 
 
266
NSSLOWKEYPrivateKey *
 
267
sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey)
 
268
{
 
269
    NSSLOWKEYPrivateKey *privKey;
 
270
    NSSLOWKEYDBHandle   *keyHandle;
 
271
 
 
272
    keyHandle = sftk_getKeyDB(slot);
 
273
    if (keyHandle == NULL) {
 
274
        return NULL;
 
275
    }
 
276
    privKey = nsslowkey_FindKeyByPublicKey(keyHandle, dbKey, slot->password);
 
277
    sftk_freeKeyDB(keyHandle);
 
278
    if (privKey == NULL) {
 
279
        return NULL;
 
280
    }
 
281
    return privKey;
 
282
}
 
283
 
 
284
static certDBEntrySMime *
 
285
sftk_getSMime(SFTKTokenObject *object)
 
286
{
 
287
    certDBEntrySMime *entry;
 
288
    NSSLOWCERTCertDBHandle *certHandle;
 
289
 
 
290
    if (object->obj.objclass != CKO_NETSCAPE_SMIME) {
 
291
        return NULL;
 
292
    }
 
293
    if (object->obj.objectInfo) {
 
294
        return (certDBEntrySMime *)object->obj.objectInfo;
 
295
    }
 
296
 
 
297
    certHandle = sftk_getCertDB(object->obj.slot);
 
298
    if (!certHandle) {
 
299
        return NULL;
 
300
    }
 
301
    entry = nsslowcert_ReadDBSMimeEntry(certHandle, (char *)object->dbKey.data);
 
302
    object->obj.objectInfo = (void *)entry;
 
303
    object->obj.infoFree = (SFTKFree) nsslowcert_DestroyDBEntry;
 
304
    sftk_freeCertDB(certHandle);
 
305
    return entry;
 
306
}
 
307
 
 
308
static certDBEntryRevocation *
 
309
sftk_getCrl(SFTKTokenObject *object)
 
310
{
 
311
    certDBEntryRevocation *crl;
 
312
    PRBool isKrl;
 
313
    NSSLOWCERTCertDBHandle *certHandle;
 
314
 
 
315
    if (object->obj.objclass != CKO_NETSCAPE_CRL) {
 
316
        return NULL;
 
317
    }
 
318
    if (object->obj.objectInfo) {
 
319
        return (certDBEntryRevocation *)object->obj.objectInfo;
 
320
    }
 
321
 
 
322
    isKrl = (PRBool) (object->obj.handle == SFTK_TOKEN_KRL_HANDLE);
 
323
    certHandle = sftk_getCertDB(object->obj.slot);
 
324
    if (!certHandle) {
 
325
        return NULL;
 
326
    }
 
327
 
 
328
    crl = nsslowcert_FindCrlByKey(certHandle, &object->dbKey, isKrl);
 
329
    object->obj.objectInfo = (void *)crl;
 
330
    object->obj.infoFree = (SFTKFree) nsslowcert_DestroyDBEntry;
 
331
    sftk_freeCertDB(certHandle);
 
332
    return crl;
 
333
}
 
334
 
 
335
static NSSLOWCERTCertificate *
 
336
sftk_getCert(SFTKTokenObject *object, NSSLOWCERTCertDBHandle *certHandle)
 
337
{
 
338
    NSSLOWCERTCertificate *cert;
 
339
    CK_OBJECT_CLASS objClass = object->obj.objclass;
 
340
 
 
341
    if ((objClass != CKO_CERTIFICATE) && (objClass != CKO_NETSCAPE_TRUST)) {
 
342
        return NULL;
 
343
    }
 
344
    if (objClass == CKO_CERTIFICATE && object->obj.objectInfo) {
 
345
        return (NSSLOWCERTCertificate *)object->obj.objectInfo;
 
346
    }
 
347
    cert = nsslowcert_FindCertByKey(certHandle, &object->dbKey);
 
348
    if (objClass == CKO_CERTIFICATE) {
 
349
        object->obj.objectInfo = (void *)cert;
 
350
        object->obj.infoFree = (SFTKFree) nsslowcert_DestroyCertificate ;
 
351
    }
 
352
    return cert;
 
353
}
 
354
 
 
355
static NSSLOWCERTTrust *
 
356
sftk_getTrust(SFTKTokenObject *object)
 
357
{
 
358
    NSSLOWCERTTrust *trust;
 
359
    NSSLOWCERTCertDBHandle *certHandle;
 
360
 
 
361
    if (object->obj.objclass != CKO_NETSCAPE_TRUST) {
 
362
        return NULL;
 
363
    }
 
364
    if (object->obj.objectInfo) {
 
365
        return (NSSLOWCERTTrust *)object->obj.objectInfo;
 
366
    }
 
367
    certHandle = sftk_getCertDB(object->obj.slot);
 
368
    if (!certHandle) {
 
369
        return NULL;
 
370
    }
 
371
    trust = nsslowcert_FindTrustByKey(certHandle, &object->dbKey);
 
372
    object->obj.objectInfo = (void *)trust;
 
373
    object->obj.infoFree = (SFTKFree) nsslowcert_DestroyTrust ;
 
374
    sftk_freeCertDB(certHandle);
 
375
    return trust;
 
376
}
 
377
 
 
378
static NSSLOWKEYPublicKey *
 
379
sftk_GetPublicKey(SFTKTokenObject *object)
 
380
{
 
381
    NSSLOWKEYPublicKey *pubKey;
 
382
    NSSLOWKEYPrivateKey *privKey;
 
383
 
 
384
    if (object->obj.objclass != CKO_PUBLIC_KEY) {
 
385
        return NULL;
 
386
    }
 
387
    if (object->obj.objectInfo) {
 
388
        return (NSSLOWKEYPublicKey *)object->obj.objectInfo;
 
389
    }
 
390
    privKey = sftk_FindKeyByPublicKey(object->obj.slot, &object->dbKey);
 
391
    if (privKey == NULL) {
 
392
        return NULL;
 
393
    }
 
394
    pubKey = nsslowkey_ConvertToPublicKey(privKey);
 
395
    nsslowkey_DestroyPrivateKey(privKey);
 
396
    object->obj.objectInfo = (void *) pubKey;
 
397
    object->obj.infoFree = (SFTKFree) nsslowkey_DestroyPublicKey ;
 
398
    return pubKey;
 
399
}
 
400
 
 
401
/*
 
402
 * we need two versions of sftk_GetPrivateKey. One version that takes the 
 
403
 * DB handle so we can pass the handle we have already acquired in,
 
404
 *  rather than going through the 'getKeyDB' code again, 
 
405
 *  which may fail the second time and another which just aquires
 
406
 *  the key handle from the slot (where we don't already have a key handle.
 
407
 * This version does the former.
 
408
 */
 
409
static NSSLOWKEYPrivateKey *
 
410
sftk_GetPrivateKeyWithDB(SFTKTokenObject *object, NSSLOWKEYDBHandle *keyHandle)
 
411
{
 
412
    NSSLOWKEYPrivateKey *privKey;
 
413
 
 
414
    if ((object->obj.objclass != CKO_PRIVATE_KEY) && 
 
415
                        (object->obj.objclass != CKO_SECRET_KEY)) {
 
416
        return NULL;
 
417
    }
 
418
    if (object->obj.objectInfo) {
 
419
        return (NSSLOWKEYPrivateKey *)object->obj.objectInfo;
 
420
    }
 
421
    privKey = nsslowkey_FindKeyByPublicKey(keyHandle, &object->dbKey,
 
422
                                           object->obj.slot->password);
 
423
    if (privKey == NULL) {
 
424
        return NULL;
 
425
    }
 
426
    object->obj.objectInfo = (void *) privKey;
 
427
    object->obj.infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey ;
 
428
    return privKey;
 
429
}
 
430
 
 
431
/* this version does the latter */
 
432
static NSSLOWKEYPrivateKey *
 
433
sftk_GetPrivateKey(SFTKTokenObject *object)
 
434
{
 
435
    NSSLOWKEYDBHandle *keyHandle;
 
436
    NSSLOWKEYPrivateKey *privKey;
 
437
 
 
438
    keyHandle = sftk_getKeyDB(object->obj.slot);
 
439
    if (!keyHandle) {
 
440
        return NULL;
 
441
    }
 
442
    privKey = sftk_GetPrivateKeyWithDB(object, keyHandle);
 
443
    sftk_freeKeyDB(keyHandle);
 
444
    return privKey;
 
445
}
 
446
 
 
447
/* sftk_GetPubItem returns data associated with the public key.
 
448
 * one only needs to free the public key. This comment is here
 
449
 * because this sematic would be non-obvious otherwise. All callers
 
450
 * should include this comment.
 
451
 */
 
452
static SECItem *
 
453
sftk_GetPubItem(NSSLOWKEYPublicKey *pubKey) {
 
454
    SECItem *pubItem = NULL;
 
455
    /* get value to compare from the cert's public key */
 
456
    switch ( pubKey->keyType ) {
 
457
    case NSSLOWKEYRSAKey:
 
458
            pubItem = &pubKey->u.rsa.modulus;
 
459
            break;
 
460
    case NSSLOWKEYDSAKey:
 
461
            pubItem = &pubKey->u.dsa.publicValue;
 
462
            break;
 
463
    case NSSLOWKEYDHKey:
 
464
            pubItem = &pubKey->u.dh.publicValue;
 
465
            break;
 
466
#ifdef NSS_ENABLE_ECC
 
467
    case NSSLOWKEYECKey:
 
468
            pubItem = &pubKey->u.ec.publicValue;
 
469
            break;
 
470
#endif /* NSS_ENABLE_ECC */
 
471
    default:
 
472
            break;
 
473
    }
 
474
    return pubItem;
 
475
}
 
476
 
 
477
static const SEC_ASN1Template sftk_SerialTemplate[] = {
 
478
    { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertificate,serialNumber) },
 
479
    { 0 }
 
480
};
 
481
 
 
482
static SFTKAttribute *
 
483
sftk_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
 
484
{
 
485
    unsigned char hash[SHA1_LENGTH];
 
486
    CK_KEY_TYPE keyType = CKK_RSA;
 
487
 
 
488
    switch (type) {
 
489
    case CKA_KEY_TYPE:
 
490
        return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
 
491
    case CKA_ID:
 
492
        SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
 
493
        return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
 
494
    case CKA_DERIVE:
 
495
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
496
    case CKA_ENCRYPT:
 
497
    case CKA_VERIFY:
 
498
    case CKA_VERIFY_RECOVER:
 
499
    case CKA_WRAP:
 
500
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
501
    case CKA_MODULUS:
 
502
        return sftk_NewTokenAttributeSigned(type,key->u.rsa.modulus.data,
 
503
                                        key->u.rsa.modulus.len, PR_FALSE);
 
504
    case CKA_PUBLIC_EXPONENT:
 
505
        return sftk_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data,
 
506
                                key->u.rsa.publicExponent.len, PR_FALSE);
 
507
    default:
 
508
        break;
 
509
    }
 
510
    return NULL;
 
511
}
 
512
 
 
513
static SFTKAttribute *
 
514
sftk_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
 
515
{
 
516
    unsigned char hash[SHA1_LENGTH];
 
517
    CK_KEY_TYPE keyType = CKK_DSA;
 
518
 
 
519
    switch (type) {
 
520
    case CKA_KEY_TYPE:
 
521
        return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
 
522
    case CKA_ID:
 
523
        SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
 
524
                                                key->u.dsa.publicValue.len);
 
525
        return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
 
526
    case CKA_DERIVE:
 
527
    case CKA_ENCRYPT:
 
528
    case CKA_VERIFY_RECOVER:
 
529
    case CKA_WRAP:
 
530
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
531
    case CKA_VERIFY:
 
532
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
533
    case CKA_VALUE:
 
534
        return sftk_NewTokenAttributeSigned(type,key->u.dsa.publicValue.data,
 
535
                                        key->u.dsa.publicValue.len, PR_FALSE);
 
536
    case CKA_PRIME:
 
537
        return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data,
 
538
                                        key->u.dsa.params.prime.len, PR_FALSE);
 
539
    case CKA_SUBPRIME:
 
540
        return sftk_NewTokenAttributeSigned(type,
 
541
                                key->u.dsa.params.subPrime.data,
 
542
                                key->u.dsa.params.subPrime.len, PR_FALSE);
 
543
    case CKA_BASE:
 
544
        return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.base.data,
 
545
                                        key->u.dsa.params.base.len, PR_FALSE);
 
546
    default:
 
547
        break;
 
548
    }
 
549
    return NULL;
 
550
}
 
551
 
 
552
static SFTKAttribute *
 
553
sftk_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
 
554
{
 
555
    unsigned char hash[SHA1_LENGTH];
 
556
    CK_KEY_TYPE keyType = CKK_DH;
 
557
 
 
558
    switch (type) {
 
559
    case CKA_KEY_TYPE:
 
560
        return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
 
561
    case CKA_ID:
 
562
        SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
 
563
        return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
 
564
    case CKA_DERIVE:
 
565
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
566
    case CKA_ENCRYPT:
 
567
    case CKA_VERIFY:
 
568
    case CKA_VERIFY_RECOVER:
 
569
    case CKA_WRAP:
 
570
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
571
    case CKA_VALUE:
 
572
        return sftk_NewTokenAttributeSigned(type,key->u.dh.publicValue.data,
 
573
                                        key->u.dh.publicValue.len, PR_FALSE);
 
574
    case CKA_PRIME:
 
575
        return sftk_NewTokenAttributeSigned(type,key->u.dh.prime.data,
 
576
                                        key->u.dh.prime.len, PR_FALSE);
 
577
    case CKA_BASE:
 
578
        return sftk_NewTokenAttributeSigned(type,key->u.dh.base.data,
 
579
                                        key->u.dh.base.len, PR_FALSE);
 
580
    default:
 
581
        break;
 
582
    }
 
583
    return NULL;
 
584
}
 
585
 
 
586
#ifdef NSS_ENABLE_ECC
 
587
static SFTKAttribute *
 
588
sftk_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
 
589
{
 
590
    unsigned char hash[SHA1_LENGTH];
 
591
    CK_KEY_TYPE keyType = CKK_EC;
 
592
 
 
593
    switch (type) {
 
594
    case CKA_KEY_TYPE:
 
595
        return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
 
596
    case CKA_ID:
 
597
        SHA1_HashBuf(hash, key->u.ec.publicValue.data,
 
598
                     key->u.ec.publicValue.len);
 
599
        return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
 
600
    case CKA_DERIVE:
 
601
    case CKA_VERIFY:
 
602
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
603
    case CKA_ENCRYPT:
 
604
    case CKA_VERIFY_RECOVER:
 
605
    case CKA_WRAP:
 
606
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
607
    case CKA_EC_PARAMS:
 
608
        /* XXX Why is the last arg PR_FALSE? */
 
609
        return sftk_NewTokenAttributeSigned(type,
 
610
                                        key->u.ec.ecParams.DEREncoding.data,
 
611
                                        key->u.ec.ecParams.DEREncoding.len,
 
612
                                        PR_FALSE);
 
613
    case CKA_EC_POINT:
 
614
        /* XXX Why is the last arg PR_FALSE? */
 
615
        return sftk_NewTokenAttributeSigned(type,key->u.ec.publicValue.data,
 
616
                                        key->u.ec.publicValue.len, PR_FALSE);
 
617
    default:
 
618
        break;
 
619
    }
 
620
    return NULL;
 
621
}
 
622
#endif /* NSS_ENABLE_ECC */
 
623
 
 
624
 
 
625
static SFTKAttribute *
 
626
sftk_FindPublicKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
 
627
{
 
628
    NSSLOWKEYPublicKey   *key;
 
629
    SFTKAttribute *att = NULL;
 
630
    char *label;
 
631
 
 
632
    switch (type) {
 
633
    case CKA_PRIVATE:
 
634
    case CKA_SENSITIVE:
 
635
    case CKA_ALWAYS_SENSITIVE:
 
636
    case CKA_NEVER_EXTRACTABLE:
 
637
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
638
    case CKA_MODIFIABLE:
 
639
    case CKA_EXTRACTABLE:
 
640
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
641
    case CKA_LABEL:
 
642
        label = sftk_FindKeyNicknameByPublicKey(object->obj.slot,
 
643
                                                &object->dbKey);
 
644
        if (label == NULL) {
 
645
           return SFTK_CLONE_ATTR(type,sftk_StaticOneAttr);
 
646
        }
 
647
        att = sftk_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE);
 
648
        PORT_Free(label);
 
649
        return att;
 
650
    default:
 
651
        break;
 
652
    }
 
653
 
 
654
    key = sftk_GetPublicKey(object);
 
655
    if (key == NULL) {
 
656
        return NULL;
 
657
    }
 
658
 
 
659
    switch (key->keyType) {
 
660
    case NSSLOWKEYRSAKey:
 
661
        return sftk_FindRSAPublicKeyAttribute(key,type);
 
662
    case NSSLOWKEYDSAKey:
 
663
        return sftk_FindDSAPublicKeyAttribute(key,type);
 
664
    case NSSLOWKEYDHKey:
 
665
        return sftk_FindDHPublicKeyAttribute(key,type);
 
666
#ifdef NSS_ENABLE_ECC
 
667
    case NSSLOWKEYECKey:
 
668
        return sftk_FindECPublicKeyAttribute(key,type);
 
669
#endif /* NSS_ENABLE_ECC */
 
670
    default:
 
671
        break;
 
672
    }
 
673
 
 
674
    return NULL;
 
675
}
 
676
 
 
677
static SFTKAttribute *
 
678
sftk_FindSecretKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
 
679
{
 
680
    NSSLOWKEYPrivateKey  *key;
 
681
    char *label;
 
682
    unsigned char *keyString;
 
683
    SFTKAttribute *att;
 
684
    int keyTypeLen;
 
685
    CK_ULONG keyLen;
 
686
    CK_KEY_TYPE keyType;
 
687
    PRUint32 keyTypeStorage;
 
688
 
 
689
    switch (type) {
 
690
    case CKA_PRIVATE:
 
691
    case CKA_SENSITIVE:
 
692
    case CKA_ALWAYS_SENSITIVE:
 
693
    case CKA_EXTRACTABLE:
 
694
    case CKA_DERIVE:
 
695
    case CKA_ENCRYPT:
 
696
    case CKA_DECRYPT:
 
697
    case CKA_SIGN:
 
698
    case CKA_VERIFY:
 
699
    case CKA_WRAP:
 
700
    case CKA_UNWRAP:
 
701
    case CKA_MODIFIABLE:
 
702
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
703
    case CKA_NEVER_EXTRACTABLE:
 
704
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
705
    case CKA_LABEL:
 
706
        label = sftk_FindKeyNicknameByPublicKey(object->obj.slot,
 
707
                                                &object->dbKey);
 
708
        if (label == NULL) {
 
709
           return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
 
710
        }
 
711
        att = sftk_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE);
 
712
        PORT_Free(label);
 
713
        return att;
 
714
    case CKA_KEY_TYPE:
 
715
    case CKA_VALUE_LEN:
 
716
    case CKA_VALUE:
 
717
        break;
 
718
    default:
 
719
        return NULL;
 
720
    }
 
721
 
 
722
    key = sftk_GetPrivateKey(object);
 
723
    if (key == NULL) {
 
724
        return NULL;
 
725
    }
 
726
    switch (type) {
 
727
    case CKA_KEY_TYPE:
 
728
        /* handle legacy databases. In legacy databases key_type was stored
 
729
         * in host order, with any leading zeros stripped off. Only key types
 
730
         * under 0x1f (AES) were stored. We assume that any values which are
 
731
         * either 1 byte long (big endian), or have byte[0] between 0 and 
 
732
         * 0x7f and bytes[1]-bytes[3] equal to '0' (little endian). All other
 
733
         * values are assumed to be from the new database, which is always 4
 
734
         * bytes in network order */
 
735
        keyType=0;
 
736
        keyString = key->u.rsa.coefficient.data;
 
737
        keyTypeLen = key->u.rsa.coefficient.len;
 
738
 
 
739
 
 
740
        /*
 
741
         * Because of various endian and word lengths The database may have
 
742
         * stored the keyType value in one of the following formats:
 
743
         *   (kt) <= 0x1f 
 
744
         *                                   length data
 
745
         * Big Endian,     pre-3.9, all lengths: 1  (kt)
 
746
         * Little Endian,  pre-3.9, 32 bits:     4  (kt) 0  0  0
 
747
         * Little Endian,  pre-3.9, 64 bits:     8  (kt) 0  0  0   0  0  0  0
 
748
         * All platforms,      3.9, 32 bits:     4    0  0  0 (kt)
 
749
         * Big Endian,         3.9, 64 bits:     8    0  0  0 (kt) 0  0  0  0
 
750
         * Little  Endian,     3.9, 64 bits:     8    0  0  0  0   0  0  0 (kt)
 
751
         * All platforms, >= 3.9.1, all lengths: 4   (a) k1 k2 k3
 
752
         * where (a) is 0 or >= 0x80. currently (a) can only be 0.
 
753
         */
 
754
        /*
 
755
         * this key was written on a 64 bit platform with a using NSS 3.9
 
756
         * or earlier. Reduce the 64 bit possibilities above. We were are
 
757
         * through, we will only have:
 
758
         * 
 
759
         * Big Endian,     pre-3.9, all lengths: 1  (kt)
 
760
         * Little Endian,  pre-3.9, all lengths: 4  (kt) 0  0  0
 
761
         * All platforms,      3.9, all lengths: 4    0  0  0 (kt)
 
762
         * All platforms, => 3.9.1, all lengths: 4   (a) k1 k2 k3
 
763
         */
 
764
        if (keyTypeLen == 8) {
 
765
            keyTypeStorage = *(PRUint32 *) keyString;
 
766
            if (keyTypeStorage == 0) {
 
767
                keyString += sizeof(PRUint32);
 
768
            }
 
769
            keyTypeLen = 4;
 
770
        }
 
771
        /*
 
772
         * Now Handle:
 
773
         *
 
774
         * All platforms,      3.9, all lengths: 4    0  0  0 (kt)
 
775
         * All platforms, => 3.9.1, all lengths: 4   (a) k1 k2 k3
 
776
         *
 
777
         * NOTE: if  kt == 0 or ak1k2k3 == 0, the test fails and
 
778
         * we handle it as:
 
779
         *
 
780
         * Little Endian,  pre-3.9, all lengths: 4  (kt) 0  0  0
 
781
         */
 
782
        if (keyTypeLen == sizeof(keyTypeStorage) &&
 
783
             (((keyString[0] & 0x80) == 0x80) ||
 
784
                !((keyString[1] == 0) && (keyString[2] == 0)
 
785
                                            && (keyString[3] == 0))) ) {
 
786
            PORT_Memcpy(&keyTypeStorage, keyString, sizeof(keyTypeStorage));
 
787
            keyType = (CK_KEY_TYPE) PR_ntohl(keyTypeStorage);
 
788
        } else {
 
789
        /*
 
790
         * Now Handle:
 
791
         *
 
792
         * Big Endian,     pre-3.9, all lengths: 1  (kt)
 
793
         * Little Endian,  pre-3.9, all lengths: 4  (kt) 0  0  0
 
794
         *  -- KeyType == 0 all other cases ---: 4    0  0  0  0
 
795
         */
 
796
            keyType = (CK_KEY_TYPE) keyString[0] ;
 
797
        }
 
798
        return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType),PR_TRUE);
 
799
    case CKA_VALUE:
 
800
        return sftk_NewTokenAttribute(type,key->u.rsa.privateExponent.data,
 
801
                                key->u.rsa.privateExponent.len, PR_FALSE);
 
802
    case CKA_VALUE_LEN:
 
803
        keyLen=key->u.rsa.privateExponent.len;
 
804
        return sftk_NewTokenAttribute(type, &keyLen, sizeof(CK_ULONG), PR_TRUE);
 
805
    }
 
806
 
 
807
    return NULL;
 
808
}
 
809
 
 
810
static SFTKAttribute *
 
811
sftk_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key,
 
812
                                CK_ATTRIBUTE_TYPE type)
 
813
{
 
814
    unsigned char hash[SHA1_LENGTH];
 
815
    CK_KEY_TYPE keyType = CKK_RSA;
 
816
 
 
817
    switch (type) {
 
818
    case CKA_KEY_TYPE:
 
819
        return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
 
820
    case CKA_ID:
 
821
        SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
 
822
        return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
 
823
    case CKA_DERIVE:
 
824
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
825
    case CKA_DECRYPT:
 
826
    case CKA_SIGN:
 
827
    case CKA_SIGN_RECOVER:
 
828
    case CKA_UNWRAP:
 
829
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
830
    case CKA_MODULUS:
 
831
        return sftk_NewTokenAttributeSigned(type,key->u.rsa.modulus.data,
 
832
                                        key->u.rsa.modulus.len, PR_FALSE);
 
833
    case CKA_PUBLIC_EXPONENT:
 
834
        return sftk_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data,
 
835
                                key->u.rsa.publicExponent.len, PR_FALSE);
 
836
    case CKA_PRIVATE_EXPONENT:
 
837
        return sftk_NewTokenAttributeSigned(type,
 
838
                                key->u.rsa.privateExponent.data,
 
839
                                key->u.rsa.privateExponent.len, PR_FALSE);
 
840
    case CKA_PRIME_1:
 
841
        return sftk_NewTokenAttributeSigned(type, key->u.rsa.prime1.data,
 
842
                                key->u.rsa.prime1.len, PR_FALSE);
 
843
    case CKA_PRIME_2:
 
844
        return sftk_NewTokenAttributeSigned(type, key->u.rsa.prime2.data,
 
845
                                key->u.rsa.prime2.len, PR_FALSE);
 
846
    case CKA_EXPONENT_1:
 
847
        return sftk_NewTokenAttributeSigned(type, key->u.rsa.exponent1.data,
 
848
                                key->u.rsa.exponent1.len, PR_FALSE);
 
849
    case CKA_EXPONENT_2:
 
850
        return sftk_NewTokenAttributeSigned(type, key->u.rsa.exponent2.data,
 
851
                                key->u.rsa.exponent2.len, PR_FALSE);
 
852
    case CKA_COEFFICIENT:
 
853
        return sftk_NewTokenAttributeSigned(type, key->u.rsa.coefficient.data,
 
854
                                key->u.rsa.coefficient.len, PR_FALSE);
 
855
    default:
 
856
        break;
 
857
    }
 
858
    return NULL;
 
859
}
 
860
 
 
861
static SFTKAttribute *
 
862
sftk_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, 
 
863
                                                        CK_ATTRIBUTE_TYPE type)
 
864
{
 
865
    unsigned char hash[SHA1_LENGTH];
 
866
    CK_KEY_TYPE keyType = CKK_DSA;
 
867
 
 
868
    switch (type) {
 
869
    case CKA_KEY_TYPE:
 
870
        return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
 
871
    case CKA_ID:
 
872
        SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
 
873
                          key->u.dsa.publicValue.len);
 
874
        return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
 
875
    case CKA_DERIVE:
 
876
    case CKA_DECRYPT:
 
877
    case CKA_SIGN_RECOVER:
 
878
    case CKA_UNWRAP:
 
879
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
880
    case CKA_SIGN:
 
881
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
882
    case CKA_VALUE:
 
883
        return sftk_NewTokenAttributeSigned(type, key->u.dsa.privateValue.data,
 
884
                                key->u.dsa.privateValue.len, PR_FALSE);
 
885
    case CKA_PRIME:
 
886
        return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data,
 
887
                                        key->u.dsa.params.prime.len, PR_FALSE);
 
888
    case CKA_SUBPRIME:
 
889
        return sftk_NewTokenAttributeSigned(type,
 
890
                                key->u.dsa.params.subPrime.data,
 
891
                                key->u.dsa.params.subPrime.len, PR_FALSE);
 
892
    case CKA_BASE:
 
893
        return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.base.data,
 
894
                                        key->u.dsa.params.base.len, PR_FALSE);
 
895
    case CKA_NETSCAPE_DB:
 
896
        return sftk_NewTokenAttributeSigned(type,
 
897
                                        key->u.dsa.publicValue.data,
 
898
                                        key->u.dsa.publicValue.len,
 
899
                                        PR_FALSE);
 
900
    default:
 
901
        break;
 
902
    }
 
903
    return NULL;
 
904
}
 
905
 
 
906
static SFTKAttribute *
 
907
sftk_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type)
 
908
{
 
909
    unsigned char hash[SHA1_LENGTH];
 
910
    CK_KEY_TYPE keyType = CKK_DH;
 
911
 
 
912
    switch (type) {
 
913
    case CKA_KEY_TYPE:
 
914
        return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
 
915
    case CKA_ID:
 
916
        SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
 
917
        return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
 
918
    case CKA_DERIVE:
 
919
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
920
    case CKA_DECRYPT:
 
921
    case CKA_SIGN:
 
922
    case CKA_SIGN_RECOVER:
 
923
    case CKA_UNWRAP:
 
924
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
925
    case CKA_VALUE:
 
926
        return sftk_NewTokenAttributeSigned(type,key->u.dh.privateValue.data,
 
927
                                        key->u.dh.privateValue.len, PR_FALSE);
 
928
    case CKA_PRIME:
 
929
        return sftk_NewTokenAttributeSigned(type,key->u.dh.prime.data,
 
930
                                        key->u.dh.prime.len, PR_FALSE);
 
931
    case CKA_BASE:
 
932
        return sftk_NewTokenAttributeSigned(type,key->u.dh.base.data,
 
933
                                        key->u.dh.base.len, PR_FALSE);
 
934
    case CKA_NETSCAPE_DB:
 
935
        return sftk_NewTokenAttributeSigned(type,
 
936
                                        key->u.dh.publicValue.data,
 
937
                                        key->u.dh.publicValue.len,
 
938
                                        PR_FALSE);
 
939
    default:
 
940
        break;
 
941
    }
 
942
    return NULL;
 
943
}
 
944
 
 
945
#ifdef NSS_ENABLE_ECC
 
946
static SFTKAttribute *
 
947
sftk_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type)
 
948
{
 
949
    unsigned char hash[SHA1_LENGTH];
 
950
    CK_KEY_TYPE keyType = CKK_EC;
 
951
 
 
952
    switch (type) {
 
953
    case CKA_KEY_TYPE:
 
954
        return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
 
955
    case CKA_ID:
 
956
        SHA1_HashBuf(hash,key->u.ec.publicValue.data,key->u.ec.publicValue.len);
 
957
        return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
 
958
    case CKA_DERIVE:
 
959
    case CKA_SIGN:
 
960
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
961
    case CKA_DECRYPT:
 
962
    case CKA_SIGN_RECOVER:
 
963
    case CKA_UNWRAP:
 
964
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
965
    case CKA_VALUE:
 
966
        return sftk_NewTokenAttributeSigned(type, key->u.ec.privateValue.data,
 
967
                                        key->u.ec.privateValue.len, PR_FALSE);
 
968
    case CKA_EC_PARAMS:
 
969
        /* XXX Why is the last arg PR_FALSE? */
 
970
        return sftk_NewTokenAttributeSigned(type,
 
971
                                        key->u.ec.ecParams.DEREncoding.data,
 
972
                                        key->u.ec.ecParams.DEREncoding.len,
 
973
                                        PR_FALSE);
 
974
    case CKA_NETSCAPE_DB:
 
975
        return sftk_NewTokenAttributeSigned(type,
 
976
                                        key->u.ec.publicValue.data,
 
977
                                        key->u.ec.publicValue.len,
 
978
                                        PR_FALSE);
 
979
    default:
 
980
        break;
 
981
    }
 
982
    return NULL;
 
983
}
 
984
#endif /* NSS_ENABLE_ECC */
 
985
 
 
986
static SFTKAttribute *
 
987
sftk_FindPrivateKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
 
988
{
 
989
    NSSLOWKEYPrivateKey  *key;
 
990
    char *label;
 
991
    SFTKAttribute *att;
 
992
 
 
993
    switch (type) {
 
994
    case CKA_PRIVATE:
 
995
    case CKA_SENSITIVE:
 
996
    case CKA_ALWAYS_SENSITIVE:
 
997
    case CKA_EXTRACTABLE:
 
998
    case CKA_MODIFIABLE:
 
999
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
1000
    case CKA_NEVER_EXTRACTABLE:
 
1001
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
1002
    case CKA_SUBJECT:
 
1003
           return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
 
1004
    case CKA_LABEL:
 
1005
        label = sftk_FindKeyNicknameByPublicKey(object->obj.slot,
 
1006
                                                &object->dbKey);
 
1007
        if (label == NULL) {
 
1008
           return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
 
1009
        }
 
1010
        att = sftk_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE);
 
1011
        PORT_Free(label);
 
1012
        return att;
 
1013
    default:
 
1014
        break;
 
1015
    }
 
1016
    key = sftk_GetPrivateKey(object);
 
1017
    if (key == NULL) {
 
1018
        return NULL;
 
1019
    }
 
1020
    switch (key->keyType) {
 
1021
    case NSSLOWKEYRSAKey:
 
1022
        return sftk_FindRSAPrivateKeyAttribute(key,type);
 
1023
    case NSSLOWKEYDSAKey:
 
1024
        return sftk_FindDSAPrivateKeyAttribute(key,type);
 
1025
    case NSSLOWKEYDHKey:
 
1026
        return sftk_FindDHPrivateKeyAttribute(key,type);
 
1027
#ifdef NSS_ENABLE_ECC
 
1028
    case NSSLOWKEYECKey:
 
1029
        return sftk_FindECPrivateKeyAttribute(key,type);
 
1030
#endif /* NSS_ENABLE_ECC */
 
1031
    default:
 
1032
        break;
 
1033
    }
 
1034
 
 
1035
    return NULL;
 
1036
}
 
1037
 
 
1038
static SFTKAttribute *
 
1039
sftk_FindSMIMEAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
 
1040
{
 
1041
    certDBEntrySMime *entry;
 
1042
    switch (type) {
 
1043
    case CKA_PRIVATE:
 
1044
    case CKA_MODIFIABLE:
 
1045
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
1046
    case CKA_NETSCAPE_EMAIL:
 
1047
        return sftk_NewTokenAttribute(type,object->dbKey.data,
 
1048
                                                object->dbKey.len-1, PR_FALSE);
 
1049
    case CKA_NETSCAPE_SMIME_TIMESTAMP:
 
1050
    case CKA_SUBJECT:
 
1051
    case CKA_VALUE:
 
1052
        break;
 
1053
    default:
 
1054
        return NULL;
 
1055
    }
 
1056
    entry = sftk_getSMime(object);
 
1057
    if (entry == NULL) {
 
1058
        return NULL;
 
1059
    }
 
1060
    switch (type) {
 
1061
    case CKA_NETSCAPE_SMIME_TIMESTAMP:
 
1062
        return sftk_NewTokenAttribute(type,entry->optionsDate.data,
 
1063
                                        entry->optionsDate.len, PR_FALSE);
 
1064
    case CKA_SUBJECT:
 
1065
        return sftk_NewTokenAttribute(type,entry->subjectName.data,
 
1066
                                        entry->subjectName.len, PR_FALSE);
 
1067
    case CKA_VALUE:
 
1068
        return sftk_NewTokenAttribute(type,entry->smimeOptions.data,
 
1069
                                        entry->smimeOptions.len, PR_FALSE);
 
1070
    default:
 
1071
        break;
 
1072
    }
 
1073
    return NULL;
 
1074
}
 
1075
 
 
1076
static SFTKAttribute *
 
1077
sftk_FindTrustAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
 
1078
{
 
1079
    NSSLOWCERTTrust *trust;
 
1080
    unsigned char hash[SHA1_LENGTH];
 
1081
    unsigned int trustFlags;
 
1082
 
 
1083
    switch (type) {
 
1084
    case CKA_PRIVATE:
 
1085
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
1086
    case CKA_MODIFIABLE:
 
1087
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
1088
    case CKA_CERT_SHA1_HASH:
 
1089
    case CKA_CERT_MD5_HASH:
 
1090
    case CKA_TRUST_CLIENT_AUTH:
 
1091
    case CKA_TRUST_SERVER_AUTH:
 
1092
    case CKA_TRUST_EMAIL_PROTECTION:
 
1093
    case CKA_TRUST_CODE_SIGNING:
 
1094
    case CKA_TRUST_STEP_UP_APPROVED:
 
1095
        break;
 
1096
    default:
 
1097
        return NULL;
 
1098
    }
 
1099
    trust = sftk_getTrust(object);
 
1100
    if (trust == NULL) {
 
1101
        return NULL;
 
1102
    }
 
1103
    switch (type) {
 
1104
    case CKA_CERT_SHA1_HASH:
 
1105
        SHA1_HashBuf(hash,trust->derCert->data,trust->derCert->len);
 
1106
        return sftk_NewTokenAttribute(type, hash, SHA1_LENGTH, PR_TRUE);
 
1107
    case CKA_CERT_MD5_HASH:
 
1108
        MD5_HashBuf(hash,trust->derCert->data,trust->derCert->len);
 
1109
        return sftk_NewTokenAttribute(type, hash, MD5_LENGTH, PR_TRUE);
 
1110
    case CKA_TRUST_CLIENT_AUTH:
 
1111
        trustFlags = trust->trust->sslFlags & CERTDB_TRUSTED_CLIENT_CA ?
 
1112
                trust->trust->sslFlags | CERTDB_TRUSTED_CA : 0 ;
 
1113
        goto trust;
 
1114
    case CKA_TRUST_SERVER_AUTH:
 
1115
        trustFlags = trust->trust->sslFlags;
 
1116
        goto trust;
 
1117
    case CKA_TRUST_EMAIL_PROTECTION:
 
1118
        trustFlags = trust->trust->emailFlags;
 
1119
        goto trust;
 
1120
    case CKA_TRUST_CODE_SIGNING:
 
1121
        trustFlags = trust->trust->objectSigningFlags;
 
1122
trust:
 
1123
        if (trustFlags & CERTDB_TRUSTED_CA ) {
 
1124
            return SFTK_CLONE_ATTR(type,sftk_StaticTrustedDelegatorAttr);
 
1125
        }
 
1126
        if (trustFlags & CERTDB_TRUSTED) {
 
1127
            return SFTK_CLONE_ATTR(type,sftk_StaticTrustedAttr);
 
1128
        }
 
1129
        if (trustFlags & CERTDB_NOT_TRUSTED) {
 
1130
            return SFTK_CLONE_ATTR(type,sftk_StaticUnTrustedAttr);
 
1131
        }
 
1132
        if (trustFlags & CERTDB_TRUSTED_UNKNOWN) {
 
1133
            return SFTK_CLONE_ATTR(type,sftk_StaticTrustUnknownAttr);
 
1134
        }
 
1135
        if (trustFlags & CERTDB_VALID_CA) {
 
1136
            return SFTK_CLONE_ATTR(type,sftk_StaticValidDelegatorAttr);
 
1137
        }
 
1138
        if (trustFlags & CERTDB_VALID_PEER) {
 
1139
            return SFTK_CLONE_ATTR(type,sftk_StaticValidPeerAttr);
 
1140
        }
 
1141
        return SFTK_CLONE_ATTR(type,sftk_StaticMustVerifyAttr);
 
1142
    case CKA_TRUST_STEP_UP_APPROVED:
 
1143
        if (trust->trust->sslFlags & CERTDB_GOVT_APPROVED_CA) {
 
1144
            return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
1145
        } else {
 
1146
            return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
1147
        }
 
1148
    default:
 
1149
        break;
 
1150
    }
 
1151
 
 
1152
#ifdef notdef
 
1153
    switch (type) {
 
1154
    case CKA_ISSUER:
 
1155
        cert = sftk_getCertObject(object);
 
1156
        if (cert == NULL) break;
 
1157
        attr = sftk_NewTokenAttribute(type,cert->derIssuer.data,
 
1158
                                                cert->derIssuer.len, PR_FALSE);
 
1159
        
 
1160
    case CKA_SERIAL_NUMBER:
 
1161
        cert = sftk_getCertObject(object);
 
1162
        if (cert == NULL) break;
 
1163
        item = SEC_ASN1EncodeItem(NULL,NULL,cert,sftk_SerialTemplate);
 
1164
        if (item == NULL) break;
 
1165
        attr = sftk_NewTokenAttribute(type, item->data, item->len, PR_TRUE);
 
1166
        SECITEM_FreeItem(item,PR_TRUE);
 
1167
    }
 
1168
    if (cert) {
 
1169
        NSSLOWCERTDestroyCertificate(cert);     
 
1170
        return attr;
 
1171
    }
 
1172
#endif
 
1173
    return NULL;
 
1174
}
 
1175
 
 
1176
static SFTKAttribute *
 
1177
sftk_FindCrlAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
 
1178
{
 
1179
    certDBEntryRevocation *crl;
 
1180
 
 
1181
    switch (type) {
 
1182
    case CKA_PRIVATE:
 
1183
    case CKA_MODIFIABLE:
 
1184
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
1185
    case CKA_NETSCAPE_KRL:
 
1186
        return ((object->obj.handle == SFTK_TOKEN_KRL_HANDLE) 
 
1187
                ? SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr)
 
1188
                : SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr));
 
1189
    case CKA_SUBJECT:
 
1190
        return sftk_NewTokenAttribute(type,object->dbKey.data,
 
1191
                                                object->dbKey.len, PR_FALSE);   
 
1192
    case CKA_NETSCAPE_URL:
 
1193
    case CKA_VALUE:
 
1194
        break;
 
1195
    default:
 
1196
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
1197
        return NULL;
 
1198
    }
 
1199
    crl =  sftk_getCrl(object);
 
1200
    if (!crl) {
 
1201
        return NULL;
 
1202
    }
 
1203
    switch (type) {
 
1204
    case CKA_NETSCAPE_URL:
 
1205
        if (crl->url == NULL) {
 
1206
            return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
 
1207
        }
 
1208
        return sftk_NewTokenAttribute(type, crl->url, 
 
1209
                                        PORT_Strlen(crl->url)+1, PR_TRUE);
 
1210
    case CKA_VALUE:
 
1211
        return sftk_NewTokenAttribute(type, crl->derCrl.data, 
 
1212
                                                crl->derCrl.len, PR_FALSE);
 
1213
    default:
 
1214
        break;
 
1215
    }
 
1216
    return NULL;
 
1217
}
 
1218
 
 
1219
static SFTKAttribute *
 
1220
sftk_FindCertAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
 
1221
{
 
1222
    NSSLOWCERTCertificate  *cert;
 
1223
    NSSLOWCERTCertDBHandle *certHandle;
 
1224
    NSSLOWKEYPublicKey     *pubKey;
 
1225
    unsigned char hash[SHA1_LENGTH];
 
1226
    SECItem *item;
 
1227
 
 
1228
    switch (type) {
 
1229
    case CKA_PRIVATE:
 
1230
        return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
 
1231
    case CKA_MODIFIABLE:
 
1232
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
1233
    case CKA_CERTIFICATE_TYPE:
 
1234
        /* hardcoding X.509 into here */
 
1235
        return SFTK_CLONE_ATTR(type,sftk_StaticX509Attr);
 
1236
    case CKA_VALUE:
 
1237
    case CKA_ID:
 
1238
    case CKA_LABEL:
 
1239
    case CKA_SUBJECT:
 
1240
    case CKA_ISSUER:
 
1241
    case CKA_SERIAL_NUMBER:
 
1242
    case CKA_NETSCAPE_EMAIL:
 
1243
        break;
 
1244
    default:
 
1245
        return NULL;
 
1246
    }
 
1247
 
 
1248
    certHandle = sftk_getCertDB(object->obj.slot);
 
1249
    if (certHandle == NULL) {
 
1250
        return NULL;
 
1251
    }
 
1252
 
 
1253
    cert = sftk_getCert(object, certHandle);
 
1254
    sftk_freeCertDB(certHandle);
 
1255
    if (cert == NULL) {
 
1256
        return NULL;
 
1257
    }
 
1258
    switch (type) {
 
1259
    case CKA_VALUE:
 
1260
        return sftk_NewTokenAttribute(type,cert->derCert.data,
 
1261
                                                cert->derCert.len,PR_FALSE);
 
1262
    case CKA_ID:
 
1263
        if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
 
1264
                ((cert->trust->emailFlags & CERTDB_USER) == 0) &&
 
1265
                ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
 
1266
            return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
 
1267
        }
 
1268
        pubKey = nsslowcert_ExtractPublicKey(cert);
 
1269
        if (pubKey == NULL) break;
 
1270
        item = sftk_GetPubItem(pubKey);
 
1271
        if (item == NULL) {
 
1272
            nsslowkey_DestroyPublicKey(pubKey);
 
1273
            break;
 
1274
        }
 
1275
        SHA1_HashBuf(hash,item->data,item->len);
 
1276
        /* item is imbedded in pubKey, just free the key */
 
1277
        nsslowkey_DestroyPublicKey(pubKey);
 
1278
        return sftk_NewTokenAttribute(type, hash, SHA1_LENGTH, PR_TRUE);
 
1279
    case CKA_LABEL:
 
1280
        return cert->nickname 
 
1281
               ? sftk_NewTokenAttribute(type, cert->nickname,
 
1282
                                        PORT_Strlen(cert->nickname), PR_FALSE) 
 
1283
               : SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
 
1284
    case CKA_SUBJECT:
 
1285
        return sftk_NewTokenAttribute(type,cert->derSubject.data,
 
1286
                                                cert->derSubject.len, PR_FALSE);
 
1287
    case CKA_ISSUER:
 
1288
        return sftk_NewTokenAttribute(type,cert->derIssuer.data,
 
1289
                                                cert->derIssuer.len, PR_FALSE);
 
1290
    case CKA_SERIAL_NUMBER:
 
1291
        return sftk_NewTokenAttribute(type,cert->derSN.data,
 
1292
                                                cert->derSN.len, PR_FALSE);
 
1293
    case CKA_NETSCAPE_EMAIL:
 
1294
        return (cert->emailAddr && cert->emailAddr[0])
 
1295
            ? sftk_NewTokenAttribute(type, cert->emailAddr,
 
1296
                                     PORT_Strlen(cert->emailAddr), PR_FALSE) 
 
1297
            : SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
 
1298
    default:
 
1299
        break;
 
1300
    }
 
1301
    return NULL;
 
1302
}
 
1303
    
 
1304
static SFTKAttribute *    
 
1305
sftk_FindTokenAttribute(SFTKTokenObject *object,CK_ATTRIBUTE_TYPE type)
 
1306
{
 
1307
    /* handle the common ones */
 
1308
    switch (type) {
 
1309
    case CKA_CLASS:
 
1310
        return sftk_NewTokenAttribute(type,&object->obj.objclass,
 
1311
                                        sizeof(object->obj.objclass),PR_FALSE);
 
1312
    case CKA_TOKEN:
 
1313
        return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
 
1314
    case CKA_LABEL:
 
1315
        if (  (object->obj.objclass == CKO_CERTIFICATE) 
 
1316
           || (object->obj.objclass == CKO_PRIVATE_KEY)
 
1317
           || (object->obj.objclass == CKO_PUBLIC_KEY)
 
1318
           || (object->obj.objclass == CKO_SECRET_KEY)) {
 
1319
            break;
 
1320
        }
 
1321
        return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
 
1322
    default:
 
1323
        break;
 
1324
    }
 
1325
    switch (object->obj.objclass) {
 
1326
    case CKO_CERTIFICATE:
 
1327
        return sftk_FindCertAttribute(object,type);
 
1328
    case CKO_NETSCAPE_CRL:
 
1329
        return sftk_FindCrlAttribute(object,type);
 
1330
    case CKO_NETSCAPE_TRUST:
 
1331
        return sftk_FindTrustAttribute(object,type);
 
1332
    case CKO_NETSCAPE_SMIME:
 
1333
        return sftk_FindSMIMEAttribute(object,type);
 
1334
    case CKO_PUBLIC_KEY:
 
1335
        return sftk_FindPublicKeyAttribute(object,type);
 
1336
    case CKO_PRIVATE_KEY:
 
1337
        return sftk_FindPrivateKeyAttribute(object,type);
 
1338
    case CKO_SECRET_KEY:
 
1339
        return sftk_FindSecretKeyAttribute(object,type);
 
1340
    default:
 
1341
        break;
 
1342
    }
 
1343
    PORT_Assert(0);
 
1344
    return NULL;
 
1345
 
1346
 
 
1347
/*
 
1348
 * look up and attribute structure from a type and Object structure.
 
1349
 * The returned attribute is referenced and needs to be freed when 
 
1350
 * it is no longer needed.
 
1351
 */
 
1352
SFTKAttribute *
 
1353
sftk_FindAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
 
1354
{
 
1355
    SFTKAttribute *attribute;
 
1356
    SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
 
1357
 
 
1358
    if (sessObject == NULL) {
 
1359
        return sftk_FindTokenAttribute(sftk_narrowToTokenObject(object),type);
 
1360
    }
 
1361
 
 
1362
    PZ_Lock(sessObject->attributeLock);
 
1363
    sftkqueue_find(attribute,type,sessObject->head, sessObject->hashSize);
 
1364
    PZ_Unlock(sessObject->attributeLock);
 
1365
 
 
1366
    return(attribute);
 
1367
}
 
1368
 
 
1369
/*
 
1370
 * Take a buffer and it's length and return it's true size in bits;
 
1371
 */
 
1372
unsigned int
 
1373
sftk_GetLengthInBits(unsigned char *buf, unsigned int bufLen)
 
1374
{
 
1375
    unsigned int size = bufLen * 8;
 
1376
    unsigned int i;
 
1377
 
 
1378
    /* Get the real length in bytes */
 
1379
    for (i=0; i < bufLen; i++) {
 
1380
        unsigned char  c = *buf++;
 
1381
        if (c != 0) {
 
1382
            unsigned char m;
 
1383
            for (m=0x80; m > 0 ;  m = m >> 1) {
 
1384
                if ((c & m) != 0) {
 
1385
                    break;
 
1386
                } 
 
1387
                size--;
 
1388
            }
 
1389
            break;
 
1390
        }
 
1391
        size-=8;
 
1392
    }
 
1393
    return size;
 
1394
}
 
1395
 
 
1396
/*
 
1397
 * Constrain a big num attribute. to size and padding
 
1398
 * minLength means length of the object must be greater than equal to minLength
 
1399
 * maxLength means length of the object must be less than equal to maxLength
 
1400
 * minMultiple means that object length mod minMultiple must equal 0.
 
1401
 * all input sizes are in bits.
 
1402
 * if any constraint is '0' that constraint is not checked.
 
1403
 */
 
1404
CK_RV
 
1405
sftk_ConstrainAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type, 
 
1406
                        int minLength, int maxLength, int minMultiple)
 
1407
{
 
1408
    SFTKAttribute *attribute;
 
1409
    int size;
 
1410
    unsigned char *ptr;
 
1411
 
 
1412
    attribute = sftk_FindAttribute(object, type);
 
1413
    if (!attribute) {
 
1414
        return CKR_TEMPLATE_INCOMPLETE;
 
1415
    }
 
1416
    ptr = (unsigned char *) attribute->attrib.pValue;
 
1417
    if (ptr == NULL) {
 
1418
        sftk_FreeAttribute(attribute);
 
1419
        return CKR_ATTRIBUTE_VALUE_INVALID;
 
1420
    }
 
1421
    size = sftk_GetLengthInBits(ptr, attribute->attrib.ulValueLen);
 
1422
    sftk_FreeAttribute(attribute);
 
1423
 
 
1424
    if ((minLength != 0) && (size <  minLength)) {
 
1425
        return CKR_ATTRIBUTE_VALUE_INVALID;
 
1426
    }
 
1427
    if ((maxLength != 0) && (size >  maxLength)) {
 
1428
        return CKR_ATTRIBUTE_VALUE_INVALID;
 
1429
    }
 
1430
    if ((minMultiple != 0) && ((size % minMultiple) != 0)) {
 
1431
        return CKR_ATTRIBUTE_VALUE_INVALID;
 
1432
    }
 
1433
    return CKR_OK;
 
1434
}
 
1435
 
 
1436
PRBool
 
1437
sftk_hasAttributeToken(SFTKTokenObject *object)
 
1438
{
 
1439
    return PR_FALSE;
 
1440
}
 
1441
 
 
1442
/*
 
1443
 * return true if object has attribute
 
1444
 */
 
1445
PRBool
 
1446
sftk_hasAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
 
1447
{
 
1448
    SFTKAttribute *attribute;
 
1449
    SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
 
1450
 
 
1451
    if (sessObject == NULL) {
 
1452
        return sftk_hasAttributeToken(sftk_narrowToTokenObject(object));
 
1453
    }
 
1454
 
 
1455
    PZ_Lock(sessObject->attributeLock);
 
1456
    sftkqueue_find(attribute,type,sessObject->head, sessObject->hashSize);
 
1457
    PZ_Unlock(sessObject->attributeLock);
 
1458
 
 
1459
    return (PRBool)(attribute != NULL);
 
1460
}
 
1461
 
 
1462
/*
 
1463
 * add an attribute to an object
 
1464
 */
 
1465
static void
 
1466
sftk_AddAttribute(SFTKObject *object,SFTKAttribute *attribute)
 
1467
{
 
1468
    SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
 
1469
 
 
1470
    if (sessObject == NULL) return;
 
1471
    PZ_Lock(sessObject->attributeLock);
 
1472
    sftkqueue_add(attribute,attribute->handle,
 
1473
                                sessObject->head, sessObject->hashSize);
 
1474
    PZ_Unlock(sessObject->attributeLock);
 
1475
}
 
1476
 
 
1477
/* 
 
1478
 * copy an unsigned attribute into a SECItem. Secitem is allocated in
 
1479
 * the specified arena.
 
1480
 */
 
1481
CK_RV
 
1482
sftk_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,SFTKObject *object,
 
1483
                                      CK_ATTRIBUTE_TYPE type)
 
1484
{
 
1485
    SFTKAttribute *attribute;
 
1486
 
 
1487
    item->data = NULL;
 
1488
 
 
1489
    attribute = sftk_FindAttribute(object, type);
 
1490
    if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
 
1491
 
 
1492
    (void)SECITEM_AllocItem(arena, item, attribute->attrib.ulValueLen);
 
1493
    if (item->data == NULL) {
 
1494
        sftk_FreeAttribute(attribute);
 
1495
        return CKR_HOST_MEMORY;
 
1496
    }
 
1497
    PORT_Memcpy(item->data, attribute->attrib.pValue, item->len);
 
1498
    sftk_FreeAttribute(attribute);
 
1499
    return CKR_OK;
 
1500
}
 
1501
 
 
1502
 
 
1503
/*
 
1504
 * delete an attribute from an object
 
1505
 */
 
1506
static void
 
1507
sftk_DeleteAttribute(SFTKObject *object, SFTKAttribute *attribute)
 
1508
{
 
1509
    SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
 
1510
 
 
1511
    if (sessObject == NULL) {
 
1512
        return ;
 
1513
    }
 
1514
    PZ_Lock(sessObject->attributeLock);
 
1515
    if (sftkqueue_is_queued(attribute,attribute->handle,
 
1516
                                sessObject->head, sessObject->hashSize)) {
 
1517
        sftkqueue_delete(attribute,attribute->handle,
 
1518
                                sessObject->head, sessObject->hashSize);
 
1519
    }
 
1520
    PZ_Unlock(sessObject->attributeLock);
 
1521
}
 
1522
 
 
1523
/*
 
1524
 * this is only valid for CK_BBOOL type attributes. Return the state
 
1525
 * of that attribute.
 
1526
 */
 
1527
PRBool
 
1528
sftk_isTrue(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
 
1529
{
 
1530
    SFTKAttribute *attribute;
 
1531
    PRBool tok = PR_FALSE;
 
1532
 
 
1533
    attribute=sftk_FindAttribute(object,type);
 
1534
    if (attribute == NULL) { return PR_FALSE; }
 
1535
    tok = (PRBool)(*(CK_BBOOL *)attribute->attrib.pValue);
 
1536
    sftk_FreeAttribute(attribute);
 
1537
 
 
1538
    return tok;
 
1539
}
 
1540
 
 
1541
/*
 
1542
 * force an attribute to null.
 
1543
 * this is for sensitive keys which are stored in the database, we don't
 
1544
 * want to keep this info around in memory in the clear.
 
1545
 */
 
1546
void
 
1547
sftk_nullAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
 
1548
{
 
1549
    SFTKAttribute *attribute;
 
1550
 
 
1551
    attribute=sftk_FindAttribute(object,type);
 
1552
    if (attribute == NULL) return;
 
1553
 
 
1554
    if (attribute->attrib.pValue != NULL) {
 
1555
        PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);
 
1556
        if (attribute->freeData) {
 
1557
            PORT_Free(attribute->attrib.pValue);
 
1558
        }
 
1559
        attribute->freeData = PR_FALSE;
 
1560
        attribute->attrib.pValue = NULL;
 
1561
        attribute->attrib.ulValueLen = 0;
 
1562
    }
 
1563
    sftk_FreeAttribute(attribute);
 
1564
}
 
1565
 
 
1566
static CK_RV
 
1567
sftk_SetCertAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type, 
 
1568
                                                void *value, unsigned int len)
 
1569
{
 
1570
    NSSLOWCERTCertificate  *cert;
 
1571
    NSSLOWCERTCertDBHandle *certHandle;
 
1572
    char *nickname = NULL;
 
1573
    SECStatus rv;
 
1574
    CK_RV crv;
 
1575
 
 
1576
    /* we can't change  the EMAIL values, but let the
 
1577
     * upper layers feel better about the fact we tried to set these */
 
1578
    if (type == CKA_NETSCAPE_EMAIL) {
 
1579
        return CKR_OK;
 
1580
    }
 
1581
 
 
1582
    certHandle = sftk_getCertDB(to->obj.slot);
 
1583
    if (certHandle == NULL) {
 
1584
        crv = CKR_TOKEN_WRITE_PROTECTED;
 
1585
        goto done;
 
1586
    }
 
1587
 
 
1588
    if ((type != CKA_LABEL)  && (type != CKA_ID)) {
 
1589
        crv = CKR_ATTRIBUTE_READ_ONLY;
 
1590
        goto done;
 
1591
    }
 
1592
 
 
1593
    cert = sftk_getCert(to, certHandle);
 
1594
    if (cert == NULL) {
 
1595
        crv = CKR_OBJECT_HANDLE_INVALID;
 
1596
        goto done;
 
1597
    }
 
1598
 
 
1599
    /* if the app is trying to set CKA_ID, it's probably because it just
 
1600
     * imported the key. Look to see if we need to set the CERTDB_USER bits.
 
1601
     */
 
1602
    if (type == CKA_ID) {
 
1603
        if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
 
1604
                ((cert->trust->emailFlags & CERTDB_USER) == 0) &&
 
1605
                ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
 
1606
            SFTKSlot *slot = to->obj.slot;
 
1607
            NSSLOWKEYDBHandle      *keyHandle;
 
1608
 
 
1609
            keyHandle = sftk_getKeyDB(slot);
 
1610
            if (keyHandle) {
 
1611
                if (nsslowkey_KeyForCertExists(keyHandle, cert)) {
 
1612
                    NSSLOWCERTCertTrust trust = *cert->trust;
 
1613
                    trust.sslFlags |= CERTDB_USER;
 
1614
                    trust.emailFlags |= CERTDB_USER;
 
1615
                    trust.objectSigningFlags |= CERTDB_USER;
 
1616
                    nsslowcert_ChangeCertTrust(certHandle,cert,&trust);
 
1617
                }
 
1618
                sftk_freeKeyDB(keyHandle);
 
1619
            }
 
1620
        }
 
1621
        crv = CKR_OK;
 
1622
        goto done;
 
1623
    }
 
1624
 
 
1625
    /* must be CKA_LABEL */
 
1626
    if (value != NULL) {
 
1627
        nickname = PORT_ZAlloc(len+1);
 
1628
        if (nickname == NULL) {
 
1629
            crv = CKR_HOST_MEMORY;
 
1630
            goto done;
 
1631
        }
 
1632
        PORT_Memcpy(nickname,value,len);
 
1633
        nickname[len] = 0;
 
1634
    }
 
1635
    rv = nsslowcert_AddPermNickname(certHandle, cert, nickname);
 
1636
    crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
 
1637
 
 
1638
done:
 
1639
    if (nickname) {
 
1640
        PORT_Free(nickname);
 
1641
    }
 
1642
    if (certHandle) {
 
1643
        sftk_freeCertDB(certHandle);
 
1644
    }
 
1645
    return crv;
 
1646
}
 
1647
 
 
1648
static CK_RV
 
1649
sftk_SetPrivateKeyAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type, 
 
1650
                                                void *value, unsigned int len)
 
1651
{
 
1652
    NSSLOWKEYPrivateKey *privKey;
 
1653
    NSSLOWKEYDBHandle   *keyHandle;
 
1654
    char *nickname = NULL;
 
1655
    SECStatus rv;
 
1656
    CK_RV crv;
 
1657
 
 
1658
    /* we can't change the ID and we don't store the subject, but let the
 
1659
     * upper layers feel better about the fact we tried to set these */
 
1660
    if ((type == CKA_ID) || (type == CKA_SUBJECT)) {
 
1661
        return CKR_OK;
 
1662
    }
 
1663
 
 
1664
    keyHandle = sftk_getKeyDB(to->obj.slot);
 
1665
    if (keyHandle == NULL) {
 
1666
        crv = CKR_TOKEN_WRITE_PROTECTED;
 
1667
        goto done;
 
1668
    }
 
1669
    if (type != CKA_LABEL) {
 
1670
        crv = CKR_ATTRIBUTE_READ_ONLY;
 
1671
        goto done;
 
1672
    }
 
1673
 
 
1674
    privKey = sftk_GetPrivateKeyWithDB(to, keyHandle);
 
1675
    if (privKey == NULL) {
 
1676
        crv = CKR_OBJECT_HANDLE_INVALID;
 
1677
        goto done;
 
1678
    }
 
1679
    if (value != NULL) {
 
1680
        nickname = PORT_ZAlloc(len+1);
 
1681
        if (nickname == NULL) {
 
1682
            crv = CKR_HOST_MEMORY;
 
1683
            goto done;
 
1684
        }
 
1685
        PORT_Memcpy(nickname,value,len);
 
1686
        nickname[len] = 0;
 
1687
    }
 
1688
    rv = nsslowkey_UpdateNickname(keyHandle, privKey, &to->dbKey, 
 
1689
                                        nickname, to->obj.slot->password);
 
1690
    crv = (rv == SECSuccess) ? CKR_OK :  CKR_DEVICE_ERROR;
 
1691
done:
 
1692
    if (nickname) {
 
1693
        PORT_Free(nickname);
 
1694
    }
 
1695
    if (keyHandle) {
 
1696
        sftk_freeKeyDB(keyHandle);
 
1697
    }
 
1698
    return crv;
 
1699
}
 
1700
 
 
1701
static CK_RV
 
1702
sftk_SetTrustAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type, 
 
1703
                                                void *value, unsigned int len)
 
1704
{
 
1705
    unsigned int flags;
 
1706
    CK_TRUST  trust;
 
1707
    NSSLOWCERTCertificate  *cert;
 
1708
    NSSLOWCERTCertDBHandle *certHandle;
 
1709
    NSSLOWCERTCertTrust    dbTrust;
 
1710
    SECStatus rv;
 
1711
    CK_RV crv;
 
1712
 
 
1713
    if (len != sizeof (CK_TRUST)) {
 
1714
        return CKR_ATTRIBUTE_VALUE_INVALID;
 
1715
    }
 
1716
    trust = *(CK_TRUST *)value;
 
1717
    flags = sftk_MapTrust(trust, (PRBool) (type == CKA_TRUST_SERVER_AUTH));
 
1718
 
 
1719
    certHandle = sftk_getCertDB(to->obj.slot);
 
1720
 
 
1721
    if (certHandle == NULL) {
 
1722
        crv = CKR_TOKEN_WRITE_PROTECTED;
 
1723
        goto done;
 
1724
    }
 
1725
 
 
1726
    cert = sftk_getCert(to, certHandle);
 
1727
    if (cert == NULL) {
 
1728
        crv = CKR_OBJECT_HANDLE_INVALID;
 
1729
        goto done;
 
1730
    }
 
1731
    dbTrust = *cert->trust;
 
1732
 
 
1733
    switch (type) {
 
1734
    case CKA_TRUST_EMAIL_PROTECTION:
 
1735
        dbTrust.emailFlags = flags |
 
1736
                (cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS);
 
1737
        break;
 
1738
    case CKA_TRUST_CODE_SIGNING:
 
1739
        dbTrust.objectSigningFlags = flags |
 
1740
                (cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS);
 
1741
        break;
 
1742
    case CKA_TRUST_CLIENT_AUTH:
 
1743
        dbTrust.sslFlags = flags | (cert->trust->sslFlags & 
 
1744
                                (CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CA));
 
1745
        break;
 
1746
    case CKA_TRUST_SERVER_AUTH:
 
1747
        dbTrust.sslFlags = flags | (cert->trust->sslFlags & 
 
1748
                        (CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CLIENT_CA));
 
1749
        break;
 
1750
    default:
 
1751
        crv = CKR_ATTRIBUTE_READ_ONLY;
 
1752
        goto done;
 
1753
    }
 
1754
 
 
1755
    rv = nsslowcert_ChangeCertTrust(certHandle, cert, &dbTrust);
 
1756
    crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
 
1757
done:
 
1758
    if (certHandle) {
 
1759
        sftk_freeCertDB(certHandle);
 
1760
    }
 
1761
    return crv;
 
1762
}
 
1763
 
 
1764
static CK_RV
 
1765
sftk_forceTokenAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type, 
 
1766
                                                void *value, unsigned int len)
 
1767
{
 
1768
    SFTKAttribute *attribute;
 
1769
    SFTKTokenObject *to = sftk_narrowToTokenObject(object);
 
1770
    CK_RV crv = CKR_ATTRIBUTE_READ_ONLY;
 
1771
 
 
1772
    PORT_Assert(to);
 
1773
    if (to == NULL) {
 
1774
        return CKR_DEVICE_ERROR;
 
1775
    }
 
1776
 
 
1777
    /* if we are just setting it to the value we already have,
 
1778
     * allow it to happen. Let label setting go through so
 
1779
     * we have the opportunity to repair any database corruption. */
 
1780
    attribute=sftk_FindAttribute(object,type);
 
1781
    PORT_Assert(attribute);
 
1782
    if (!attribute) {
 
1783
        return CKR_ATTRIBUTE_TYPE_INVALID;
 
1784
 
 
1785
    }
 
1786
    if ((type != CKA_LABEL) && (attribute->attrib.ulValueLen == len) &&
 
1787
        PORT_Memcmp(attribute->attrib.pValue,value,len) == 0) {
 
1788
        sftk_FreeAttribute(attribute);
 
1789
        return CKR_OK;
 
1790
    }
 
1791
 
 
1792
    switch (object->objclass) {
 
1793
    case CKO_CERTIFICATE:
 
1794
        /* change NICKNAME, EMAIL,  */
 
1795
        crv = sftk_SetCertAttribute(to,type,value,len);
 
1796
        break;
 
1797
    case CKO_NETSCAPE_CRL:
 
1798
        /* change URL */
 
1799
        break;
 
1800
    case CKO_NETSCAPE_TRUST:
 
1801
        crv = sftk_SetTrustAttribute(to,type,value,len);
 
1802
        break;
 
1803
    case CKO_PRIVATE_KEY:
 
1804
    case CKO_SECRET_KEY:
 
1805
        crv = sftk_SetPrivateKeyAttribute(to,type,value,len);
 
1806
        break;
 
1807
    }
 
1808
    sftk_FreeAttribute(attribute);
 
1809
    return crv;
 
1810
}
 
1811
        
 
1812
/*
 
1813
 * force an attribute to a spaecif value.
 
1814
 */
 
1815
CK_RV
 
1816
sftk_forceAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type, void *value,
 
1817
                                                unsigned int len)
 
1818
{
 
1819
    SFTKAttribute *attribute;
 
1820
    void *att_val = NULL;
 
1821
    PRBool freeData = PR_FALSE;
 
1822
 
 
1823
    PORT_Assert(object);
 
1824
    PORT_Assert(object->refCount);
 
1825
    PORT_Assert(object->slot);
 
1826
    if (!object ||
 
1827
        !object->refCount ||
 
1828
        !object->slot) {
 
1829
        return CKR_DEVICE_ERROR;
 
1830
    }
 
1831
    if (sftk_isToken(object->handle)) {
 
1832
        return sftk_forceTokenAttribute(object,type,value,len);
 
1833
    }
 
1834
    attribute=sftk_FindAttribute(object,type);
 
1835
    if (attribute == NULL) return sftk_AddAttributeType(object,type,value,len);
 
1836
 
 
1837
 
 
1838
    if (value) {
 
1839
        if (len <= ATTR_SPACE) {
 
1840
            att_val = attribute->space;
 
1841
        } else {
 
1842
            att_val = PORT_Alloc(len);
 
1843
            freeData = PR_TRUE;
 
1844
        }
 
1845
        if (att_val == NULL) {
 
1846
            return CKR_HOST_MEMORY;
 
1847
        }
 
1848
        if (attribute->attrib.pValue == att_val) {
 
1849
            PORT_Memset(attribute->attrib.pValue,0,
 
1850
                                        attribute->attrib.ulValueLen);
 
1851
        }
 
1852
        PORT_Memcpy(att_val,value,len);
 
1853
    }
 
1854
    if (attribute->attrib.pValue != NULL) {
 
1855
        if (attribute->attrib.pValue != att_val) {
 
1856
            PORT_Memset(attribute->attrib.pValue,0,
 
1857
                                        attribute->attrib.ulValueLen);
 
1858
        }
 
1859
        if (attribute->freeData) {
 
1860
            PORT_Free(attribute->attrib.pValue);
 
1861
        }
 
1862
        attribute->freeData = PR_FALSE;
 
1863
        attribute->attrib.pValue = NULL;
 
1864
        attribute->attrib.ulValueLen = 0;
 
1865
    }
 
1866
    if (att_val) {
 
1867
        attribute->attrib.pValue = att_val;
 
1868
        attribute->attrib.ulValueLen = len;
 
1869
        attribute->freeData = freeData;
 
1870
    }
 
1871
    sftk_FreeAttribute(attribute);
 
1872
    return CKR_OK;
 
1873
}
 
1874
 
 
1875
/*
 
1876
 * return a null terminated string from attribute 'type'. This string
 
1877
 * is allocated and needs to be freed with PORT_Free() When complete.
 
1878
 */
 
1879
char *
 
1880
sftk_getString(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
 
1881
{
 
1882
    SFTKAttribute *attribute;
 
1883
    char *label = NULL;
 
1884
 
 
1885
    attribute=sftk_FindAttribute(object,type);
 
1886
    if (attribute == NULL) return NULL;
 
1887
 
 
1888
    if (attribute->attrib.pValue != NULL) {
 
1889
        label = (char *) PORT_Alloc(attribute->attrib.ulValueLen+1);
 
1890
        if (label == NULL) {
 
1891
            sftk_FreeAttribute(attribute);
 
1892
            return NULL;
 
1893
        }
 
1894
 
 
1895
        PORT_Memcpy(label,attribute->attrib.pValue,
 
1896
                                                attribute->attrib.ulValueLen);
 
1897
        label[attribute->attrib.ulValueLen] = 0;
 
1898
    }
 
1899
    sftk_FreeAttribute(attribute);
 
1900
    return label;
 
1901
}
 
1902
 
 
1903
/*
 
1904
 * decode when a particular attribute may be modified
 
1905
 *      SFTK_NEVER: This attribute must be set at object creation time and
 
1906
 *  can never be modified.
 
1907
 *      SFTK_ONCOPY: This attribute may be modified only when you copy the
 
1908
 *  object.
 
1909
 *      SFTK_SENSITIVE: The CKA_SENSITIVE attribute can only be changed from
 
1910
 *  CK_FALSE to CK_TRUE.
 
1911
 *      SFTK_ALWAYS: This attribute can always be modified.
 
1912
 * Some attributes vary their modification type based on the class of the 
 
1913
 *   object.
 
1914
 */
 
1915
SFTKModifyType
 
1916
sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
 
1917
{
 
1918
    /* if we don't know about it, user user defined, always allow modify */
 
1919
    SFTKModifyType mtype = SFTK_ALWAYS; 
 
1920
 
 
1921
    switch(type) {
 
1922
    /* NEVER */
 
1923
    case CKA_CLASS:
 
1924
    case CKA_CERTIFICATE_TYPE:
 
1925
    case CKA_KEY_TYPE:
 
1926
    case CKA_MODULUS:
 
1927
    case CKA_MODULUS_BITS:
 
1928
    case CKA_PUBLIC_EXPONENT:
 
1929
    case CKA_PRIVATE_EXPONENT:
 
1930
    case CKA_PRIME:
 
1931
    case CKA_SUBPRIME:
 
1932
    case CKA_BASE:
 
1933
    case CKA_PRIME_1:
 
1934
    case CKA_PRIME_2:
 
1935
    case CKA_EXPONENT_1:
 
1936
    case CKA_EXPONENT_2:
 
1937
    case CKA_COEFFICIENT:
 
1938
    case CKA_VALUE_LEN:
 
1939
    case CKA_ALWAYS_SENSITIVE:
 
1940
    case CKA_NEVER_EXTRACTABLE:
 
1941
    case CKA_NETSCAPE_DB:
 
1942
        mtype = SFTK_NEVER;
 
1943
        break;
 
1944
 
 
1945
    /* ONCOPY */
 
1946
    case CKA_TOKEN:
 
1947
    case CKA_PRIVATE:
 
1948
    case CKA_MODIFIABLE:
 
1949
        mtype = SFTK_ONCOPY;
 
1950
        break;
 
1951
 
 
1952
    /* SENSITIVE */
 
1953
    case CKA_SENSITIVE:
 
1954
    case CKA_EXTRACTABLE:
 
1955
        mtype = SFTK_SENSITIVE;
 
1956
        break;
 
1957
 
 
1958
    /* ALWAYS */
 
1959
    case CKA_LABEL:
 
1960
    case CKA_APPLICATION:
 
1961
    case CKA_ID:
 
1962
    case CKA_SERIAL_NUMBER:
 
1963
    case CKA_START_DATE:
 
1964
    case CKA_END_DATE:
 
1965
    case CKA_DERIVE:
 
1966
    case CKA_ENCRYPT:
 
1967
    case CKA_DECRYPT:
 
1968
    case CKA_SIGN:
 
1969
    case CKA_VERIFY:
 
1970
    case CKA_SIGN_RECOVER:
 
1971
    case CKA_VERIFY_RECOVER:
 
1972
    case CKA_WRAP:
 
1973
    case CKA_UNWRAP:
 
1974
        mtype = SFTK_ALWAYS;
 
1975
        break;
 
1976
 
 
1977
    /* DEPENDS ON CLASS */
 
1978
    case CKA_VALUE:
 
1979
        mtype = (inClass == CKO_DATA) ? SFTK_ALWAYS : SFTK_NEVER;
 
1980
        break;
 
1981
 
 
1982
    case CKA_SUBJECT:
 
1983
        mtype = (inClass == CKO_CERTIFICATE) ? SFTK_NEVER : SFTK_ALWAYS;
 
1984
        break;
 
1985
    default:
 
1986
        break;
 
1987
    }
 
1988
    return mtype;
 
1989
}
 
1990
 
 
1991
/* decode if a particular attribute is sensitive (cannot be read
 
1992
 * back to the user of if the object is set to SENSITIVE) */
 
1993
PRBool
 
1994
sftk_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
 
1995
{
 
1996
    switch(type) {
 
1997
    /* ALWAYS */
 
1998
    case CKA_PRIVATE_EXPONENT:
 
1999
    case CKA_PRIME_1:
 
2000
    case CKA_PRIME_2:
 
2001
    case CKA_EXPONENT_1:
 
2002
    case CKA_EXPONENT_2:
 
2003
    case CKA_COEFFICIENT:
 
2004
        return PR_TRUE;
 
2005
 
 
2006
    /* DEPENDS ON CLASS */
 
2007
    case CKA_VALUE:
 
2008
        /* PRIVATE and SECRET KEYS have SENSITIVE values */
 
2009
        return (PRBool)((inClass == CKO_PRIVATE_KEY) || (inClass == CKO_SECRET_KEY));
 
2010
 
 
2011
    default:
 
2012
        break;
 
2013
    }
 
2014
    return PR_FALSE;
 
2015
}
 
2016
 
 
2017
/* 
 
2018
 * copy an attribute into a SECItem. Secitem is allocated in the specified
 
2019
 * arena.
 
2020
 */
 
2021
CK_RV
 
2022
sftk_Attribute2SecItem(PLArenaPool *arena,SECItem *item,SFTKObject *object,
 
2023
                                        CK_ATTRIBUTE_TYPE type)
 
2024
{
 
2025
    int len;
 
2026
    SFTKAttribute *attribute;
 
2027
 
 
2028
    attribute = sftk_FindAttribute(object, type);
 
2029
    if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
 
2030
    len = attribute->attrib.ulValueLen;
 
2031
 
 
2032
    if (arena) {
 
2033
        item->data = (unsigned char *) PORT_ArenaAlloc(arena,len);
 
2034
    } else {
 
2035
        item->data = (unsigned char *) PORT_Alloc(len);
 
2036
    }
 
2037
    if (item->data == NULL) {
 
2038
        sftk_FreeAttribute(attribute);
 
2039
        return CKR_HOST_MEMORY;
 
2040
    }
 
2041
    item->len = len;
 
2042
    PORT_Memcpy(item->data,attribute->attrib.pValue, len);
 
2043
    sftk_FreeAttribute(attribute);
 
2044
    return CKR_OK;
 
2045
}
 
2046
 
 
2047
CK_RV
 
2048
sftk_GetULongAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
 
2049
                                                         CK_ULONG *longData)
 
2050
{
 
2051
    SFTKAttribute *attribute;
 
2052
 
 
2053
    attribute = sftk_FindAttribute(object, type);
 
2054
    if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
 
2055
 
 
2056
    if (attribute->attrib.ulValueLen != sizeof(CK_ULONG)) {
 
2057
        return CKR_ATTRIBUTE_VALUE_INVALID;
 
2058
    }
 
2059
 
 
2060
    *longData = *(CK_ULONG *)attribute->attrib.pValue;
 
2061
    sftk_FreeAttribute(attribute);
 
2062
    return CKR_OK;
 
2063
}
 
2064
 
 
2065
void
 
2066
sftk_DeleteAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
 
2067
{
 
2068
    SFTKAttribute *attribute;
 
2069
    attribute = sftk_FindAttribute(object, type);
 
2070
    if (attribute == NULL) return ;
 
2071
    sftk_DeleteAttribute(object,attribute);
 
2072
    sftk_FreeAttribute(attribute);
 
2073
}
 
2074
 
 
2075
CK_RV
 
2076
sftk_AddAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type,void *valPtr,
 
2077
                                                        CK_ULONG length)
 
2078
{
 
2079
    SFTKAttribute *attribute;
 
2080
    attribute = sftk_NewAttribute(object,type,valPtr,length);
 
2081
    if (attribute == NULL) { return CKR_HOST_MEMORY; }
 
2082
    sftk_AddAttribute(object,attribute);
 
2083
    return CKR_OK;
 
2084
}
 
2085
 
 
2086
/*
 
2087
 * ******************** Object Utilities *******************************
 
2088
 */
 
2089
 
 
2090
static SECStatus
 
2091
sftk_deleteTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
 
2092
{
 
2093
   SECItem *item;
 
2094
   PRBool rem;
 
2095
 
 
2096
   item = (SECItem *)PL_HashTableLookup(slot->tokenHashTable, (void *)handle);
 
2097
   rem = PL_HashTableRemove(slot->tokenHashTable,(void *)handle) ;
 
2098
   if (rem && item) {
 
2099
        SECITEM_FreeItem(item,PR_TRUE);
 
2100
   }
 
2101
   return rem ? SECSuccess : SECFailure;
 
2102
}
 
2103
 
 
2104
/* must be called holding sftk_tokenKeyLock(slot) */
 
2105
static SECStatus
 
2106
sftk_addTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle, SECItem *key)
 
2107
{
 
2108
    PLHashEntry *entry;
 
2109
    SECItem *item;
 
2110
 
 
2111
    /* don't add a new handle in the middle of closing down a slot */
 
2112
    if (!slot->present) {
 
2113
        return SECFailure;
 
2114
    }
 
2115
 
 
2116
    item = SECITEM_DupItem(key);
 
2117
    if (item == NULL) {
 
2118
        return SECFailure;
 
2119
    }
 
2120
    entry = PL_HashTableAdd(slot->tokenHashTable,(void *)handle,item);
 
2121
    if (entry == NULL) {
 
2122
        SECITEM_FreeItem(item,PR_TRUE);
 
2123
        return SECFailure;
 
2124
    }
 
2125
    return SECSuccess;
 
2126
}
 
2127
 
 
2128
/* must be called holding sftk_tokenKeyLock(slot) */
 
2129
static SECItem *
 
2130
sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
 
2131
{
 
2132
    return (SECItem *)PL_HashTableLookup(slot->tokenHashTable, (void *)handle);
 
2133
}
 
2134
 
 
2135
/*
 
2136
 * use the refLock. This operations should be very rare, so the added
 
2137
 * contention on the ref lock should be lower than the overhead of adding
 
2138
 * a new lock. We use separate functions for this just in case I'm wrong.
 
2139
 */
 
2140
static void
 
2141
sftk_tokenKeyLock(SFTKSlot *slot) {
 
2142
    PZ_Lock(slot->objectLock);
 
2143
}
 
2144
 
 
2145
static void
 
2146
sftk_tokenKeyUnlock(SFTKSlot *slot) {
 
2147
    PZ_Unlock(slot->objectLock);
 
2148
}
 
2149
 
 
2150
static PRIntn
 
2151
sftk_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg)
 
2152
{
 
2153
    SECItem *item = (SECItem *)entry->value;
 
2154
 
 
2155
    SECITEM_FreeItem(item, PR_TRUE);
 
2156
    return HT_ENUMERATE_NEXT;
 
2157
}
 
2158
 
 
2159
CK_RV
 
2160
SFTK_ClearTokenKeyHashTable(SFTKSlot *slot)
 
2161
{
 
2162
    sftk_tokenKeyLock(slot);
 
2163
    PORT_Assert(!slot->present);
 
2164
    PL_HashTableEnumerateEntries(slot->tokenHashTable, sftk_freeHashItem, NULL);
 
2165
    sftk_tokenKeyUnlock(slot);
 
2166
    return CKR_OK;
 
2167
}
 
2168
 
 
2169
 
 
2170
/* allocation hooks that allow us to recycle old object structures */
 
2171
static SFTKObjectFreeList sessionObjectList = { NULL, NULL, 0 };
 
2172
static SFTKObjectFreeList tokenObjectList = { NULL, NULL, 0 };
 
2173
 
 
2174
SFTKObject *
 
2175
sftk_GetObjectFromList(PRBool *hasLocks, PRBool optimizeSpace, 
 
2176
     SFTKObjectFreeList *list, unsigned int hashSize, PRBool isSessionObject)
 
2177
{
 
2178
    SFTKObject *object;
 
2179
    int size = 0;
 
2180
 
 
2181
    if (!optimizeSpace) {
 
2182
        PZ_Lock(list->lock);
 
2183
        object = list->head;
 
2184
        if (object) {
 
2185
            list->head = object->next;
 
2186
            list->count--;
 
2187
        }       
 
2188
        PZ_Unlock(list->lock);
 
2189
        if (object) {
 
2190
            object->next = object->prev = NULL;
 
2191
            *hasLocks = PR_TRUE;
 
2192
            return object;
 
2193
        }
 
2194
    }
 
2195
    size = isSessionObject ? sizeof(SFTKSessionObject) 
 
2196
                + hashSize *sizeof(SFTKAttribute *) : sizeof(SFTKTokenObject);
 
2197
 
 
2198
    object  = (SFTKObject*)PORT_ZAlloc(size);
 
2199
    if (isSessionObject) {
 
2200
        ((SFTKSessionObject *)object)->hashSize = hashSize;
 
2201
    }
 
2202
    *hasLocks = PR_FALSE;
 
2203
    return object;
 
2204
}
 
2205
 
 
2206
static void
 
2207
sftk_PutObjectToList(SFTKObject *object, SFTKObjectFreeList *list,
 
2208
                                                PRBool isSessionObject) {
 
2209
 
 
2210
    /* the code below is equivalent to :
 
2211
     *     optimizeSpace = isSessionObject ? object->optimizeSpace : PR_FALSE;
 
2212
     * just faster.
 
2213
     */
 
2214
    PRBool optimizeSpace = isSessionObject && 
 
2215
                                ((SFTKSessionObject *)object)->optimizeSpace; 
 
2216
    if (!optimizeSpace && (list->count < MAX_OBJECT_LIST_SIZE)) {
 
2217
        PZ_Lock(list->lock);
 
2218
        object->next = list->head;
 
2219
        list->head = object;
 
2220
        list->count++;
 
2221
        PZ_Unlock(list->lock);
 
2222
        return;
 
2223
    }
 
2224
    if (isSessionObject) {
 
2225
        SFTKSessionObject *so = (SFTKSessionObject *)object;
 
2226
        PZ_DestroyLock(so->attributeLock);
 
2227
        so->attributeLock = NULL;
 
2228
    }
 
2229
    PZ_DestroyLock(object->refLock);
 
2230
    object->refLock = NULL;
 
2231
    PORT_Free(object);
 
2232
}
 
2233
 
 
2234
static SFTKObject *
 
2235
sftk_freeObjectData(SFTKObject *object) {
 
2236
   SFTKObject *next = object->next;
 
2237
 
 
2238
   PORT_Free(object);
 
2239
   return next;
 
2240
}
 
2241
 
 
2242
static void
 
2243
sftk_InitFreeList(SFTKObjectFreeList *list)
 
2244
{
 
2245
    list->lock = PZ_NewLock(nssILockObject);
 
2246
}
 
2247
 
 
2248
void sftk_InitFreeLists(void)
 
2249
{
 
2250
    sftk_InitFreeList(&sessionObjectList);
 
2251
    sftk_InitFreeList(&tokenObjectList);
 
2252
}
 
2253
   
 
2254
static void
 
2255
sftk_CleanupFreeList(SFTKObjectFreeList *list, PRBool isSessionList)
 
2256
{
 
2257
    SFTKObject *object;
 
2258
 
 
2259
    if (!list->lock) {
 
2260
        return;
 
2261
    }
 
2262
    PZ_Lock(list->lock);
 
2263
    for (object= list->head; object != NULL; 
 
2264
                                        object = sftk_freeObjectData(object)) {
 
2265
        PZ_DestroyLock(object->refLock);
 
2266
        if (isSessionList) {
 
2267
            PZ_DestroyLock(((SFTKSessionObject *)object)->attributeLock);
 
2268
        }
 
2269
    }
 
2270
    list->count = 0;
 
2271
    list->head = NULL;
 
2272
    PZ_Unlock(list->lock);
 
2273
    PZ_DestroyLock(list->lock);
 
2274
    list->lock = NULL;
 
2275
}
 
2276
 
 
2277
void
 
2278
sftk_CleanupFreeLists(void)
 
2279
{
 
2280
    sftk_CleanupFreeList(&sessionObjectList, PR_TRUE);
 
2281
    sftk_CleanupFreeList(&tokenObjectList, PR_FALSE);
 
2282
}
 
2283
 
 
2284
 
 
2285
/*
 
2286
 * Create a new object
 
2287
 */
 
2288
SFTKObject *
 
2289
sftk_NewObject(SFTKSlot *slot)
 
2290
{
 
2291
    SFTKObject *object;
 
2292
    SFTKSessionObject *sessObject;
 
2293
    PRBool hasLocks = PR_FALSE;
 
2294
    unsigned int i;
 
2295
    unsigned int hashSize = 0;
 
2296
 
 
2297
    hashSize = (slot->optimizeSpace) ? SPACE_ATTRIBUTE_HASH_SIZE :
 
2298
                                TIME_ATTRIBUTE_HASH_SIZE;
 
2299
 
 
2300
    object = sftk_GetObjectFromList(&hasLocks, slot->optimizeSpace,
 
2301
                                &sessionObjectList,  hashSize, PR_TRUE);
 
2302
    if (object == NULL) {
 
2303
        return NULL;
 
2304
    }
 
2305
    sessObject = (SFTKSessionObject *)object;
 
2306
    sessObject->nextAttr = 0;
 
2307
 
 
2308
    for (i=0; i < MAX_OBJS_ATTRS; i++) {
 
2309
        sessObject->attrList[i].attrib.pValue = NULL;
 
2310
        sessObject->attrList[i].freeData = PR_FALSE;
 
2311
    }
 
2312
    sessObject->optimizeSpace = slot->optimizeSpace;
 
2313
 
 
2314
    object->handle = 0;
 
2315
    object->next = object->prev = NULL;
 
2316
    object->slot = slot;
 
2317
    
 
2318
    object->refCount = 1;
 
2319
    sessObject->sessionList.next = NULL;
 
2320
    sessObject->sessionList.prev = NULL;
 
2321
    sessObject->sessionList.parent = object;
 
2322
    sessObject->session = NULL;
 
2323
    sessObject->wasDerived = PR_FALSE;
 
2324
    if (!hasLocks) object->refLock = PZ_NewLock(nssILockRefLock);
 
2325
    if (object->refLock == NULL) {
 
2326
        PORT_Free(object);
 
2327
        return NULL;
 
2328
    }
 
2329
    if (!hasLocks) sessObject->attributeLock = PZ_NewLock(nssILockAttribute);
 
2330
    if (sessObject->attributeLock == NULL) {
 
2331
        PZ_DestroyLock(object->refLock);
 
2332
        PORT_Free(object);
 
2333
        return NULL;
 
2334
    }
 
2335
    for (i=0; i < sessObject->hashSize; i++) {
 
2336
        sessObject->head[i] = NULL;
 
2337
    }
 
2338
    object->objectInfo = NULL;
 
2339
    object->infoFree = NULL;
 
2340
    return object;
 
2341
}
 
2342
 
 
2343
static CK_RV
 
2344
sftk_DestroySessionObjectData(SFTKSessionObject *so)
 
2345
{
 
2346
        int i;
 
2347
 
 
2348
        for (i=0; i < MAX_OBJS_ATTRS; i++) {
 
2349
            unsigned char *value = so->attrList[i].attrib.pValue;
 
2350
            if (value) {
 
2351
                PORT_Memset(value,0,so->attrList[i].attrib.ulValueLen);
 
2352
                if (so->attrList[i].freeData) {
 
2353
                    PORT_Free(value);
 
2354
                }
 
2355
                so->attrList[i].attrib.pValue = NULL;
 
2356
                so->attrList[i].freeData = PR_FALSE;
 
2357
            }
 
2358
        }
 
2359
/*      PZ_DestroyLock(so->attributeLock);*/
 
2360
        return CKR_OK;
 
2361
}
 
2362
 
 
2363
/*
 
2364
 * free all the data associated with an object. Object reference count must
 
2365
 * be 'zero'.
 
2366
 */
 
2367
static CK_RV
 
2368
sftk_DestroyObject(SFTKObject *object)
 
2369
{
 
2370
    CK_RV crv = CKR_OK;
 
2371
    SFTKSessionObject *so = sftk_narrowToSessionObject(object);
 
2372
    SFTKTokenObject *to = sftk_narrowToTokenObject(object);
 
2373
 
 
2374
    PORT_Assert(object->refCount == 0);
 
2375
 
 
2376
    /* delete the database value */
 
2377
    if (to) {
 
2378
        if (to->dbKey.data) {
 
2379
           PORT_Free(to->dbKey.data);
 
2380
           to->dbKey.data = NULL;
 
2381
        }
 
2382
    } 
 
2383
    if (so) {
 
2384
        sftk_DestroySessionObjectData(so);
 
2385
    }
 
2386
    if (object->objectInfo) {
 
2387
        (*object->infoFree)(object->objectInfo);
 
2388
        object->objectInfo = NULL;
 
2389
        object->infoFree = NULL;
 
2390
    }
 
2391
    if (so) {
 
2392
        sftk_PutObjectToList(object,&sessionObjectList,PR_TRUE);
 
2393
    } else {
 
2394
        sftk_PutObjectToList(object,&tokenObjectList,PR_FALSE);
 
2395
    }
 
2396
    return crv;
 
2397
}
 
2398
 
 
2399
void
 
2400
sftk_ReferenceObject(SFTKObject *object)
 
2401
{
 
2402
    PZ_Lock(object->refLock);
 
2403
    object->refCount++;
 
2404
    PZ_Unlock(object->refLock);
 
2405
}
 
2406
 
 
2407
static SFTKObject *
 
2408
sftk_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, SFTKSlot *slot)
 
2409
{
 
2410
    SFTKObject *object;
 
2411
    PRUint32 index = sftk_hash(handle, slot->tokObjHashSize);
 
2412
 
 
2413
    if (sftk_isToken(handle)) {
 
2414
        return sftk_NewTokenObject(slot, NULL, handle);
 
2415
    }
 
2416
 
 
2417
    PZ_Lock(slot->objectLock);
 
2418
    sftkqueue_find2(object, handle, index, slot->tokObjects);
 
2419
    if (object) {
 
2420
        sftk_ReferenceObject(object);
 
2421
    }
 
2422
    PZ_Unlock(slot->objectLock);
 
2423
 
 
2424
    return(object);
 
2425
}
 
2426
/*
 
2427
 * look up and object structure from a handle. OBJECT_Handles only make
 
2428
 * sense in terms of a given session.  make a reference to that object
 
2429
 * structure returned.
 
2430
 */
 
2431
SFTKObject *
 
2432
sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle, SFTKSession *session)
 
2433
{
 
2434
    SFTKSlot *slot = sftk_SlotFromSession(session);
 
2435
 
 
2436
    return sftk_ObjectFromHandleOnSlot(handle,slot);
 
2437
}
 
2438
 
 
2439
 
 
2440
/*
 
2441
 * release a reference to an object handle
 
2442
 */
 
2443
SFTKFreeStatus
 
2444
sftk_FreeObject(SFTKObject *object)
 
2445
{
 
2446
    PRBool destroy = PR_FALSE;
 
2447
    CK_RV crv;
 
2448
 
 
2449
    PZ_Lock(object->refLock);
 
2450
    if (object->refCount == 1) destroy = PR_TRUE;
 
2451
    object->refCount--;
 
2452
    PZ_Unlock(object->refLock);
 
2453
 
 
2454
    if (destroy) {
 
2455
        crv = sftk_DestroyObject(object);
 
2456
        if (crv != CKR_OK) {
 
2457
           return SFTK_DestroyFailure;
 
2458
        } 
 
2459
        return SFTK_Destroyed;
 
2460
    }
 
2461
    return SFTK_Busy;
 
2462
}
 
2463
 
 
2464
/*
 
2465
 * add an object to a slot and session queue. These two functions
 
2466
 * adopt the object.
 
2467
 */
 
2468
void
 
2469
sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object)
 
2470
{
 
2471
    PRUint32 index = sftk_hash(object->handle, slot->tokObjHashSize);
 
2472
    sftkqueue_init_element(object);
 
2473
    PZ_Lock(slot->objectLock);
 
2474
    sftkqueue_add2(object, object->handle, index, slot->tokObjects);
 
2475
    PZ_Unlock(slot->objectLock);
 
2476
}
 
2477
 
 
2478
void
 
2479
sftk_AddObject(SFTKSession *session, SFTKObject *object)
 
2480
{
 
2481
    SFTKSlot *slot = sftk_SlotFromSession(session);
 
2482
    SFTKSessionObject *so = sftk_narrowToSessionObject(object);
 
2483
 
 
2484
    if (so) {
 
2485
        PZ_Lock(session->objectLock);
 
2486
        sftkqueue_add(&so->sessionList,0,session->objects,0);
 
2487
        so->session = session;
 
2488
        PZ_Unlock(session->objectLock);
 
2489
    }
 
2490
    sftk_AddSlotObject(slot,object);
 
2491
    sftk_ReferenceObject(object);
 
2492
 
2493
 
 
2494
/*
 
2495
 * add an object to a slot andsession queue
 
2496
 */
 
2497
CK_RV
 
2498
sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
 
2499
{
 
2500
    SFTKSlot *slot = sftk_SlotFromSession(session);
 
2501
    SFTKSessionObject *so = sftk_narrowToSessionObject(object);
 
2502
    SFTKTokenObject *to = sftk_narrowToTokenObject(object);
 
2503
    CK_RV crv = CKR_OK;
 
2504
    SECStatus rv;
 
2505
    NSSLOWCERTCertificate *cert;
 
2506
    NSSLOWCERTCertTrust tmptrust;
 
2507
    PRBool isKrl;
 
2508
    PRUint32 index = sftk_hash(object->handle, slot->tokObjHashSize);
 
2509
 
 
2510
  /* Handle Token case */
 
2511
    if (so && so->session) {
 
2512
        SFTKSession *session = so->session;
 
2513
        PZ_Lock(session->objectLock);
 
2514
        sftkqueue_delete(&so->sessionList,0,session->objects,0);
 
2515
        PZ_Unlock(session->objectLock);
 
2516
        PZ_Lock(slot->objectLock);
 
2517
        sftkqueue_delete2(object, object->handle, index, slot->tokObjects);
 
2518
        PZ_Unlock(slot->objectLock);
 
2519
        sftkqueue_clear_deleted_element(object);
 
2520
        sftk_FreeObject(object); /* reduce it's reference count */
 
2521
    } else {
 
2522
        NSSLOWKEYDBHandle *keyHandle;
 
2523
        NSSLOWCERTCertDBHandle *certHandle;
 
2524
 
 
2525
        PORT_Assert(to);
 
2526
        /* remove the objects from the real data base */
 
2527
        switch (object->handle & SFTK_TOKEN_TYPE_MASK) {
 
2528
        case SFTK_TOKEN_TYPE_PRIV:
 
2529
        case SFTK_TOKEN_TYPE_KEY:
 
2530
            /* KEYID is the public KEY for DSA and DH, and the MODULUS for
 
2531
             *  RSA */
 
2532
            keyHandle = sftk_getKeyDB(slot);
 
2533
            if (!keyHandle) {
 
2534
                crv = CKR_TOKEN_WRITE_PROTECTED;
 
2535
                break;
 
2536
            }
 
2537
            rv = nsslowkey_DeleteKey(keyHandle, &to->dbKey);
 
2538
            sftk_freeKeyDB(keyHandle);
 
2539
            if (rv != SECSuccess) {
 
2540
                crv = CKR_DEVICE_ERROR;
 
2541
            }
 
2542
            break;
 
2543
        case SFTK_TOKEN_TYPE_PUB:
 
2544
            break; /* public keys only exist at the behest of the priv key */
 
2545
        case SFTK_TOKEN_TYPE_CERT:
 
2546
            certHandle = sftk_getCertDB(slot);
 
2547
            if (!certHandle) {
 
2548
                crv = CKR_TOKEN_WRITE_PROTECTED;
 
2549
                break;
 
2550
            }
 
2551
            cert = nsslowcert_FindCertByKey(certHandle,&to->dbKey);
 
2552
            sftk_freeCertDB(certHandle);
 
2553
            if (cert == NULL) {
 
2554
                crv = CKR_DEVICE_ERROR;
 
2555
                break;
 
2556
            }
 
2557
            rv = nsslowcert_DeletePermCertificate(cert);
 
2558
            if (rv != SECSuccess) {
 
2559
                crv = CKR_DEVICE_ERROR;
 
2560
            }
 
2561
            nsslowcert_DestroyCertificate(cert);
 
2562
            break;
 
2563
        case SFTK_TOKEN_TYPE_CRL:
 
2564
            certHandle = sftk_getCertDB(slot);
 
2565
            if (!certHandle) {
 
2566
                crv = CKR_TOKEN_WRITE_PROTECTED;
 
2567
                break;
 
2568
            }
 
2569
            isKrl = (PRBool) (object->handle == SFTK_TOKEN_KRL_HANDLE);
 
2570
            rv = nsslowcert_DeletePermCRL(certHandle, &to->dbKey, isKrl);
 
2571
            sftk_freeCertDB(certHandle);
 
2572
            if (rv == SECFailure) crv = CKR_DEVICE_ERROR;
 
2573
            break;
 
2574
        case SFTK_TOKEN_TYPE_TRUST:
 
2575
            certHandle = sftk_getCertDB(slot);
 
2576
            if (!certHandle) {
 
2577
                crv = CKR_TOKEN_WRITE_PROTECTED;
 
2578
                break;
 
2579
            }
 
2580
            cert = nsslowcert_FindCertByKey(certHandle, &to->dbKey);
 
2581
            if (cert == NULL) {
 
2582
                sftk_freeCertDB(certHandle);
 
2583
                crv = CKR_DEVICE_ERROR;
 
2584
                break;
 
2585
            }
 
2586
            tmptrust = *cert->trust;
 
2587
            tmptrust.sslFlags &= CERTDB_PRESERVE_TRUST_BITS;
 
2588
            tmptrust.emailFlags &= CERTDB_PRESERVE_TRUST_BITS;
 
2589
            tmptrust.objectSigningFlags &= CERTDB_PRESERVE_TRUST_BITS;
 
2590
            tmptrust.sslFlags |= CERTDB_TRUSTED_UNKNOWN;
 
2591
            tmptrust.emailFlags |= CERTDB_TRUSTED_UNKNOWN;
 
2592
            tmptrust.objectSigningFlags |= CERTDB_TRUSTED_UNKNOWN;
 
2593
            rv = nsslowcert_ChangeCertTrust(certHandle, cert, &tmptrust);
 
2594
            sftk_freeCertDB(certHandle);
 
2595
            if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
 
2596
            nsslowcert_DestroyCertificate(cert);
 
2597
            break;
 
2598
        default:
 
2599
            break;
 
2600
        }
 
2601
        sftk_tokenKeyLock(object->slot);
 
2602
        sftk_deleteTokenKeyByHandle(object->slot,object->handle);
 
2603
        sftk_tokenKeyUnlock(object->slot);
 
2604
    } 
 
2605
    return crv;
 
2606
}
 
2607
 
 
2608
/*
 
2609
 * Token objects don't explicitly store their attributes, so we need to know
 
2610
 * what attributes make up a particular token object before we can copy it.
 
2611
 * below are the tables by object type.
 
2612
 */
 
2613
static const CK_ATTRIBUTE_TYPE commonAttrs[] = {
 
2614
    CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_MODIFIABLE
 
2615
};
 
2616
static const CK_ULONG commonAttrsCount = 
 
2617
                        sizeof(commonAttrs)/sizeof(commonAttrs[0]);
 
2618
 
 
2619
static const CK_ATTRIBUTE_TYPE commonKeyAttrs[] = {
 
2620
    CKA_ID, CKA_START_DATE, CKA_END_DATE, CKA_DERIVE, CKA_LOCAL, CKA_KEY_TYPE
 
2621
};
 
2622
static const CK_ULONG commonKeyAttrsCount = 
 
2623
                        sizeof(commonKeyAttrs)/sizeof(commonKeyAttrs[0]);
 
2624
 
 
2625
static const CK_ATTRIBUTE_TYPE secretKeyAttrs[] = {
 
2626
    CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN,
 
2627
    CKA_VERIFY, CKA_WRAP, CKA_UNWRAP, CKA_VALUE
 
2628
};
 
2629
static const CK_ULONG secretKeyAttrsCount = 
 
2630
                        sizeof(secretKeyAttrs)/sizeof(secretKeyAttrs[0]);
 
2631
 
 
2632
static const CK_ATTRIBUTE_TYPE commonPubKeyAttrs[] = {
 
2633
    CKA_ENCRYPT, CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_WRAP, CKA_SUBJECT
 
2634
};
 
2635
static const CK_ULONG commonPubKeyAttrsCount = 
 
2636
                        sizeof(commonPubKeyAttrs)/sizeof(commonPubKeyAttrs[0]);
 
2637
 
 
2638
static const CK_ATTRIBUTE_TYPE rsaPubKeyAttrs[] = {
 
2639
    CKA_MODULUS, CKA_PUBLIC_EXPONENT
 
2640
};
 
2641
static const CK_ULONG rsaPubKeyAttrsCount = 
 
2642
                        sizeof(rsaPubKeyAttrs)/sizeof(rsaPubKeyAttrs[0]);
 
2643
 
 
2644
static const CK_ATTRIBUTE_TYPE dsaPubKeyAttrs[] = {
 
2645
    CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE
 
2646
};
 
2647
static const CK_ULONG dsaPubKeyAttrsCount = 
 
2648
                        sizeof(dsaPubKeyAttrs)/sizeof(dsaPubKeyAttrs[0]);
 
2649
 
 
2650
static const CK_ATTRIBUTE_TYPE dhPubKeyAttrs[] = {
 
2651
    CKA_PRIME, CKA_BASE, CKA_VALUE
 
2652
};
 
2653
static const CK_ULONG dhPubKeyAttrsCount = 
 
2654
                        sizeof(dhPubKeyAttrs)/sizeof(dhPubKeyAttrs[0]);
 
2655
#ifdef NSS_ENABLE_ECC
 
2656
static const CK_ATTRIBUTE_TYPE ecPubKeyAttrs[] = {
 
2657
    CKA_EC_PARAMS, CKA_EC_POINT
 
2658
};
 
2659
static const CK_ULONG ecPubKeyAttrsCount = 
 
2660
                        sizeof(ecPubKeyAttrs)/sizeof(ecPubKeyAttrs[0]);
 
2661
#endif
 
2662
 
 
2663
static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = {
 
2664
    CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER, CKA_UNWRAP, CKA_SUBJECT,
 
2665
    CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NETSCAPE_DB
 
2666
};
 
2667
static const CK_ULONG commonPrivKeyAttrsCount = 
 
2668
                sizeof(commonPrivKeyAttrs)/sizeof(commonPrivKeyAttrs[0]);
 
2669
 
 
2670
static const CK_ATTRIBUTE_TYPE rsaPrivKeyAttrs[] = {
 
2671
    CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, 
 
2672
    CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT
 
2673
};
 
2674
static const CK_ULONG rsaPrivKeyAttrsCount = 
 
2675
                        sizeof(rsaPrivKeyAttrs)/sizeof(rsaPrivKeyAttrs[0]);
 
2676
 
 
2677
static const CK_ATTRIBUTE_TYPE dsaPrivKeyAttrs[] = {
 
2678
    CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE
 
2679
};
 
2680
static const CK_ULONG dsaPrivKeyAttrsCount = 
 
2681
                        sizeof(dsaPrivKeyAttrs)/sizeof(dsaPrivKeyAttrs[0]);
 
2682
 
 
2683
static const CK_ATTRIBUTE_TYPE dhPrivKeyAttrs[] = {
 
2684
    CKA_PRIME, CKA_BASE, CKA_VALUE
 
2685
};
 
2686
static const CK_ULONG dhPrivKeyAttrsCount = 
 
2687
                        sizeof(dhPrivKeyAttrs)/sizeof(dhPrivKeyAttrs[0]);
 
2688
#ifdef NSS_ENABLE_ECC
 
2689
static const CK_ATTRIBUTE_TYPE ecPrivKeyAttrs[] = {
 
2690
    CKA_EC_PARAMS, CKA_VALUE
 
2691
};
 
2692
static const CK_ULONG ecPrivKeyAttrsCount = 
 
2693
                        sizeof(ecPrivKeyAttrs)/sizeof(ecPrivKeyAttrs[0]);
 
2694
#endif
 
2695
 
 
2696
static const CK_ATTRIBUTE_TYPE certAttrs[] = {
 
2697
    CKA_CERTIFICATE_TYPE, CKA_VALUE, CKA_SUBJECT, CKA_ISSUER, CKA_SERIAL_NUMBER
 
2698
};
 
2699
static const CK_ULONG certAttrsCount = 
 
2700
                sizeof(certAttrs)/sizeof(certAttrs[0]);
 
2701
 
 
2702
static const CK_ATTRIBUTE_TYPE trustAttrs[] = {
 
2703
    CKA_ISSUER, CKA_SERIAL_NUMBER, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH,
 
2704
    CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_EMAIL_PROTECTION,
 
2705
    CKA_TRUST_CODE_SIGNING, CKA_TRUST_STEP_UP_APPROVED
 
2706
};
 
2707
static const CK_ULONG trustAttrsCount = 
 
2708
                sizeof(trustAttrs)/sizeof(trustAttrs[0]);
 
2709
 
 
2710
static const CK_ATTRIBUTE_TYPE smimeAttrs[] = {
 
2711
    CKA_SUBJECT, CKA_NETSCAPE_EMAIL, CKA_NETSCAPE_SMIME_TIMESTAMP, CKA_VALUE
 
2712
};
 
2713
static const CK_ULONG smimeAttrsCount = 
 
2714
                sizeof(smimeAttrs)/sizeof(smimeAttrs[0]);
 
2715
 
 
2716
static const CK_ATTRIBUTE_TYPE crlAttrs[] = {
 
2717
    CKA_SUBJECT, CKA_VALUE, CKA_NETSCAPE_URL, CKA_NETSCAPE_KRL
 
2718
};
 
2719
static const CK_ULONG crlAttrsCount = 
 
2720
                sizeof(crlAttrs)/sizeof(crlAttrs[0]);
 
2721
 
 
2722
/* copy an object based on it's table */
 
2723
CK_RV
 
2724
stfk_CopyTokenAttributes(SFTKObject *destObject,SFTKTokenObject *src_to,
 
2725
        const CK_ATTRIBUTE_TYPE *attrArray, CK_ULONG attrCount)
 
2726
{
 
2727
    SFTKAttribute *attribute;
 
2728
    SFTKAttribute *newAttribute;
 
2729
    CK_RV crv = CKR_OK;
 
2730
    unsigned int i;
 
2731
 
 
2732
    for (i=0; i < attrCount; i++) {
 
2733
        if (!sftk_hasAttribute(destObject,attrArray[i])) {
 
2734
            attribute =sftk_FindAttribute(&src_to->obj, attrArray[i]);
 
2735
            if (!attribute) {
 
2736
                continue; /* return CKR_ATTRIBUTE_VALUE_INVALID; */
 
2737
            }
 
2738
            /* we need to copy the attribute since each attribute
 
2739
             * only has one set of link list pointers */
 
2740
            newAttribute = sftk_NewAttribute( destObject,
 
2741
                                sftk_attr_expand(&attribute->attrib));
 
2742
            sftk_FreeAttribute(attribute); /* free the old attribute */
 
2743
            if (!newAttribute) {
 
2744
                return CKR_HOST_MEMORY;
 
2745
            }
 
2746
            sftk_AddAttribute(destObject,newAttribute);
 
2747
        }
 
2748
    }
 
2749
    return crv;
 
2750
}
 
2751
 
 
2752
CK_RV
 
2753
stfk_CopyTokenPrivateKey(SFTKObject *destObject,SFTKTokenObject *src_to)
 
2754
{
 
2755
    CK_RV crv;
 
2756
    CK_KEY_TYPE key_type;
 
2757
    SFTKAttribute *attribute;
 
2758
 
 
2759
    /* copy the common attributes for all keys first */
 
2760
    crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
 
2761
                                                        commonKeyAttrsCount);
 
2762
    if (crv != CKR_OK) {
 
2763
        goto fail;
 
2764
    }
 
2765
    /* copy the common attributes for all private keys next */
 
2766
    crv = stfk_CopyTokenAttributes(destObject, src_to, commonPrivKeyAttrs,
 
2767
                                                commonPrivKeyAttrsCount);
 
2768
    if (crv != CKR_OK) {
 
2769
        goto fail;
 
2770
    }
 
2771
    attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE);
 
2772
    PORT_Assert(attribute); /* if it wasn't here, ww should have failed
 
2773
                             * copying the common attributes */
 
2774
    if (!attribute) {
 
2775
        /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but
 
2776
         * the fact is, the only reason we couldn't get the attribute would
 
2777
         * be a memory error or database error (an error in the 'device').
 
2778
         * if we have a database error code, we could return it here */
 
2779
        crv = CKR_DEVICE_ERROR;
 
2780
        goto fail;
 
2781
    }
 
2782
    key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
 
2783
    sftk_FreeAttribute(attribute);
 
2784
    
 
2785
    /* finally copy the attributes for various private key types */
 
2786
    switch (key_type) {
 
2787
    case CKK_RSA:
 
2788
        crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPrivKeyAttrs,
 
2789
                                                        rsaPrivKeyAttrsCount);
 
2790
        break;
 
2791
    case CKK_DSA:
 
2792
        crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPrivKeyAttrs,
 
2793
                                                        dsaPrivKeyAttrsCount);
 
2794
        break;
 
2795
    case CKK_DH:
 
2796
        crv = stfk_CopyTokenAttributes(destObject, src_to, dhPrivKeyAttrs,
 
2797
                                                        dhPrivKeyAttrsCount);
 
2798
        break;
 
2799
#ifdef NSS_ENABLE_ECC
 
2800
    case CKK_EC:
 
2801
        crv = stfk_CopyTokenAttributes(destObject, src_to, ecPrivKeyAttrs,
 
2802
                                                        ecPrivKeyAttrsCount);
 
2803
        break;
 
2804
#endif
 
2805
     default:
 
2806
        crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types
 
2807
                                * of token keys into our database. */
 
2808
    }
 
2809
fail:
 
2810
    return crv;
 
2811
}
 
2812
 
 
2813
CK_RV
 
2814
stfk_CopyTokenPublicKey(SFTKObject *destObject,SFTKTokenObject *src_to)
 
2815
{
 
2816
    CK_RV crv;
 
2817
    CK_KEY_TYPE key_type;
 
2818
    SFTKAttribute *attribute;
 
2819
 
 
2820
    /* copy the common attributes for all keys first */
 
2821
    crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
 
2822
                                                        commonKeyAttrsCount);
 
2823
    if (crv != CKR_OK) {
 
2824
        goto fail;
 
2825
    }
 
2826
 
 
2827
    /* copy the common attributes for all public keys next */
 
2828
    crv = stfk_CopyTokenAttributes(destObject, src_to, commonPubKeyAttrs,
 
2829
                                                        commonPubKeyAttrsCount);
 
2830
    if (crv != CKR_OK) {
 
2831
        goto fail;
 
2832
    }
 
2833
    attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE);
 
2834
    PORT_Assert(attribute); /* if it wasn't here, ww should have failed
 
2835
                             * copying the common attributes */
 
2836
    if (!attribute) {
 
2837
        /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but
 
2838
         * the fact is, the only reason we couldn't get the attribute would
 
2839
         * be a memory error or database error (an error in the 'device').
 
2840
         * if we have a database error code, we could return it here */
 
2841
        crv = CKR_DEVICE_ERROR;
 
2842
        goto fail;
 
2843
    }
 
2844
    key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
 
2845
    sftk_FreeAttribute(attribute);
 
2846
    
 
2847
    /* finally copy the attributes for various public key types */
 
2848
    switch (key_type) {
 
2849
    case CKK_RSA:
 
2850
        crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPubKeyAttrs,
 
2851
                                                        rsaPubKeyAttrsCount);
 
2852
        break;
 
2853
    case CKK_DSA:
 
2854
        crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPubKeyAttrs,
 
2855
                                                        dsaPubKeyAttrsCount);
 
2856
        break;
 
2857
    case CKK_DH:
 
2858
        crv = stfk_CopyTokenAttributes(destObject, src_to, dhPubKeyAttrs,
 
2859
                                                        dhPubKeyAttrsCount);
 
2860
        break;
 
2861
#ifdef NSS_ENABLE_ECC
 
2862
    case CKK_EC:
 
2863
        crv = stfk_CopyTokenAttributes(destObject, src_to, ecPubKeyAttrs,
 
2864
                                                        ecPubKeyAttrsCount);
 
2865
        break;
 
2866
#endif
 
2867
     default:
 
2868
        crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types
 
2869
                                * of token keys into our database. */
 
2870
    }
 
2871
fail:
 
2872
    return crv;
 
2873
}
 
2874
CK_RV
 
2875
stfk_CopyTokenSecretKey(SFTKObject *destObject,SFTKTokenObject *src_to)
 
2876
{
 
2877
    CK_RV crv;
 
2878
    crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
 
2879
                                                        commonKeyAttrsCount);
 
2880
    if (crv != CKR_OK) {
 
2881
        goto fail;
 
2882
    }
 
2883
    crv = stfk_CopyTokenAttributes(destObject, src_to, secretKeyAttrs,
 
2884
                                                        secretKeyAttrsCount);
 
2885
fail:
 
2886
    return crv;
 
2887
}
 
2888
 
 
2889
/*
 
2890
 * Copy a token object. We need to explicitly copy the relevant
 
2891
 * attributes since token objects don't store those attributes in
 
2892
 * the token itself.
 
2893
 */
 
2894
CK_RV
 
2895
sftk_CopyTokenObject(SFTKObject *destObject,SFTKObject *srcObject)
 
2896
{
 
2897
    SFTKTokenObject *src_to = sftk_narrowToTokenObject(srcObject);
 
2898
    CK_RV crv;
 
2899
 
 
2900
    PORT_Assert(src_to);
 
2901
    if (src_to == NULL) {
 
2902
        return CKR_DEVICE_ERROR; /* internal state inconsistant */
 
2903
    }
 
2904
 
 
2905
    crv = stfk_CopyTokenAttributes(destObject, src_to, commonAttrs,
 
2906
                                                        commonAttrsCount);
 
2907
    if (crv != CKR_OK) {
 
2908
        goto fail;
 
2909
    }
 
2910
    switch (src_to->obj.objclass) {
 
2911
    case CKO_CERTIFICATE:
 
2912
        crv = stfk_CopyTokenAttributes(destObject, src_to, certAttrs,
 
2913
                                                        certAttrsCount);
 
2914
        break;
 
2915
    case CKO_NETSCAPE_TRUST:
 
2916
        crv = stfk_CopyTokenAttributes(destObject, src_to, trustAttrs,
 
2917
                                                        trustAttrsCount);
 
2918
        break;
 
2919
    case CKO_NETSCAPE_SMIME:
 
2920
        crv = stfk_CopyTokenAttributes(destObject, src_to, smimeAttrs,
 
2921
                                                        smimeAttrsCount);
 
2922
        break;
 
2923
    case CKO_NETSCAPE_CRL:
 
2924
        crv = stfk_CopyTokenAttributes(destObject, src_to, crlAttrs,
 
2925
                                                        crlAttrsCount);
 
2926
        break;
 
2927
    case CKO_PRIVATE_KEY:
 
2928
        crv = stfk_CopyTokenPrivateKey(destObject,src_to);
 
2929
        break;
 
2930
    case CKO_PUBLIC_KEY:
 
2931
        crv = stfk_CopyTokenPublicKey(destObject,src_to);
 
2932
        break;
 
2933
    case CKO_SECRET_KEY:
 
2934
        crv = stfk_CopyTokenSecretKey(destObject,src_to);
 
2935
        break;
 
2936
    default:
 
2937
        crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types
 
2938
                                * of token keys into our database. */
 
2939
    }
 
2940
fail:
 
2941
    return crv;
 
2942
}
 
2943
 
 
2944
/*
 
2945
 * copy the attributes from one object to another. Don't overwrite existing
 
2946
 * attributes. NOTE: This is a pretty expensive operation since it
 
2947
 * grabs the attribute locks for the src object for a *long* time.
 
2948
 */
 
2949
CK_RV
 
2950
sftk_CopyObject(SFTKObject *destObject,SFTKObject *srcObject)
 
2951
{
 
2952
    SFTKAttribute *attribute;
 
2953
    SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject);
 
2954
    unsigned int i;
 
2955
 
 
2956
    if (src_so == NULL) {
 
2957
        return sftk_CopyTokenObject(destObject,srcObject); 
 
2958
    }
 
2959
 
 
2960
    PZ_Lock(src_so->attributeLock);
 
2961
    for(i=0; i < src_so->hashSize; i++) {
 
2962
        attribute = src_so->head[i];
 
2963
        do {
 
2964
            if (attribute) {
 
2965
                if (!sftk_hasAttribute(destObject,attribute->handle)) {
 
2966
                    /* we need to copy the attribute since each attribute
 
2967
                     * only has one set of link list pointers */
 
2968
                    SFTKAttribute *newAttribute = sftk_NewAttribute(
 
2969
                          destObject,sftk_attr_expand(&attribute->attrib));
 
2970
                    if (newAttribute == NULL) {
 
2971
                        PZ_Unlock(src_so->attributeLock);
 
2972
                        return CKR_HOST_MEMORY;
 
2973
                    }
 
2974
                    sftk_AddAttribute(destObject,newAttribute);
 
2975
                }
 
2976
                attribute=attribute->next;
 
2977
            }
 
2978
        } while (attribute != NULL);
 
2979
    }
 
2980
    PZ_Unlock(src_so->attributeLock);
 
2981
 
 
2982
    return CKR_OK;
 
2983
}
 
2984
 
 
2985
/*
 
2986
 * ******************** Search Utilities *******************************
 
2987
 */
 
2988
 
 
2989
/* add an object to a search list */
 
2990
CK_RV
 
2991
AddToList(SFTKObjectListElement **list,SFTKObject *object)
 
2992
{
 
2993
     SFTKObjectListElement *newElem = 
 
2994
        (SFTKObjectListElement *)PORT_Alloc(sizeof(SFTKObjectListElement));
 
2995
 
 
2996
     if (newElem == NULL) return CKR_HOST_MEMORY;
 
2997
 
 
2998
     newElem->next = *list;
 
2999
     newElem->object = object;
 
3000
     sftk_ReferenceObject(object);
 
3001
 
 
3002
    *list = newElem;
 
3003
    return CKR_OK;
 
3004
}
 
3005
 
 
3006
 
 
3007
/* return true if the object matches the template */
 
3008
PRBool
 
3009
sftk_objectMatch(SFTKObject *object,CK_ATTRIBUTE_PTR theTemplate,int count)
 
3010
{
 
3011
    int i;
 
3012
 
 
3013
    for (i=0; i < count; i++) {
 
3014
        SFTKAttribute *attribute = sftk_FindAttribute(object,theTemplate[i].type);
 
3015
        if (attribute == NULL) {
 
3016
            return PR_FALSE;
 
3017
        }
 
3018
        if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) {
 
3019
            if (PORT_Memcmp(attribute->attrib.pValue,theTemplate[i].pValue,
 
3020
                                        theTemplate[i].ulValueLen) == 0) {
 
3021
                sftk_FreeAttribute(attribute);
 
3022
                continue;
 
3023
            }
 
3024
        }
 
3025
        sftk_FreeAttribute(attribute);
 
3026
        return PR_FALSE;
 
3027
    }
 
3028
    return PR_TRUE;
 
3029
}
 
3030
 
 
3031
/* search through all the objects in the queue and return the template matches
 
3032
 * in the object list.
 
3033
 */
 
3034
CK_RV
 
3035
sftk_searchObjectList(SFTKSearchResults *search,SFTKObject **head, 
 
3036
        unsigned int size, PZLock *lock, CK_ATTRIBUTE_PTR theTemplate, 
 
3037
                                                int count, PRBool isLoggedIn)
 
3038
{
 
3039
    unsigned int i;
 
3040
    SFTKObject *object;
 
3041
    CK_RV crv = CKR_OK;
 
3042
 
 
3043
    for(i=0; i < size; i++) {
 
3044
        /* We need to hold the lock to copy a consistant version of
 
3045
         * the linked list. */
 
3046
        PZ_Lock(lock);
 
3047
        for (object = head[i]; object != NULL; object= object->next) {
 
3048
            if (sftk_objectMatch(object,theTemplate,count)) {
 
3049
                /* don't return objects that aren't yet visible */
 
3050
                if ((!isLoggedIn) && sftk_isTrue(object,CKA_PRIVATE)) continue;
 
3051
                sftk_addHandle(search,object->handle);
 
3052
            }
 
3053
        }
 
3054
        PZ_Unlock(lock);
 
3055
    }
 
3056
    return crv;
 
3057
}
 
3058
 
 
3059
/*
 
3060
 * free a single list element. Return the Next object in the list.
 
3061
 */
 
3062
SFTKObjectListElement *
 
3063
sftk_FreeObjectListElement(SFTKObjectListElement *objectList)
 
3064
{
 
3065
    SFTKObjectListElement *ol = objectList->next;
 
3066
 
 
3067
    sftk_FreeObject(objectList->object);
 
3068
    PORT_Free(objectList);
 
3069
    return ol;
 
3070
}
 
3071
 
 
3072
/* free an entire object list */
 
3073
void
 
3074
sftk_FreeObjectList(SFTKObjectListElement *objectList)
 
3075
{
 
3076
    SFTKObjectListElement *ol;
 
3077
 
 
3078
    for (ol= objectList; ol != NULL; ol = sftk_FreeObjectListElement(ol)) {}
 
3079
}
 
3080
 
 
3081
/*
 
3082
 * free a search structure
 
3083
 */
 
3084
void
 
3085
sftk_FreeSearch(SFTKSearchResults *search)
 
3086
{
 
3087
    if (search->handles) {
 
3088
        PORT_Free(search->handles);
 
3089
    }
 
3090
    PORT_Free(search);
 
3091
}
 
3092
 
 
3093
/*
 
3094
 * ******************** Session Utilities *******************************
 
3095
 */
 
3096
 
 
3097
/* update the sessions state based in it's flags and wether or not it's
 
3098
 * logged in */
 
3099
void
 
3100
sftk_update_state(SFTKSlot *slot,SFTKSession *session)
 
3101
{
 
3102
    if (slot->isLoggedIn) {
 
3103
        if (slot->ssoLoggedIn) {
 
3104
            session->info.state = CKS_RW_SO_FUNCTIONS;
 
3105
        } else if (session->info.flags & CKF_RW_SESSION) {
 
3106
            session->info.state = CKS_RW_USER_FUNCTIONS;
 
3107
        } else {
 
3108
            session->info.state = CKS_RO_USER_FUNCTIONS;
 
3109
        }
 
3110
    } else {
 
3111
        if (session->info.flags & CKF_RW_SESSION) {
 
3112
            session->info.state = CKS_RW_PUBLIC_SESSION;
 
3113
        } else {
 
3114
            session->info.state = CKS_RO_PUBLIC_SESSION;
 
3115
        }
 
3116
    }
 
3117
}
 
3118
 
 
3119
/* update the state of all the sessions on a slot */
 
3120
void
 
3121
sftk_update_all_states(SFTKSlot *slot)
 
3122
{
 
3123
    unsigned int i;
 
3124
    SFTKSession *session;
 
3125
 
 
3126
    for (i=0; i < slot->sessHashSize; i++) {
 
3127
        PZLock *lock = SFTK_SESSION_LOCK(slot,i);
 
3128
        PZ_Lock(lock);
 
3129
        for (session = slot->head[i]; session; session = session->next) {
 
3130
            sftk_update_state(slot,session);
 
3131
        }
 
3132
        PZ_Unlock(lock);
 
3133
    }
 
3134
}
 
3135
 
 
3136
/*
 
3137
 * context are cipher and digest contexts that are associated with a session
 
3138
 */
 
3139
void
 
3140
sftk_FreeContext(SFTKSessionContext *context)
 
3141
{
 
3142
    if (context->cipherInfo) {
 
3143
        (*context->destroy)(context->cipherInfo,PR_TRUE);
 
3144
    }
 
3145
    if (context->hashInfo) {
 
3146
        (*context->hashdestroy)(context->hashInfo,PR_TRUE);
 
3147
    }
 
3148
    if (context->key) {
 
3149
        sftk_FreeObject(context->key);
 
3150
        context->key = NULL;
 
3151
    }
 
3152
    PORT_Free(context);
 
3153
}
 
3154
 
 
3155
/*
 
3156
 * create a new nession. NOTE: The session handle is not set, and the
 
3157
 * session is not added to the slot's session queue.
 
3158
 */
 
3159
SFTKSession *
 
3160
sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
 
3161
                                                             CK_FLAGS flags)
 
3162
{
 
3163
    SFTKSession *session;
 
3164
    SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
 
3165
 
 
3166
    if (slot == NULL) return NULL;
 
3167
 
 
3168
    session = (SFTKSession*)PORT_Alloc(sizeof(SFTKSession));
 
3169
    if (session == NULL) return NULL;
 
3170
 
 
3171
    session->next = session->prev = NULL;
 
3172
    session->refCount = 1;
 
3173
    session->enc_context = NULL;
 
3174
    session->hash_context = NULL;
 
3175
    session->sign_context = NULL;
 
3176
    session->search = NULL;
 
3177
    session->objectIDCount = 1;
 
3178
    session->objectLock = PZ_NewLock(nssILockObject);
 
3179
    if (session->objectLock == NULL) {
 
3180
        PORT_Free(session);
 
3181
        return NULL;
 
3182
    }
 
3183
    session->objects[0] = NULL;
 
3184
 
 
3185
    session->slot = slot;
 
3186
    session->notify = notify;
 
3187
    session->appData = pApplication;
 
3188
    session->info.flags = flags;
 
3189
    session->info.slotID = slotID;
 
3190
    session->info.ulDeviceError = 0;
 
3191
    sftk_update_state(slot,session);
 
3192
    return session;
 
3193
}
 
3194
 
 
3195
 
 
3196
/* free all the data associated with a session. */
 
3197
static void
 
3198
sftk_DestroySession(SFTKSession *session)
 
3199
{
 
3200
    SFTKObjectList *op,*next;
 
3201
    PORT_Assert(session->refCount == 0);
 
3202
 
 
3203
    /* clean out the attributes */
 
3204
    /* since no one is referencing us, it's safe to walk the chain
 
3205
     * without a lock */
 
3206
    for (op = session->objects[0]; op != NULL; op = next) {
 
3207
        next = op->next;
 
3208
        /* paranoia */
 
3209
        op->next = op->prev = NULL;
 
3210
        sftk_DeleteObject(session,op->parent);
 
3211
    }
 
3212
    PZ_DestroyLock(session->objectLock);
 
3213
    if (session->enc_context) {
 
3214
        sftk_FreeContext(session->enc_context);
 
3215
    }
 
3216
    if (session->hash_context) {
 
3217
        sftk_FreeContext(session->hash_context);
 
3218
    }
 
3219
    if (session->sign_context) {
 
3220
        sftk_FreeContext(session->sign_context);
 
3221
    }
 
3222
    if (session->search) {
 
3223
        sftk_FreeSearch(session->search);
 
3224
    }
 
3225
    PORT_Free(session);
 
3226
}
 
3227
 
 
3228
 
 
3229
/*
 
3230
 * look up a session structure from a session handle
 
3231
 * generate a reference to it.
 
3232
 */
 
3233
SFTKSession *
 
3234
sftk_SessionFromHandle(CK_SESSION_HANDLE handle)
 
3235
{
 
3236
    SFTKSlot    *slot = sftk_SlotFromSessionHandle(handle);
 
3237
    SFTKSession *session;
 
3238
    PZLock      *lock;
 
3239
    
 
3240
    if (!slot) return NULL;
 
3241
    lock = SFTK_SESSION_LOCK(slot,handle);
 
3242
 
 
3243
    PZ_Lock(lock);
 
3244
    sftkqueue_find(session,handle,slot->head,slot->sessHashSize);
 
3245
    if (session) session->refCount++;
 
3246
    PZ_Unlock(lock);
 
3247
 
 
3248
    return (session);
 
3249
}
 
3250
 
 
3251
/*
 
3252
 * release a reference to a session handle
 
3253
 */
 
3254
void
 
3255
sftk_FreeSession(SFTKSession *session)
 
3256
{
 
3257
    PRBool destroy = PR_FALSE;
 
3258
    SFTKSlot *slot = sftk_SlotFromSession(session);
 
3259
    PZLock *lock = SFTK_SESSION_LOCK(slot,session->handle);
 
3260
 
 
3261
    PZ_Lock(lock);
 
3262
    if (session->refCount == 1) destroy = PR_TRUE;
 
3263
    session->refCount--;
 
3264
    PZ_Unlock(lock);
 
3265
 
 
3266
    if (destroy) sftk_DestroySession(session);
 
3267
}
 
3268
/*
 
3269
 * handle Token Object stuff
 
3270
 */
 
3271
static void
 
3272
sftk_XORHash(unsigned char *key, unsigned char *dbkey, int len)
 
3273
{
 
3274
   int i;
 
3275
 
 
3276
   PORT_Memset(key, 0, 4);
 
3277
 
 
3278
   for (i=0; i < len-4; i += 4) {
 
3279
        key[0] ^= dbkey[i];
 
3280
        key[1] ^= dbkey[i+1];
 
3281
        key[2] ^= dbkey[i+2];
 
3282
        key[3] ^= dbkey[i+3];
 
3283
   }
 
3284
}
 
3285
 
 
3286
/* Make a token handle for an object and record it so we can find it again */
 
3287
CK_OBJECT_HANDLE
 
3288
sftk_mkHandle(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class)
 
3289
{
 
3290
    unsigned char hashBuf[4];
 
3291
    CK_OBJECT_HANDLE handle;
 
3292
    SECItem *key;
 
3293
 
 
3294
    handle = class;
 
3295
    /* there is only one KRL, use a fixed handle for it */
 
3296
    if (handle != SFTK_TOKEN_KRL_HANDLE) {
 
3297
        sftk_XORHash(hashBuf,dbKey->data,dbKey->len);
 
3298
        handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) | 
 
3299
                                        (hashBuf[2] << 8)  | hashBuf[3];
 
3300
        handle = SFTK_TOKEN_MAGIC | class | 
 
3301
                        (handle & ~(SFTK_TOKEN_TYPE_MASK|SFTK_TOKEN_MASK));
 
3302
        /* we have a CRL who's handle has randomly matched the reserved KRL
 
3303
         * handle, increment it */
 
3304
        if (handle == SFTK_TOKEN_KRL_HANDLE) {
 
3305
            handle++;
 
3306
        }
 
3307
    }
 
3308
 
 
3309
    sftk_tokenKeyLock(slot);
 
3310
    while ((key = sftk_lookupTokenKeyByHandle(slot,handle)) != NULL) {
 
3311
        if (SECITEM_ItemsAreEqual(key,dbKey)) {
 
3312
           sftk_tokenKeyUnlock(slot);
 
3313
           return handle;
 
3314
        }
 
3315
        handle++;
 
3316
    }
 
3317
    sftk_addTokenKeyByHandle(slot,handle,dbKey);
 
3318
    sftk_tokenKeyUnlock(slot);
 
3319
    return handle;
 
3320
}
 
3321
 
 
3322
PRBool
 
3323
sftk_poisonHandle(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class)
 
3324
{
 
3325
    unsigned char hashBuf[4];
 
3326
    CK_OBJECT_HANDLE handle;
 
3327
    SECItem *key;
 
3328
 
 
3329
    handle = class;
 
3330
    /* there is only one KRL, use a fixed handle for it */
 
3331
    if (handle != SFTK_TOKEN_KRL_HANDLE) {
 
3332
        sftk_XORHash(hashBuf,dbKey->data,dbKey->len);
 
3333
        handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) | 
 
3334
                                        (hashBuf[2] << 8)  | hashBuf[3];
 
3335
        handle = SFTK_TOKEN_MAGIC | class | 
 
3336
                        (handle & ~(SFTK_TOKEN_TYPE_MASK|SFTK_TOKEN_MASK));
 
3337
        /* we have a CRL who's handle has randomly matched the reserved KRL
 
3338
         * handle, increment it */
 
3339
        if (handle == SFTK_TOKEN_KRL_HANDLE) {
 
3340
            handle++;
 
3341
        }
 
3342
    }
 
3343
    sftk_tokenKeyLock(slot);
 
3344
    while ((key = sftk_lookupTokenKeyByHandle(slot,handle)) != NULL) {
 
3345
        if (SECITEM_ItemsAreEqual(key,dbKey)) {
 
3346
           key->data[0] ^= 0x80;
 
3347
           sftk_tokenKeyUnlock(slot);
 
3348
           return PR_TRUE;
 
3349
        }
 
3350
        handle++;
 
3351
    }
 
3352
    sftk_tokenKeyUnlock(slot);
 
3353
    return PR_FALSE;
 
3354
}
 
3355
 
 
3356
void
 
3357
sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle)
 
3358
{
 
3359
    if (search->handles == NULL) {
 
3360
        return;
 
3361
    }
 
3362
    if (search->size >= search->array_size) {
 
3363
        search->array_size += NSC_SEARCH_BLOCK_SIZE;
 
3364
        search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles,
 
3365
                                 sizeof(CK_OBJECT_HANDLE)* search->array_size);
 
3366
        if (search->handles == NULL) {
 
3367
           return;
 
3368
        }
 
3369
    }
 
3370
    search->handles[search->size] = handle;
 
3371
    search->size++;
 
3372
}
 
3373
 
 
3374
static const CK_OBJECT_HANDLE sftk_classArray[] = {
 
3375
    0, CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_SECRET_KEY,
 
3376
    CKO_NETSCAPE_TRUST, CKO_NETSCAPE_CRL, CKO_NETSCAPE_SMIME,
 
3377
     CKO_CERTIFICATE };
 
3378
 
 
3379
#define handleToClass(handle) \
 
3380
    sftk_classArray[((handle & SFTK_TOKEN_TYPE_MASK))>>28]
 
3381
 
 
3382
SFTKObject *
 
3383
sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
 
3384
{
 
3385
    SFTKObject *object = NULL;
 
3386
    SFTKTokenObject *tokObject = NULL;
 
3387
    PRBool hasLocks = PR_FALSE;
 
3388
    SECStatus rv;
 
3389
 
 
3390
    object = sftk_GetObjectFromList(&hasLocks, PR_FALSE, &tokenObjectList,  0,
 
3391
                                                        PR_FALSE);
 
3392
    if (object == NULL) {
 
3393
        return NULL;
 
3394
    }
 
3395
    tokObject = (SFTKTokenObject *) object;
 
3396
 
 
3397
    object->objclass = handleToClass(handle);
 
3398
    object->handle = handle;
 
3399
    object->slot = slot;
 
3400
    object->objectInfo = NULL;
 
3401
    object->infoFree = NULL;
 
3402
    if (dbKey == NULL) {
 
3403
        sftk_tokenKeyLock(slot);
 
3404
        dbKey = sftk_lookupTokenKeyByHandle(slot,handle);
 
3405
        if (dbKey == NULL) {
 
3406
            sftk_tokenKeyUnlock(slot);
 
3407
            goto loser;
 
3408
        }
 
3409
        rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey);
 
3410
        sftk_tokenKeyUnlock(slot);
 
3411
    } else {
 
3412
        rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey);
 
3413
    }
 
3414
    if (rv != SECSuccess) {
 
3415
        goto loser;
 
3416
    }
 
3417
    if (!hasLocks) {
 
3418
        object->refLock = PZ_NewLock(nssILockRefLock);
 
3419
    }
 
3420
    if (object->refLock == NULL) {
 
3421
        goto loser;
 
3422
    }
 
3423
    object->refCount = 1;
 
3424
 
 
3425
    return object;
 
3426
loser:
 
3427
    if (object) {
 
3428
        (void) sftk_DestroyObject(object);
 
3429
    }
 
3430
    return NULL;
 
3431
 
 
3432
}
 
3433
 
 
3434
PRBool
 
3435
sftk_tokenMatch(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class,
 
3436
                                        CK_ATTRIBUTE_PTR theTemplate,int count)
 
3437
{
 
3438
    SFTKObject *object;
 
3439
    PRBool ret;
 
3440
 
 
3441
    object = sftk_NewTokenObject(slot,dbKey,SFTK_TOKEN_MASK|class);
 
3442
    if (object == NULL) {
 
3443
        return PR_FALSE;
 
3444
    }
 
3445
 
 
3446
    ret = sftk_objectMatch(object,theTemplate,count);
 
3447
    sftk_FreeObject(object);
 
3448
    return ret;
 
3449
}
 
3450
 
 
3451
SFTKTokenObject *
 
3452
sftk_convertSessionToToken(SFTKObject *obj)
 
3453
{
 
3454
    SECItem *key;
 
3455
    SFTKSessionObject *so = (SFTKSessionObject *)obj;
 
3456
    SFTKTokenObject *to = sftk_narrowToTokenObject(obj);
 
3457
    SECStatus rv;
 
3458
 
 
3459
    sftk_DestroySessionObjectData(so);
 
3460
    PZ_DestroyLock(so->attributeLock);
 
3461
    if (to == NULL) {
 
3462
        return NULL;
 
3463
    }
 
3464
    sftk_tokenKeyLock(so->obj.slot);
 
3465
    key = sftk_lookupTokenKeyByHandle(so->obj.slot,so->obj.handle);
 
3466
    if (key == NULL) {
 
3467
        sftk_tokenKeyUnlock(so->obj.slot);
 
3468
        return NULL;
 
3469
    }
 
3470
    rv = SECITEM_CopyItem(NULL,&to->dbKey,key);
 
3471
    sftk_tokenKeyUnlock(so->obj.slot);
 
3472
    if (rv == SECFailure) {
 
3473
        return NULL;
 
3474
    }
 
3475
 
 
3476
    return to;
 
3477
 
 
3478
}
 
3479
 
 
3480
SFTKSessionObject *
 
3481
sftk_narrowToSessionObject(SFTKObject *obj)
 
3482
{
 
3483
    return !sftk_isToken(obj->handle) ? (SFTKSessionObject *)obj : NULL;
 
3484
}
 
3485
 
 
3486
SFTKTokenObject *
 
3487
sftk_narrowToTokenObject(SFTKObject *obj)
 
3488
{
 
3489
    return sftk_isToken(obj->handle) ? (SFTKTokenObject *)obj : NULL;
 
3490
}
 
3491