Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/nss/lib/pk11wrap/pk11skey.c
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
/*
5
 * This file implements the Symkey wrapper and the PKCS context
6
 * Interfaces.
7
 */
8
9
#include "seccomon.h"
10
#include "secmod.h"
11
#include "nssilock.h"
12
#include "secmodi.h"
13
#include "secmodti.h"
14
#include "pkcs11.h"
15
#include "pk11func.h"
16
#include "secitem.h"
17
#include "secoid.h"
18
#include "secerr.h"
19
#include "hasht.h"
20
21
static ECPointEncoding pk11_ECGetPubkeyEncoding(const SECKEYPublicKey *pubKey);
22
23
static void
24
pk11_EnterKeyMonitor(PK11SymKey *symKey)
25
0
{
26
0
    if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe))
27
0
        PK11_EnterSlotMonitor(symKey->slot);
28
0
}
29
30
static void
31
pk11_ExitKeyMonitor(PK11SymKey *symKey)
32
0
{
33
0
    if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe))
34
0
        PK11_ExitSlotMonitor(symKey->slot);
35
0
}
36
37
/*
38
 * pk11_getKeyFromList returns a symKey that has a session (if needSession
39
 * was specified), or explicitly does not have a session (if needSession
40
 * was not specified).
41
 */
42
static PK11SymKey *
43
pk11_getKeyFromList(PK11SlotInfo *slot, PRBool needSession)
44
0
{
45
0
    PK11SymKey *symKey = NULL;
46
0
47
0
    PZ_Lock(slot->freeListLock);
48
0
    /* own session list are symkeys with sessions that the symkey owns.
49
0
     * 'most' symkeys will own their own session. */
50
0
    if (needSession) {
51
0
        if (slot->freeSymKeysWithSessionHead) {
52
0
            symKey = slot->freeSymKeysWithSessionHead;
53
0
            slot->freeSymKeysWithSessionHead = symKey->next;
54
0
            slot->keyCount--;
55
0
        }
56
0
    }
57
0
    /* if we don't need a symkey with its own session, or we couldn't find
58
0
     * one on the owner list, get one from the non-owner free list. */
59
0
    if (!symKey) {
60
0
        if (slot->freeSymKeysHead) {
61
0
            symKey = slot->freeSymKeysHead;
62
0
            slot->freeSymKeysHead = symKey->next;
63
0
            slot->keyCount--;
64
0
        }
65
0
    }
66
0
    PZ_Unlock(slot->freeListLock);
67
0
    if (symKey) {
68
0
        symKey->next = NULL;
69
0
        if (!needSession) {
70
0
            return symKey;
71
0
        }
72
0
        /* if we are getting an owner key, make sure we have a valid session.
73
0
         * session could be invalid if the token has been removed or because
74
0
         * we got it from the non-owner free list */
75
0
        if ((symKey->series != slot->series) ||
76
0
            (symKey->session == CK_INVALID_SESSION)) {
77
0
            symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner);
78
0
        }
79
0
        PORT_Assert(symKey->session != CK_INVALID_SESSION);
80
0
        if (symKey->session != CK_INVALID_SESSION)
81
0
            return symKey;
82
0
        PK11_FreeSymKey(symKey);
83
0
        /* if we are here, we need a session, but couldn't get one, it's
84
0
         * unlikely we pk11_GetNewSession will succeed if we call it a second
85
0
         * time. */
86
0
        return NULL;
87
0
    }
88
0
89
0
    symKey = PORT_New(PK11SymKey);
90
0
    if (symKey == NULL) {
91
0
        return NULL;
92
0
    }
93
0
94
0
    symKey->next = NULL;
95
0
    if (needSession) {
96
0
        symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner);
97
0
        PORT_Assert(symKey->session != CK_INVALID_SESSION);
98
0
        if (symKey->session == CK_INVALID_SESSION) {
99
0
            PK11_FreeSymKey(symKey);
100
0
            symKey = NULL;
101
0
        }
102
0
    } else {
103
0
        symKey->session = CK_INVALID_SESSION;
104
0
    }
105
0
    return symKey;
106
0
}
107
108
/* Caller MUST hold slot->freeListLock (or ref count == 0?) !! */
109
void
110
PK11_CleanKeyList(PK11SlotInfo *slot)
111
0
{
112
0
    PK11SymKey *symKey = NULL;
113
0
114
0
    while (slot->freeSymKeysWithSessionHead) {
115
0
        symKey = slot->freeSymKeysWithSessionHead;
116
0
        slot->freeSymKeysWithSessionHead = symKey->next;
117
0
        pk11_CloseSession(slot, symKey->session, symKey->sessionOwner);
118
0
        PORT_Free(symKey);
119
0
    }
120
0
    while (slot->freeSymKeysHead) {
121
0
        symKey = slot->freeSymKeysHead;
122
0
        slot->freeSymKeysHead = symKey->next;
123
0
        pk11_CloseSession(slot, symKey->session, symKey->sessionOwner);
124
0
        PORT_Free(symKey);
125
0
    }
126
0
    return;
127
0
}
128
129
/*
130
 * create a symetric key:
131
 *      Slot is the slot to create the key in.
132
 *      type is the mechanism type
133
 *      owner is does this symKey structure own it's object handle (rare
134
 *        that this is false).
135
 *      needSession means the returned symKey will return with a valid session
136
 *        allocated already.
137
 */
138
static PK11SymKey *
139
pk11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
140
                  PRBool owner, PRBool needSession, void *wincx)
141
0
{
142
0
143
0
    PK11SymKey *symKey = pk11_getKeyFromList(slot, needSession);
144
0
145
0
    if (symKey == NULL) {
146
0
        return NULL;
147
0
    }
148
0
    /* if needSession was specified, make sure we have a valid session.
149
0
     * callers which specify needSession as false should do their own
150
0
     * check of the session before returning the symKey */
151
0
    if (needSession && symKey->session == CK_INVALID_SESSION) {
152
0
        PK11_FreeSymKey(symKey);
153
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
154
0
        return NULL;
155
0
    }
156
0
157
0
    symKey->type = type;
158
0
    symKey->data.type = siBuffer;
159
0
    symKey->data.data = NULL;
160
0
    symKey->data.len = 0;
161
0
    symKey->owner = owner;
162
0
    symKey->objectID = CK_INVALID_HANDLE;
163
0
    symKey->slot = slot;
164
0
    symKey->series = slot->series;
165
0
    symKey->cx = wincx;
166
0
    symKey->size = 0;
167
0
    symKey->refCount = 1;
168
0
    symKey->origin = PK11_OriginNULL;
169
0
    symKey->parent = NULL;
170
0
    symKey->freeFunc = NULL;
171
0
    symKey->userData = NULL;
172
0
    PK11_ReferenceSlot(slot);
173
0
    return symKey;
174
0
}
175
176
/*
177
 * destroy a symetric key
178
 */
179
void
180
PK11_FreeSymKey(PK11SymKey *symKey)
181
0
{
182
0
    PK11SlotInfo *slot;
183
0
    PRBool freeit = PR_TRUE;
184
0
185
0
    if (!symKey) {
186
0
        return;
187
0
    }
188
0
189
0
    if (PR_ATOMIC_DECREMENT(&symKey->refCount) == 0) {
190
0
        PK11SymKey *parent = symKey->parent;
191
0
192
0
        symKey->parent = NULL;
193
0
        if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE) {
194
0
            pk11_EnterKeyMonitor(symKey);
195
0
            (void)PK11_GETTAB(symKey->slot)->C_DestroyObject(symKey->session, symKey->objectID);
196
0
            pk11_ExitKeyMonitor(symKey);
197
0
        }
198
0
        if (symKey->data.data) {
199
0
            PORT_Memset(symKey->data.data, 0, symKey->data.len);
200
0
            PORT_Free(symKey->data.data);
201
0
        }
202
0
        /* free any existing data */
203
0
        if (symKey->userData && symKey->freeFunc) {
204
0
            (*symKey->freeFunc)(symKey->userData);
205
0
        }
206
0
        slot = symKey->slot;
207
0
        PZ_Lock(slot->freeListLock);
208
0
        if (slot->keyCount < slot->maxKeyCount) {
209
0
            /*
210
0
             * freeSymkeysWithSessionHead contain a list of reusable
211
0
             *  SymKey structures with valid sessions.
212
0
             *    sessionOwner must be true.
213
0
             *    session must be valid.
214
0
             * freeSymKeysHead contain a list of SymKey structures without
215
0
             *  valid session.
216
0
             *    session must be CK_INVALID_SESSION.
217
0
             *    though sessionOwner is false, callers should not depend on
218
0
             *    this fact.
219
0
             */
220
0
            if (symKey->sessionOwner) {
221
0
                PORT_Assert(symKey->session != CK_INVALID_SESSION);
222
0
                symKey->next = slot->freeSymKeysWithSessionHead;
223
0
                slot->freeSymKeysWithSessionHead = symKey;
224
0
            } else {
225
0
                symKey->session = CK_INVALID_SESSION;
226
0
                symKey->next = slot->freeSymKeysHead;
227
0
                slot->freeSymKeysHead = symKey;
228
0
            }
229
0
            slot->keyCount++;
230
0
            symKey->slot = NULL;
231
0
            freeit = PR_FALSE;
232
0
        }
233
0
        PZ_Unlock(slot->freeListLock);
234
0
        if (freeit) {
235
0
            pk11_CloseSession(symKey->slot, symKey->session,
236
0
                              symKey->sessionOwner);
237
0
            PORT_Free(symKey);
238
0
        }
239
0
        PK11_FreeSlot(slot);
240
0
241
0
        if (parent) {
242
0
            PK11_FreeSymKey(parent);
243
0
        }
244
0
    }
245
0
}
246
247
PK11SymKey *
248
PK11_ReferenceSymKey(PK11SymKey *symKey)
249
0
{
250
0
    PR_ATOMIC_INCREMENT(&symKey->refCount);
251
0
    return symKey;
252
0
}
253
254
/*
255
 * Accessors
256
 */
257
CK_MECHANISM_TYPE
258
PK11_GetMechanism(PK11SymKey *symKey)
259
0
{
260
0
    return symKey->type;
261
0
}
262
263
/*
264
 * return the slot associated with a symetric key
265
 */
266
PK11SlotInfo *
267
PK11_GetSlotFromKey(PK11SymKey *symKey)
268
0
{
269
0
    return PK11_ReferenceSlot(symKey->slot);
270
0
}
271
272
CK_KEY_TYPE
273
PK11_GetSymKeyType(PK11SymKey *symKey)
274
0
{
275
0
    return PK11_GetKeyType(symKey->type, symKey->size);
276
0
}
277
278
PK11SymKey *
279
PK11_GetNextSymKey(PK11SymKey *symKey)
280
0
{
281
0
    return symKey ? symKey->next : NULL;
282
0
}
283
284
char *
285
PK11_GetSymKeyNickname(PK11SymKey *symKey)
286
0
{
287
0
    return PK11_GetObjectNickname(symKey->slot, symKey->objectID);
288
0
}
289
290
SECStatus
291
PK11_SetSymKeyNickname(PK11SymKey *symKey, const char *nickname)
292
0
{
293
0
    return PK11_SetObjectNickname(symKey->slot, symKey->objectID, nickname);
294
0
}
295
296
void *
297
PK11_GetSymKeyUserData(PK11SymKey *symKey)
298
0
{
299
0
    return symKey->userData;
300
0
}
301
302
void
303
PK11_SetSymKeyUserData(PK11SymKey *symKey, void *userData,
304
                       PK11FreeDataFunc freeFunc)
305
0
{
306
0
    /* free any existing data */
307
0
    if (symKey->userData && symKey->freeFunc) {
308
0
        (*symKey->freeFunc)(symKey->userData);
309
0
    }
310
0
    symKey->userData = userData;
311
0
    symKey->freeFunc = freeFunc;
312
0
    return;
313
0
}
314
315
/*
316
 * turn key handle into an appropriate key object
317
 */
318
PK11SymKey *
319
PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin,
320
                      CK_MECHANISM_TYPE type, CK_OBJECT_HANDLE keyID, PRBool owner, void *wincx)
321
0
{
322
0
    PK11SymKey *symKey;
323
0
    PRBool needSession = !(owner && parent);
324
0
325
0
    if (keyID == CK_INVALID_HANDLE) {
326
0
        return NULL;
327
0
    }
328
0
329
0
    symKey = pk11_CreateSymKey(slot, type, owner, needSession, wincx);
330
0
    if (symKey == NULL) {
331
0
        return NULL;
332
0
    }
333
0
334
0
    symKey->objectID = keyID;
335
0
    symKey->origin = origin;
336
0
337
0
    /* adopt the parent's session */
338
0
    /* This is only used by SSL. What we really want here is a session
339
0
     * structure with a ref count so  the session goes away only after all the
340
0
     * keys do. */
341
0
    if (!needSession) {
342
0
        symKey->sessionOwner = PR_FALSE;
343
0
        symKey->session = parent->session;
344
0
        symKey->parent = PK11_ReferenceSymKey(parent);
345
0
        /* This is the only case where pk11_CreateSymKey does not explicitly
346
0
         * check symKey->session. We need to assert here to make sure.
347
0
         * the session isn't invalid. */
348
0
        PORT_Assert(parent->session != CK_INVALID_SESSION);
349
0
        if (parent->session == CK_INVALID_SESSION) {
350
0
            PK11_FreeSymKey(symKey);
351
0
            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
352
0
            return NULL;
353
0
        }
354
0
    }
355
0
356
0
    return symKey;
357
0
}
358
359
/*
360
 * turn key handle into an appropriate key object
361
 */
362
PK11SymKey *
363
PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type,
364
                int series, void *wincx)
365
0
{
366
0
    PK11SymKey *symKey = NULL;
367
0
368
0
    if (slot->series != series)
369
0
        return NULL;
370
0
    if (slot->refKeys[wrap] == CK_INVALID_HANDLE)
371
0
        return NULL;
372
0
    if (type == CKM_INVALID_MECHANISM)
373
0
        type = slot->wrapMechanism;
374
0
375
0
    symKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive,
376
0
                                   slot->wrapMechanism, slot->refKeys[wrap], PR_FALSE, wincx);
377
0
    return symKey;
378
0
}
379
380
/*
381
 * This function is not thread-safe because it sets wrapKey->sessionOwner
382
 * without using a lock or atomic routine.  It can only be called when
383
 * only one thread has a reference to wrapKey.
384
 */
385
void
386
PK11_SetWrapKey(PK11SlotInfo *slot, int wrap, PK11SymKey *wrapKey)
387
0
{
388
0
    /* save the handle and mechanism for the wrapping key */
389
0
    /* mark the key and session as not owned by us to they don't get freed
390
0
     * when the key goes way... that lets us reuse the key later */
391
0
    slot->refKeys[wrap] = wrapKey->objectID;
392
0
    wrapKey->owner = PR_FALSE;
393
0
    wrapKey->sessionOwner = PR_FALSE;
394
0
    slot->wrapMechanism = wrapKey->type;
395
0
}
396
397
/*
398
 * figure out if a key is still valid or if it is stale.
399
 */
400
PRBool
401
PK11_VerifyKeyOK(PK11SymKey *key)
402
0
{
403
0
    if (!PK11_IsPresent(key->slot)) {
404
0
        return PR_FALSE;
405
0
    }
406
0
    return (PRBool)(key->series == key->slot->series);
407
0
}
408
409
static PK11SymKey *
410
pk11_ImportSymKeyWithTempl(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
411
                           PK11Origin origin, PRBool isToken, CK_ATTRIBUTE *keyTemplate,
412
                           unsigned int templateCount, SECItem *key, void *wincx)
413
0
{
414
0
    PK11SymKey *symKey;
415
0
    SECStatus rv;
416
0
417
0
    symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx);
418
0
    if (symKey == NULL) {
419
0
        return NULL;
420
0
    }
421
0
422
0
    symKey->size = key->len;
423
0
424
0
    PK11_SETATTRS(&keyTemplate[templateCount], CKA_VALUE, key->data, key->len);
425
0
    templateCount++;
426
0
427
0
    if (SECITEM_CopyItem(NULL, &symKey->data, key) != SECSuccess) {
428
0
        PK11_FreeSymKey(symKey);
429
0
        return NULL;
430
0
    }
431
0
432
0
    symKey->origin = origin;
433
0
434
0
    /* import the keys */
435
0
    rv = PK11_CreateNewObject(slot, symKey->session, keyTemplate,
436
0
                              templateCount, isToken, &symKey->objectID);
437
0
    if (rv != SECSuccess) {
438
0
        PK11_FreeSymKey(symKey);
439
0
        return NULL;
440
0
    }
441
0
442
0
    return symKey;
443
0
}
444
445
/*
446
 * turn key bits into an appropriate key object
447
 */
448
PK11SymKey *
449
PK11_ImportSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
450
                  PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key, void *wincx)
451
0
{
452
0
    PK11SymKey *symKey;
453
0
    unsigned int templateCount = 0;
454
0
    CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
455
0
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
456
0
    CK_BBOOL cktrue = CK_TRUE; /* sigh */
457
0
    CK_ATTRIBUTE keyTemplate[5];
458
0
    CK_ATTRIBUTE *attrs = keyTemplate;
459
0
460
0
    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
461
0
    attrs++;
462
0
    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
463
0
    attrs++;
464
0
    PK11_SETATTRS(attrs, operation, &cktrue, 1);
465
0
    attrs++;
466
0
    templateCount = attrs - keyTemplate;
467
0
    PR_ASSERT(templateCount + 1 <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE));
468
0
469
0
    keyType = PK11_GetKeyType(type, key->len);
470
0
    symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, PR_FALSE,
471
0
                                        keyTemplate, templateCount, key, wincx);
472
0
    return symKey;
473
0
}
474
475
/*
476
 * turn key bits into an appropriate key object
477
 */
478
PK11SymKey *
479
PK11_ImportSymKeyWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
480
                           PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key,
481
                           CK_FLAGS flags, PRBool isPerm, void *wincx)
482
0
{
483
0
    PK11SymKey *symKey;
484
0
    unsigned int templateCount = 0;
485
0
    CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
486
0
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
487
0
    CK_BBOOL cktrue = CK_TRUE; /* sigh */
488
0
    CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
489
0
    CK_ATTRIBUTE *attrs = keyTemplate;
490
0
491
0
    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
492
0
    attrs++;
493
0
    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
494
0
    attrs++;
495
0
    if (isPerm) {
496
0
        PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue));
497
0
        attrs++;
498
0
        /* sigh some tokens think CKA_PRIVATE = false is a reasonable
499
0
         * default for secret keys */
500
0
        PK11_SETATTRS(attrs, CKA_PRIVATE, &cktrue, sizeof(cktrue));
501
0
        attrs++;
502
0
    }
503
0
    attrs += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
504
0
    if ((operation != CKA_FLAGS_ONLY) &&
505
0
        !pk11_FindAttrInTemplate(keyTemplate, attrs - keyTemplate, operation)) {
506
0
        PK11_SETATTRS(attrs, operation, &cktrue, sizeof(cktrue));
507
0
        attrs++;
508
0
    }
509
0
    templateCount = attrs - keyTemplate;
510
0
    PR_ASSERT(templateCount + 1 <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE));
511
0
512
0
    keyType = PK11_GetKeyType(type, key->len);
513
0
    symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, isPerm,
514
0
                                        keyTemplate, templateCount, key, wincx);
515
0
    if (symKey && isPerm) {
516
0
        symKey->owner = PR_FALSE;
517
0
    }
518
0
    return symKey;
519
0
}
520
521
PK11SymKey *
522
PK11_FindFixedKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *keyID,
523
                  void *wincx)
524
0
{
525
0
    CK_ATTRIBUTE findTemp[4];
526
0
    CK_ATTRIBUTE *attrs;
527
0
    CK_BBOOL ckTrue = CK_TRUE;
528
0
    CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY;
529
0
    int tsize = 0;
530
0
    CK_OBJECT_HANDLE key_id;
531
0
532
0
    attrs = findTemp;
533
0
    PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass));
534
0
    attrs++;
535
0
    PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue));
536
0
    attrs++;
537
0
    if (keyID) {
538
0
        PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len);
539
0
        attrs++;
540
0
    }
541
0
    tsize = attrs - findTemp;
542
0
    PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE));
543
0
544
0
    key_id = pk11_FindObjectByTemplate(slot, findTemp, tsize);
545
0
    if (key_id == CK_INVALID_HANDLE) {
546
0
        return NULL;
547
0
    }
548
0
    return PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, type, key_id,
549
0
                                 PR_FALSE, wincx);
550
0
}
551
552
PK11SymKey *
553
PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx)
554
0
{
555
0
    CK_ATTRIBUTE findTemp[4];
556
0
    CK_ATTRIBUTE *attrs;
557
0
    CK_BBOOL ckTrue = CK_TRUE;
558
0
    CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY;
559
0
    int tsize = 0;
560
0
    int objCount = 0;
561
0
    CK_OBJECT_HANDLE *key_ids;
562
0
    PK11SymKey *nextKey = NULL;
563
0
    PK11SymKey *topKey = NULL;
564
0
    int i, len;
565
0
566
0
    attrs = findTemp;
567
0
    PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass));
568
0
    attrs++;
569
0
    PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue));
570
0
    attrs++;
571
0
    if (nickname) {
572
0
        len = PORT_Strlen(nickname);
573
0
        PK11_SETATTRS(attrs, CKA_LABEL, nickname, len);
574
0
        attrs++;
575
0
    }
576
0
    tsize = attrs - findTemp;
577
0
    PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE));
578
0
579
0
    key_ids = pk11_FindObjectsByTemplate(slot, findTemp, tsize, &objCount);
580
0
    if (key_ids == NULL) {
581
0
        return NULL;
582
0
    }
583
0
584
0
    for (i = 0; i < objCount; i++) {
585
0
        SECItem typeData;
586
0
        CK_KEY_TYPE type = CKK_GENERIC_SECRET;
587
0
        SECStatus rv = PK11_ReadAttribute(slot, key_ids[i],
588
0
                                          CKA_KEY_TYPE, NULL, &typeData);
589
0
        if (rv == SECSuccess) {
590
0
            if (typeData.len == sizeof(CK_KEY_TYPE)) {
591
0
                type = *(CK_KEY_TYPE *)typeData.data;
592
0
            }
593
0
            PORT_Free(typeData.data);
594
0
        }
595
0
        nextKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive,
596
0
                                        PK11_GetKeyMechanism(type), key_ids[i], PR_FALSE, wincx);
597
0
        if (nextKey) {
598
0
            nextKey->next = topKey;
599
0
            topKey = nextKey;
600
0
        }
601
0
    }
602
0
    PORT_Free(key_ids);
603
0
    return topKey;
604
0
}
605
606
void *
607
PK11_GetWindow(PK11SymKey *key)
608
0
{
609
0
    return key->cx;
610
0
}
611
612
/*
613
 * extract a symetric key value. NOTE: if the key is sensitive, we will
614
 * not be able to do this operation. This function is used to move
615
 * keys from one token to another */
616
SECStatus
617
PK11_ExtractKeyValue(PK11SymKey *symKey)
618
0
{
619
0
    SECStatus rv;
620
0
621
0
    if (symKey->data.data != NULL) {
622
0
        if (symKey->size == 0) {
623
0
            symKey->size = symKey->data.len;
624
0
        }
625
0
        return SECSuccess;
626
0
    }
627
0
628
0
    if (symKey->slot == NULL) {
629
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
630
0
        return SECFailure;
631
0
    }
632
0
633
0
    rv = PK11_ReadAttribute(symKey->slot, symKey->objectID, CKA_VALUE, NULL,
634
0
                            &symKey->data);
635
0
    if (rv == SECSuccess) {
636
0
        symKey->size = symKey->data.len;
637
0
    }
638
0
    return rv;
639
0
}
640
641
SECStatus
642
PK11_DeleteTokenSymKey(PK11SymKey *symKey)
643
0
{
644
0
    if (!PK11_IsPermObject(symKey->slot, symKey->objectID)) {
645
0
        return SECFailure;
646
0
    }
647
0
    PK11_DestroyTokenObject(symKey->slot, symKey->objectID);
648
0
    symKey->objectID = CK_INVALID_HANDLE;
649
0
    return SECSuccess;
650
0
}
651
652
SECItem *
653
PK11_GetKeyData(PK11SymKey *symKey)
654
0
{
655
0
    return &symKey->data;
656
0
}
657
658
/* This symbol is exported for backward compatibility. */
659
SECItem *
660
__PK11_GetKeyData(PK11SymKey *symKey)
661
0
{
662
0
    return PK11_GetKeyData(symKey);
663
0
}
664
665
/*
666
 * PKCS #11 key Types with predefined length
667
 */
668
unsigned int
669
pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType)
670
0
{
671
0
    int length = 0;
672
0
    switch (keyType) {
673
0
        case CKK_DES:
674
0
            length = 8;
675
0
            break;
676
0
        case CKK_DES2:
677
0
            length = 16;
678
0
            break;
679
0
        case CKK_DES3:
680
0
            length = 24;
681
0
            break;
682
0
        case CKK_SKIPJACK:
683
0
            length = 10;
684
0
            break;
685
0
        case CKK_BATON:
686
0
            length = 20;
687
0
            break;
688
0
        case CKK_JUNIPER:
689
0
            length = 20;
690
0
            break;
691
0
        default:
692
0
            break;
693
0
    }
694
0
    return length;
695
0
}
696
697
/* return the keylength if possible.  '0' if not */
698
unsigned int
699
PK11_GetKeyLength(PK11SymKey *key)
700
0
{
701
0
    CK_KEY_TYPE keyType;
702
0
703
0
    if (key->size != 0)
704
0
        return key->size;
705
0
706
0
    /* First try to figure out the key length from its type */
707
0
    keyType = PK11_ReadULongAttribute(key->slot, key->objectID, CKA_KEY_TYPE);
708
0
    key->size = pk11_GetPredefinedKeyLength(keyType);
709
0
    if ((keyType == CKK_GENERIC_SECRET) &&
710
0
        (key->type == CKM_SSL3_PRE_MASTER_KEY_GEN)) {
711
0
        key->size = 48;
712
0
    }
713
0
714
0
    if (key->size != 0)
715
0
        return key->size;
716
0
717
0
    if (key->data.data == NULL) {
718
0
        PK11_ExtractKeyValue(key);
719
0
    }
720
0
    /* key is probably secret. Look up its length */
721
0
    /*  this is new PKCS #11 version 2.0 functionality. */
722
0
    if (key->size == 0) {
723
0
        CK_ULONG keyLength;
724
0
725
0
        keyLength = PK11_ReadULongAttribute(key->slot, key->objectID, CKA_VALUE_LEN);
726
0
        if (keyLength != CK_UNAVAILABLE_INFORMATION) {
727
0
            key->size = (unsigned int)keyLength;
728
0
        }
729
0
    }
730
0
731
0
    return key->size;
732
0
}
733
734
/* return the strength of a key. This is different from length in that
735
 * 1) it returns the size in bits, and 2) it returns only the secret portions
736
 * of the key minus any checksums or parity.
737
 */
738
unsigned int
739
PK11_GetKeyStrength(PK11SymKey *key, SECAlgorithmID *algid)
740
0
{
741
0
    int size = 0;
742
0
    CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; /* RC2 only */
743
0
    SECItem *param = NULL;                               /* RC2 only */
744
0
    CK_RC2_CBC_PARAMS *rc2_params = NULL;                /* RC2 ONLY */
745
0
    unsigned int effectiveBits = 0;                      /* RC2 ONLY */
746
0
747
0
    switch (PK11_GetKeyType(key->type, 0)) {
748
0
        case CKK_CDMF:
749
0
            return 40;
750
0
        case CKK_DES:
751
0
            return 56;
752
0
        case CKK_DES3:
753
0
        case CKK_DES2:
754
0
            size = PK11_GetKeyLength(key);
755
0
            if (size == 16) {
756
0
                /* double des */
757
0
                return 112; /* 16*7 */
758
0
            }
759
0
            return 168;
760
0
        /*
761
0
         * RC2 has is different than other ciphers in that it allows the user
762
0
         * to deprecating keysize while still requiring all the bits for the
763
0
         * original key. The info
764
0
         * on what the effective key strength is in the parameter for the key.
765
0
         * In S/MIME this parameter is stored in the DER encoded algid. In Our
766
0
         * other uses of RC2, effectiveBits == keyBits, so this code functions
767
0
         * correctly without an algid.
768
0
         */
769
0
        case CKK_RC2:
770
0
            /* if no algid was provided, fall through to default */
771
0
            if (!algid) {
772
0
                break;
773
0
            }
774
0
            /* verify that the algid is for RC2 */
775
0
            mechanism = PK11_AlgtagToMechanism(SECOID_GetAlgorithmTag(algid));
776
0
            if ((mechanism != CKM_RC2_CBC) && (mechanism != CKM_RC2_ECB)) {
777
0
                break;
778
0
            }
779
0
780
0
            /* now get effective bits from the algorithm ID. */
781
0
            param = PK11_ParamFromAlgid(algid);
782
0
            /* if we couldn't get memory just use key length */
783
0
            if (param == NULL) {
784
0
                break;
785
0
            }
786
0
787
0
            rc2_params = (CK_RC2_CBC_PARAMS *)param->data;
788
0
            /* paranoia... shouldn't happen */
789
0
            PORT_Assert(param->data != NULL);
790
0
            if (param->data == NULL) {
791
0
                SECITEM_FreeItem(param, PR_TRUE);
792
0
                break;
793
0
            }
794
0
            effectiveBits = (unsigned int)rc2_params->ulEffectiveBits;
795
0
            SECITEM_FreeItem(param, PR_TRUE);
796
0
            param = NULL;
797
0
            rc2_params = NULL; /* paranoia */
798
0
799
0
            /* we have effective bits, is and allocated memory is free, now
800
0
             * we need to return the smaller of effective bits and keysize */
801
0
            size = PK11_GetKeyLength(key);
802
0
            if ((unsigned int)size * 8 > effectiveBits) {
803
0
                return effectiveBits;
804
0
            }
805
0
806
0
            return size * 8; /* the actual key is smaller, the strength can't be
807
0
                              * greater than the actual key size */
808
0
809
0
        default:
810
0
            break;
811
0
    }
812
0
    return PK11_GetKeyLength(key) * 8;
813
0
}
814
815
/*
816
 * The next three utilities are to deal with the fact that a given operation
817
 * may be a multi-slot affair. This creates a new key object that is copied
818
 * into the new slot.
819
 */
820
PK11SymKey *
821
pk11_CopyToSlotPerm(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
822
                    CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags,
823
                    PRBool isPerm, PK11SymKey *symKey)
824
0
{
825
0
    SECStatus rv;
826
0
    PK11SymKey *newKey = NULL;
827
0
828
0
    /* Extract the raw key data if possible */
829
0
    if (symKey->data.data == NULL) {
830
0
        rv = PK11_ExtractKeyValue(symKey);
831
0
        /* KEY is sensitive, we're try key exchanging it. */
832
0
        if (rv != SECSuccess) {
833
0
            return pk11_KeyExchange(slot, type, operation,
834
0
                                    flags, isPerm, symKey);
835
0
        }
836
0
    }
837
0
838
0
    newKey = PK11_ImportSymKeyWithFlags(slot, type, symKey->origin,
839
0
                                        operation, &symKey->data, flags, isPerm, symKey->cx);
840
0
    if (newKey == NULL) {
841
0
        newKey = pk11_KeyExchange(slot, type, operation, flags, isPerm, symKey);
842
0
    }
843
0
    return newKey;
844
0
}
845
846
PK11SymKey *
847
pk11_CopyToSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
848
                CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey)
849
0
{
850
0
    return pk11_CopyToSlotPerm(slot, type, operation, 0, PR_FALSE, symKey);
851
0
}
852
853
/*
854
 * Make sure the slot we are in is the correct slot for the operation
855
 * by verifying that it supports all of the specified mechanism types.
856
 */
857
PK11SymKey *
858
pk11_ForceSlotMultiple(PK11SymKey *symKey, CK_MECHANISM_TYPE *type,
859
                       int mechCount, CK_ATTRIBUTE_TYPE operation)
860
0
{
861
0
    PK11SlotInfo *slot = symKey->slot;
862
0
    PK11SymKey *newKey = NULL;
863
0
    PRBool needToCopy = PR_FALSE;
864
0
    int i;
865
0
866
0
    if (slot == NULL) {
867
0
        needToCopy = PR_TRUE;
868
0
    } else {
869
0
        i = 0;
870
0
        while ((i < mechCount) && (needToCopy == PR_FALSE)) {
871
0
            if (!PK11_DoesMechanism(slot, type[i])) {
872
0
                needToCopy = PR_TRUE;
873
0
            }
874
0
            i++;
875
0
        }
876
0
    }
877
0
878
0
    if (needToCopy == PR_TRUE) {
879
0
        slot = PK11_GetBestSlotMultiple(type, mechCount, symKey->cx);
880
0
        if (slot == NULL) {
881
0
            PORT_SetError(SEC_ERROR_NO_MODULE);
882
0
            return NULL;
883
0
        }
884
0
        newKey = pk11_CopyToSlot(slot, type[0], operation, symKey);
885
0
        PK11_FreeSlot(slot);
886
0
    }
887
0
    return newKey;
888
0
}
889
890
/*
891
 * Make sure the slot we are in is the correct slot for the operation
892
 */
893
PK11SymKey *
894
pk11_ForceSlot(PK11SymKey *symKey, CK_MECHANISM_TYPE type,
895
               CK_ATTRIBUTE_TYPE operation)
896
0
{
897
0
    return pk11_ForceSlotMultiple(symKey, &type, 1, operation);
898
0
}
899
900
PK11SymKey *
901
PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation,
902
                CK_FLAGS flags, PRBool perm, PK11SymKey *symKey)
903
0
{
904
0
    if (symKey->slot == slot) {
905
0
        if (perm) {
906
0
            return PK11_ConvertSessionSymKeyToTokenSymKey(symKey, symKey->cx);
907
0
        } else {
908
0
            return PK11_ReferenceSymKey(symKey);
909
0
        }
910
0
    }
911
0
912
0
    return pk11_CopyToSlotPerm(slot, symKey->type,
913
0
                               operation, flags, perm, symKey);
914
0
}
915
916
/*
917
 * Use the token to generate a key.
918
 *
919
 * keySize must be 'zero' for fixed key length algorithms. A nonzero
920
 *  keySize causes the CKA_VALUE_LEN attribute to be added to the template
921
 *  for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN
922
 *  attribute for keys with fixed length. The exception is DES2. If you
923
 *  select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN
924
 *  parameter and use the key size to determine which underlying DES keygen
925
 *  function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN).
926
 *
927
 * keyType must be -1 for most algorithms. Some PBE algorthims cannot
928
 *  determine the correct key type from the mechanism or the parameters,
929
 *  so key type must be specified. Other PKCS #11 mechanisms may do so in
930
 *  the future. Currently there is no need to export this publically.
931
 *  Keep it private until there is a need in case we need to expand the
932
 *  keygen parameters again...
933
 *
934
 * CK_FLAGS flags: key operation flags
935
 * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags
936
 */
937
PK11SymKey *
938
pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
939
                                    SECItem *param, CK_KEY_TYPE keyType, int keySize, SECItem *keyid,
940
                                    CK_FLAGS opFlags, PK11AttrFlags attrFlags, void *wincx)
941
0
{
942
0
    PK11SymKey *symKey;
943
0
    CK_ATTRIBUTE genTemplate[MAX_TEMPL_ATTRS];
944
0
    CK_ATTRIBUTE *attrs = genTemplate;
945
0
    int count = sizeof(genTemplate) / sizeof(genTemplate[0]);
946
0
    CK_MECHANISM_TYPE keyGenType;
947
0
    CK_BBOOL cktrue = CK_TRUE;
948
0
    CK_BBOOL ckfalse = CK_FALSE;
949
0
    CK_ULONG ck_key_size; /* only used for variable-length keys */
950
0
951
0
    if (pk11_BadAttrFlags(attrFlags)) {
952
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
953
0
        return NULL;
954
0
    }
955
0
956
0
    if ((keySize != 0) && (type != CKM_DES3_CBC) &&
957
0
        (type != CKM_DES3_CBC_PAD) && (type != CKM_DES3_ECB)) {
958
0
        ck_key_size = keySize; /* Convert to PK11 type */
959
0
960
0
        PK11_SETATTRS(attrs, CKA_VALUE_LEN, &ck_key_size, sizeof(ck_key_size));
961
0
        attrs++;
962
0
    }
963
0
964
0
    if (keyType != -1) {
965
0
        PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(CK_KEY_TYPE));
966
0
        attrs++;
967
0
    }
968
0
969
0
    /* Include key id value if provided */
970
0
    if (keyid) {
971
0
        PK11_SETATTRS(attrs, CKA_ID, keyid->data, keyid->len);
972
0
        attrs++;
973
0
    }
974
0
975
0
    attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse);
976
0
    attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue);
977
0
978
0
    count = attrs - genTemplate;
979
0
    PR_ASSERT(count <= sizeof(genTemplate) / sizeof(CK_ATTRIBUTE));
980
0
981
0
    keyGenType = PK11_GetKeyGenWithSize(type, keySize);
982
0
    if (keyGenType == CKM_FAKE_RANDOM) {
983
0
        PORT_SetError(SEC_ERROR_NO_MODULE);
984
0
        return NULL;
985
0
    }
986
0
    symKey = PK11_KeyGenWithTemplate(slot, type, keyGenType,
987
0
                                     param, genTemplate, count, wincx);
988
0
    if (symKey != NULL) {
989
0
        symKey->size = keySize;
990
0
    }
991
0
    return symKey;
992
0
}
993
994
/*
995
 * Use the token to generate a key.  - Public
996
 *
997
 * keySize must be 'zero' for fixed key length algorithms. A nonzero
998
 *  keySize causes the CKA_VALUE_LEN attribute to be added to the template
999
 *  for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN
1000
 *  attribute for keys with fixed length. The exception is DES2. If you
1001
 *  select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN
1002
 *  parameter and use the key size to determine which underlying DES keygen
1003
 *  function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN).
1004
 *
1005
 * CK_FLAGS flags: key operation flags
1006
 * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags
1007
 */
1008
PK11SymKey *
1009
PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
1010
                          SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags,
1011
                          PK11AttrFlags attrFlags, void *wincx)
1012
0
{
1013
0
    return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param, -1, keySize,
1014
0
                                               keyid, opFlags, attrFlags, wincx);
1015
0
}
1016
1017
/*
1018
 * Use the token to generate a key. keySize must be 'zero' for fixed key
1019
 * length algorithms. A nonzero keySize causes the CKA_VALUE_LEN attribute
1020
 * to be added to the template for the key. PKCS #11 modules fail if you
1021
 * specify the CKA_VALUE_LEN attribute for keys with fixed length.
1022
 * NOTE: this means to generate a DES2 key from this interface you must
1023
 * specify CKM_DES2_KEY_GEN as the mechanism directly; specifying
1024
 * CKM_DES3_CBC as the mechanism and 16 as keySize currently doesn't work.
1025
 */
1026
PK11SymKey *
1027
PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param,
1028
                 int keySize, SECItem *keyid, PRBool isToken, void *wincx)
1029
0
{
1030
0
    PK11SymKey *symKey;
1031
0
    PRBool weird = PR_FALSE; /* hack for fortezza */
1032
0
    CK_FLAGS opFlags = CKF_SIGN;
1033
0
    PK11AttrFlags attrFlags = 0;
1034
0
1035
0
    if ((keySize == -1) && (type == CKM_SKIPJACK_CBC64)) {
1036
0
        weird = PR_TRUE;
1037
0
        keySize = 0;
1038
0
    }
1039
0
1040
0
    opFlags |= weird ? CKF_DECRYPT : CKF_ENCRYPT;
1041
0
1042
0
    if (isToken) {
1043
0
        attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE);
1044
0
    }
1045
0
1046
0
    symKey = pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param,
1047
0
                                                 -1, keySize, keyid, opFlags, attrFlags, wincx);
1048
0
    if (symKey && weird) {
1049
0
        PK11_SetFortezzaHack(symKey);
1050
0
    }
1051
0
1052
0
    return symKey;
1053
0
}
1054
1055
PK11SymKey *
1056
PK11_KeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param,
1057
            int keySize, void *wincx)
1058
0
{
1059
0
    return PK11_TokenKeyGen(slot, type, param, keySize, 0, PR_FALSE, wincx);
1060
0
}
1061
1062
PK11SymKey *
1063
PK11_KeyGenWithTemplate(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
1064
                        CK_MECHANISM_TYPE keyGenType,
1065
                        SECItem *param, CK_ATTRIBUTE *attrs,
1066
                        unsigned int attrsCount, void *wincx)
1067
0
{
1068
0
    PK11SymKey *symKey;
1069
0
    CK_SESSION_HANDLE session;
1070
0
    CK_MECHANISM mechanism;
1071
0
    CK_RV crv;
1072
0
    PRBool isToken = CK_FALSE;
1073
0
    CK_ULONG keySize = 0;
1074
0
    unsigned i;
1075
0
1076
0
    /* Extract the template's CKA_VALUE_LEN into keySize and CKA_TOKEN into
1077
0
       isToken. */
1078
0
    for (i = 0; i < attrsCount; ++i) {
1079
0
        switch (attrs[i].type) {
1080
0
            case CKA_VALUE_LEN:
1081
0
                if (attrs[i].pValue == NULL ||
1082
0
                    attrs[i].ulValueLen != sizeof(CK_ULONG)) {
1083
0
                    PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT));
1084
0
                    return NULL;
1085
0
                }
1086
0
                keySize = *(CK_ULONG *)attrs[i].pValue;
1087
0
                break;
1088
0
            case CKA_TOKEN:
1089
0
                if (attrs[i].pValue == NULL ||
1090
0
                    attrs[i].ulValueLen != sizeof(CK_BBOOL)) {
1091
0
                    PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT));
1092
0
                    return NULL;
1093
0
                }
1094
0
                isToken = (*(CK_BBOOL *)attrs[i].pValue) ? PR_TRUE : PR_FALSE;
1095
0
                break;
1096
0
        }
1097
0
    }
1098
0
1099
0
    /* find a slot to generate the key into */
1100
0
    /* Only do slot management if this is not a token key */
1101
0
    if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot, type))) {
1102
0
        PK11SlotInfo *bestSlot = PK11_GetBestSlot(type, wincx);
1103
0
        if (bestSlot == NULL) {
1104
0
            PORT_SetError(SEC_ERROR_NO_MODULE);
1105
0
            return NULL;
1106
0
        }
1107
0
        symKey = pk11_CreateSymKey(bestSlot, type, !isToken, PR_TRUE, wincx);
1108
0
        PK11_FreeSlot(bestSlot);
1109
0
    } else {
1110
0
        symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx);
1111
0
    }
1112
0
    if (symKey == NULL)
1113
0
        return NULL;
1114
0
1115
0
    symKey->size = keySize;
1116
0
    symKey->origin = PK11_OriginGenerated;
1117
0
1118
0
    /* Set the parameters for the key gen if provided */
1119
0
    mechanism.mechanism = keyGenType;
1120
0
    mechanism.pParameter = NULL;
1121
0
    mechanism.ulParameterLen = 0;
1122
0
    if (param) {
1123
0
        mechanism.pParameter = param->data;
1124
0
        mechanism.ulParameterLen = param->len;
1125
0
    }
1126
0
1127
0
    /* Get session and perform locking */
1128
0
    if (isToken) {
1129
0
        PK11_Authenticate(symKey->slot, PR_TRUE, wincx);
1130
0
        /* Should always be original slot */
1131
0
        session = PK11_GetRWSession(symKey->slot);
1132
0
        symKey->owner = PR_FALSE;
1133
0
    } else {
1134
0
        session = symKey->session;
1135
0
        if (session != CK_INVALID_SESSION)
1136
0
            pk11_EnterKeyMonitor(symKey);
1137
0
    }
1138
0
    if (session == CK_INVALID_SESSION) {
1139
0
        PK11_FreeSymKey(symKey);
1140
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
1141
0
        return NULL;
1142
0
    }
1143
0
1144
0
    crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session, &mechanism, attrs, attrsCount, &symKey->objectID);
1145
0
1146
0
    /* Release lock and session */
1147
0
    if (isToken) {
1148
0
        PK11_RestoreROSession(symKey->slot, session);
1149
0
    } else {
1150
0
        pk11_ExitKeyMonitor(symKey);
1151
0
    }
1152
0
1153
0
    if (crv != CKR_OK) {
1154
0
        PK11_FreeSymKey(symKey);
1155
0
        PORT_SetError(PK11_MapError(crv));
1156
0
        return NULL;
1157
0
    }
1158
0
1159
0
    return symKey;
1160
0
}
1161
1162
/* --- */
1163
PK11SymKey *
1164
PK11_GenDES3TokenKey(PK11SlotInfo *slot, SECItem *keyid, void *cx)
1165
0
{
1166
0
    return PK11_TokenKeyGen(slot, CKM_DES3_CBC, 0, 0, keyid, PR_TRUE, cx);
1167
0
}
1168
1169
PK11SymKey *
1170
PK11_ConvertSessionSymKeyToTokenSymKey(PK11SymKey *symk, void *wincx)
1171
0
{
1172
0
    PK11SlotInfo *slot = symk->slot;
1173
0
    CK_ATTRIBUTE template[1];
1174
0
    CK_ATTRIBUTE *attrs = template;
1175
0
    CK_BBOOL cktrue = CK_TRUE;
1176
0
    CK_RV crv;
1177
0
    CK_OBJECT_HANDLE newKeyID;
1178
0
    CK_SESSION_HANDLE rwsession;
1179
0
1180
0
    PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue));
1181
0
    attrs++;
1182
0
1183
0
    PK11_Authenticate(slot, PR_TRUE, wincx);
1184
0
    rwsession = PK11_GetRWSession(slot);
1185
0
    if (rwsession == CK_INVALID_SESSION) {
1186
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
1187
0
        return NULL;
1188
0
    }
1189
0
    crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, symk->objectID,
1190
0
                                          template, 1, &newKeyID);
1191
0
    PK11_RestoreROSession(slot, rwsession);
1192
0
1193
0
    if (crv != CKR_OK) {
1194
0
        PORT_SetError(PK11_MapError(crv));
1195
0
        return NULL;
1196
0
    }
1197
0
1198
0
    return PK11_SymKeyFromHandle(slot, NULL /*parent*/, symk->origin,
1199
0
                                 symk->type, newKeyID, PR_FALSE /*owner*/, NULL /*wincx*/);
1200
0
}
1201
1202
/*
1203
 * This function does a straight public key wrap (which only RSA can do).
1204
 * Use PK11_PubGenKey and PK11_WrapSymKey to implement the FORTEZZA and
1205
 * Diffie-Hellman Ciphers. */
1206
SECStatus
1207
PK11_PubWrapSymKey(CK_MECHANISM_TYPE type, SECKEYPublicKey *pubKey,
1208
                   PK11SymKey *symKey, SECItem *wrappedKey)
1209
0
{
1210
0
    PK11SlotInfo *slot;
1211
0
    CK_ULONG len = wrappedKey->len;
1212
0
    PK11SymKey *newKey = NULL;
1213
0
    CK_OBJECT_HANDLE id;
1214
0
    CK_MECHANISM mechanism;
1215
0
    PRBool owner = PR_TRUE;
1216
0
    CK_SESSION_HANDLE session;
1217
0
    CK_RV crv;
1218
0
1219
0
    if (symKey == NULL) {
1220
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1221
0
        return SECFailure;
1222
0
    }
1223
0
1224
0
    /* if this slot doesn't support the mechanism, go to a slot that does */
1225
0
    newKey = pk11_ForceSlot(symKey, type, CKA_ENCRYPT);
1226
0
    if (newKey != NULL) {
1227
0
        symKey = newKey;
1228
0
    }
1229
0
1230
0
    if (symKey->slot == NULL) {
1231
0
        PORT_SetError(SEC_ERROR_NO_MODULE);
1232
0
        return SECFailure;
1233
0
    }
1234
0
1235
0
    slot = symKey->slot;
1236
0
    mechanism.mechanism = pk11_mapWrapKeyType(pubKey->keyType);
1237
0
    mechanism.pParameter = NULL;
1238
0
    mechanism.ulParameterLen = 0;
1239
0
1240
0
    id = PK11_ImportPublicKey(slot, pubKey, PR_FALSE);
1241
0
    if (id == CK_INVALID_HANDLE) {
1242
0
        if (newKey) {
1243
0
            PK11_FreeSymKey(newKey);
1244
0
        }
1245
0
        return SECFailure; /* Error code has been set. */
1246
0
    }
1247
0
1248
0
    session = pk11_GetNewSession(slot, &owner);
1249
0
    if (!owner || !(slot->isThreadSafe))
1250
0
        PK11_EnterSlotMonitor(slot);
1251
0
    crv = PK11_GETTAB(slot)->C_WrapKey(session, &mechanism,
1252
0
                                       id, symKey->objectID, wrappedKey->data, &len);
1253
0
    if (!owner || !(slot->isThreadSafe))
1254
0
        PK11_ExitSlotMonitor(slot);
1255
0
    pk11_CloseSession(slot, session, owner);
1256
0
    if (newKey) {
1257
0
        PK11_FreeSymKey(newKey);
1258
0
    }
1259
0
1260
0
    if (crv != CKR_OK) {
1261
0
        PORT_SetError(PK11_MapError(crv));
1262
0
        return SECFailure;
1263
0
    }
1264
0
    wrappedKey->len = len;
1265
0
    return SECSuccess;
1266
0
}
1267
1268
/*
1269
 * this little function uses the Encrypt function to wrap a key, just in
1270
 * case we have problems with the wrap implementation for a token.
1271
 */
1272
static SECStatus
1273
pk11_HandWrap(PK11SymKey *wrappingKey, SECItem *param, CK_MECHANISM_TYPE type,
1274
              SECItem *inKey, SECItem *outKey)
1275
0
{
1276
0
    PK11SlotInfo *slot;
1277
0
    CK_ULONG len;
1278
0
    SECItem *data;
1279
0
    CK_MECHANISM mech;
1280
0
    PRBool owner = PR_TRUE;
1281
0
    CK_SESSION_HANDLE session;
1282
0
    CK_RV crv;
1283
0
1284
0
    slot = wrappingKey->slot;
1285
0
    /* use NULL IV's for wrapping */
1286
0
    mech.mechanism = type;
1287
0
    if (param) {
1288
0
        mech.pParameter = param->data;
1289
0
        mech.ulParameterLen = param->len;
1290
0
    } else {
1291
0
        mech.pParameter = NULL;
1292
0
        mech.ulParameterLen = 0;
1293
0
    }
1294
0
    session = pk11_GetNewSession(slot, &owner);
1295
0
    if (!owner || !(slot->isThreadSafe))
1296
0
        PK11_EnterSlotMonitor(slot);
1297
0
    crv = PK11_GETTAB(slot)->C_EncryptInit(session, &mech,
1298
0
                                           wrappingKey->objectID);
1299
0
    if (crv != CKR_OK) {
1300
0
        if (!owner || !(slot->isThreadSafe))
1301
0
            PK11_ExitSlotMonitor(slot);
1302
0
        pk11_CloseSession(slot, session, owner);
1303
0
        PORT_SetError(PK11_MapError(crv));
1304
0
        return SECFailure;
1305
0
    }
1306
0
1307
0
    /* keys are almost always aligned, but if we get this far,
1308
0
     * we've gone above and beyond anyway... */
1309
0
    data = PK11_BlockData(inKey, PK11_GetBlockSize(type, param));
1310
0
    if (data == NULL) {
1311
0
        if (!owner || !(slot->isThreadSafe))
1312
0
            PK11_ExitSlotMonitor(slot);
1313
0
        pk11_CloseSession(slot, session, owner);
1314
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
1315
0
        return SECFailure;
1316
0
    }
1317
0
    len = outKey->len;
1318
0
    crv = PK11_GETTAB(slot)->C_Encrypt(session, data->data, data->len,
1319
0
                                       outKey->data, &len);
1320
0
    if (!owner || !(slot->isThreadSafe))
1321
0
        PK11_ExitSlotMonitor(slot);
1322
0
    pk11_CloseSession(slot, session, owner);
1323
0
    SECITEM_FreeItem(data, PR_TRUE);
1324
0
    outKey->len = len;
1325
0
    if (crv != CKR_OK) {
1326
0
        PORT_SetError(PK11_MapError(crv));
1327
0
        return SECFailure;
1328
0
    }
1329
0
    return SECSuccess;
1330
0
}
1331
1332
/*
1333
 * This function does a symetric based wrap.
1334
 */
1335
SECStatus
1336
PK11_WrapSymKey(CK_MECHANISM_TYPE type, SECItem *param,
1337
                PK11SymKey *wrappingKey, PK11SymKey *symKey, SECItem *wrappedKey)
1338
0
{
1339
0
    PK11SlotInfo *slot;
1340
0
    CK_ULONG len = wrappedKey->len;
1341
0
    PK11SymKey *newKey = NULL;
1342
0
    SECItem *param_save = NULL;
1343
0
    CK_MECHANISM mechanism;
1344
0
    PRBool owner = PR_TRUE;
1345
0
    CK_SESSION_HANDLE session;
1346
0
    CK_RV crv;
1347
0
    SECStatus rv;
1348
0
1349
0
    /* if this slot doesn't support the mechanism, go to a slot that does */
1350
0
    /* Force symKey and wrappingKey into the same slot */
1351
0
    if ((wrappingKey->slot == NULL) || (symKey->slot != wrappingKey->slot)) {
1352
0
        /* first try copying the wrapping Key to the symKey slot */
1353
0
        if (symKey->slot && PK11_DoesMechanism(symKey->slot, type)) {
1354
0
            newKey = pk11_CopyToSlot(symKey->slot, type, CKA_WRAP, wrappingKey);
1355
0
        }
1356
0
        /* Nope, try it the other way */
1357
0
        if (newKey == NULL) {
1358
0
            if (wrappingKey->slot) {
1359
0
                newKey = pk11_CopyToSlot(wrappingKey->slot,
1360
0
                                         symKey->type, CKA_ENCRYPT, symKey);
1361
0
            }
1362
0
            /* just not playing... one last thing, can we get symKey's data?
1363
0
             * If it's possible, we it should already be in the
1364
0
             * symKey->data.data pointer because pk11_CopyToSlot would have
1365
0
             * tried to put it there. */
1366
0
            if (newKey == NULL) {
1367
0
                /* Can't get symKey's data: Game Over */
1368
0
                if (symKey->data.data == NULL) {
1369
0
                    PORT_SetError(SEC_ERROR_NO_MODULE);
1370
0
                    return SECFailure;
1371
0
                }
1372
0
                if (param == NULL) {
1373
0
                    param_save = param = PK11_ParamFromIV(type, NULL);
1374
0
                }
1375
0
                rv = pk11_HandWrap(wrappingKey, param, type,
1376
0
                                   &symKey->data, wrappedKey);
1377
0
                if (param_save)
1378
0
                    SECITEM_FreeItem(param_save, PR_TRUE);
1379
0
                return rv;
1380
0
            }
1381
0
            /* we successfully moved the sym Key */
1382
0
            symKey = newKey;
1383
0
        } else {
1384
0
            /* we successfully moved the wrapping Key */
1385
0
            wrappingKey = newKey;
1386
0
        }
1387
0
    }
1388
0
1389
0
    /* at this point both keys are in the same token */
1390
0
    slot = wrappingKey->slot;
1391
0
    mechanism.mechanism = type;
1392
0
    /* use NULL IV's for wrapping */
1393
0
    if (param == NULL) {
1394
0
        param_save = param = PK11_ParamFromIV(type, NULL);
1395
0
    }
1396
0
    if (param) {
1397
0
        mechanism.pParameter = param->data;
1398
0
        mechanism.ulParameterLen = param->len;
1399
0
    } else {
1400
0
        mechanism.pParameter = NULL;
1401
0
        mechanism.ulParameterLen = 0;
1402
0
    }
1403
0
1404
0
    len = wrappedKey->len;
1405
0
1406
0
    session = pk11_GetNewSession(slot, &owner);
1407
0
    if (!owner || !(slot->isThreadSafe))
1408
0
        PK11_EnterSlotMonitor(slot);
1409
0
    crv = PK11_GETTAB(slot)->C_WrapKey(session, &mechanism,
1410
0
                                       wrappingKey->objectID, symKey->objectID,
1411
0
                                       wrappedKey->data, &len);
1412
0
    if (!owner || !(slot->isThreadSafe))
1413
0
        PK11_ExitSlotMonitor(slot);
1414
0
    pk11_CloseSession(slot, session, owner);
1415
0
    rv = SECSuccess;
1416
0
    if (crv != CKR_OK) {
1417
0
        /* can't wrap it? try hand wrapping it... */
1418
0
        do {
1419
0
            if (symKey->data.data == NULL) {
1420
0
                rv = PK11_ExtractKeyValue(symKey);
1421
0
                if (rv != SECSuccess)
1422
0
                    break;
1423
0
            }
1424
0
            rv = pk11_HandWrap(wrappingKey, param, type, &symKey->data,
1425
0
                               wrappedKey);
1426
0
        } while (PR_FALSE);
1427
0
    } else {
1428
0
        wrappedKey->len = len;
1429
0
    }
1430
0
    if (newKey)
1431
0
        PK11_FreeSymKey(newKey);
1432
0
    if (param_save)
1433
0
        SECITEM_FreeItem(param_save, PR_TRUE);
1434
0
    return rv;
1435
0
}
1436
1437
/*
1438
 * This Generates a new key based on a symetricKey
1439
 */
1440
PK11SymKey *
1441
PK11_Derive(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, SECItem *param,
1442
            CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1443
            int keySize)
1444
0
{
1445
0
    return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation,
1446
0
                                   keySize, NULL, 0, PR_FALSE);
1447
0
}
1448
1449
PK11SymKey *
1450
PK11_DeriveWithFlags(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
1451
                     SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1452
                     int keySize, CK_FLAGS flags)
1453
0
{
1454
0
    CK_BBOOL ckTrue = CK_TRUE;
1455
0
    CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
1456
0
    unsigned int templateCount;
1457
0
1458
0
    templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
1459
0
    return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation,
1460
0
                                   keySize, keyTemplate, templateCount, PR_FALSE);
1461
0
}
1462
1463
PK11SymKey *
1464
PK11_DeriveWithFlagsPerm(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
1465
                         SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1466
                         int keySize, CK_FLAGS flags, PRBool isPerm)
1467
0
{
1468
0
    CK_BBOOL cktrue = CK_TRUE;
1469
0
    CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
1470
0
    CK_ATTRIBUTE *attrs;
1471
0
    unsigned int templateCount = 0;
1472
0
1473
0
    attrs = keyTemplate;
1474
0
    if (isPerm) {
1475
0
        PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
1476
0
        attrs++;
1477
0
    }
1478
0
    templateCount = attrs - keyTemplate;
1479
0
    templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
1480
0
    return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation,
1481
0
                                   keySize, keyTemplate, templateCount, isPerm);
1482
0
}
1483
1484
PK11SymKey *
1485
PK11_DeriveWithTemplate(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
1486
                        SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1487
                        int keySize, CK_ATTRIBUTE *userAttr, unsigned int numAttrs,
1488
                        PRBool isPerm)
1489
0
{
1490
0
    PK11SlotInfo *slot = baseKey->slot;
1491
0
    PK11SymKey *symKey;
1492
0
    PK11SymKey *newBaseKey = NULL;
1493
0
    CK_BBOOL cktrue = CK_TRUE;
1494
0
    CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
1495
0
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
1496
0
    CK_ULONG valueLen = 0;
1497
0
    CK_MECHANISM mechanism;
1498
0
    CK_RV crv;
1499
0
#define MAX_ADD_ATTRS 4
1500
0
    CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS + MAX_ADD_ATTRS];
1501
0
#undef MAX_ADD_ATTRS
1502
0
    CK_ATTRIBUTE *attrs = keyTemplate;
1503
0
    CK_SESSION_HANDLE session;
1504
0
    unsigned int templateCount;
1505
0
1506
0
    if (numAttrs > MAX_TEMPL_ATTRS) {
1507
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1508
0
        return NULL;
1509
0
    }
1510
0
1511
0
    /* first copy caller attributes in. */
1512
0
    for (templateCount = 0; templateCount < numAttrs; ++templateCount) {
1513
0
        *attrs++ = *userAttr++;
1514
0
    }
1515
0
1516
0
    /* We only add the following attributes to the template if the caller
1517
0
    ** didn't already supply them.
1518
0
    */
1519
0
    if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) {
1520
0
        PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass);
1521
0
        attrs++;
1522
0
    }
1523
0
    if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) {
1524
0
        keyType = PK11_GetKeyType(target, keySize);
1525
0
        PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType);
1526
0
        attrs++;
1527
0
    }
1528
0
    if (keySize > 0 &&
1529
0
        !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) {
1530
0
        valueLen = (CK_ULONG)keySize;
1531
0
        PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen);
1532
0
        attrs++;
1533
0
    }
1534
0
    if ((operation != CKA_FLAGS_ONLY) &&
1535
0
        !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) {
1536
0
        PK11_SETATTRS(attrs, operation, &cktrue, sizeof cktrue);
1537
0
        attrs++;
1538
0
    }
1539
0
1540
0
    templateCount = attrs - keyTemplate;
1541
0
    PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE));
1542
0
1543
0
    /* move the key to a slot that can do the function */
1544
0
    if (!PK11_DoesMechanism(slot, derive)) {
1545
0
        /* get a new base key & slot */
1546
0
        PK11SlotInfo *newSlot = PK11_GetBestSlot(derive, baseKey->cx);
1547
0
1548
0
        if (newSlot == NULL)
1549
0
            return NULL;
1550
0
1551
0
        newBaseKey = pk11_CopyToSlot(newSlot, derive, CKA_DERIVE,
1552
0
                                     baseKey);
1553
0
        PK11_FreeSlot(newSlot);
1554
0
        if (newBaseKey == NULL)
1555
0
            return NULL;
1556
0
        baseKey = newBaseKey;
1557
0
        slot = baseKey->slot;
1558
0
    }
1559
0
1560
0
    /* get our key Structure */
1561
0
    symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, baseKey->cx);
1562
0
    if (symKey == NULL) {
1563
0
        return NULL;
1564
0
    }
1565
0
1566
0
    symKey->size = keySize;
1567
0
1568
0
    mechanism.mechanism = derive;
1569
0
    if (param) {
1570
0
        mechanism.pParameter = param->data;
1571
0
        mechanism.ulParameterLen = param->len;
1572
0
    } else {
1573
0
        mechanism.pParameter = NULL;
1574
0
        mechanism.ulParameterLen = 0;
1575
0
    }
1576
0
    symKey->origin = PK11_OriginDerive;
1577
0
1578
0
    if (isPerm) {
1579
0
        session = PK11_GetRWSession(slot);
1580
0
    } else {
1581
0
        pk11_EnterKeyMonitor(symKey);
1582
0
        session = symKey->session;
1583
0
    }
1584
0
    if (session == CK_INVALID_SESSION) {
1585
0
        if (!isPerm)
1586
0
            pk11_ExitKeyMonitor(symKey);
1587
0
        crv = CKR_SESSION_HANDLE_INVALID;
1588
0
    } else {
1589
0
        crv = PK11_GETTAB(slot)->C_DeriveKey(session, &mechanism,
1590
0
                                             baseKey->objectID, keyTemplate, templateCount, &symKey->objectID);
1591
0
        if (isPerm) {
1592
0
            PK11_RestoreROSession(slot, session);
1593
0
        } else {
1594
0
            pk11_ExitKeyMonitor(symKey);
1595
0
        }
1596
0
    }
1597
0
    if (newBaseKey)
1598
0
        PK11_FreeSymKey(newBaseKey);
1599
0
    if (crv != CKR_OK) {
1600
0
        PK11_FreeSymKey(symKey);
1601
0
        return NULL;
1602
0
    }
1603
0
    return symKey;
1604
0
}
1605
1606
/* Create a new key by concatenating base and data
1607
 */
1608
static PK11SymKey *
1609
pk11_ConcatenateBaseAndData(PK11SymKey *base,
1610
                            CK_BYTE *data, CK_ULONG dataLen, CK_MECHANISM_TYPE target,
1611
                            CK_ATTRIBUTE_TYPE operation)
1612
0
{
1613
0
    CK_KEY_DERIVATION_STRING_DATA mechParams;
1614
0
    SECItem param;
1615
0
1616
0
    if (base == NULL) {
1617
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1618
0
        return NULL;
1619
0
    }
1620
0
1621
0
    mechParams.pData = data;
1622
0
    mechParams.ulLen = dataLen;
1623
0
    param.data = (unsigned char *)&mechParams;
1624
0
    param.len = sizeof(CK_KEY_DERIVATION_STRING_DATA);
1625
0
1626
0
    return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_DATA,
1627
0
                       &param, target, operation, 0);
1628
0
}
1629
1630
/* Create a new key by concatenating base and key
1631
 */
1632
static PK11SymKey *
1633
pk11_ConcatenateBaseAndKey(PK11SymKey *base,
1634
                           PK11SymKey *key, CK_MECHANISM_TYPE target,
1635
                           CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize)
1636
0
{
1637
0
    SECItem param;
1638
0
1639
0
    if ((base == NULL) || (key == NULL)) {
1640
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1641
0
        return NULL;
1642
0
    }
1643
0
1644
0
    param.data = (unsigned char *)&(key->objectID);
1645
0
    param.len = sizeof(CK_OBJECT_HANDLE);
1646
0
1647
0
    return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_KEY,
1648
0
                       &param, target, operation, keySize);
1649
0
}
1650
1651
/* Create a new key whose value is the hash of tobehashed.
1652
 * type is the mechanism for the derived key.
1653
 */
1654
static PK11SymKey *
1655
pk11_HashKeyDerivation(PK11SymKey *toBeHashed,
1656
                       CK_MECHANISM_TYPE hashMechanism, CK_MECHANISM_TYPE target,
1657
                       CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize)
1658
0
{
1659
0
    return PK11_Derive(toBeHashed, hashMechanism, NULL, target, operation, keySize);
1660
0
}
1661
1662
/* This function implements the ANSI X9.63 key derivation function
1663
 */
1664
static PK11SymKey *
1665
pk11_ANSIX963Derive(PK11SymKey *sharedSecret,
1666
                    CK_EC_KDF_TYPE kdf, SECItem *sharedData,
1667
                    CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
1668
                    CK_ULONG keySize)
1669
0
{
1670
0
    CK_KEY_TYPE keyType;
1671
0
    CK_MECHANISM_TYPE hashMechanism, mechanismArray[4];
1672
0
    CK_ULONG derivedKeySize, HashLen, counter, maxCounter, bufferLen;
1673
0
    CK_ULONG SharedInfoLen;
1674
0
    CK_BYTE *buffer = NULL;
1675
0
    PK11SymKey *toBeHashed, *hashOutput;
1676
0
    PK11SymKey *newSharedSecret = NULL;
1677
0
    PK11SymKey *oldIntermediateResult, *intermediateResult = NULL;
1678
0
1679
0
    if (sharedSecret == NULL) {
1680
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1681
0
        return NULL;
1682
0
    }
1683
0
1684
0
    switch (kdf) {
1685
0
        case CKD_SHA1_KDF:
1686
0
            HashLen = SHA1_LENGTH;
1687
0
            hashMechanism = CKM_SHA1_KEY_DERIVATION;
1688
0
            break;
1689
0
        case CKD_SHA224_KDF:
1690
0
            HashLen = SHA224_LENGTH;
1691
0
            hashMechanism = CKM_SHA224_KEY_DERIVATION;
1692
0
            break;
1693
0
        case CKD_SHA256_KDF:
1694
0
            HashLen = SHA256_LENGTH;
1695
0
            hashMechanism = CKM_SHA256_KEY_DERIVATION;
1696
0
            break;
1697
0
        case CKD_SHA384_KDF:
1698
0
            HashLen = SHA384_LENGTH;
1699
0
            hashMechanism = CKM_SHA384_KEY_DERIVATION;
1700
0
            break;
1701
0
        case CKD_SHA512_KDF:
1702
0
            HashLen = SHA512_LENGTH;
1703
0
            hashMechanism = CKM_SHA512_KEY_DERIVATION;
1704
0
            break;
1705
0
        default:
1706
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
1707
0
            return NULL;
1708
0
    }
1709
0
1710
0
    derivedKeySize = keySize;
1711
0
    if (derivedKeySize == 0) {
1712
0
        keyType = PK11_GetKeyType(target, keySize);
1713
0
        derivedKeySize = pk11_GetPredefinedKeyLength(keyType);
1714
0
        if (derivedKeySize == 0) {
1715
0
            derivedKeySize = HashLen;
1716
0
        }
1717
0
    }
1718
0
1719
0
    /* Check that key_len isn't too long.  The maximum key length could be
1720
0
     * greatly increased if the code below did not limit the 4-byte counter
1721
0
     * to a maximum value of 255. */
1722
0
    if (derivedKeySize > 254 * HashLen) {
1723
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1724
0
        return NULL;
1725
0
    }
1726
0
1727
0
    maxCounter = derivedKeySize / HashLen;
1728
0
    if (derivedKeySize > maxCounter * HashLen)
1729
0
        maxCounter++;
1730
0
1731
0
    if ((sharedData == NULL) || (sharedData->data == NULL))
1732
0
        SharedInfoLen = 0;
1733
0
    else
1734
0
        SharedInfoLen = sharedData->len;
1735
0
1736
0
    bufferLen = SharedInfoLen + 4;
1737
0
1738
0
    /* Populate buffer with Counter || sharedData
1739
0
     * where Counter is 0x00000001. */
1740
0
    buffer = (unsigned char *)PORT_Alloc(bufferLen);
1741
0
    if (buffer == NULL) {
1742
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
1743
0
        return NULL;
1744
0
    }
1745
0
1746
0
    buffer[0] = 0;
1747
0
    buffer[1] = 0;
1748
0
    buffer[2] = 0;
1749
0
    buffer[3] = 1;
1750
0
    if (SharedInfoLen > 0) {
1751
0
        PORT_Memcpy(&buffer[4], sharedData->data, SharedInfoLen);
1752
0
    }
1753
0
1754
0
    /* Look for a slot that supports the mechanisms needed
1755
0
     * to implement the ANSI X9.63 KDF as well as the
1756
0
     * target mechanism.
1757
0
     */
1758
0
    mechanismArray[0] = CKM_CONCATENATE_BASE_AND_DATA;
1759
0
    mechanismArray[1] = hashMechanism;
1760
0
    mechanismArray[2] = CKM_CONCATENATE_BASE_AND_KEY;
1761
0
    mechanismArray[3] = target;
1762
0
1763
0
    newSharedSecret = pk11_ForceSlotMultiple(sharedSecret,
1764
0
                                             mechanismArray, 4, operation);
1765
0
    if (newSharedSecret != NULL) {
1766
0
        sharedSecret = newSharedSecret;
1767
0
    }
1768
0
1769
0
    for (counter = 1; counter <= maxCounter; counter++) {
1770
0
        /* Concatenate shared_secret and buffer */
1771
0
        toBeHashed = pk11_ConcatenateBaseAndData(sharedSecret, buffer,
1772
0
                                                 bufferLen, hashMechanism, operation);
1773
0
        if (toBeHashed == NULL) {
1774
0
            goto loser;
1775
0
        }
1776
0
1777
0
        /* Hash value */
1778
0
        if (maxCounter == 1) {
1779
0
            /* In this case the length of the key to be derived is
1780
0
             * less than or equal to the length of the hash output.
1781
0
             * So, the output of the hash operation will be the
1782
0
             * dervied key. */
1783
0
            hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism,
1784
0
                                                target, operation, keySize);
1785
0
        } else {
1786
0
            /* In this case, the output of the hash operation will be
1787
0
             * concatenated with other data to create the derived key. */
1788
0
            hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism,
1789
0
                                                CKM_CONCATENATE_BASE_AND_KEY, operation, 0);
1790
0
        }
1791
0
        PK11_FreeSymKey(toBeHashed);
1792
0
        if (hashOutput == NULL) {
1793
0
            goto loser;
1794
0
        }
1795
0
1796
0
        /* Append result to intermediate result, if necessary */
1797
0
        oldIntermediateResult = intermediateResult;
1798
0
1799
0
        if (oldIntermediateResult == NULL) {
1800
0
            intermediateResult = hashOutput;
1801
0
        } else {
1802
0
            if (counter == maxCounter) {
1803
0
                /* This is the final concatenation, and so the output
1804
0
                 * will be the derived key. */
1805
0
                intermediateResult =
1806
0
                    pk11_ConcatenateBaseAndKey(oldIntermediateResult,
1807
0
                                               hashOutput, target, operation, keySize);
1808
0
            } else {
1809
0
                /* The output of this concatenation will be concatenated
1810
0
                 * with other data to create the derived key. */
1811
0
                intermediateResult =
1812
0
                    pk11_ConcatenateBaseAndKey(oldIntermediateResult,
1813
0
                                               hashOutput, CKM_CONCATENATE_BASE_AND_KEY,
1814
0
                                               operation, 0);
1815
0
            }
1816
0
1817
0
            PK11_FreeSymKey(hashOutput);
1818
0
            PK11_FreeSymKey(oldIntermediateResult);
1819
0
            if (intermediateResult == NULL) {
1820
0
                goto loser;
1821
0
            }
1822
0
        }
1823
0
1824
0
        /* Increment counter (assumes maxCounter < 255) */
1825
0
        buffer[3]++;
1826
0
    }
1827
0
1828
0
    PORT_ZFree(buffer, bufferLen);
1829
0
    if (newSharedSecret != NULL)
1830
0
        PK11_FreeSymKey(newSharedSecret);
1831
0
    return intermediateResult;
1832
0
1833
0
loser:
1834
0
    PORT_ZFree(buffer, bufferLen);
1835
0
    if (newSharedSecret != NULL)
1836
0
        PK11_FreeSymKey(newSharedSecret);
1837
0
    if (intermediateResult != NULL)
1838
0
        PK11_FreeSymKey(intermediateResult);
1839
0
    return NULL;
1840
0
}
1841
1842
/*
1843
 * This Generates a wrapping key based on a privateKey, publicKey, and two
1844
 * random numbers. For Mail usage RandomB should be NULL. In the Sender's
1845
 * case RandomA is generate, outherwize it is passed.
1846
 */
1847
PK11SymKey *
1848
PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
1849
               PRBool isSender, SECItem *randomA, SECItem *randomB,
1850
               CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
1851
               CK_ATTRIBUTE_TYPE operation, int keySize, void *wincx)
1852
0
{
1853
0
    PK11SlotInfo *slot = privKey->pkcs11Slot;
1854
0
    CK_MECHANISM mechanism;
1855
0
    PK11SymKey *symKey;
1856
0
    CK_RV crv;
1857
0
1858
0
    /* get our key Structure */
1859
0
    symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx);
1860
0
    if (symKey == NULL) {
1861
0
        return NULL;
1862
0
    }
1863
0
1864
0
    symKey->origin = PK11_OriginDerive;
1865
0
1866
0
    switch (privKey->keyType) {
1867
0
        case rsaKey:
1868
0
        case rsaPssKey:
1869
0
        case rsaOaepKey:
1870
0
        case nullKey:
1871
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
1872
0
            break;
1873
0
        case dsaKey:
1874
0
        case keaKey:
1875
0
        case fortezzaKey: {
1876
0
            static unsigned char rb_email[128] = { 0 };
1877
0
            CK_KEA_DERIVE_PARAMS param;
1878
0
            param.isSender = (CK_BBOOL)isSender;
1879
0
            param.ulRandomLen = randomA->len;
1880
0
            param.pRandomA = randomA->data;
1881
0
            param.pRandomB = rb_email;
1882
0
            param.pRandomB[127] = 1;
1883
0
            if (randomB)
1884
0
                param.pRandomB = randomB->data;
1885
0
            if (pubKey->keyType == fortezzaKey) {
1886
0
                param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len;
1887
0
                param.pPublicData = pubKey->u.fortezza.KEAKey.data;
1888
0
            } else {
1889
0
                /* assert type == keaKey */
1890
0
                /* XXX change to match key key types */
1891
0
                param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len;
1892
0
                param.pPublicData = pubKey->u.fortezza.KEAKey.data;
1893
0
            }
1894
0
1895
0
            mechanism.mechanism = derive;
1896
0
            mechanism.pParameter = &param;
1897
0
            mechanism.ulParameterLen = sizeof(param);
1898
0
1899
0
            /* get a new symKey structure */
1900
0
            pk11_EnterKeyMonitor(symKey);
1901
0
            crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism,
1902
0
                                                 privKey->pkcs11ID, NULL, 0,
1903
0
                                                 &symKey->objectID);
1904
0
            pk11_ExitKeyMonitor(symKey);
1905
0
            if (crv == CKR_OK)
1906
0
                return symKey;
1907
0
            PORT_SetError(PK11_MapError(crv));
1908
0
        } break;
1909
0
        case dhKey: {
1910
0
            CK_BBOOL cktrue = CK_TRUE;
1911
0
            CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
1912
0
            CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
1913
0
            CK_ULONG key_size = 0;
1914
0
            CK_ATTRIBUTE keyTemplate[4];
1915
0
            int templateCount;
1916
0
            CK_ATTRIBUTE *attrs = keyTemplate;
1917
0
1918
0
            if (pubKey->keyType != dhKey) {
1919
0
                PORT_SetError(SEC_ERROR_BAD_KEY);
1920
0
                break;
1921
0
            }
1922
0
1923
0
            PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
1924
0
            attrs++;
1925
0
            PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
1926
0
            attrs++;
1927
0
            PK11_SETATTRS(attrs, operation, &cktrue, 1);
1928
0
            attrs++;
1929
0
            PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size));
1930
0
            attrs++;
1931
0
            templateCount = attrs - keyTemplate;
1932
0
            PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE));
1933
0
1934
0
            keyType = PK11_GetKeyType(target, keySize);
1935
0
            key_size = keySize;
1936
0
            symKey->size = keySize;
1937
0
            if (key_size == 0)
1938
0
                templateCount--;
1939
0
1940
0
            mechanism.mechanism = derive;
1941
0
1942
0
            /* we can undefine these when we define diffie-helman keys */
1943
0
1944
0
            mechanism.pParameter = pubKey->u.dh.publicValue.data;
1945
0
            mechanism.ulParameterLen = pubKey->u.dh.publicValue.len;
1946
0
1947
0
            pk11_EnterKeyMonitor(symKey);
1948
0
            crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism,
1949
0
                                                 privKey->pkcs11ID, keyTemplate,
1950
0
                                                 templateCount, &symKey->objectID);
1951
0
            pk11_ExitKeyMonitor(symKey);
1952
0
            if (crv == CKR_OK)
1953
0
                return symKey;
1954
0
            PORT_SetError(PK11_MapError(crv));
1955
0
        } break;
1956
0
        case ecKey: {
1957
0
            CK_BBOOL cktrue = CK_TRUE;
1958
0
            CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
1959
0
            CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
1960
0
            CK_ULONG key_size = 0;
1961
0
            CK_ATTRIBUTE keyTemplate[4];
1962
0
            int templateCount;
1963
0
            CK_ATTRIBUTE *attrs = keyTemplate;
1964
0
            CK_ECDH1_DERIVE_PARAMS *mechParams = NULL;
1965
0
1966
0
            if (pubKey->keyType != ecKey) {
1967
0
                PORT_SetError(SEC_ERROR_BAD_KEY);
1968
0
                break;
1969
0
            }
1970
0
1971
0
            PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
1972
0
            attrs++;
1973
0
            PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
1974
0
            attrs++;
1975
0
            PK11_SETATTRS(attrs, operation, &cktrue, 1);
1976
0
            attrs++;
1977
0
            PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size));
1978
0
            attrs++;
1979
0
            templateCount = attrs - keyTemplate;
1980
0
            PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE));
1981
0
1982
0
            keyType = PK11_GetKeyType(target, keySize);
1983
0
            key_size = keySize;
1984
0
            if (key_size == 0) {
1985
0
                if ((key_size = pk11_GetPredefinedKeyLength(keyType))) {
1986
0
                    templateCount--;
1987
0
                } else {
1988
0
                    /* sigh, some tokens can't figure this out and require
1989
0
                     * CKA_VALUE_LEN to be set */
1990
0
                    key_size = SHA1_LENGTH;
1991
0
                }
1992
0
            }
1993
0
            symKey->size = key_size;
1994
0
1995
0
            mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS);
1996
0
            mechParams->kdf = CKD_SHA1_KDF;
1997
0
            mechParams->ulSharedDataLen = 0;
1998
0
            mechParams->pSharedData = NULL;
1999
0
            mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len;
2000
0
            mechParams->pPublicData = pubKey->u.ec.publicValue.data;
2001
0
2002
0
            mechanism.mechanism = derive;
2003
0
            mechanism.pParameter = mechParams;
2004
0
            mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
2005
0
2006
0
            pk11_EnterKeyMonitor(symKey);
2007
0
            crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session,
2008
0
                                                 &mechanism, privKey->pkcs11ID, keyTemplate,
2009
0
                                                 templateCount, &symKey->objectID);
2010
0
            pk11_ExitKeyMonitor(symKey);
2011
0
2012
0
            /* old PKCS #11 spec was ambiguous on what needed to be passed,
2013
0
             * try this again with and encoded public key */
2014
0
            if (crv != CKR_OK && pk11_ECGetPubkeyEncoding(pubKey) != ECPoint_XOnly) {
2015
0
                SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
2016
0
                                                       &pubKey->u.ec.publicValue,
2017
0
                                                       SEC_ASN1_GET(SEC_OctetStringTemplate));
2018
0
                if (pubValue == NULL) {
2019
0
                    PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));
2020
0
                    break;
2021
0
                }
2022
0
                mechParams->ulPublicDataLen = pubValue->len;
2023
0
                mechParams->pPublicData = pubValue->data;
2024
0
2025
0
                pk11_EnterKeyMonitor(symKey);
2026
0
                crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session,
2027
0
                                                     &mechanism, privKey->pkcs11ID, keyTemplate,
2028
0
                                                     templateCount, &symKey->objectID);
2029
0
                pk11_ExitKeyMonitor(symKey);
2030
0
2031
0
                SECITEM_FreeItem(pubValue, PR_TRUE);
2032
0
            }
2033
0
2034
0
            PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));
2035
0
2036
0
            if (crv == CKR_OK)
2037
0
                return symKey;
2038
0
            PORT_SetError(PK11_MapError(crv));
2039
0
        }
2040
0
    }
2041
0
2042
0
    PK11_FreeSymKey(symKey);
2043
0
    return NULL;
2044
0
}
2045
2046
/* Test for curves that are known to use a special encoding.
2047
 * Extend this function when additional curves are added. */
2048
static ECPointEncoding
2049
pk11_ECGetPubkeyEncoding(const SECKEYPublicKey *pubKey)
2050
0
{
2051
0
    SECItem oid;
2052
0
    SECStatus rv;
2053
0
    PORTCheapArenaPool tmpArena;
2054
0
    ECPointEncoding encoding = ECPoint_Undefined;
2055
0
2056
0
    PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
2057
0
2058
0
    /* decode the OID tag */
2059
0
    rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &oid,
2060
0
                                SEC_ASN1_GET(SEC_ObjectIDTemplate),
2061
0
                                &pubKey->u.ec.DEREncodedParams);
2062
0
    if (rv == SECSuccess) {
2063
0
        SECOidTag tag = SECOID_FindOIDTag(&oid);
2064
0
        switch (tag) {
2065
0
            case SEC_OID_CURVE25519:
2066
0
                encoding = ECPoint_XOnly;
2067
0
                break;
2068
0
            case SEC_OID_SECG_EC_SECP256R1:
2069
0
            case SEC_OID_SECG_EC_SECP384R1:
2070
0
            case SEC_OID_SECG_EC_SECP521R1:
2071
0
            default:
2072
0
                /* unknown curve, default to uncompressed */
2073
0
                encoding = ECPoint_Uncompressed;
2074
0
        }
2075
0
    }
2076
0
    PORT_DestroyCheapArena(&tmpArena);
2077
0
    return encoding;
2078
0
}
2079
2080
/* Returns the size of the public key, or 0 if there
2081
 * is an error. */
2082
static CK_ULONG
2083
pk11_ECPubKeySize(SECKEYPublicKey *pubKey)
2084
0
{
2085
0
    SECItem *publicValue = &pubKey->u.ec.publicValue;
2086
0
2087
0
    ECPointEncoding encoding = pk11_ECGetPubkeyEncoding(pubKey);
2088
0
    if (encoding == ECPoint_XOnly) {
2089
0
        return publicValue->len;
2090
0
    }
2091
0
    if (encoding == ECPoint_Uncompressed) {
2092
0
        /* key encoded in uncompressed form */
2093
0
        return ((publicValue->len - 1) / 2);
2094
0
    }
2095
0
    /* key encoding not recognized */
2096
0
    return 0;
2097
0
}
2098
2099
static PK11SymKey *
2100
pk11_PubDeriveECKeyWithKDF(
2101
    SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
2102
    PRBool isSender, SECItem *randomA, SECItem *randomB,
2103
    CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
2104
    CK_ATTRIBUTE_TYPE operation, int keySize,
2105
    CK_ULONG kdf, SECItem *sharedData, void *wincx)
2106
0
{
2107
0
    PK11SlotInfo *slot = privKey->pkcs11Slot;
2108
0
    PK11SymKey *symKey;
2109
0
    PK11SymKey *SharedSecret;
2110
0
    CK_MECHANISM mechanism;
2111
0
    CK_RV crv;
2112
0
    CK_BBOOL cktrue = CK_TRUE;
2113
0
    CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
2114
0
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
2115
0
    CK_ULONG key_size = 0;
2116
0
    CK_ATTRIBUTE keyTemplate[4];
2117
0
    int templateCount;
2118
0
    CK_ATTRIBUTE *attrs = keyTemplate;
2119
0
    CK_ECDH1_DERIVE_PARAMS *mechParams = NULL;
2120
0
2121
0
    if (pubKey->keyType != ecKey) {
2122
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
2123
0
        return NULL;
2124
0
    }
2125
0
    if ((kdf != CKD_NULL) && (kdf != CKD_SHA1_KDF) &&
2126
0
        (kdf != CKD_SHA224_KDF) && (kdf != CKD_SHA256_KDF) &&
2127
0
        (kdf != CKD_SHA384_KDF) && (kdf != CKD_SHA512_KDF)) {
2128
0
        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
2129
0
        return NULL;
2130
0
    }
2131
0
2132
0
    /* get our key Structure */
2133
0
    symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx);
2134
0
    if (symKey == NULL) {
2135
0
        return NULL;
2136
0
    }
2137
0
2138
0
    symKey->origin = PK11_OriginDerive;
2139
0
2140
0
    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
2141
0
    attrs++;
2142
0
    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
2143
0
    attrs++;
2144
0
    PK11_SETATTRS(attrs, operation, &cktrue, 1);
2145
0
    attrs++;
2146
0
    PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size));
2147
0
    attrs++;
2148
0
    templateCount = attrs - keyTemplate;
2149
0
    PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE));
2150
0
2151
0
    keyType = PK11_GetKeyType(target, keySize);
2152
0
    key_size = keySize;
2153
0
    if (key_size == 0) {
2154
0
        if ((key_size = pk11_GetPredefinedKeyLength(keyType))) {
2155
0
            templateCount--;
2156
0
        } else {
2157
0
            /* sigh, some tokens can't figure this out and require
2158
0
             * CKA_VALUE_LEN to be set */
2159
0
            switch (kdf) {
2160
0
                case CKD_NULL:
2161
0
                    key_size = pk11_ECPubKeySize(pubKey);
2162
0
                    if (key_size == 0) {
2163
0
                        PK11_FreeSymKey(symKey);
2164
0
                        return NULL;
2165
0
                    }
2166
0
                    break;
2167
0
                case CKD_SHA1_KDF:
2168
0
                    key_size = SHA1_LENGTH;
2169
0
                    break;
2170
0
                case CKD_SHA224_KDF:
2171
0
                    key_size = SHA224_LENGTH;
2172
0
                    break;
2173
0
                case CKD_SHA256_KDF:
2174
0
                    key_size = SHA256_LENGTH;
2175
0
                    break;
2176
0
                case CKD_SHA384_KDF:
2177
0
                    key_size = SHA384_LENGTH;
2178
0
                    break;
2179
0
                case CKD_SHA512_KDF:
2180
0
                    key_size = SHA512_LENGTH;
2181
0
                    break;
2182
0
                default:
2183
0
                    PORT_Assert(!"Invalid CKD");
2184
0
                    PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
2185
0
                    return NULL;
2186
0
            }
2187
0
        }
2188
0
    }
2189
0
    symKey->size = key_size;
2190
0
2191
0
    mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS);
2192
0
    if (!mechParams) {
2193
0
        PK11_FreeSymKey(symKey);
2194
0
        return NULL;
2195
0
    }
2196
0
    mechParams->kdf = kdf;
2197
0
    if (sharedData == NULL) {
2198
0
        mechParams->ulSharedDataLen = 0;
2199
0
        mechParams->pSharedData = NULL;
2200
0
    } else {
2201
0
        mechParams->ulSharedDataLen = sharedData->len;
2202
0
        mechParams->pSharedData = sharedData->data;
2203
0
    }
2204
0
    mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len;
2205
0
    mechParams->pPublicData = pubKey->u.ec.publicValue.data;
2206
0
2207
0
    mechanism.mechanism = derive;
2208
0
    mechanism.pParameter = mechParams;
2209
0
    mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS);
2210
0
2211
0
    pk11_EnterKeyMonitor(symKey);
2212
0
    crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism,
2213
0
                                         privKey->pkcs11ID, keyTemplate,
2214
0
                                         templateCount, &symKey->objectID);
2215
0
    pk11_ExitKeyMonitor(symKey);
2216
0
2217
0
    /* old PKCS #11 spec was ambiguous on what needed to be passed,
2218
0
     * try this again with an encoded public key */
2219
0
    if (crv != CKR_OK) {
2220
0
        /* For curves that only use X as public value and no encoding we don't
2221
0
         * have to try again. (Currently only Curve25519) */
2222
0
        if (pk11_ECGetPubkeyEncoding(pubKey) == ECPoint_XOnly) {
2223
0
            goto loser;
2224
0
        }
2225
0
        SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
2226
0
                                               &pubKey->u.ec.publicValue,
2227
0
                                               SEC_ASN1_GET(SEC_OctetStringTemplate));
2228
0
        if (pubValue == NULL) {
2229
0
            goto loser;
2230
0
        }
2231
0
        mechParams->ulPublicDataLen = pubValue->len;
2232
0
        mechParams->pPublicData = pubValue->data;
2233
0
2234
0
        pk11_EnterKeyMonitor(symKey);
2235
0
        crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session,
2236
0
                                             &mechanism, privKey->pkcs11ID, keyTemplate,
2237
0
                                             templateCount, &symKey->objectID);
2238
0
        pk11_ExitKeyMonitor(symKey);
2239
0
2240
0
        if ((crv != CKR_OK) && (kdf != CKD_NULL)) {
2241
0
            /* Some PKCS #11 libraries cannot perform the key derivation
2242
0
             * function. So, try calling C_DeriveKey with CKD_NULL and then
2243
0
             * performing the KDF separately.
2244
0
             */
2245
0
            CK_ULONG derivedKeySize = key_size;
2246
0
2247
0
            keyType = CKK_GENERIC_SECRET;
2248
0
            key_size = pk11_ECPubKeySize(pubKey);
2249
0
            if (key_size == 0) {
2250
0
                SECITEM_FreeItem(pubValue, PR_TRUE);
2251
0
                goto loser;
2252
0
            }
2253
0
            SharedSecret = symKey;
2254
0
            SharedSecret->size = key_size;
2255
0
2256
0
            mechParams->kdf = CKD_NULL;
2257
0
            mechParams->ulSharedDataLen = 0;
2258
0
            mechParams->pSharedData = NULL;
2259
0
            mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len;
2260
0
            mechParams->pPublicData = pubKey->u.ec.publicValue.data;
2261
0
2262
0
            pk11_EnterKeyMonitor(SharedSecret);
2263
0
            crv = PK11_GETTAB(slot)->C_DeriveKey(SharedSecret->session,
2264
0
                                                 &mechanism, privKey->pkcs11ID, keyTemplate,
2265
0
                                                 templateCount, &SharedSecret->objectID);
2266
0
            pk11_ExitKeyMonitor(SharedSecret);
2267
0
2268
0
            if (crv != CKR_OK) {
2269
0
                /* old PKCS #11 spec was ambiguous on what needed to be passed,
2270
0
                 * try this one final time with an encoded public key */
2271
0
                mechParams->ulPublicDataLen = pubValue->len;
2272
0
                mechParams->pPublicData = pubValue->data;
2273
0
2274
0
                pk11_EnterKeyMonitor(SharedSecret);
2275
0
                crv = PK11_GETTAB(slot)->C_DeriveKey(SharedSecret->session,
2276
0
                                                     &mechanism, privKey->pkcs11ID, keyTemplate,
2277
0
                                                     templateCount, &SharedSecret->objectID);
2278
0
                pk11_ExitKeyMonitor(SharedSecret);
2279
0
            }
2280
0
2281
0
            /* Perform KDF. */
2282
0
            if (crv == CKR_OK) {
2283
0
                symKey = pk11_ANSIX963Derive(SharedSecret, kdf,
2284
0
                                             sharedData, target, operation,
2285
0
                                             derivedKeySize);
2286
0
                PK11_FreeSymKey(SharedSecret);
2287
0
                if (symKey == NULL) {
2288
0
                    SECITEM_FreeItem(pubValue, PR_TRUE);
2289
0
                    PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));
2290
0
                    return NULL;
2291
0
                }
2292
0
            }
2293
0
        }
2294
0
        SECITEM_FreeItem(pubValue, PR_TRUE);
2295
0
    }
2296
0
2297
0
loser:
2298
0
    PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS));
2299
0
2300
0
    if (crv != CKR_OK) {
2301
0
        PK11_FreeSymKey(symKey);
2302
0
        symKey = NULL;
2303
0
        PORT_SetError(PK11_MapError(crv));
2304
0
    }
2305
0
    return symKey;
2306
0
}
2307
2308
PK11SymKey *
2309
PK11_PubDeriveWithKDF(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
2310
                      PRBool isSender, SECItem *randomA, SECItem *randomB,
2311
                      CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
2312
                      CK_ATTRIBUTE_TYPE operation, int keySize,
2313
                      CK_ULONG kdf, SECItem *sharedData, void *wincx)
2314
0
{
2315
0
2316
0
    switch (privKey->keyType) {
2317
0
        case rsaKey:
2318
0
        case nullKey:
2319
0
        case dsaKey:
2320
0
        case keaKey:
2321
0
        case fortezzaKey:
2322
0
        case dhKey:
2323
0
            return PK11_PubDerive(privKey, pubKey, isSender, randomA, randomB,
2324
0
                                  derive, target, operation, keySize, wincx);
2325
0
        case ecKey:
2326
0
            return pk11_PubDeriveECKeyWithKDF(privKey, pubKey, isSender,
2327
0
                                              randomA, randomB, derive, target,
2328
0
                                              operation, keySize,
2329
0
                                              kdf, sharedData, wincx);
2330
0
        default:
2331
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
2332
0
            break;
2333
0
    }
2334
0
2335
0
    return NULL;
2336
0
}
2337
2338
/*
2339
 * this little function uses the Decrypt function to unwrap a key, just in
2340
 * case we are having problem with unwrap. NOTE: The key size may
2341
 * not be preserved properly for some algorithms!
2342
 */
2343
static PK11SymKey *
2344
pk11_HandUnwrap(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey,
2345
                CK_MECHANISM *mech, SECItem *inKey, CK_MECHANISM_TYPE target,
2346
                CK_ATTRIBUTE *keyTemplate, unsigned int templateCount,
2347
                int key_size, void *wincx, CK_RV *crvp, PRBool isPerm)
2348
0
{
2349
0
    CK_ULONG len;
2350
0
    SECItem outKey;
2351
0
    PK11SymKey *symKey;
2352
0
    CK_RV crv;
2353
0
    PRBool owner = PR_TRUE;
2354
0
    CK_SESSION_HANDLE session;
2355
0
2356
0
    /* remove any VALUE_LEN parameters */
2357
0
    if (keyTemplate[templateCount - 1].type == CKA_VALUE_LEN) {
2358
0
        templateCount--;
2359
0
    }
2360
0
2361
0
    /* keys are almost always aligned, but if we get this far,
2362
0
     * we've gone above and beyond anyway... */
2363
0
    outKey.data = (unsigned char *)PORT_Alloc(inKey->len);
2364
0
    if (outKey.data == NULL) {
2365
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
2366
0
        if (crvp)
2367
0
            *crvp = CKR_HOST_MEMORY;
2368
0
        return NULL;
2369
0
    }
2370
0
    len = inKey->len;
2371
0
2372
0
    /* use NULL IV's for wrapping */
2373
0
    session = pk11_GetNewSession(slot, &owner);
2374
0
    if (!owner || !(slot->isThreadSafe))
2375
0
        PK11_EnterSlotMonitor(slot);
2376
0
    crv = PK11_GETTAB(slot)->C_DecryptInit(session, mech, wrappingKey);
2377
0
    if (crv != CKR_OK) {
2378
0
        if (!owner || !(slot->isThreadSafe))
2379
0
            PK11_ExitSlotMonitor(slot);
2380
0
        pk11_CloseSession(slot, session, owner);
2381
0
        PORT_Free(outKey.data);
2382
0
        PORT_SetError(PK11_MapError(crv));
2383
0
        if (crvp)
2384
0
            *crvp = crv;
2385
0
        return NULL;
2386
0
    }
2387
0
    crv = PK11_GETTAB(slot)->C_Decrypt(session, inKey->data, inKey->len,
2388
0
                                       outKey.data, &len);
2389
0
    if (!owner || !(slot->isThreadSafe))
2390
0
        PK11_ExitSlotMonitor(slot);
2391
0
    pk11_CloseSession(slot, session, owner);
2392
0
    if (crv != CKR_OK) {
2393
0
        PORT_Free(outKey.data);
2394
0
        PORT_SetError(PK11_MapError(crv));
2395
0
        if (crvp)
2396
0
            *crvp = crv;
2397
0
        return NULL;
2398
0
    }
2399
0
2400
0
    outKey.len = (key_size == 0) ? len : key_size;
2401
0
    outKey.type = siBuffer;
2402
0
2403
0
    if (PK11_DoesMechanism(slot, target)) {
2404
0
        symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap,
2405
0
                                            isPerm, keyTemplate,
2406
0
                                            templateCount, &outKey, wincx);
2407
0
    } else {
2408
0
        slot = PK11_GetBestSlot(target, wincx);
2409
0
        if (slot == NULL) {
2410
0
            PORT_SetError(SEC_ERROR_NO_MODULE);
2411
0
            PORT_Free(outKey.data);
2412
0
            if (crvp)
2413
0
                *crvp = CKR_DEVICE_ERROR;
2414
0
            return NULL;
2415
0
        }
2416
0
        symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap,
2417
0
                                            isPerm, keyTemplate,
2418
0
                                            templateCount, &outKey, wincx);
2419
0
        PK11_FreeSlot(slot);
2420
0
    }
2421
0
    PORT_Free(outKey.data);
2422
0
2423
0
    if (crvp)
2424
0
        *crvp = symKey ? CKR_OK : CKR_DEVICE_ERROR;
2425
0
    return symKey;
2426
0
}
2427
2428
/*
2429
 * The wrap/unwrap function is pretty much the same for private and
2430
 * public keys. It's just getting the Object ID and slot right. This is
2431
 * the combined unwrap function.
2432
 */
2433
static PK11SymKey *
2434
pk11_AnyUnwrapKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey,
2435
                  CK_MECHANISM_TYPE wrapType, SECItem *param, SECItem *wrappedKey,
2436
                  CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize,
2437
                  void *wincx, CK_ATTRIBUTE *userAttr, unsigned int numAttrs, PRBool isPerm)
2438
0
{
2439
0
    PK11SymKey *symKey;
2440
0
    SECItem *param_free = NULL;
2441
0
    CK_BBOOL cktrue = CK_TRUE;
2442
0
    CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
2443
0
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
2444
0
    CK_ULONG valueLen = 0;
2445
0
    CK_MECHANISM mechanism;
2446
0
    CK_SESSION_HANDLE rwsession;
2447
0
    CK_RV crv;
2448
0
    CK_MECHANISM_INFO mechanism_info;
2449
0
#define MAX_ADD_ATTRS 4
2450
0
    CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS + MAX_ADD_ATTRS];
2451
0
#undef MAX_ADD_ATTRS
2452
0
    CK_ATTRIBUTE *attrs = keyTemplate;
2453
0
    unsigned int templateCount;
2454
0
2455
0
    if (numAttrs > MAX_TEMPL_ATTRS) {
2456
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
2457
0
        return NULL;
2458
0
    }
2459
0
2460
0
    /* first copy caller attributes in. */
2461
0
    for (templateCount = 0; templateCount < numAttrs; ++templateCount) {
2462
0
        *attrs++ = *userAttr++;
2463
0
    }
2464
0
2465
0
    /* We only add the following attributes to the template if the caller
2466
0
    ** didn't already supply them.
2467
0
    */
2468
0
    if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) {
2469
0
        PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass);
2470
0
        attrs++;
2471
0
    }
2472
0
    if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) {
2473
0
        keyType = PK11_GetKeyType(target, keySize);
2474
0
        PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType);
2475
0
        attrs++;
2476
0
    }
2477
0
    if ((operation != CKA_FLAGS_ONLY) &&
2478
0
        !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) {
2479
0
        PK11_SETATTRS(attrs, operation, &cktrue, 1);
2480
0
        attrs++;
2481
0
    }
2482
0
2483
0
    /*
2484
0
     * must be last in case we need to use this template to import the key
2485
0
     */
2486
0
    if (keySize > 0 &&
2487
0
        !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) {
2488
0
        valueLen = (CK_ULONG)keySize;
2489
0
        PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen);
2490
0
        attrs++;
2491
0
    }
2492
0
2493
0
    templateCount = attrs - keyTemplate;
2494
0
    PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE));
2495
0
2496
0
    /* find out if we can do wrap directly. Because the RSA case if *very*
2497
0
     * common, cache the results for it. */
2498
0
    if ((wrapType == CKM_RSA_PKCS) && (slot->hasRSAInfo)) {
2499
0
        mechanism_info.flags = slot->RSAInfoFlags;
2500
0
    } else {
2501
0
        if (!slot->isThreadSafe)
2502
0
            PK11_EnterSlotMonitor(slot);
2503
0
        crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID, wrapType,
2504
0
                                                    &mechanism_info);
2505
0
        if (!slot->isThreadSafe)
2506
0
            PK11_ExitSlotMonitor(slot);
2507
0
        if (crv != CKR_OK) {
2508
0
            mechanism_info.flags = 0;
2509
0
        }
2510
0
        if (wrapType == CKM_RSA_PKCS) {
2511
0
            slot->RSAInfoFlags = mechanism_info.flags;
2512
0
            slot->hasRSAInfo = PR_TRUE;
2513
0
        }
2514
0
    }
2515
0
2516
0
    /* initialize the mechanism structure */
2517
0
    mechanism.mechanism = wrapType;
2518
0
    /* use NULL IV's for wrapping */
2519
0
    if (param == NULL)
2520
0
        param = param_free = PK11_ParamFromIV(wrapType, NULL);
2521
0
    if (param) {
2522
0
        mechanism.pParameter = param->data;
2523
0
        mechanism.ulParameterLen = param->len;
2524
0
    } else {
2525
0
        mechanism.pParameter = NULL;
2526
0
        mechanism.ulParameterLen = 0;
2527
0
    }
2528
0
2529
0
    if ((mechanism_info.flags & CKF_DECRYPT) && !PK11_DoesMechanism(slot, target)) {
2530
0
        symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey,
2531
0
                                 target, keyTemplate, templateCount, keySize,
2532
0
                                 wincx, &crv, isPerm);
2533
0
        if (symKey) {
2534
0
            if (param_free)
2535
0
                SECITEM_FreeItem(param_free, PR_TRUE);
2536
0
            return symKey;
2537
0
        }
2538
0
        /*
2539
0
         * if the RSA OP simply failed, don't try to unwrap again
2540
0
         * with this module.
2541
0
         */
2542
0
        if (crv == CKR_DEVICE_ERROR) {
2543
0
            if (param_free)
2544
0
                SECITEM_FreeItem(param_free, PR_TRUE);
2545
0
            return NULL;
2546
0
        }
2547
0
        /* fall through, maybe they incorrectly set CKF_DECRYPT */
2548
0
    }
2549
0
2550
0
    /* get our key Structure */
2551
0
    symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, wincx);
2552
0
    if (symKey == NULL) {
2553
0
        if (param_free)
2554
0
            SECITEM_FreeItem(param_free, PR_TRUE);
2555
0
        return NULL;
2556
0
    }
2557
0
2558
0
    symKey->size = keySize;
2559
0
    symKey->origin = PK11_OriginUnwrap;
2560
0
2561
0
    if (isPerm) {
2562
0
        rwsession = PK11_GetRWSession(slot);
2563
0
    } else {
2564
0
        pk11_EnterKeyMonitor(symKey);
2565
0
        rwsession = symKey->session;
2566
0
    }
2567
0
    PORT_Assert(rwsession != CK_INVALID_SESSION);
2568
0
    if (rwsession == CK_INVALID_SESSION)
2569
0
        crv = CKR_SESSION_HANDLE_INVALID;
2570
0
    else
2571
0
        crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession, &mechanism, wrappingKey,
2572
0
                                             wrappedKey->data, wrappedKey->len,
2573
0
                                             keyTemplate, templateCount,
2574
0
                                             &symKey->objectID);
2575
0
    if (isPerm) {
2576
0
        if (rwsession != CK_INVALID_SESSION)
2577
0
            PK11_RestoreROSession(slot, rwsession);
2578
0
    } else {
2579
0
        pk11_ExitKeyMonitor(symKey);
2580
0
    }
2581
0
    if (param_free)
2582
0
        SECITEM_FreeItem(param_free, PR_TRUE);
2583
0
    if (crv != CKR_OK) {
2584
0
        PK11_FreeSymKey(symKey);
2585
0
        symKey = NULL;
2586
0
        if (crv != CKR_DEVICE_ERROR) {
2587
0
            /* try hand Unwrapping */
2588
0
            symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey,
2589
0
                                     target, keyTemplate, templateCount,
2590
0
                                     keySize, wincx, NULL, isPerm);
2591
0
        }
2592
0
    }
2593
0
2594
0
    return symKey;
2595
0
}
2596
2597
/* use a symetric key to unwrap another symetric key */
2598
PK11SymKey *
2599
PK11_UnwrapSymKey(PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType,
2600
                  SECItem *param, SECItem *wrappedKey,
2601
                  CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
2602
                  int keySize)
2603
0
{
2604
0
    return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID,
2605
0
                             wrapType, param, wrappedKey, target, operation, keySize,
2606
0
                             wrappingKey->cx, NULL, 0, PR_FALSE);
2607
0
}
2608
2609
/* use a symetric key to unwrap another symetric key */
2610
PK11SymKey *
2611
PK11_UnwrapSymKeyWithFlags(PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType,
2612
                           SECItem *param, SECItem *wrappedKey,
2613
                           CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
2614
                           int keySize, CK_FLAGS flags)
2615
0
{
2616
0
    CK_BBOOL ckTrue = CK_TRUE;
2617
0
    CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
2618
0
    unsigned int templateCount;
2619
0
2620
0
    templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
2621
0
    return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID,
2622
0
                             wrapType, param, wrappedKey, target, operation, keySize,
2623
0
                             wrappingKey->cx, keyTemplate, templateCount, PR_FALSE);
2624
0
}
2625
2626
PK11SymKey *
2627
PK11_UnwrapSymKeyWithFlagsPerm(PK11SymKey *wrappingKey,
2628
                               CK_MECHANISM_TYPE wrapType,
2629
                               SECItem *param, SECItem *wrappedKey,
2630
                               CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
2631
                               int keySize, CK_FLAGS flags, PRBool isPerm)
2632
0
{
2633
0
    CK_BBOOL cktrue = CK_TRUE;
2634
0
    CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
2635
0
    CK_ATTRIBUTE *attrs;
2636
0
    unsigned int templateCount;
2637
0
2638
0
    attrs = keyTemplate;
2639
0
    if (isPerm) {
2640
0
        PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
2641
0
        attrs++;
2642
0
    }
2643
0
    templateCount = attrs - keyTemplate;
2644
0
    templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
2645
0
2646
0
    return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID,
2647
0
                             wrapType, param, wrappedKey, target, operation, keySize,
2648
0
                             wrappingKey->cx, keyTemplate, templateCount, isPerm);
2649
0
}
2650
2651
/* unwrap a symetric key with a private key. */
2652
PK11SymKey *
2653
PK11_PubUnwrapSymKey(SECKEYPrivateKey *wrappingKey, SECItem *wrappedKey,
2654
                     CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize)
2655
0
{
2656
0
    CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType);
2657
0
    PK11SlotInfo *slot = wrappingKey->pkcs11Slot;
2658
0
2659
0
    if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey, CKA_PRIVATE)) {
2660
0
        PK11_HandlePasswordCheck(slot, wrappingKey->wincx);
2661
0
    }
2662
0
2663
0
    return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID,
2664
0
                             wrapType, NULL, wrappedKey, target, operation, keySize,
2665
0
                             wrappingKey->wincx, NULL, 0, PR_FALSE);
2666
0
}
2667
2668
/* unwrap a symetric key with a private key. */
2669
PK11SymKey *
2670
PK11_PubUnwrapSymKeyWithFlags(SECKEYPrivateKey *wrappingKey,
2671
                              SECItem *wrappedKey, CK_MECHANISM_TYPE target,
2672
                              CK_ATTRIBUTE_TYPE operation, int keySize, CK_FLAGS flags)
2673
0
{
2674
0
    CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType);
2675
0
    CK_BBOOL ckTrue = CK_TRUE;
2676
0
    CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
2677
0
    unsigned int templateCount;
2678
0
    PK11SlotInfo *slot = wrappingKey->pkcs11Slot;
2679
0
2680
0
    templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue);
2681
0
2682
0
    if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey, CKA_PRIVATE)) {
2683
0
        PK11_HandlePasswordCheck(slot, wrappingKey->wincx);
2684
0
    }
2685
0
2686
0
    return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID,
2687
0
                             wrapType, NULL, wrappedKey, target, operation, keySize,
2688
0
                             wrappingKey->wincx, keyTemplate, templateCount, PR_FALSE);
2689
0
}
2690
2691
PK11SymKey *
2692
PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey,
2693
                                  SECItem *wrappedKey, CK_MECHANISM_TYPE target,
2694
                                  CK_ATTRIBUTE_TYPE operation, int keySize,
2695
                                  CK_FLAGS flags, PRBool isPerm)
2696
0
{
2697
0
    CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType);
2698
0
    CK_BBOOL cktrue = CK_TRUE;
2699
0
    CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
2700
0
    CK_ATTRIBUTE *attrs;
2701
0
    unsigned int templateCount;
2702
0
    PK11SlotInfo *slot = wrappingKey->pkcs11Slot;
2703
0
2704
0
    attrs = keyTemplate;
2705
0
    if (isPerm) {
2706
0
        PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
2707
0
        attrs++;
2708
0
    }
2709
0
    templateCount = attrs - keyTemplate;
2710
0
2711
0
    templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue);
2712
0
2713
0
    if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey, CKA_PRIVATE)) {
2714
0
        PK11_HandlePasswordCheck(slot, wrappingKey->wincx);
2715
0
    }
2716
0
2717
0
    return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID,
2718
0
                             wrapType, NULL, wrappedKey, target, operation, keySize,
2719
0
                             wrappingKey->wincx, keyTemplate, templateCount, isPerm);
2720
0
}
2721
2722
PK11SymKey *
2723
PK11_CopySymKeyForSigning(PK11SymKey *originalKey, CK_MECHANISM_TYPE mech)
2724
0
{
2725
0
    CK_RV crv;
2726
0
    CK_ATTRIBUTE setTemplate;
2727
0
    CK_BBOOL ckTrue = CK_TRUE;
2728
0
    PK11SlotInfo *slot = originalKey->slot;
2729
0
2730
0
    /* first just try to set this key up for signing */
2731
0
    PK11_SETATTRS(&setTemplate, CKA_SIGN, &ckTrue, sizeof(ckTrue));
2732
0
    pk11_EnterKeyMonitor(originalKey);
2733
0
    crv = PK11_GETTAB(slot)->C_SetAttributeValue(originalKey->session,
2734
0
                                                 originalKey->objectID, &setTemplate, 1);
2735
0
    pk11_ExitKeyMonitor(originalKey);
2736
0
    if (crv == CKR_OK) {
2737
0
        return PK11_ReferenceSymKey(originalKey);
2738
0
    }
2739
0
2740
0
    /* nope, doesn't like it, use the pk11 copy object command */
2741
0
    return pk11_CopyToSlot(slot, mech, CKA_SIGN, originalKey);
2742
0
}
2743
2744
void
2745
PK11_SetFortezzaHack(PK11SymKey *symKey)
2746
0
{
2747
0
    symKey->origin = PK11_OriginFortezzaHack;
2748
0
}
2749
2750
/*
2751
 * This is required to allow FORTEZZA_NULL and FORTEZZA_RC4
2752
 * working. This function simply gets a valid IV for the keys.
2753
 */
2754
SECStatus
2755
PK11_GenerateFortezzaIV(PK11SymKey *symKey, unsigned char *iv, int len)
2756
0
{
2757
0
    CK_MECHANISM mech_info;
2758
0
    CK_ULONG count = 0;
2759
0
    CK_RV crv;
2760
0
    SECStatus rv = SECFailure;
2761
0
2762
0
    mech_info.mechanism = CKM_SKIPJACK_CBC64;
2763
0
    mech_info.pParameter = iv;
2764
0
    mech_info.ulParameterLen = len;
2765
0
2766
0
    /* generate the IV for fortezza */
2767
0
    PK11_EnterSlotMonitor(symKey->slot);
2768
0
    crv = PK11_GETTAB(symKey->slot)->C_EncryptInit(symKey->slot->session, &mech_info, symKey->objectID);
2769
0
    if (crv == CKR_OK) {
2770
0
        PK11_GETTAB(symKey->slot)->C_EncryptFinal(symKey->slot->session, NULL, &count);
2771
0
        rv = SECSuccess;
2772
0
    }
2773
0
    PK11_ExitSlotMonitor(symKey->slot);
2774
0
    return rv;
2775
0
}
2776
2777
CK_OBJECT_HANDLE
2778
PK11_GetSymKeyHandle(PK11SymKey *symKey)
2779
0
{
2780
0
    return symKey->objectID;
2781
0
}