Coverage Report

Created: 2024-05-20 06:23

/src/nss/lib/softoken/pkcs11c.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 PKCS 11 on top of our existing security modules
6
 *
7
 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
8
 *   This implementation has two slots:
9
 *      slot 1 is our generic crypto support. It does not require login.
10
 *   It supports Public Key ops, and all they bulk ciphers and hashes.
11
 *   It can also support Private Key ops for imported Private keys. It does
12
 *   not have any token storage.
13
 *      slot 2 is our private key support. It requires a login before use. It
14
 *   can store Private Keys and Certs as token objects. Currently only private
15
 *   keys and their associated Certificates are saved on the token.
16
 *
17
 *   In this implementation, session objects are only visible to the session
18
 *   that created or generated them.
19
 */
20
21
#include <limits.h> /* for UINT_MAX and ULONG_MAX */
22
23
#include "seccomon.h"
24
#include "secitem.h"
25
#include "secport.h"
26
#include "blapi.h"
27
#include "pkcs11.h"
28
#include "pkcs11i.h"
29
#include "pkcs1sig.h"
30
#include "lowkeyi.h"
31
#include "secder.h"
32
#include "secdig.h"
33
#include "lowpbe.h" /* We do PBE below */
34
#include "pkcs11t.h"
35
#include "secoid.h"
36
#include "cmac.h"
37
#include "alghmac.h"
38
#include "softoken.h"
39
#include "secasn1.h"
40
#include "secerr.h"
41
#include "kem.h"
42
#include "kyber.h"
43
44
#include "prprf.h"
45
#include "prenv.h"
46
47
#define __PASTE(x, y) x##y
48
25.4k
#define BAD_PARAM_CAST(pMech, typeSize) (!pMech->pParameter || pMech->ulParameterLen < typeSize)
49
/*
50
 * we renamed all our internal functions, get the correct
51
 * definitions for them...
52
 */
53
#undef CK_PKCS11_FUNCTION_INFO
54
#undef CK_NEED_ARG_LIST
55
56
#define CK_PKCS11_3_0 1
57
58
#define CK_EXTERN extern
59
#define CK_PKCS11_FUNCTION_INFO(func) \
60
    CK_RV __PASTE(NS, func)
61
#define CK_NEED_ARG_LIST 1
62
63
#include "pkcs11f.h"
64
65
/* create a definition of SHA1 that's consistent
66
 * with the rest of the CKM_SHAxxx hashes*/
67
217k
#define CKM_SHA1 CKM_SHA_1
68
13.3k
#define CKM_SHA1_HMAC CKM_SHA_1_HMAC
69
0
#define CKM_SHA1_HMAC_GENERAL CKM_SHA_1_HMAC_GENERAL
70
71
typedef struct {
72
    PRUint8 client_version[2];
73
    PRUint8 random[46];
74
} SSL3RSAPreMasterSecret;
75
76
static void
77
sftk_Null(void *data, PRBool freeit)
78
18.9k
{
79
18.9k
    return;
80
18.9k
}
81
82
#ifdef EC_DEBUG
83
#define SEC_PRINT(str1, str2, num, sitem)             \
84
    printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
85
           str1, str2, num, sitem->len);              \
86
    for (i = 0; i < sitem->len; i++) {                \
87
        printf("%02x:", sitem->data[i]);              \
88
    }                                                 \
89
    printf("\n")
90
#else
91
#undef EC_DEBUG
92
#define SEC_PRINT(a, b, c, d)
93
#endif
94
95
/*
96
 * free routines.... Free local type  allocated data, and convert
97
 * other free routines to the destroy signature.
98
 */
99
static void
100
sftk_FreePrivKey(NSSLOWKEYPrivateKey *key, PRBool freeit)
101
0
{
102
0
    nsslowkey_DestroyPrivateKey(key);
103
0
}
104
105
static void
106
sftk_Space(void *data, PRBool freeit)
107
34.9k
{
108
34.9k
    PORT_Free(data);
109
34.9k
}
110
111
static void
112
sftk_ZSpace(void *data, PRBool freeit)
113
2.86k
{
114
2.86k
    size_t len = *(size_t *)data;
115
2.86k
    PORT_ZFree(data, len);
116
2.86k
}
117
118
/*
119
 * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
120
 * Deprecating a full des key to 40 bit key strenth.
121
 */
122
static CK_RV
123
sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey)
124
0
{
125
0
    unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae };
126
0
    unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 };
127
0
    unsigned char enc_src[8];
128
0
    unsigned char enc_dest[8];
129
0
    unsigned int leng, i;
130
0
    DESContext *descx;
131
0
    SECStatus rv;
132
0
    CK_RV crv = CKR_OK;
133
134
    /* zero the parity bits */
135
0
    for (i = 0; i < 8; i++) {
136
0
        enc_src[i] = cdmfkey[i] & 0xfe;
137
0
    }
138
139
    /* encrypt with key 1 */
140
0
    descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE);
141
0
    if (descx == NULL) {
142
0
        crv = CKR_HOST_MEMORY;
143
0
        goto done;
144
0
    }
145
0
    rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8);
146
0
    DES_DestroyContext(descx, PR_TRUE);
147
0
    if (rv != SECSuccess) {
148
0
        crv = sftk_MapCryptError(PORT_GetError());
149
0
        goto done;
150
0
    }
151
152
    /* xor source with des, zero the parity bits and deprecate the key*/
153
0
    for (i = 0; i < 8; i++) {
154
0
        if (i & 1) {
155
0
            enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe;
156
0
        } else {
157
0
            enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e;
158
0
        }
159
0
    }
160
161
    /* encrypt with key 2 */
162
0
    descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE);
163
0
    if (descx == NULL) {
164
0
        crv = CKR_HOST_MEMORY;
165
0
        goto done;
166
0
    }
167
0
    rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8);
168
0
    DES_DestroyContext(descx, PR_TRUE);
169
0
    if (rv != SECSuccess) {
170
0
        crv = sftk_MapCryptError(PORT_GetError());
171
0
        goto done;
172
0
    }
173
174
    /* set the corret parity on our new des key */
175
0
    sftk_FormatDESKey(deskey, 8);
176
0
done:
177
0
    PORT_Memset(enc_src, 0, sizeof enc_src);
178
0
    PORT_Memset(enc_dest, 0, sizeof enc_dest);
179
0
    return crv;
180
0
}
181
182
/* NSC_DestroyObject destroys an object. */
183
CK_RV
184
NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
185
198k
{
186
198k
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
187
198k
    SFTKSession *session;
188
198k
    SFTKObject *object;
189
198k
    SFTKFreeStatus status;
190
191
198k
    CHECK_FORK();
192
193
198k
    if (slot == NULL) {
194
0
        return CKR_SESSION_HANDLE_INVALID;
195
0
    }
196
    /*
197
     * This whole block just makes sure we really can destroy the
198
     * requested object.
199
     */
200
198k
    session = sftk_SessionFromHandle(hSession);
201
198k
    if (session == NULL) {
202
0
        return CKR_SESSION_HANDLE_INVALID;
203
0
    }
204
205
198k
    object = sftk_ObjectFromHandle(hObject, session);
206
198k
    if (object == NULL) {
207
0
        sftk_FreeSession(session);
208
0
        return CKR_OBJECT_HANDLE_INVALID;
209
0
    }
210
211
    /* don't destroy a private object if we aren't logged in */
212
198k
    if ((!slot->isLoggedIn) && (slot->needLogin) &&
213
198k
        (sftk_isTrue(object, CKA_PRIVATE))) {
214
0
        sftk_FreeSession(session);
215
0
        sftk_FreeObject(object);
216
0
        return CKR_USER_NOT_LOGGED_IN;
217
0
    }
218
219
    /* don't destroy a token object if we aren't in a rw session */
220
221
198k
    if (((session->info.flags & CKF_RW_SESSION) == 0) &&
222
198k
        (sftk_isTrue(object, CKA_TOKEN))) {
223
0
        sftk_FreeSession(session);
224
0
        sftk_FreeObject(object);
225
0
        return CKR_SESSION_READ_ONLY;
226
0
    }
227
228
198k
    sftk_DeleteObject(session, object);
229
230
198k
    sftk_FreeSession(session);
231
232
    /*
233
     * get some indication if the object is destroyed. Note: this is not
234
     * 100%. Someone may have an object reference outstanding (though that
235
     * should not be the case by here. Also note that the object is "half"
236
     * destroyed. Our internal representation is destroyed, but it may still
237
     * be in the data base.
238
     */
239
198k
    status = sftk_FreeObject(object);
240
241
198k
    return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;
242
198k
}
243
244
/*
245
 * Returns true if "params" contains a valid set of PSS parameters
246
 */
247
static PRBool
248
sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params)
249
2.86k
{
250
2.86k
    if (!params) {
251
0
        return PR_FALSE;
252
0
    }
253
2.86k
    if (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL ||
254
2.86k
        sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) {
255
0
        return PR_FALSE;
256
0
    }
257
2.86k
    return PR_TRUE;
258
2.86k
}
259
260
/*
261
 * Returns true if "params" contains a valid set of OAEP parameters
262
 */
263
static PRBool
264
sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS *params)
265
0
{
266
0
    if (!params) {
267
0
        return PR_FALSE;
268
0
    }
269
    /* The requirements of ulSourceLen/pSourceData come from PKCS #11, which
270
     * state:
271
     *   If the parameter is empty, pSourceData must be NULL and
272
     *   ulSourceDataLen must be zero.
273
     */
274
0
    if (params->source != CKZ_DATA_SPECIFIED ||
275
0
        (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) ||
276
0
        (sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) ||
277
0
        (params->ulSourceDataLen == 0 && params->pSourceData != NULL) ||
278
0
        (params->ulSourceDataLen != 0 && params->pSourceData == NULL)) {
279
0
        return PR_FALSE;
280
0
    }
281
0
    return PR_TRUE;
282
0
}
283
284
/*
285
 * return a context based on the SFTKContext type.
286
 */
287
SFTKSessionContext *
288
sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type)
289
885k
{
290
885k
    switch (type) {
291
21.3k
        case SFTK_ENCRYPT:
292
40.3k
        case SFTK_DECRYPT:
293
45.7k
        case SFTK_MESSAGE_ENCRYPT:
294
62.4k
        case SFTK_MESSAGE_DECRYPT:
295
62.4k
            return session->enc_context;
296
640k
        case SFTK_HASH:
297
640k
            return session->hash_context;
298
172k
        case SFTK_SIGN:
299
172k
        case SFTK_SIGN_RECOVER:
300
180k
        case SFTK_VERIFY:
301
182k
        case SFTK_VERIFY_RECOVER:
302
182k
        case SFTK_MESSAGE_SIGN:
303
182k
        case SFTK_MESSAGE_VERIFY:
304
182k
            return session->hash_context;
305
885k
    }
306
0
    return NULL;
307
885k
}
308
309
/*
310
 * change a context based on the SFTKContext type.
311
 */
312
void
313
sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
314
                      SFTKSessionContext *context)
315
448k
{
316
448k
    switch (type) {
317
14.4k
        case SFTK_ENCRYPT:
318
19.6k
        case SFTK_DECRYPT:
319
21.9k
        case SFTK_MESSAGE_ENCRYPT:
320
24.2k
        case SFTK_MESSAGE_DECRYPT:
321
24.2k
            session->enc_context = context;
322
24.2k
            break;
323
304k
        case SFTK_HASH:
324
304k
            session->hash_context = context;
325
304k
            break;
326
110k
        case SFTK_SIGN:
327
110k
        case SFTK_SIGN_RECOVER:
328
118k
        case SFTK_VERIFY:
329
119k
        case SFTK_VERIFY_RECOVER:
330
119k
        case SFTK_MESSAGE_SIGN:
331
119k
        case SFTK_MESSAGE_VERIFY:
332
119k
            session->hash_context = context;
333
119k
            break;
334
448k
    }
335
448k
    return;
336
448k
}
337
338
/*
339
 * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal,
340
 * and C_XXX function. The function takes a session handle, the context type,
341
 * and wether or not the session needs to be multipart. It returns the context,
342
 * and optionally returns the session pointer (if sessionPtr != NULL) if session
343
 * pointer is returned, the caller is responsible for freeing it.
344
 */
345
CK_RV
346
sftk_GetContext(CK_SESSION_HANDLE handle, SFTKSessionContext **contextPtr,
347
                SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr)
348
624k
{
349
624k
    SFTKSession *session;
350
624k
    SFTKSessionContext *context;
351
352
624k
    session = sftk_SessionFromHandle(handle);
353
624k
    if (session == NULL)
354
0
        return CKR_SESSION_HANDLE_INVALID;
355
624k
    context = sftk_ReturnContextByType(session, type);
356
    /* make sure the context is valid */
357
624k
    if ((context == NULL) || (context->type != type) || (needMulti && !(context->multi))) {
358
27.2k
        sftk_FreeSession(session);
359
27.2k
        return CKR_OPERATION_NOT_INITIALIZED;
360
27.2k
    }
361
597k
    *contextPtr = context;
362
597k
    if (sessionPtr != NULL) {
363
262k
        *sessionPtr = session;
364
334k
    } else {
365
334k
        sftk_FreeSession(session);
366
334k
    }
367
597k
    return CKR_OK;
368
624k
}
369
370
/** Terminate operation (in the PKCS#11 spec sense).
371
 *  Intuitive name for FreeContext/SetNullContext pair.
372
 */
373
void
374
sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype,
375
                 SFTKSessionContext *context)
376
187k
{
377
187k
    session->lastOpWasFIPS = context->isFIPS;
378
187k
    sftk_FreeContext(context);
379
187k
    sftk_SetContextByType(session, ctype, NULL);
380
187k
}
381
382
/*
383
 ************** Crypto Functions:     Encrypt ************************
384
 */
385
386
/*
387
 * All the NSC_InitXXX functions have a set of common checks and processing they
388
 * all need to do at the beginning. This is done here.
389
 */
390
CK_RV
391
sftk_InitGeneric(SFTKSession *session, CK_MECHANISM *pMechanism,
392
                 SFTKSessionContext **contextPtr,
393
                 SFTKContextType ctype, SFTKObject **keyPtr,
394
                 CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
395
                 CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation)
396
240k
{
397
240k
    SFTKObject *key = NULL;
398
240k
    SFTKAttribute *att;
399
240k
    SFTKSessionContext *context;
400
401
    /* We can only init if there is not current context active */
402
240k
    if (sftk_ReturnContextByType(session, ctype) != NULL) {
403
0
        return CKR_OPERATION_ACTIVE;
404
0
    }
405
406
    /* find the key */
407
240k
    if (keyPtr) {
408
84.8k
        key = sftk_ObjectFromHandle(hKey, session);
409
84.8k
        if (key == NULL) {
410
0
            return CKR_KEY_HANDLE_INVALID;
411
0
        }
412
413
        /* make sure it's a valid  key for this operation */
414
84.8k
        if (((key->objclass != CKO_SECRET_KEY) &&
415
84.8k
             (key->objclass != pubKeyType)) ||
416
84.8k
            !sftk_isTrue(key, operation)) {
417
0
            sftk_FreeObject(key);
418
0
            return CKR_KEY_TYPE_INCONSISTENT;
419
0
        }
420
        /* get the key type */
421
84.8k
        att = sftk_FindAttribute(key, CKA_KEY_TYPE);
422
84.8k
        if (att == NULL) {
423
0
            sftk_FreeObject(key);
424
0
            return CKR_KEY_TYPE_INCONSISTENT;
425
0
        }
426
84.8k
        PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE));
427
84.8k
        if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) {
428
0
            sftk_FreeAttribute(att);
429
0
            sftk_FreeObject(key);
430
0
            return CKR_ATTRIBUTE_VALUE_INVALID;
431
0
        }
432
84.8k
        PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE));
433
84.8k
        sftk_FreeAttribute(att);
434
84.8k
        *keyPtr = key;
435
84.8k
    }
436
437
    /* allocate the context structure */
438
240k
    context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext));
439
240k
    if (context == NULL) {
440
0
        if (key)
441
0
            sftk_FreeObject(key);
442
0
        return CKR_HOST_MEMORY;
443
0
    }
444
240k
    context->type = ctype;
445
240k
    context->multi = PR_TRUE;
446
240k
    context->rsa = PR_FALSE;
447
240k
    context->cipherInfo = NULL;
448
240k
    context->hashInfo = NULL;
449
240k
    context->doPad = PR_FALSE;
450
240k
    context->padDataLength = 0;
451
240k
    context->key = key;
452
240k
    context->blockSize = 0;
453
240k
    context->maxLen = 0;
454
240k
    context->isFIPS = sftk_operationIsFIPS(session->slot, pMechanism,
455
240k
                                           operation, key);
456
240k
    *contextPtr = context;
457
240k
    return CKR_OK;
458
240k
}
459
460
static int
461
sftk_aes_mode(CK_MECHANISM_TYPE mechanism)
462
6.38k
{
463
6.38k
    switch (mechanism) {
464
153
        case CKM_AES_CBC_PAD:
465
6.38k
        case CKM_AES_CBC:
466
6.38k
            return NSS_AES_CBC;
467
0
        case CKM_AES_ECB:
468
0
            return NSS_AES;
469
0
        case CKM_AES_CTS:
470
0
            return NSS_AES_CTS;
471
0
        case CKM_AES_CTR:
472
0
            return NSS_AES_CTR;
473
0
        case CKM_AES_GCM:
474
0
            return NSS_AES_GCM;
475
6.38k
    }
476
0
    return -1;
477
6.38k
}
478
479
static SECStatus
480
sftk_RSAEncryptRaw(NSSLOWKEYPublicKey *key, unsigned char *output,
481
                   unsigned int *outputLen, unsigned int maxLen,
482
                   const unsigned char *input, unsigned int inputLen)
483
0
{
484
0
    SECStatus rv = SECFailure;
485
486
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
487
0
    if (key->keyType != NSSLOWKEYRSAKey) {
488
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
489
0
        return SECFailure;
490
0
    }
491
492
0
    rv = RSA_EncryptRaw(&key->u.rsa, output, outputLen, maxLen, input,
493
0
                        inputLen);
494
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
495
0
        sftk_fatalError = PR_TRUE;
496
0
    }
497
498
0
    return rv;
499
0
}
500
501
static SECStatus
502
sftk_RSADecryptRaw(NSSLOWKEYPrivateKey *key, unsigned char *output,
503
                   unsigned int *outputLen, unsigned int maxLen,
504
                   const unsigned char *input, unsigned int inputLen)
505
0
{
506
0
    SECStatus rv = SECFailure;
507
508
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
509
0
    if (key->keyType != NSSLOWKEYRSAKey) {
510
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
511
0
        return SECFailure;
512
0
    }
513
514
0
    rv = RSA_DecryptRaw(&key->u.rsa, output, outputLen, maxLen, input,
515
0
                        inputLen);
516
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
517
0
        sftk_fatalError = PR_TRUE;
518
0
    }
519
520
0
    return rv;
521
0
}
522
523
static SECStatus
524
sftk_RSAEncrypt(NSSLOWKEYPublicKey *key, unsigned char *output,
525
                unsigned int *outputLen, unsigned int maxLen,
526
                const unsigned char *input, unsigned int inputLen)
527
2.73k
{
528
2.73k
    SECStatus rv = SECFailure;
529
530
2.73k
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
531
2.73k
    if (key->keyType != NSSLOWKEYRSAKey) {
532
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
533
0
        return SECFailure;
534
0
    }
535
536
2.73k
    rv = RSA_EncryptBlock(&key->u.rsa, output, outputLen, maxLen, input,
537
2.73k
                          inputLen);
538
2.73k
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
539
0
        sftk_fatalError = PR_TRUE;
540
0
    }
541
542
2.73k
    return rv;
543
2.73k
}
544
545
static SECStatus
546
sftk_RSADecrypt(NSSLOWKEYPrivateKey *key, unsigned char *output,
547
                unsigned int *outputLen, unsigned int maxLen,
548
                const unsigned char *input, unsigned int inputLen)
549
47
{
550
47
    SECStatus rv = SECFailure;
551
552
47
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
553
47
    if (key->keyType != NSSLOWKEYRSAKey) {
554
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
555
0
        return SECFailure;
556
0
    }
557
558
47
    rv = RSA_DecryptBlock(&key->u.rsa, output, outputLen, maxLen, input,
559
47
                          inputLen);
560
47
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
561
0
        sftk_fatalError = PR_TRUE;
562
0
    }
563
564
47
    return rv;
565
47
}
566
567
static void
568
sftk_freeRSAOAEPInfo(SFTKOAEPInfo *info, PRBool freeit)
569
0
{
570
0
    PORT_ZFree(info->params.pSourceData, info->params.ulSourceDataLen);
571
0
    PORT_ZFree(info, sizeof(SFTKOAEPInfo));
572
0
}
573
574
static SECStatus
575
sftk_RSAEncryptOAEP(SFTKOAEPInfo *info, unsigned char *output,
576
                    unsigned int *outputLen, unsigned int maxLen,
577
                    const unsigned char *input, unsigned int inputLen)
578
0
{
579
0
    HASH_HashType hashAlg;
580
0
    HASH_HashType maskHashAlg;
581
582
0
    PORT_Assert(info->key.pub->keyType == NSSLOWKEYRSAKey);
583
0
    if (info->key.pub->keyType != NSSLOWKEYRSAKey) {
584
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
585
0
        return SECFailure;
586
0
    }
587
588
0
    hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg);
589
0
    maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf);
590
591
0
    return RSA_EncryptOAEP(&info->key.pub->u.rsa, hashAlg, maskHashAlg,
592
0
                           (const unsigned char *)info->params.pSourceData,
593
0
                           info->params.ulSourceDataLen, NULL, 0,
594
0
                           output, outputLen, maxLen, input, inputLen);
595
0
}
596
597
static SECStatus
598
sftk_RSADecryptOAEP(SFTKOAEPInfo *info, unsigned char *output,
599
                    unsigned int *outputLen, unsigned int maxLen,
600
                    const unsigned char *input, unsigned int inputLen)
601
0
{
602
0
    SECStatus rv = SECFailure;
603
0
    HASH_HashType hashAlg;
604
0
    HASH_HashType maskHashAlg;
605
606
0
    PORT_Assert(info->key.priv->keyType == NSSLOWKEYRSAKey);
607
0
    if (info->key.priv->keyType != NSSLOWKEYRSAKey) {
608
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
609
0
        return SECFailure;
610
0
    }
611
612
0
    hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg);
613
0
    maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf);
614
615
0
    rv = RSA_DecryptOAEP(&info->key.priv->u.rsa, hashAlg, maskHashAlg,
616
0
                         (const unsigned char *)info->params.pSourceData,
617
0
                         info->params.ulSourceDataLen,
618
0
                         output, outputLen, maxLen, input, inputLen);
619
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
620
0
        sftk_fatalError = PR_TRUE;
621
0
    }
622
0
    return rv;
623
0
}
624
625
static SFTKChaCha20Poly1305Info *
626
sftk_ChaCha20Poly1305_CreateContext(const unsigned char *key,
627
                                    unsigned int keyLen,
628
                                    const CK_NSS_AEAD_PARAMS *params)
629
0
{
630
0
    SFTKChaCha20Poly1305Info *ctx;
631
632
0
    if (params->ulNonceLen != sizeof(ctx->nonce)) {
633
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
634
0
        return NULL;
635
0
    }
636
637
0
    ctx = PORT_New(SFTKChaCha20Poly1305Info);
638
0
    if (ctx == NULL) {
639
0
        return NULL;
640
0
    }
641
642
0
    if (ChaCha20Poly1305_InitContext(&ctx->freeblCtx, key, keyLen,
643
0
                                     params->ulTagLen) != SECSuccess) {
644
0
        PORT_Free(ctx);
645
0
        return NULL;
646
0
    }
647
648
0
    PORT_Memcpy(ctx->nonce, params->pNonce, sizeof(ctx->nonce));
649
650
    /* AAD data and length must both be null, or both non-null. */
651
0
    PORT_Assert((params->pAAD == NULL) == (params->ulAADLen == 0));
652
653
0
    if (params->ulAADLen > sizeof(ctx->ad)) {
654
        /* Need to allocate an overflow buffer for the additional data. */
655
0
        ctx->adOverflow = (unsigned char *)PORT_Alloc(params->ulAADLen);
656
0
        if (!ctx->adOverflow) {
657
0
            PORT_Free(ctx);
658
0
            return NULL;
659
0
        }
660
0
        PORT_Memcpy(ctx->adOverflow, params->pAAD, params->ulAADLen);
661
0
    } else {
662
0
        ctx->adOverflow = NULL;
663
0
        if (params->pAAD) {
664
0
            PORT_Memcpy(ctx->ad, params->pAAD, params->ulAADLen);
665
0
        }
666
0
    }
667
0
    ctx->adLen = params->ulAADLen;
668
669
0
    return ctx;
670
0
}
671
672
static void
673
sftk_ChaCha20Poly1305_DestroyContext(SFTKChaCha20Poly1305Info *ctx,
674
                                     PRBool freeit)
675
0
{
676
0
    ChaCha20Poly1305_DestroyContext(&ctx->freeblCtx, PR_FALSE);
677
0
    if (ctx->adOverflow != NULL) {
678
0
        PORT_ZFree(ctx->adOverflow, ctx->adLen);
679
0
        ctx->adOverflow = NULL;
680
0
    } else {
681
0
        PORT_Memset(ctx->ad, 0, ctx->adLen);
682
0
    }
683
0
    ctx->adLen = 0;
684
0
    if (freeit) {
685
0
        PORT_Free(ctx);
686
0
    }
687
0
}
688
689
static SECStatus
690
sftk_ChaCha20Poly1305_Encrypt(const SFTKChaCha20Poly1305Info *ctx,
691
                              unsigned char *output, unsigned int *outputLen,
692
                              unsigned int maxOutputLen,
693
                              const unsigned char *input, unsigned int inputLen)
694
0
{
695
0
    const unsigned char *ad = ctx->adOverflow;
696
697
0
    if (ad == NULL) {
698
0
        ad = ctx->ad;
699
0
    }
700
701
0
    return ChaCha20Poly1305_Seal(&ctx->freeblCtx, output, outputLen,
702
0
                                 maxOutputLen, input, inputLen, ctx->nonce,
703
0
                                 sizeof(ctx->nonce), ad, ctx->adLen);
704
0
}
705
706
static SECStatus
707
sftk_ChaCha20Poly1305_Decrypt(const SFTKChaCha20Poly1305Info *ctx,
708
                              unsigned char *output, unsigned int *outputLen,
709
                              unsigned int maxOutputLen,
710
                              const unsigned char *input, unsigned int inputLen)
711
0
{
712
0
    const unsigned char *ad = ctx->adOverflow;
713
714
0
    if (ad == NULL) {
715
0
        ad = ctx->ad;
716
0
    }
717
718
0
    return ChaCha20Poly1305_Open(&ctx->freeblCtx, output, outputLen,
719
0
                                 maxOutputLen, input, inputLen, ctx->nonce,
720
0
                                 sizeof(ctx->nonce), ad, ctx->adLen);
721
0
}
722
723
static SECStatus
724
sftk_ChaCha20Ctr(const SFTKChaCha20CtrInfo *ctx,
725
                 unsigned char *output, unsigned int *outputLen,
726
                 unsigned int maxOutputLen,
727
                 const unsigned char *input, unsigned int inputLen)
728
0
{
729
0
    if (maxOutputLen < inputLen) {
730
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
731
0
        return SECFailure;
732
0
    }
733
0
    ChaCha20_Xor(output, input, inputLen, ctx->key,
734
0
                 ctx->nonce, ctx->counter);
735
0
    *outputLen = inputLen;
736
0
    return SECSuccess;
737
0
}
738
739
static void
740
sftk_ChaCha20Ctr_DestroyContext(SFTKChaCha20CtrInfo *ctx,
741
                                PRBool freeit)
742
0
{
743
0
    memset(ctx, 0, sizeof(*ctx));
744
0
    if (freeit) {
745
0
        PORT_Free(ctx);
746
0
    }
747
0
}
748
749
/** NSC_CryptInit initializes an encryption/Decryption operation.
750
 *
751
 * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey.
752
 * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block
753
 *  ciphers MAC'ing.
754
 */
755
CK_RV
756
sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
757
               CK_OBJECT_HANDLE hKey,
758
               CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage,
759
               SFTKContextType contextType, PRBool isEncrypt)
760
15.0k
{
761
15.0k
    SFTKSession *session;
762
15.0k
    SFTKObject *key;
763
15.0k
    SFTKSessionContext *context;
764
15.0k
    SFTKAttribute *att;
765
15.0k
#ifndef NSS_DISABLE_DEPRECATED_RC2
766
15.0k
    CK_RC2_CBC_PARAMS *rc2_param;
767
15.0k
    unsigned effectiveKeyLength;
768
15.0k
#endif
769
#if NSS_SOFTOKEN_DOES_RC5
770
    CK_RC5_CBC_PARAMS *rc5_param;
771
    SECItem rc5Key;
772
#endif
773
15.0k
    CK_NSS_GCM_PARAMS nss_gcm_param;
774
15.0k
    void *aes_param;
775
15.0k
    CK_NSS_AEAD_PARAMS nss_aead_params;
776
15.0k
    CK_NSS_AEAD_PARAMS *nss_aead_params_ptr = NULL;
777
15.0k
    CK_KEY_TYPE key_type;
778
15.0k
    CK_RV crv = CKR_OK;
779
15.0k
    unsigned char newdeskey[24];
780
15.0k
    PRBool useNewKey = PR_FALSE;
781
15.0k
    int t;
782
783
15.0k
    if (!pMechanism) {
784
0
        return CKR_MECHANISM_PARAM_INVALID;
785
0
    }
786
787
15.0k
    crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage);
788
15.0k
    if (crv != CKR_OK)
789
18
        return crv;
790
791
15.0k
    session = sftk_SessionFromHandle(hSession);
792
15.0k
    if (session == NULL)
793
0
        return CKR_SESSION_HANDLE_INVALID;
794
795
15.0k
    crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key,
796
15.0k
                           hKey, &key_type,
797
15.0k
                           isEncrypt ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY,
798
15.0k
                           keyUsage);
799
800
15.0k
    if (crv != CKR_OK) {
801
0
        sftk_FreeSession(session);
802
0
        return crv;
803
0
    }
804
805
15.0k
    context->doPad = PR_FALSE;
806
15.0k
    switch (pMechanism->mechanism) {
807
2.78k
        case CKM_RSA_PKCS:
808
2.78k
        case CKM_RSA_X_509:
809
2.78k
            if (key_type != CKK_RSA) {
810
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
811
0
                break;
812
0
            }
813
2.78k
            context->multi = PR_FALSE;
814
2.78k
            context->rsa = PR_TRUE;
815
2.78k
            if (isEncrypt) {
816
2.73k
                NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
817
2.73k
                if (pubKey == NULL) {
818
0
                    crv = CKR_KEY_HANDLE_INVALID;
819
0
                    break;
820
0
                }
821
2.73k
                context->maxLen = nsslowkey_PublicModulusLen(pubKey);
822
2.73k
                context->cipherInfo = (void *)pubKey;
823
2.73k
                context->update = (SFTKCipher)(pMechanism->mechanism == CKM_RSA_X_509
824
2.73k
                                                   ? sftk_RSAEncryptRaw
825
2.73k
                                                   : sftk_RSAEncrypt);
826
2.73k
            } else {
827
47
                NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key, CKK_RSA, &crv);
828
47
                if (privKey == NULL) {
829
0
                    crv = CKR_KEY_HANDLE_INVALID;
830
0
                    break;
831
0
                }
832
47
                context->maxLen = nsslowkey_PrivateModulusLen(privKey);
833
47
                context->cipherInfo = (void *)privKey;
834
47
                context->update = (SFTKCipher)(pMechanism->mechanism == CKM_RSA_X_509
835
47
                                                   ? sftk_RSADecryptRaw
836
47
                                                   : sftk_RSADecrypt);
837
47
            }
838
2.78k
            context->destroy = sftk_Null;
839
2.78k
            break;
840
0
        case CKM_RSA_PKCS_OAEP:
841
0
            if (key_type != CKK_RSA) {
842
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
843
0
                break;
844
0
            }
845
0
            if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) ||
846
0
                !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter)) {
847
0
                crv = CKR_MECHANISM_PARAM_INVALID;
848
0
                break;
849
0
            }
850
0
            context->multi = PR_FALSE;
851
0
            context->rsa = PR_TRUE;
852
0
            {
853
0
                SFTKOAEPInfo *info;
854
0
                CK_RSA_PKCS_OAEP_PARAMS *params =
855
0
                    (CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter;
856
                /* make a copy of the source data value for future
857
                 * use (once the user has reclaimed his data in pParameter)*/
858
0
                void *newSource = NULL;
859
0
                if (params->pSourceData) {
860
0
                    newSource = PORT_Alloc(params->ulSourceDataLen);
861
0
                    if (newSource == NULL) {
862
0
                        crv = CKR_HOST_MEMORY;
863
0
                        break;
864
0
                    }
865
0
                    PORT_Memcpy(newSource, params->pSourceData, params->ulSourceDataLen);
866
0
                }
867
0
                info = PORT_New(SFTKOAEPInfo);
868
0
                if (info == NULL) {
869
0
                    PORT_ZFree(newSource, params->ulSourceDataLen);
870
0
                    crv = CKR_HOST_MEMORY;
871
0
                    break;
872
0
                }
873
0
                info->params = *params;
874
0
                info->params.pSourceData = newSource;
875
0
                info->isEncrypt = isEncrypt;
876
877
                /* now setup encryption and decryption contexts */
878
0
                if (isEncrypt) {
879
0
                    info->key.pub = sftk_GetPubKey(key, CKK_RSA, &crv);
880
0
                    if (info->key.pub == NULL) {
881
0
                        sftk_freeRSAOAEPInfo(info, PR_TRUE);
882
0
                        crv = CKR_KEY_HANDLE_INVALID;
883
0
                        break;
884
0
                    }
885
0
                    context->update = (SFTKCipher)sftk_RSAEncryptOAEP;
886
0
                    context->maxLen = nsslowkey_PublicModulusLen(info->key.pub);
887
0
                } else {
888
0
                    info->key.priv = sftk_GetPrivKey(key, CKK_RSA, &crv);
889
0
                    if (info->key.priv == NULL) {
890
0
                        sftk_freeRSAOAEPInfo(info, PR_TRUE);
891
0
                        crv = CKR_KEY_HANDLE_INVALID;
892
0
                        break;
893
0
                    }
894
0
                    context->update = (SFTKCipher)sftk_RSADecryptOAEP;
895
0
                    context->maxLen = nsslowkey_PrivateModulusLen(info->key.priv);
896
0
                }
897
0
                context->cipherInfo = info;
898
0
            }
899
0
            context->destroy = (SFTKDestroy)sftk_freeRSAOAEPInfo;
900
0
            break;
901
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
902
0
        case CKM_RC2_CBC_PAD:
903
0
            context->doPad = PR_TRUE;
904
        /* fall thru */
905
0
        case CKM_RC2_ECB:
906
0
        case CKM_RC2_CBC:
907
0
            context->blockSize = 8;
908
0
            if (key_type != CKK_RC2) {
909
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
910
0
                break;
911
0
            }
912
0
            att = sftk_FindAttribute(key, CKA_VALUE);
913
0
            if (att == NULL) {
914
0
                crv = CKR_KEY_HANDLE_INVALID;
915
0
                break;
916
0
            }
917
918
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_CBC_PARAMS))) {
919
0
                crv = CKR_MECHANISM_PARAM_INVALID;
920
0
                break;
921
0
            }
922
0
            rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
923
0
            effectiveKeyLength = (rc2_param->ulEffectiveBits + 7) / 8;
924
0
            context->cipherInfo =
925
0
                RC2_CreateContext((unsigned char *)att->attrib.pValue,
926
0
                                  att->attrib.ulValueLen, rc2_param->iv,
927
0
                                  pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : NSS_RC2_CBC, effectiveKeyLength);
928
0
            sftk_FreeAttribute(att);
929
0
            if (context->cipherInfo == NULL) {
930
0
                crv = CKR_HOST_MEMORY;
931
0
                break;
932
0
            }
933
0
            context->update = (SFTKCipher)(isEncrypt ? RC2_Encrypt : RC2_Decrypt);
934
0
            context->destroy = (SFTKDestroy)RC2_DestroyContext;
935
0
            break;
936
0
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
937
938
#if NSS_SOFTOKEN_DOES_RC5
939
        case CKM_RC5_CBC_PAD:
940
            context->doPad = PR_TRUE;
941
        /* fall thru */
942
        case CKM_RC5_ECB:
943
        case CKM_RC5_CBC:
944
            if (key_type != CKK_RC5) {
945
                crv = CKR_KEY_TYPE_INCONSISTENT;
946
                break;
947
            }
948
            att = sftk_FindAttribute(key, CKA_VALUE);
949
            if (att == NULL) {
950
                crv = CKR_KEY_HANDLE_INVALID;
951
                break;
952
            }
953
954
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_CBC_PARAMS))) {
955
                crv = CKR_MECHANISM_PARAM_INVALID;
956
                break;
957
            }
958
            rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
959
            context->blockSize = rc5_param->ulWordsize * 2;
960
            rc5Key.data = (unsigned char *)att->attrib.pValue;
961
            rc5Key.len = att->attrib.ulValueLen;
962
            context->cipherInfo = RC5_CreateContext(&rc5Key, rc5_param->ulRounds,
963
                                                    rc5_param->ulWordsize, rc5_param->pIv,
964
                                                    pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);
965
            sftk_FreeAttribute(att);
966
            if (context->cipherInfo == NULL) {
967
                crv = CKR_HOST_MEMORY;
968
                break;
969
            }
970
            context->update = (SFTKCipher)(isEncrypt ? RC5_Encrypt : RC5_Decrypt);
971
            context->destroy = (SFTKDestroy)RC5_DestroyContext;
972
            break;
973
#endif
974
498
        case CKM_RC4:
975
498
            if (key_type != CKK_RC4) {
976
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
977
0
                break;
978
0
            }
979
498
            att = sftk_FindAttribute(key, CKA_VALUE);
980
498
            if (att == NULL) {
981
0
                crv = CKR_KEY_HANDLE_INVALID;
982
0
                break;
983
0
            }
984
498
            context->cipherInfo =
985
498
                RC4_CreateContext((unsigned char *)att->attrib.pValue,
986
498
                                  att->attrib.ulValueLen);
987
498
            sftk_FreeAttribute(att);
988
498
            if (context->cipherInfo == NULL) {
989
0
                crv = CKR_HOST_MEMORY; /* WRONG !!! */
990
0
                break;
991
0
            }
992
498
            context->update = (SFTKCipher)(isEncrypt ? RC4_Encrypt : RC4_Decrypt);
993
498
            context->destroy = (SFTKDestroy)RC4_DestroyContext;
994
498
            break;
995
0
        case CKM_CDMF_CBC_PAD:
996
0
            context->doPad = PR_TRUE;
997
        /* fall thru */
998
0
        case CKM_CDMF_ECB:
999
0
        case CKM_CDMF_CBC:
1000
0
            if (key_type != CKK_CDMF) {
1001
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1002
0
                break;
1003
0
            }
1004
0
            t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;
1005
0
            goto finish_des;
1006
0
        case CKM_DES_ECB:
1007
0
            if (key_type != CKK_DES) {
1008
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1009
0
                break;
1010
0
            }
1011
0
            t = NSS_DES;
1012
0
            goto finish_des;
1013
0
        case CKM_DES_CBC_PAD:
1014
0
            context->doPad = PR_TRUE;
1015
        /* fall thru */
1016
356
        case CKM_DES_CBC:
1017
356
            if (key_type != CKK_DES) {
1018
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1019
0
                break;
1020
0
            }
1021
356
            t = NSS_DES_CBC;
1022
356
            goto finish_des;
1023
1.73k
        case CKM_DES3_ECB:
1024
1.73k
            if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
1025
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1026
0
                break;
1027
0
            }
1028
1.73k
            t = NSS_DES_EDE3;
1029
1.73k
            goto finish_des;
1030
0
        case CKM_DES3_CBC_PAD:
1031
0
            context->doPad = PR_TRUE;
1032
        /* fall thru */
1033
1.60k
        case CKM_DES3_CBC:
1034
1.60k
            if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
1035
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1036
0
                break;
1037
0
            }
1038
1.60k
            t = NSS_DES_EDE3_CBC;
1039
3.69k
        finish_des:
1040
3.69k
            if ((t != NSS_DES && t != NSS_DES_EDE3) && (pMechanism->pParameter == NULL ||
1041
1.96k
                                                        pMechanism->ulParameterLen < 8)) {
1042
0
                crv = CKR_DOMAIN_PARAMS_INVALID;
1043
0
                break;
1044
0
            }
1045
3.69k
            context->blockSize = 8;
1046
3.69k
            att = sftk_FindAttribute(key, CKA_VALUE);
1047
3.69k
            if (att == NULL) {
1048
0
                crv = CKR_KEY_HANDLE_INVALID;
1049
0
                break;
1050
0
            }
1051
3.69k
            if (key_type == CKK_DES2 &&
1052
3.69k
                (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) {
1053
                /* extend DES2 key to DES3 key. */
1054
0
                memcpy(newdeskey, att->attrib.pValue, 16);
1055
0
                memcpy(newdeskey + 16, newdeskey, 8);
1056
0
                useNewKey = PR_TRUE;
1057
3.69k
            } else if (key_type == CKK_CDMF) {
1058
0
                crv = sftk_cdmf2des((unsigned char *)att->attrib.pValue, newdeskey);
1059
0
                if (crv != CKR_OK) {
1060
0
                    sftk_FreeAttribute(att);
1061
0
                    break;
1062
0
                }
1063
0
                useNewKey = PR_TRUE;
1064
0
            }
1065
3.69k
            context->cipherInfo = DES_CreateContext(
1066
3.69k
                useNewKey ? newdeskey : (unsigned char *)att->attrib.pValue,
1067
3.69k
                (unsigned char *)pMechanism->pParameter, t, isEncrypt);
1068
3.69k
            if (useNewKey)
1069
0
                memset(newdeskey, 0, sizeof newdeskey);
1070
3.69k
            sftk_FreeAttribute(att);
1071
3.69k
            if (context->cipherInfo == NULL) {
1072
0
                crv = CKR_HOST_MEMORY;
1073
0
                break;
1074
0
            }
1075
3.69k
            context->update = (SFTKCipher)(isEncrypt ? DES_Encrypt : DES_Decrypt);
1076
3.69k
            context->destroy = (SFTKDestroy)DES_DestroyContext;
1077
3.69k
            break;
1078
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
1079
0
        case CKM_SEED_CBC_PAD:
1080
0
            context->doPad = PR_TRUE;
1081
        /* fall thru */
1082
564
        case CKM_SEED_CBC:
1083
564
            if (!pMechanism->pParameter ||
1084
564
                pMechanism->ulParameterLen != 16) {
1085
0
                crv = CKR_MECHANISM_PARAM_INVALID;
1086
0
                break;
1087
0
            }
1088
        /* fall thru */
1089
564
        case CKM_SEED_ECB:
1090
564
            context->blockSize = 16;
1091
564
            if (key_type != CKK_SEED) {
1092
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1093
0
                break;
1094
0
            }
1095
564
            att = sftk_FindAttribute(key, CKA_VALUE);
1096
564
            if (att == NULL) {
1097
0
                crv = CKR_KEY_HANDLE_INVALID;
1098
0
                break;
1099
0
            }
1100
564
            context->cipherInfo = SEED_CreateContext(
1101
564
                (unsigned char *)att->attrib.pValue,
1102
564
                (unsigned char *)pMechanism->pParameter,
1103
564
                pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC,
1104
564
                isEncrypt);
1105
564
            sftk_FreeAttribute(att);
1106
564
            if (context->cipherInfo == NULL) {
1107
0
                crv = CKR_HOST_MEMORY;
1108
0
                break;
1109
0
            }
1110
564
            context->update = (SFTKCipher)(isEncrypt ? SEED_Encrypt : SEED_Decrypt);
1111
564
            context->destroy = (SFTKDestroy)SEED_DestroyContext;
1112
564
            break;
1113
0
#endif /* NSS_DISABLE_DEPRECATED_SEED */
1114
0
        case CKM_CAMELLIA_CBC_PAD:
1115
0
            context->doPad = PR_TRUE;
1116
        /* fall thru */
1117
1.08k
        case CKM_CAMELLIA_CBC:
1118
1.08k
            if (!pMechanism->pParameter ||
1119
1.08k
                pMechanism->ulParameterLen != 16) {
1120
0
                crv = CKR_MECHANISM_PARAM_INVALID;
1121
0
                break;
1122
0
            }
1123
        /* fall thru */
1124
1.08k
        case CKM_CAMELLIA_ECB:
1125
1.08k
            context->blockSize = 16;
1126
1.08k
            if (key_type != CKK_CAMELLIA) {
1127
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1128
0
                break;
1129
0
            }
1130
1.08k
            att = sftk_FindAttribute(key, CKA_VALUE);
1131
1.08k
            if (att == NULL) {
1132
0
                crv = CKR_KEY_HANDLE_INVALID;
1133
0
                break;
1134
0
            }
1135
1.08k
            context->cipherInfo = Camellia_CreateContext(
1136
1.08k
                (unsigned char *)att->attrib.pValue,
1137
1.08k
                (unsigned char *)pMechanism->pParameter,
1138
1.08k
                pMechanism->mechanism ==
1139
1.08k
                        CKM_CAMELLIA_ECB
1140
1.08k
                    ? NSS_CAMELLIA
1141
1.08k
                    : NSS_CAMELLIA_CBC,
1142
1.08k
                isEncrypt, att->attrib.ulValueLen);
1143
1.08k
            sftk_FreeAttribute(att);
1144
1.08k
            if (context->cipherInfo == NULL) {
1145
0
                crv = CKR_HOST_MEMORY;
1146
0
                break;
1147
0
            }
1148
1.08k
            context->update = (SFTKCipher)(isEncrypt ? Camellia_Encrypt : Camellia_Decrypt);
1149
1.08k
            context->destroy = (SFTKDestroy)Camellia_DestroyContext;
1150
1.08k
            break;
1151
1152
153
        case CKM_AES_CBC_PAD:
1153
153
            context->doPad = PR_TRUE;
1154
        /* fall thru */
1155
153
        case CKM_AES_ECB:
1156
6.38k
        case CKM_AES_CBC:
1157
6.38k
            context->blockSize = 16;
1158
6.38k
        case CKM_AES_CTS:
1159
6.38k
        case CKM_AES_CTR:
1160
6.38k
        case CKM_AES_GCM:
1161
6.38k
            aes_param = pMechanism->pParameter;
1162
            /*
1163
             *  Due to a mismatch between the documentation and the header
1164
             *  file, two different definitions for CK_GCM_PARAMS exist.
1165
             *  The header file is normative according to Oasis, but NSS used
1166
             *  the documentation. In PKCS #11 v3.0, this was reconciled in
1167
             *  favor of the header file definition. To maintain binary
1168
             *  compatibility, NSS now defines CK_GCM_PARAMS_V3 as the official
1169
             *  version v3 (V2.4 header file) and CK_NSS_GCM_PARAMS as the
1170
             *  legacy (V2.4 documentation, NSS version). CK_GCM_PARAMS
1171
             *  is defined as CK_GCM_PARAMS_V3 if NSS_PKCS11_2_0_COMPAT is not
1172
             *  defined and CK_NSS_GCM_PARAMS if it is. Internally
1173
             *  softoken continues to use the legacy version. The code below
1174
             *  automatically detects which parameter was passed in and
1175
             *  converts CK_GCM_PARAMS_V3 to the CK_NSS_GCM_PARAMS (legacy
1176
             *  version) on the fly. NSS proper will eventually start
1177
             *  using the CK_GCM_PARAMS_V3 version and fall back to the
1178
             *  CK_NSS_GCM_PARAMS if the CK_GCM_PARAMS_V3 version fails with
1179
             *  CKR_MECHANISM_PARAM_INVALID.
1180
             */
1181
6.38k
            if (pMechanism->mechanism == CKM_AES_GCM) {
1182
0
                if (!aes_param) {
1183
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1184
0
                    break;
1185
0
                }
1186
0
                if (pMechanism->ulParameterLen == sizeof(CK_GCM_PARAMS_V3)) {
1187
                    /* convert the true V3 parameters into the old NSS parameters */
1188
0
                    CK_GCM_PARAMS_V3 *gcm_params = (CK_GCM_PARAMS_V3 *)aes_param;
1189
0
                    if (gcm_params->ulIvLen * 8 != gcm_params->ulIvBits) {
1190
                        /* only support byte aligned IV lengths */
1191
0
                        crv = CKR_MECHANISM_PARAM_INVALID;
1192
0
                        break;
1193
0
                    }
1194
0
                    aes_param = (void *)&nss_gcm_param;
1195
0
                    nss_gcm_param.pIv = gcm_params->pIv;
1196
0
                    nss_gcm_param.ulIvLen = gcm_params->ulIvLen;
1197
0
                    nss_gcm_param.pAAD = gcm_params->pAAD;
1198
0
                    nss_gcm_param.ulAADLen = gcm_params->ulAADLen;
1199
0
                    nss_gcm_param.ulTagBits = gcm_params->ulTagBits;
1200
0
                } else if (pMechanism->ulParameterLen != sizeof(CK_NSS_GCM_PARAMS)) {
1201
                    /* neither old nor new style params, must be invalid */
1202
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1203
0
                    break;
1204
0
                }
1205
6.38k
            } else if ((pMechanism->mechanism == CKM_AES_CTR && BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CTR_PARAMS))) ||
1206
6.38k
                       ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CTS) && BAD_PARAM_CAST(pMechanism, AES_BLOCK_SIZE))) {
1207
0
                crv = CKR_MECHANISM_PARAM_INVALID;
1208
0
                break;
1209
0
            }
1210
1211
6.38k
            if (pMechanism->mechanism == CKM_AES_GCM) {
1212
0
                context->multi = PR_FALSE;
1213
0
            }
1214
6.38k
            if (key_type != CKK_AES) {
1215
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1216
0
                break;
1217
0
            }
1218
6.38k
            att = sftk_FindAttribute(key, CKA_VALUE);
1219
6.38k
            if (att == NULL) {
1220
0
                crv = CKR_KEY_HANDLE_INVALID;
1221
0
                break;
1222
0
            }
1223
6.38k
            context->cipherInfo = AES_CreateContext(
1224
6.38k
                (unsigned char *)att->attrib.pValue,
1225
6.38k
                (unsigned char *)aes_param,
1226
6.38k
                sftk_aes_mode(pMechanism->mechanism),
1227
6.38k
                isEncrypt, att->attrib.ulValueLen, 16);
1228
6.38k
            sftk_FreeAttribute(att);
1229
6.38k
            if (context->cipherInfo == NULL) {
1230
0
                crv = CKR_HOST_MEMORY;
1231
0
                break;
1232
0
            }
1233
6.38k
            context->update = (SFTKCipher)(isEncrypt ? AES_Encrypt : AES_Decrypt);
1234
6.38k
            context->destroy = (SFTKDestroy)AES_DestroyContext;
1235
6.38k
            break;
1236
1237
0
        case CKM_NSS_CHACHA20_POLY1305:
1238
0
        case CKM_CHACHA20_POLY1305:
1239
0
            if (pMechanism->mechanism == CKM_NSS_CHACHA20_POLY1305) {
1240
0
                if (key_type != CKK_NSS_CHACHA20) {
1241
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
1242
0
                    break;
1243
0
                }
1244
0
                if ((pMechanism->pParameter == NULL) ||
1245
0
                    (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS))) {
1246
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1247
0
                    break;
1248
0
                }
1249
0
                nss_aead_params_ptr = (CK_NSS_AEAD_PARAMS *)pMechanism->pParameter;
1250
0
            } else {
1251
0
                CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR chacha_poly_params;
1252
0
                if (key_type != CKK_CHACHA20) {
1253
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
1254
0
                    break;
1255
0
                }
1256
0
                if ((pMechanism->pParameter == NULL) ||
1257
0
                    (pMechanism->ulParameterLen !=
1258
0
                     sizeof(CK_SALSA20_CHACHA20_POLY1305_PARAMS))) {
1259
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1260
0
                    break;
1261
0
                }
1262
0
                chacha_poly_params = (CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR)
1263
0
                                         pMechanism->pParameter;
1264
0
                nss_aead_params_ptr = &nss_aead_params;
1265
0
                nss_aead_params.pNonce = chacha_poly_params->pNonce;
1266
0
                nss_aead_params.ulNonceLen = chacha_poly_params->ulNonceLen;
1267
0
                nss_aead_params.pAAD = chacha_poly_params->pAAD;
1268
0
                nss_aead_params.ulAADLen = chacha_poly_params->ulAADLen;
1269
0
                nss_aead_params.ulTagLen = 16; /* Poly1305 is always 16 */
1270
0
            }
1271
1272
0
            context->multi = PR_FALSE;
1273
0
            att = sftk_FindAttribute(key, CKA_VALUE);
1274
0
            if (att == NULL) {
1275
0
                crv = CKR_KEY_HANDLE_INVALID;
1276
0
                break;
1277
0
            }
1278
0
            context->cipherInfo = sftk_ChaCha20Poly1305_CreateContext(
1279
0
                (unsigned char *)att->attrib.pValue, att->attrib.ulValueLen,
1280
0
                nss_aead_params_ptr);
1281
0
            sftk_FreeAttribute(att);
1282
0
            if (context->cipherInfo == NULL) {
1283
0
                crv = sftk_MapCryptError(PORT_GetError());
1284
0
                break;
1285
0
            }
1286
0
            context->update = (SFTKCipher)(isEncrypt ? sftk_ChaCha20Poly1305_Encrypt : sftk_ChaCha20Poly1305_Decrypt);
1287
0
            context->destroy = (SFTKDestroy)sftk_ChaCha20Poly1305_DestroyContext;
1288
0
            break;
1289
1290
0
        case CKM_NSS_CHACHA20_CTR: /* old NSS private version */
1291
0
        case CKM_CHACHA20:         /* PKCS #11 v3 version */
1292
0
        {
1293
0
            unsigned char *counter;
1294
0
            unsigned char *nonce;
1295
0
            unsigned long counter_len;
1296
0
            unsigned long nonce_len;
1297
0
            context->multi = PR_FALSE;
1298
0
            if (pMechanism->mechanism == CKM_NSS_CHACHA20_CTR) {
1299
0
                if (key_type != CKK_NSS_CHACHA20) {
1300
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
1301
0
                    break;
1302
0
                }
1303
0
                if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) {
1304
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1305
0
                    break;
1306
0
                }
1307
0
                counter_len = 4;
1308
0
                counter = pMechanism->pParameter;
1309
0
                nonce = counter + 4;
1310
0
                nonce_len = 12;
1311
0
            } else {
1312
0
                CK_CHACHA20_PARAMS_PTR chacha20_param_ptr;
1313
0
                if (key_type != CKK_CHACHA20) {
1314
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
1315
0
                    break;
1316
0
                }
1317
0
                if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != sizeof(CK_CHACHA20_PARAMS)) {
1318
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1319
0
                    break;
1320
0
                }
1321
0
                chacha20_param_ptr = (CK_CHACHA20_PARAMS_PTR)pMechanism->pParameter;
1322
0
                if ((chacha20_param_ptr->blockCounterBits != 32) &&
1323
0
                    (chacha20_param_ptr->blockCounterBits != 64)) {
1324
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1325
0
                    break;
1326
0
                }
1327
0
                counter_len = chacha20_param_ptr->blockCounterBits / PR_BITS_PER_BYTE;
1328
0
                counter = chacha20_param_ptr->pBlockCounter;
1329
0
                nonce = chacha20_param_ptr->pNonce;
1330
0
                nonce_len = chacha20_param_ptr->ulNonceBits / PR_BITS_PER_BYTE;
1331
0
            }
1332
1333
0
            att = sftk_FindAttribute(key, CKA_VALUE);
1334
0
            if (att == NULL) {
1335
0
                crv = CKR_KEY_HANDLE_INVALID;
1336
0
                break;
1337
0
            }
1338
0
            SFTKChaCha20CtrInfo *ctx = PORT_ZNew(SFTKChaCha20CtrInfo);
1339
0
            if (!ctx) {
1340
0
                sftk_FreeAttribute(att);
1341
0
                crv = CKR_HOST_MEMORY;
1342
0
                break;
1343
0
            }
1344
0
            if (att->attrib.ulValueLen != sizeof(ctx->key)) {
1345
0
                sftk_FreeAttribute(att);
1346
0
                PORT_Free(ctx);
1347
0
                crv = CKR_KEY_HANDLE_INVALID;
1348
0
                break;
1349
0
            }
1350
0
            memcpy(ctx->key, att->attrib.pValue, att->attrib.ulValueLen);
1351
0
            sftk_FreeAttribute(att);
1352
1353
            /* make sure we don't overflow our parameters */
1354
0
            if ((sizeof(ctx->counter) < counter_len) ||
1355
0
                (sizeof(ctx->nonce) < nonce_len)) {
1356
0
                PORT_Free(ctx);
1357
0
                crv = CKR_MECHANISM_PARAM_INVALID;
1358
0
                break;
1359
0
            }
1360
1361
            /* The counter is little endian. */
1362
0
            int i = 0;
1363
0
            for (; i < counter_len; ++i) {
1364
0
                ctx->counter |= (PRUint32)counter[i] << (i * 8);
1365
0
            }
1366
0
            memcpy(ctx->nonce, nonce, nonce_len);
1367
0
            context->cipherInfo = ctx;
1368
0
            context->update = (SFTKCipher)sftk_ChaCha20Ctr;
1369
0
            context->destroy = (SFTKDestroy)sftk_ChaCha20Ctr_DestroyContext;
1370
0
            break;
1371
0
        }
1372
1373
0
        case CKM_NSS_AES_KEY_WRAP_PAD:
1374
0
        case CKM_AES_KEY_WRAP_PAD:
1375
0
            context->doPad = PR_TRUE;
1376
        /* fall thru */
1377
0
        case CKM_NSS_AES_KEY_WRAP:
1378
0
        case CKM_AES_KEY_WRAP:
1379
0
            context->blockSize = 8;
1380
0
        case CKM_AES_KEY_WRAP_KWP:
1381
0
            context->multi = PR_FALSE;
1382
0
            if (key_type != CKK_AES) {
1383
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1384
0
                break;
1385
0
            }
1386
0
            att = sftk_FindAttribute(key, CKA_VALUE);
1387
0
            if (att == NULL) {
1388
0
                crv = CKR_KEY_HANDLE_INVALID;
1389
0
                break;
1390
0
            }
1391
0
            context->cipherInfo = AESKeyWrap_CreateContext(
1392
0
                (unsigned char *)att->attrib.pValue,
1393
0
                (unsigned char *)pMechanism->pParameter,
1394
0
                isEncrypt, att->attrib.ulValueLen);
1395
0
            sftk_FreeAttribute(att);
1396
0
            if (context->cipherInfo == NULL) {
1397
0
                crv = CKR_HOST_MEMORY;
1398
0
                break;
1399
0
            }
1400
0
            if (pMechanism->mechanism == CKM_AES_KEY_WRAP_KWP) {
1401
0
                context->update = (SFTKCipher)(isEncrypt ? AESKeyWrap_EncryptKWP
1402
0
                                                         : AESKeyWrap_DecryptKWP);
1403
0
            } else {
1404
0
                context->update = (SFTKCipher)(isEncrypt ? AESKeyWrap_Encrypt
1405
0
                                                         : AESKeyWrap_Decrypt);
1406
0
            }
1407
0
            context->destroy = (SFTKDestroy)AESKeyWrap_DestroyContext;
1408
0
            break;
1409
1410
0
        default:
1411
0
            crv = CKR_MECHANISM_INVALID;
1412
0
            break;
1413
15.0k
    }
1414
1415
15.0k
    if (crv != CKR_OK) {
1416
0
        sftk_FreeContext(context);
1417
0
        sftk_FreeSession(session);
1418
0
        return crv;
1419
0
    }
1420
15.0k
    sftk_SetContextByType(session, contextType, context);
1421
15.0k
    sftk_FreeSession(session);
1422
15.0k
    return CKR_OK;
1423
15.0k
}
1424
1425
/* NSC_EncryptInit initializes an encryption operation. */
1426
CK_RV
1427
NSC_EncryptInit(CK_SESSION_HANDLE hSession,
1428
                CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1429
5.32k
{
1430
5.32k
    CHECK_FORK();
1431
5.32k
    return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT,
1432
5.32k
                          SFTK_ENCRYPT, PR_TRUE);
1433
5.32k
}
1434
1435
/* NSC_EncryptUpdate continues a multiple-part encryption operation. */
1436
CK_RV
1437
NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,
1438
                  CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
1439
                  CK_ULONG_PTR pulEncryptedPartLen)
1440
2.27k
{
1441
2.27k
    SFTKSessionContext *context;
1442
2.27k
    unsigned int outlen, i;
1443
2.27k
    unsigned int padoutlen = 0;
1444
2.27k
    unsigned int maxout = *pulEncryptedPartLen;
1445
2.27k
    CK_RV crv;
1446
2.27k
    SECStatus rv;
1447
1448
2.27k
    CHECK_FORK();
1449
1450
    /* make sure we're legal */
1451
2.27k
    crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, NULL);
1452
2.27k
    if (crv != CKR_OK)
1453
0
        return crv;
1454
1455
2.27k
    if (!pEncryptedPart) {
1456
0
        if (context->doPad) {
1457
0
            CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength;
1458
0
            CK_ULONG blocksToSend = totalDataAvailable / context->blockSize;
1459
1460
0
            *pulEncryptedPartLen = blocksToSend * context->blockSize;
1461
0
            return CKR_OK;
1462
0
        }
1463
0
        *pulEncryptedPartLen = ulPartLen;
1464
0
        return CKR_OK;
1465
0
    }
1466
1467
    /* do padding */
1468
2.27k
    if (context->doPad) {
1469
        /* deal with previous buffered data */
1470
153
        if (context->padDataLength != 0) {
1471
            /* fill in the padded to a full block size */
1472
0
            for (i = context->padDataLength;
1473
0
                 (ulPartLen != 0) && i < context->blockSize; i++) {
1474
0
                context->padBuf[i] = *pPart++;
1475
0
                ulPartLen--;
1476
0
                context->padDataLength++;
1477
0
            }
1478
1479
            /* not enough data to encrypt yet? then return */
1480
0
            if (context->padDataLength != context->blockSize) {
1481
0
                *pulEncryptedPartLen = 0;
1482
0
                return CKR_OK;
1483
0
            }
1484
            /* encrypt the current padded data */
1485
0
            rv = (*context->update)(context->cipherInfo, pEncryptedPart,
1486
0
                                    &padoutlen, maxout, context->padBuf,
1487
0
                                    context->blockSize);
1488
0
            if (rv != SECSuccess) {
1489
0
                return sftk_MapCryptError(PORT_GetError());
1490
0
            }
1491
0
            pEncryptedPart += padoutlen;
1492
0
            maxout -= padoutlen;
1493
0
        }
1494
        /* save the residual */
1495
153
        context->padDataLength = ulPartLen % context->blockSize;
1496
153
        if (context->padDataLength) {
1497
153
            PORT_Memcpy(context->padBuf,
1498
153
                        &pPart[ulPartLen - context->padDataLength],
1499
153
                        context->padDataLength);
1500
153
            ulPartLen -= context->padDataLength;
1501
153
        }
1502
        /* if we've exhausted our new buffer, we're done */
1503
153
        if (ulPartLen == 0) {
1504
0
            *pulEncryptedPartLen = padoutlen;
1505
0
            return CKR_OK;
1506
0
        }
1507
153
    }
1508
1509
    /* do it: NOTE: this assumes buf size in is >= buf size out! */
1510
2.27k
    rv = (*context->update)(context->cipherInfo, pEncryptedPart,
1511
2.27k
                            &outlen, maxout, pPart, ulPartLen);
1512
2.27k
    if (rv != SECSuccess) {
1513
0
        return sftk_MapCryptError(PORT_GetError());
1514
0
    }
1515
2.27k
    *pulEncryptedPartLen = (CK_ULONG)(outlen + padoutlen);
1516
2.27k
    return CKR_OK;
1517
2.27k
}
1518
1519
/* NSC_EncryptFinal finishes a multiple-part encryption operation. */
1520
CK_RV
1521
NSC_EncryptFinal(CK_SESSION_HANDLE hSession,
1522
                 CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
1523
153
{
1524
153
    SFTKSession *session;
1525
153
    SFTKSessionContext *context;
1526
153
    unsigned int outlen, i;
1527
153
    unsigned int maxout = *pulLastEncryptedPartLen;
1528
153
    CK_RV crv;
1529
153
    SECStatus rv = SECSuccess;
1530
153
    PRBool contextFinished = PR_TRUE;
1531
1532
153
    CHECK_FORK();
1533
1534
    /* make sure we're legal */
1535
153
    crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, &session);
1536
153
    if (crv != CKR_OK)
1537
0
        return crv;
1538
1539
153
    *pulLastEncryptedPartLen = 0;
1540
153
    if (!pLastEncryptedPart) {
1541
        /* caller is checking the amount of remaining data */
1542
0
        if (context->blockSize > 0 && context->doPad) {
1543
0
            *pulLastEncryptedPartLen = context->blockSize;
1544
0
            contextFinished = PR_FALSE; /* still have padding to go */
1545
0
        }
1546
0
        goto finish;
1547
0
    }
1548
1549
    /* do padding */
1550
153
    if (context->doPad) {
1551
153
        unsigned char padbyte = (unsigned char)(context->blockSize - context->padDataLength);
1552
        /* fill out rest of pad buffer with pad magic*/
1553
1.37k
        for (i = context->padDataLength; i < context->blockSize; i++) {
1554
1.22k
            context->padBuf[i] = padbyte;
1555
1.22k
        }
1556
153
        rv = (*context->update)(context->cipherInfo, pLastEncryptedPart,
1557
153
                                &outlen, maxout, context->padBuf, context->blockSize);
1558
153
        if (rv == SECSuccess)
1559
153
            *pulLastEncryptedPartLen = (CK_ULONG)outlen;
1560
153
    }
1561
1562
153
finish:
1563
153
    if (contextFinished)
1564
153
        sftk_TerminateOp(session, SFTK_ENCRYPT, context);
1565
153
    sftk_FreeSession(session);
1566
153
    return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
1567
153
}
1568
1569
/* NSC_Encrypt encrypts single-part data. */
1570
CK_RV
1571
NSC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
1572
            CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
1573
            CK_ULONG_PTR pulEncryptedDataLen)
1574
4.62k
{
1575
4.62k
    SFTKSession *session;
1576
4.62k
    SFTKSessionContext *context;
1577
4.62k
    unsigned int outlen;
1578
4.62k
    unsigned int maxoutlen = *pulEncryptedDataLen;
1579
4.62k
    CK_RV crv;
1580
4.62k
    CK_RV crv2;
1581
4.62k
    SECStatus rv = SECSuccess;
1582
4.62k
    SECItem pText;
1583
1584
4.62k
    pText.type = siBuffer;
1585
4.62k
    pText.data = pData;
1586
4.62k
    pText.len = ulDataLen;
1587
1588
4.62k
    CHECK_FORK();
1589
1590
    /* make sure we're legal */
1591
4.62k
    crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, &session);
1592
4.62k
    if (crv != CKR_OK)
1593
0
        return crv;
1594
1595
4.62k
    if (!pEncryptedData) {
1596
0
        outlen = context->rsa ? context->maxLen : ulDataLen + 2 * context->blockSize;
1597
0
        goto done;
1598
0
    }
1599
1600
4.62k
    if (context->doPad) {
1601
153
        if (context->multi) {
1602
153
            CK_ULONG updateLen = maxoutlen;
1603
153
            CK_ULONG finalLen;
1604
            /* padding is fairly complicated, have the update and final
1605
             * code deal with it */
1606
153
            sftk_FreeSession(session);
1607
153
            crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData,
1608
153
                                    &updateLen);
1609
153
            if (crv != CKR_OK) {
1610
0
                updateLen = 0;
1611
0
            }
1612
153
            maxoutlen -= updateLen;
1613
153
            pEncryptedData += updateLen;
1614
153
            finalLen = maxoutlen;
1615
153
            crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen);
1616
153
            if (crv == CKR_OK && crv2 == CKR_OK) {
1617
153
                *pulEncryptedDataLen = updateLen + finalLen;
1618
153
            }
1619
153
            return crv == CKR_OK ? crv2 : crv;
1620
153
        }
1621
        /* doPad without multi means that padding must be done on the first
1622
        ** and only update.  There will be no final.
1623
        */
1624
0
        PORT_Assert(context->blockSize > 1);
1625
0
        if (context->blockSize > 1) {
1626
0
            CK_ULONG remainder = ulDataLen % context->blockSize;
1627
0
            CK_ULONG padding = context->blockSize - remainder;
1628
0
            pText.len += padding;
1629
0
            pText.data = PORT_ZAlloc(pText.len);
1630
0
            if (pText.data) {
1631
0
                memcpy(pText.data, pData, ulDataLen);
1632
0
                memset(pText.data + ulDataLen, padding, padding);
1633
0
            } else {
1634
0
                crv = CKR_HOST_MEMORY;
1635
0
                goto fail;
1636
0
            }
1637
0
        }
1638
0
    }
1639
1640
    /* do it: NOTE: this assumes buf size is big enough. */
1641
4.46k
    rv = (*context->update)(context->cipherInfo, pEncryptedData,
1642
4.46k
                            &outlen, maxoutlen, pText.data, pText.len);
1643
4.46k
    crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
1644
4.46k
    if (pText.data != pData)
1645
0
        PORT_ZFree(pText.data, pText.len);
1646
4.46k
fail:
1647
4.46k
    sftk_TerminateOp(session, SFTK_ENCRYPT, context);
1648
4.46k
done:
1649
4.46k
    sftk_FreeSession(session);
1650
4.46k
    if (crv == CKR_OK) {
1651
4.46k
        *pulEncryptedDataLen = (CK_ULONG)outlen;
1652
4.46k
    }
1653
4.46k
    return crv;
1654
4.46k
}
1655
1656
/*
1657
 ************** Crypto Functions:     Decrypt ************************
1658
 */
1659
1660
/* NSC_DecryptInit initializes a decryption operation. */
1661
CK_RV
1662
NSC_DecryptInit(CK_SESSION_HANDLE hSession,
1663
                CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1664
5.18k
{
1665
5.18k
    CHECK_FORK();
1666
5.18k
    return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT,
1667
5.18k
                          SFTK_DECRYPT, PR_FALSE);
1668
5.18k
}
1669
1670
/* NSC_DecryptUpdate continues a multiple-part decryption operation. */
1671
CK_RV
1672
NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
1673
                  CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
1674
                  CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
1675
13.7k
{
1676
13.7k
    SFTKSessionContext *context;
1677
13.7k
    unsigned int padoutlen = 0;
1678
13.7k
    unsigned int outlen;
1679
13.7k
    unsigned int maxout = *pulPartLen;
1680
13.7k
    CK_RV crv;
1681
13.7k
    SECStatus rv;
1682
1683
13.7k
    CHECK_FORK();
1684
1685
    /* make sure we're legal */
1686
13.7k
    crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, NULL);
1687
13.7k
    if (crv != CKR_OK)
1688
0
        return crv;
1689
1690
    /* this can only happen on an NSS programming error */
1691
13.7k
    PORT_Assert((context->padDataLength == 0) || context->padDataLength == context->blockSize);
1692
1693
13.7k
    if (context->doPad) {
1694
        /* Check the data length for block ciphers. If we are padding,
1695
         * then we must be using a block cipher. In the non-padding case
1696
         * the error will be returned by the underlying decryption
1697
         * function when we do the actual decrypt. We need to do the
1698
         * check here to avoid returning a negative length to the caller
1699
         * or reading before the beginning of the pEncryptedPart buffer.
1700
         */
1701
0
        if ((ulEncryptedPartLen == 0) ||
1702
0
            (ulEncryptedPartLen % context->blockSize) != 0) {
1703
0
            return CKR_ENCRYPTED_DATA_LEN_RANGE;
1704
0
        }
1705
0
    }
1706
1707
13.7k
    if (!pPart) {
1708
0
        if (context->doPad) {
1709
0
            *pulPartLen =
1710
0
                ulEncryptedPartLen + context->padDataLength - context->blockSize;
1711
0
            return CKR_OK;
1712
0
        }
1713
        /* for stream ciphers there is are no constraints on ulEncryptedPartLen.
1714
         * for block ciphers, it must be a multiple of blockSize. The error is
1715
         * detected when this function is called again do decrypt the output.
1716
         */
1717
0
        *pulPartLen = ulEncryptedPartLen;
1718
0
        return CKR_OK;
1719
0
    }
1720
1721
13.7k
    if (context->doPad) {
1722
        /* first decrypt our saved buffer */
1723
0
        if (context->padDataLength != 0) {
1724
0
            rv = (*context->update)(context->cipherInfo, pPart, &padoutlen,
1725
0
                                    maxout, context->padBuf, context->blockSize);
1726
0
            if (rv != SECSuccess)
1727
0
                return sftk_MapDecryptError(PORT_GetError());
1728
0
            pPart += padoutlen;
1729
0
            maxout -= padoutlen;
1730
0
        }
1731
        /* now save the final block for the next decrypt or the final */
1732
0
        PORT_Memcpy(context->padBuf, &pEncryptedPart[ulEncryptedPartLen - context->blockSize],
1733
0
                    context->blockSize);
1734
0
        context->padDataLength = context->blockSize;
1735
0
        ulEncryptedPartLen -= context->padDataLength;
1736
0
    }
1737
1738
    /* do it: NOTE: this assumes buf size in is >= buf size out! */
1739
13.7k
    rv = (*context->update)(context->cipherInfo, pPart, &outlen,
1740
13.7k
                            maxout, pEncryptedPart, ulEncryptedPartLen);
1741
13.7k
    if (rv != SECSuccess) {
1742
0
        return sftk_MapDecryptError(PORT_GetError());
1743
0
    }
1744
13.7k
    *pulPartLen = (CK_ULONG)(outlen + padoutlen);
1745
13.7k
    return CKR_OK;
1746
13.7k
}
1747
1748
/* NSC_DecryptFinal finishes a multiple-part decryption operation. */
1749
CK_RV
1750
NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
1751
                 CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen)
1752
0
{
1753
0
    SFTKSession *session;
1754
0
    SFTKSessionContext *context;
1755
0
    unsigned int outlen;
1756
0
    unsigned int maxout = *pulLastPartLen;
1757
0
    CK_RV crv;
1758
0
    SECStatus rv = SECSuccess;
1759
1760
0
    CHECK_FORK();
1761
1762
    /* make sure we're legal */
1763
0
    crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, &session);
1764
0
    if (crv != CKR_OK)
1765
0
        return crv;
1766
1767
0
    *pulLastPartLen = 0;
1768
0
    if (!pLastPart) {
1769
        /* caller is checking the amount of remaining data */
1770
0
        if (context->padDataLength > 0) {
1771
0
            *pulLastPartLen = context->padDataLength;
1772
0
        }
1773
0
        goto finish;
1774
0
    }
1775
1776
0
    if (context->doPad) {
1777
        /* decrypt our saved buffer */
1778
0
        if (context->padDataLength != 0) {
1779
            /* this assumes that pLastPart is big enough to hold the *whole*
1780
             * buffer!!! */
1781
0
            rv = (*context->update)(context->cipherInfo, pLastPart, &outlen,
1782
0
                                    maxout, context->padBuf, context->blockSize);
1783
0
            if (rv != SECSuccess) {
1784
0
                crv = sftk_MapDecryptError(PORT_GetError());
1785
0
            } else {
1786
0
                unsigned int padSize = 0;
1787
0
                crv = sftk_CheckCBCPadding(pLastPart, outlen,
1788
0
                                           context->blockSize, &padSize);
1789
                /* Update pulLastPartLen, in constant time, if crv is OK */
1790
0
                *pulLastPartLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulLastPartLen);
1791
0
            }
1792
0
        }
1793
0
    }
1794
1795
0
    sftk_TerminateOp(session, SFTK_DECRYPT, context);
1796
0
finish:
1797
0
    sftk_FreeSession(session);
1798
0
    return crv;
1799
0
}
1800
1801
/* NSC_Decrypt decrypts encrypted data in a single part. */
1802
CK_RV
1803
NSC_Decrypt(CK_SESSION_HANDLE hSession,
1804
            CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
1805
            CK_ULONG_PTR pulDataLen)
1806
47
{
1807
47
    SFTKSession *session;
1808
47
    SFTKSessionContext *context;
1809
47
    unsigned int outlen;
1810
47
    unsigned int maxoutlen = *pulDataLen;
1811
47
    CK_RV crv;
1812
47
    CK_RV crv2;
1813
47
    SECStatus rv = SECSuccess;
1814
1815
47
    CHECK_FORK();
1816
1817
    /* make sure we're legal */
1818
47
    crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_FALSE, &session);
1819
47
    if (crv != CKR_OK)
1820
0
        return crv;
1821
1822
47
    if (!pData) {
1823
0
        *pulDataLen = (CK_ULONG)(ulEncryptedDataLen + context->blockSize);
1824
0
        goto done;
1825
0
    }
1826
1827
47
    if (context->doPad && context->multi) {
1828
0
        CK_ULONG updateLen = maxoutlen;
1829
0
        CK_ULONG finalLen;
1830
        /* padding is fairly complicated, have the update and final
1831
         * code deal with it */
1832
0
        sftk_FreeSession(session);
1833
0
        crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
1834
0
                                pData, &updateLen);
1835
0
        if (crv == CKR_OK) {
1836
0
            maxoutlen -= updateLen;
1837
0
            pData += updateLen;
1838
0
        }
1839
0
        finalLen = maxoutlen;
1840
0
        crv2 = NSC_DecryptFinal(hSession, pData, &finalLen);
1841
0
        if (crv == CKR_OK) {
1842
0
            *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv2), updateLen + finalLen, *pulDataLen);
1843
0
            return crv2;
1844
0
        } else {
1845
0
            return crv;
1846
0
        }
1847
0
    }
1848
1849
47
    rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
1850
47
                            pEncryptedData, ulEncryptedDataLen);
1851
    /* XXX need to do MUCH better error mapping than this. */
1852
47
    crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
1853
47
    if (rv == SECSuccess) {
1854
7
        if (context->doPad) {
1855
0
            unsigned int padSize = 0;
1856
0
            crv = sftk_CheckCBCPadding(pData, outlen, context->blockSize,
1857
0
                                       &padSize);
1858
            /* Update pulDataLen, in constant time, if crv is OK */
1859
0
            *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulDataLen);
1860
7
        } else {
1861
7
            *pulDataLen = (CK_ULONG)outlen;
1862
7
        }
1863
7
    }
1864
47
    sftk_TerminateOp(session, SFTK_DECRYPT, context);
1865
47
done:
1866
47
    sftk_FreeSession(session);
1867
47
    return crv;
1868
47
}
1869
1870
/*
1871
 ************** Crypto Functions:     Digest (HASH)  ************************
1872
 */
1873
1874
/* NSC_DigestInit initializes a message-digesting operation. */
1875
CK_RV
1876
NSC_DigestInit(CK_SESSION_HANDLE hSession,
1877
               CK_MECHANISM_PTR pMechanism)
1878
155k
{
1879
155k
    SFTKSession *session;
1880
155k
    SFTKSessionContext *context;
1881
155k
    CK_RV crv = CKR_OK;
1882
1883
155k
    CHECK_FORK();
1884
1885
155k
    session = sftk_SessionFromHandle(hSession);
1886
155k
    if (session == NULL)
1887
0
        return CKR_SESSION_HANDLE_INVALID;
1888
155k
    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_HASH,
1889
155k
                           NULL, 0, NULL, 0, CKA_DIGEST);
1890
155k
    if (crv != CKR_OK) {
1891
0
        sftk_FreeSession(session);
1892
0
        return crv;
1893
0
    }
1894
1895
155k
#define INIT_MECH(mmm)                                         \
1896
155k
    case CKM_##mmm: {                                          \
1897
155k
        mmm##Context *mmm##_ctx = mmm##_NewContext();          \
1898
155k
        context->cipherInfo = (void *)mmm##_ctx;               \
1899
155k
        context->cipherInfoLen = mmm##_FlattenSize(mmm##_ctx); \
1900
155k
        context->currentMech = CKM_##mmm;                      \
1901
155k
        context->hashUpdate = (SFTKHash)mmm##_Update;          \
1902
155k
        context->end = (SFTKEnd)mmm##_End;                     \
1903
155k
        context->destroy = (SFTKDestroy)mmm##_DestroyContext;  \
1904
155k
        context->maxLen = mmm##_LENGTH;                        \
1905
155k
        if (mmm##_ctx)                                         \
1906
155k
            mmm##_Begin(mmm##_ctx);                            \
1907
155k
        else                                                   \
1908
155k
            crv = CKR_HOST_MEMORY;                             \
1909
155k
        break;                                                 \
1910
155k
    }
1911
1912
155k
    switch (pMechanism->mechanism) {
1913
0
        INIT_MECH(MD2)
1914
16.3k
        INIT_MECH(MD5)
1915
108k
        INIT_MECH(SHA1)
1916
0
        INIT_MECH(SHA224)
1917
20.4k
        INIT_MECH(SHA256)
1918
9.71k
        INIT_MECH(SHA384)
1919
766
        INIT_MECH(SHA512)
1920
0
        INIT_MECH(SHA3_224)
1921
0
        INIT_MECH(SHA3_256)
1922
0
        INIT_MECH(SHA3_384)
1923
0
        INIT_MECH(SHA3_512)
1924
1925
0
        default:
1926
0
            crv = CKR_MECHANISM_INVALID;
1927
0
            break;
1928
155k
    }
1929
1930
155k
    if (crv != CKR_OK) {
1931
0
        sftk_FreeContext(context);
1932
0
        sftk_FreeSession(session);
1933
0
        return crv;
1934
0
    }
1935
155k
    sftk_SetContextByType(session, SFTK_HASH, context);
1936
155k
    sftk_FreeSession(session);
1937
155k
    return CKR_OK;
1938
155k
}
1939
1940
/* NSC_Digest digests data in a single part. */
1941
CK_RV
1942
NSC_Digest(CK_SESSION_HANDLE hSession,
1943
           CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,
1944
           CK_ULONG_PTR pulDigestLen)
1945
0
{
1946
0
    SFTKSession *session;
1947
0
    SFTKSessionContext *context;
1948
0
    unsigned int digestLen;
1949
0
    unsigned int maxout = *pulDigestLen;
1950
0
    CK_RV crv;
1951
1952
0
    CHECK_FORK();
1953
1954
    /* make sure we're legal */
1955
0
    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_FALSE, &session);
1956
0
    if (crv != CKR_OK)
1957
0
        return crv;
1958
1959
0
    if (pDigest == NULL) {
1960
0
        *pulDigestLen = context->maxLen;
1961
0
        goto finish;
1962
0
    }
1963
1964
0
#if (ULONG_MAX > UINT_MAX)
1965
    /* The context->hashUpdate function takes an unsigned int for its data
1966
     * length argument, but NSC_Digest takes an unsigned long. */
1967
0
    while (ulDataLen > UINT_MAX) {
1968
0
        (*context->hashUpdate)(context->cipherInfo, pData, UINT_MAX);
1969
0
        pData += UINT_MAX;
1970
0
        ulDataLen -= UINT_MAX;
1971
0
    }
1972
0
#endif
1973
0
    (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen);
1974
1975
    /*  NOTE: this assumes buf size is bigenough for the algorithm */
1976
0
    (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
1977
0
    *pulDigestLen = digestLen;
1978
1979
0
    sftk_TerminateOp(session, SFTK_HASH, context);
1980
0
finish:
1981
0
    sftk_FreeSession(session);
1982
0
    return CKR_OK;
1983
0
}
1984
1985
/* NSC_DigestUpdate continues a multiple-part message-digesting operation. */
1986
CK_RV
1987
NSC_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
1988
                 CK_ULONG ulPartLen)
1989
276k
{
1990
276k
    SFTKSessionContext *context;
1991
276k
    CK_RV crv;
1992
1993
276k
    CHECK_FORK();
1994
1995
    /* make sure we're legal */
1996
276k
    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, NULL);
1997
276k
    if (crv != CKR_OK)
1998
0
        return crv;
1999
2000
276k
#if (ULONG_MAX > UINT_MAX)
2001
    /* The context->hashUpdate function takes an unsigned int for its data
2002
     * length argument, but NSC_DigestUpdate takes an unsigned long. */
2003
276k
    while (ulPartLen > UINT_MAX) {
2004
0
        (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX);
2005
0
        pPart += UINT_MAX;
2006
0
        ulPartLen -= UINT_MAX;
2007
0
    }
2008
276k
#endif
2009
276k
    (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen);
2010
2011
276k
    return CKR_OK;
2012
276k
}
2013
2014
/* NSC_DigestFinal finishes a multiple-part message-digesting operation. */
2015
CK_RV
2016
NSC_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
2017
                CK_ULONG_PTR pulDigestLen)
2018
141k
{
2019
141k
    SFTKSession *session;
2020
141k
    SFTKSessionContext *context;
2021
141k
    unsigned int maxout = *pulDigestLen;
2022
141k
    unsigned int digestLen;
2023
141k
    CK_RV crv;
2024
2025
141k
    CHECK_FORK();
2026
2027
    /* make sure we're legal */
2028
141k
    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
2029
141k
    if (crv != CKR_OK)
2030
12.5k
        return crv;
2031
2032
128k
    if (pDigest != NULL) {
2033
128k
        (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
2034
128k
        *pulDigestLen = digestLen;
2035
128k
        sftk_TerminateOp(session, SFTK_HASH, context);
2036
128k
    } else {
2037
0
        *pulDigestLen = context->maxLen;
2038
0
    }
2039
2040
128k
    sftk_FreeSession(session);
2041
128k
    return CKR_OK;
2042
141k
}
2043
2044
/*
2045
 * these helper functions are used by Generic Macing and Signing functions
2046
 * that use hashes as part of their operations.
2047
 */
2048
#define DOSUB(mmm)                                                \
2049
    static CK_RV                                                  \
2050
        sftk_doSub##mmm(SFTKSessionContext *context)              \
2051
7
    {                                                             \
2052
7
        mmm##Context *mmm##_ctx = mmm##_NewContext();             \
2053
7
        context->hashInfo = (void *)mmm##_ctx;                    \
2054
7
        context->hashUpdate = (SFTKHash)mmm##_Update;             \
2055
7
        context->end = (SFTKEnd)mmm##_End;                        \
2056
7
        context->hashdestroy = (SFTKDestroy)mmm##_DestroyContext; \
2057
7
        if (!context->hashInfo) {                                 \
2058
0
            return CKR_HOST_MEMORY;                               \
2059
0
        }                                                         \
2060
7
        mmm##_Begin(mmm##_ctx);                                   \
2061
7
        return CKR_OK;                                            \
2062
7
    }
Unexecuted instantiation: pkcs11c.c:sftk_doSubMD5
Unexecuted instantiation: pkcs11c.c:sftk_doSubMD2
Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA1
Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA224
pkcs11c.c:sftk_doSubSHA256
Line
Count
Source
2051
5
    {                                                             \
2052
5
        mmm##Context *mmm##_ctx = mmm##_NewContext();             \
2053
5
        context->hashInfo = (void *)mmm##_ctx;                    \
2054
5
        context->hashUpdate = (SFTKHash)mmm##_Update;             \
2055
5
        context->end = (SFTKEnd)mmm##_End;                        \
2056
5
        context->hashdestroy = (SFTKDestroy)mmm##_DestroyContext; \
2057
5
        if (!context->hashInfo) {                                 \
2058
0
            return CKR_HOST_MEMORY;                               \
2059
0
        }                                                         \
2060
5
        mmm##_Begin(mmm##_ctx);                                   \
2061
5
        return CKR_OK;                                            \
2062
5
    }
Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA384
pkcs11c.c:sftk_doSubSHA512
Line
Count
Source
2051
2
    {                                                             \
2052
2
        mmm##Context *mmm##_ctx = mmm##_NewContext();             \
2053
2
        context->hashInfo = (void *)mmm##_ctx;                    \
2054
2
        context->hashUpdate = (SFTKHash)mmm##_Update;             \
2055
2
        context->end = (SFTKEnd)mmm##_End;                        \
2056
2
        context->hashdestroy = (SFTKDestroy)mmm##_DestroyContext; \
2057
2
        if (!context->hashInfo) {                                 \
2058
0
            return CKR_HOST_MEMORY;                               \
2059
0
        }                                                         \
2060
2
        mmm##_Begin(mmm##_ctx);                                   \
2061
2
        return CKR_OK;                                            \
2062
2
    }
2063
2064
DOSUB(MD2)
2065
DOSUB(MD5)
2066
DOSUB(SHA1)
2067
DOSUB(SHA224)
2068
DOSUB(SHA256)
2069
DOSUB(SHA384)
2070
DOSUB(SHA512)
2071
2072
static SECStatus
2073
sftk_SignCopy(
2074
    CK_ULONG *copyLen,
2075
    void *out, unsigned int *outLength,
2076
    unsigned int maxLength,
2077
    const unsigned char *hashResult,
2078
    unsigned int hashResultLength)
2079
24.1k
{
2080
24.1k
    unsigned int toCopy = *copyLen;
2081
24.1k
    if (toCopy > maxLength) {
2082
0
        toCopy = maxLength;
2083
0
    }
2084
24.1k
    if (toCopy > hashResultLength) {
2085
0
        toCopy = hashResultLength;
2086
0
    }
2087
24.1k
    memcpy(out, hashResult, toCopy);
2088
24.1k
    if (outLength) {
2089
24.1k
        *outLength = toCopy;
2090
24.1k
    }
2091
24.1k
    return SECSuccess;
2092
24.1k
}
2093
2094
/* Verify is just a compare for HMAC */
2095
static SECStatus
2096
sftk_HMACCmp(CK_ULONG *copyLen, unsigned char *sig, unsigned int sigLen,
2097
             unsigned char *hash, unsigned int hashLen)
2098
0
{
2099
0
    if (NSS_SecureMemcmp(sig, hash, *copyLen) == 0) {
2100
0
        return SECSuccess;
2101
0
    }
2102
2103
0
    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
2104
0
    return SECFailure;
2105
0
}
2106
2107
/*
2108
 * common HMAC + CMAC initialization routine
2109
 */
2110
static CK_RV
2111
sftk_doMACInit(CK_MECHANISM_TYPE mech, SFTKSessionContext *session,
2112
               SFTKObject *key, CK_ULONG mac_size)
2113
28.1k
{
2114
28.1k
    CK_RV crv;
2115
28.1k
    sftk_MACCtx *context;
2116
28.1k
    CK_ULONG *intpointer;
2117
28.1k
    PRBool isFIPS = sftk_isFIPS(key->slot->slotID);
2118
2119
    /* Set up the initial context. */
2120
28.1k
    crv = sftk_MAC_Create(mech, key, &context);
2121
28.1k
    if (crv != CKR_OK) {
2122
0
        return crv;
2123
0
    }
2124
2125
28.1k
    session->hashInfo = context;
2126
28.1k
    session->multi = PR_TRUE;
2127
2128
    /* Required by FIPS 198 Section 4. Delay this check until after the MAC
2129
     * has been initialized to steal the output size of the MAC. */
2130
28.1k
    if (isFIPS && (mac_size < 4 || mac_size < context->mac_size / 2)) {
2131
0
        sftk_MAC_Destroy(context, PR_TRUE);
2132
0
        return CKR_BUFFER_TOO_SMALL;
2133
0
    }
2134
2135
    /* Configure our helper functions appropriately. Note that these casts
2136
     * ignore the return values. */
2137
28.1k
    session->hashUpdate = (SFTKHash)sftk_MAC_Update;
2138
28.1k
    session->end = (SFTKEnd)sftk_MAC_Finish;
2139
28.1k
    session->hashdestroy = (SFTKDestroy)sftk_MAC_Destroy;
2140
2141
28.1k
    intpointer = PORT_New(CK_ULONG);
2142
28.1k
    if (intpointer == NULL) {
2143
0
        sftk_MAC_Destroy(context, PR_TRUE);
2144
0
        return CKR_HOST_MEMORY;
2145
0
    }
2146
28.1k
    *intpointer = mac_size;
2147
28.1k
    session->cipherInfo = intpointer;
2148
2149
    /* Since we're only "hashing", copy the result from session->end to the
2150
     * caller using sftk_SignCopy. */
2151
28.1k
    session->update = (SFTKCipher)sftk_SignCopy;
2152
28.1k
    session->verify = (SFTKVerify)sftk_HMACCmp;
2153
28.1k
    session->destroy = (SFTKDestroy)sftk_Space;
2154
2155
28.1k
    session->maxLen = context->mac_size;
2156
2157
28.1k
    return CKR_OK;
2158
28.1k
}
2159
2160
/*
2161
 *  SSL Macing support. SSL Macs are inited, then update with the base
2162
 * hashing algorithm, then finalized in sign and verify
2163
 */
2164
2165
/*
2166
 * FROM SSL:
2167
 * 60 bytes is 3 times the maximum length MAC size that is supported.
2168
 * We probably should have one copy of this table. We still need this table
2169
 * in ssl to 'sign' the handshake hashes.
2170
 */
2171
static unsigned char ssl_pad_1[60] = {
2172
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2173
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2174
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2175
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2176
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2177
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2178
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2179
    0x36, 0x36, 0x36, 0x36
2180
};
2181
static unsigned char ssl_pad_2[60] = {
2182
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2183
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2184
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2185
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2186
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2187
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2188
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2189
    0x5c, 0x5c, 0x5c, 0x5c
2190
};
2191
2192
static SECStatus
2193
sftk_SSLMACSign(SFTKSSLMACInfo *info, unsigned char *sig, unsigned int *sigLen,
2194
                unsigned int maxLen, unsigned char *hash, unsigned int hashLen)
2195
0
{
2196
0
    unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
2197
0
    unsigned int out;
2198
2199
0
    info->begin(info->hashContext);
2200
0
    info->update(info->hashContext, info->key, info->keySize);
2201
0
    info->update(info->hashContext, ssl_pad_2, info->padSize);
2202
0
    info->update(info->hashContext, hash, hashLen);
2203
0
    info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH);
2204
0
    PORT_Memcpy(sig, tmpBuf, info->macSize);
2205
0
    PORT_Memset(tmpBuf, 0, info->macSize);
2206
0
    *sigLen = info->macSize;
2207
0
    return SECSuccess;
2208
0
}
2209
2210
static SECStatus
2211
sftk_SSLMACVerify(SFTKSSLMACInfo *info, unsigned char *sig, unsigned int sigLen,
2212
                  unsigned char *hash, unsigned int hashLen)
2213
0
{
2214
0
    unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
2215
0
    unsigned int out;
2216
0
    int cmp;
2217
2218
0
    info->begin(info->hashContext);
2219
0
    info->update(info->hashContext, info->key, info->keySize);
2220
0
    info->update(info->hashContext, ssl_pad_2, info->padSize);
2221
0
    info->update(info->hashContext, hash, hashLen);
2222
0
    info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH);
2223
0
    cmp = NSS_SecureMemcmp(sig, tmpBuf, info->macSize);
2224
0
    PORT_Memset(tmpBuf, 0, info->macSize);
2225
0
    return (cmp == 0) ? SECSuccess : SECFailure;
2226
0
}
2227
2228
/*
2229
 * common HMAC initalization routine
2230
 */
2231
static CK_RV
2232
sftk_doSSLMACInit(SFTKSessionContext *context, SECOidTag oid,
2233
                  SFTKObject *key, CK_ULONG mac_size)
2234
0
{
2235
0
    SFTKAttribute *keyval;
2236
0
    SFTKBegin begin;
2237
0
    int padSize;
2238
0
    SFTKSSLMACInfo *sslmacinfo;
2239
0
    CK_RV crv = CKR_MECHANISM_INVALID;
2240
2241
0
    if (oid == SEC_OID_SHA1) {
2242
0
        crv = sftk_doSubSHA1(context);
2243
0
        if (crv != CKR_OK)
2244
0
            return crv;
2245
0
        begin = (SFTKBegin)SHA1_Begin;
2246
0
        padSize = 40;
2247
0
    } else {
2248
0
        crv = sftk_doSubMD5(context);
2249
0
        if (crv != CKR_OK)
2250
0
            return crv;
2251
0
        begin = (SFTKBegin)MD5_Begin;
2252
0
        padSize = 48;
2253
0
    }
2254
0
    context->multi = PR_TRUE;
2255
2256
0
    keyval = sftk_FindAttribute(key, CKA_VALUE);
2257
0
    if (keyval == NULL)
2258
0
        return CKR_KEY_SIZE_RANGE;
2259
2260
0
    context->hashUpdate(context->hashInfo, keyval->attrib.pValue,
2261
0
                        keyval->attrib.ulValueLen);
2262
0
    context->hashUpdate(context->hashInfo, ssl_pad_1, padSize);
2263
0
    sslmacinfo = (SFTKSSLMACInfo *)PORT_Alloc(sizeof(SFTKSSLMACInfo));
2264
0
    if (sslmacinfo == NULL) {
2265
0
        sftk_FreeAttribute(keyval);
2266
0
        return CKR_HOST_MEMORY;
2267
0
    }
2268
0
    sslmacinfo->size = sizeof(SFTKSSLMACInfo);
2269
0
    sslmacinfo->macSize = mac_size;
2270
0
    sslmacinfo->hashContext = context->hashInfo;
2271
0
    PORT_Memcpy(sslmacinfo->key, keyval->attrib.pValue,
2272
0
                keyval->attrib.ulValueLen);
2273
0
    sslmacinfo->keySize = keyval->attrib.ulValueLen;
2274
0
    sslmacinfo->begin = begin;
2275
0
    sslmacinfo->end = context->end;
2276
0
    sslmacinfo->update = context->hashUpdate;
2277
0
    sslmacinfo->padSize = padSize;
2278
0
    sftk_FreeAttribute(keyval);
2279
0
    context->cipherInfo = (void *)sslmacinfo;
2280
0
    context->destroy = (SFTKDestroy)sftk_ZSpace;
2281
0
    context->update = (SFTKCipher)sftk_SSLMACSign;
2282
0
    context->verify = (SFTKVerify)sftk_SSLMACVerify;
2283
0
    context->maxLen = mac_size;
2284
0
    return CKR_OK;
2285
0
}
2286
2287
/*
2288
 ************** Crypto Functions:     Sign  ************************
2289
 */
2290
2291
/**
2292
 * Check if We're using CBCMacing and initialize the session context if we are.
2293
 *  @param contextType SFTK_SIGN or SFTK_VERIFY
2294
 *  @param keyUsage    check whether key allows this usage
2295
 */
2296
static CK_RV
2297
sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
2298
                CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage,
2299
                SFTKContextType contextType)
2300
2301
64.4k
{
2302
64.4k
    CK_MECHANISM cbc_mechanism;
2303
64.4k
    CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE;
2304
64.4k
#ifndef NSS_DISABLE_DEPRECATED_RC2
2305
64.4k
    CK_RC2_CBC_PARAMS rc2_params;
2306
64.4k
#endif
2307
#if NSS_SOFTOKEN_DOES_RC5
2308
    CK_RC5_CBC_PARAMS rc5_params;
2309
    CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
2310
#endif
2311
64.4k
    unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
2312
64.4k
    unsigned char k2[SFTK_MAX_BLOCK_SIZE];
2313
64.4k
    unsigned char k3[SFTK_MAX_BLOCK_SIZE];
2314
64.4k
    SFTKSessionContext *context;
2315
64.4k
    CK_RV crv;
2316
64.4k
    unsigned int blockSize;
2317
64.4k
    PRBool isXCBC = PR_FALSE;
2318
2319
64.4k
    if (!pMechanism) {
2320
0
        return CKR_MECHANISM_PARAM_INVALID;
2321
0
    }
2322
2323
64.4k
    switch (pMechanism->mechanism) {
2324
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
2325
0
        case CKM_RC2_MAC_GENERAL:
2326
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_MAC_GENERAL_PARAMS))) {
2327
0
                return CKR_MECHANISM_PARAM_INVALID;
2328
0
            }
2329
0
            mac_bytes =
2330
0
                ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
2331
        /* fall through */
2332
0
        case CKM_RC2_MAC:
2333
            /* this works because ulEffectiveBits is in the same place in both the
2334
             * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */
2335
0
            rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *)
2336
0
                                              pMechanism->pParameter)
2337
0
                                             ->ulEffectiveBits;
2338
0
            PORT_Memset(rc2_params.iv, 0, sizeof(rc2_params.iv));
2339
0
            cbc_mechanism.mechanism = CKM_RC2_CBC;
2340
0
            cbc_mechanism.pParameter = &rc2_params;
2341
0
            cbc_mechanism.ulParameterLen = sizeof(rc2_params);
2342
0
            blockSize = 8;
2343
0
            break;
2344
0
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
2345
2346
#if NSS_SOFTOKEN_DOES_RC5
2347
        case CKM_RC5_MAC_GENERAL:
2348
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
2349
                return CKR_MECHANISM_PARAM_INVALID;
2350
            }
2351
            mac_bytes =
2352
                ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
2353
        /* fall through */
2354
        case CKM_RC5_MAC:
2355
            /* this works because ulEffectiveBits is in the same place in both the
2356
             * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */
2357
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
2358
                return CKR_MECHANISM_PARAM_INVALID;
2359
            }
2360
            rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter;
2361
            rc5_params.ulWordsize = rc5_mac->ulWordsize;
2362
            rc5_params.ulRounds = rc5_mac->ulRounds;
2363
            rc5_params.pIv = ivBlock;
2364
            if ((blockSize = rc5_mac->ulWordsize * 2) > SFTK_MAX_BLOCK_SIZE)
2365
                return CKR_MECHANISM_PARAM_INVALID;
2366
            rc5_params.ulIvLen = blockSize;
2367
            PORT_Memset(ivBlock, 0, blockSize);
2368
            cbc_mechanism.mechanism = CKM_RC5_CBC;
2369
            cbc_mechanism.pParameter = &rc5_params;
2370
            cbc_mechanism.ulParameterLen = sizeof(rc5_params);
2371
            break;
2372
#endif
2373
        /* add cast and idea later */
2374
0
        case CKM_DES_MAC_GENERAL:
2375
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2376
        /* fall through */
2377
0
        case CKM_DES_MAC:
2378
0
            blockSize = 8;
2379
0
            PORT_Memset(ivBlock, 0, blockSize);
2380
0
            cbc_mechanism.mechanism = CKM_DES_CBC;
2381
0
            cbc_mechanism.pParameter = &ivBlock;
2382
0
            cbc_mechanism.ulParameterLen = blockSize;
2383
0
            break;
2384
0
        case CKM_DES3_MAC_GENERAL:
2385
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2386
        /* fall through */
2387
0
        case CKM_DES3_MAC:
2388
0
            blockSize = 8;
2389
0
            PORT_Memset(ivBlock, 0, blockSize);
2390
0
            cbc_mechanism.mechanism = CKM_DES3_CBC;
2391
0
            cbc_mechanism.pParameter = &ivBlock;
2392
0
            cbc_mechanism.ulParameterLen = blockSize;
2393
0
            break;
2394
0
        case CKM_CDMF_MAC_GENERAL:
2395
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2396
        /* fall through */
2397
0
        case CKM_CDMF_MAC:
2398
0
            blockSize = 8;
2399
0
            PORT_Memset(ivBlock, 0, blockSize);
2400
0
            cbc_mechanism.mechanism = CKM_CDMF_CBC;
2401
0
            cbc_mechanism.pParameter = &ivBlock;
2402
0
            cbc_mechanism.ulParameterLen = blockSize;
2403
0
            break;
2404
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
2405
0
        case CKM_SEED_MAC_GENERAL:
2406
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2407
        /* fall through */
2408
0
        case CKM_SEED_MAC:
2409
0
            blockSize = 16;
2410
0
            PORT_Memset(ivBlock, 0, blockSize);
2411
0
            cbc_mechanism.mechanism = CKM_SEED_CBC;
2412
0
            cbc_mechanism.pParameter = &ivBlock;
2413
0
            cbc_mechanism.ulParameterLen = blockSize;
2414
0
            break;
2415
0
#endif /* NSS_DISABLE_DEPRECATED_SEED */
2416
0
        case CKM_CAMELLIA_MAC_GENERAL:
2417
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2418
        /* fall through */
2419
0
        case CKM_CAMELLIA_MAC:
2420
0
            blockSize = 16;
2421
0
            PORT_Memset(ivBlock, 0, blockSize);
2422
0
            cbc_mechanism.mechanism = CKM_CAMELLIA_CBC;
2423
0
            cbc_mechanism.pParameter = &ivBlock;
2424
0
            cbc_mechanism.ulParameterLen = blockSize;
2425
0
            break;
2426
0
        case CKM_AES_MAC_GENERAL:
2427
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2428
        /* fall through */
2429
0
        case CKM_AES_MAC:
2430
0
            blockSize = 16;
2431
0
            PORT_Memset(ivBlock, 0, blockSize);
2432
0
            cbc_mechanism.mechanism = CKM_AES_CBC;
2433
0
            cbc_mechanism.pParameter = &ivBlock;
2434
0
            cbc_mechanism.ulParameterLen = blockSize;
2435
0
            break;
2436
0
        case CKM_AES_XCBC_MAC_96:
2437
0
        case CKM_AES_XCBC_MAC:
2438
            /* The only difference between CKM_AES_XCBC_MAC
2439
             * and CKM_AES_XCBC_MAC_96 is the size of the returned mac. */
2440
0
            mac_bytes = pMechanism->mechanism == CKM_AES_XCBC_MAC_96 ? 12 : 16;
2441
0
            blockSize = 16;
2442
0
            PORT_Memset(ivBlock, 0, blockSize);
2443
0
            cbc_mechanism.mechanism = CKM_AES_CBC;
2444
0
            cbc_mechanism.pParameter = &ivBlock;
2445
0
            cbc_mechanism.ulParameterLen = blockSize;
2446
            /* is XCBC requires extra processing at the end of the operation */
2447
0
            isXCBC = PR_TRUE;
2448
            /* The input key is used to generate k1, k2, and k3. k2 and k3
2449
             * are used at the end in the pad step. k1 replaces the input
2450
             * key in the aes cbc mac */
2451
0
            crv = sftk_aes_xcbc_new_keys(hSession, hKey, &hKey, k2, k3);
2452
0
            if (crv != CKR_OK) {
2453
0
                return crv;
2454
0
            }
2455
0
            break;
2456
64.4k
        default:
2457
64.4k
            return CKR_FUNCTION_NOT_SUPPORTED;
2458
64.4k
    }
2459
2460
    /* if MAC size is externally supplied, it should be checked.
2461
     */
2462
0
    if (mac_bytes == SFTK_INVALID_MAC_SIZE)
2463
0
        mac_bytes = blockSize >> 1;
2464
0
    else {
2465
0
        if (mac_bytes > blockSize) {
2466
0
            crv = CKR_MECHANISM_PARAM_INVALID;
2467
0
            goto fail;
2468
0
        }
2469
0
    }
2470
2471
0
    crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey,
2472
0
                         CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */
2473
0
                         keyUsage, contextType, PR_TRUE);
2474
0
    if (crv != CKR_OK)
2475
0
        goto fail;
2476
0
    crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL);
2477
2478
    /* this shouldn't happen! */
2479
0
    PORT_Assert(crv == CKR_OK);
2480
0
    if (crv != CKR_OK)
2481
0
        goto fail;
2482
0
    context->blockSize = blockSize;
2483
0
    context->macSize = mac_bytes;
2484
0
    context->isXCBC = isXCBC;
2485
0
    if (isXCBC) {
2486
        /* save the xcbc specific parameters */
2487
0
        PORT_Memcpy(context->k2, k2, blockSize);
2488
0
        PORT_Memcpy(context->k3, k3, blockSize);
2489
0
        PORT_Memset(k2, 0, blockSize);
2490
0
        PORT_Memset(k3, 0, blockSize);
2491
        /* get rid of the temp key now that the context has been created */
2492
0
        NSC_DestroyObject(hSession, hKey);
2493
0
    }
2494
0
    return CKR_OK;
2495
0
fail:
2496
0
    if (isXCBC) {
2497
0
        PORT_Memset(k2, 0, blockSize);
2498
0
        PORT_Memset(k3, 0, blockSize);
2499
0
        NSC_DestroyObject(hSession, hKey); /* get rid of our temp key */
2500
0
    }
2501
0
    return crv;
2502
0
}
2503
2504
/*
2505
 * encode RSA PKCS #1 Signature data before signing...
2506
 */
2507
static SECStatus
2508
sftk_RSAHashSign(SFTKHashSignInfo *info, unsigned char *sig,
2509
                 unsigned int *sigLen, unsigned int maxLen,
2510
                 const unsigned char *hash, unsigned int hashLen)
2511
0
{
2512
0
    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
2513
0
    if (info->key->keyType != NSSLOWKEYRSAKey) {
2514
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
2515
0
        return SECFailure;
2516
0
    }
2517
2518
0
    return RSA_HashSign(info->hashOid, info->key, sig, sigLen, maxLen,
2519
0
                        hash, hashLen);
2520
0
}
2521
2522
/* XXX Old template; want to expunge it eventually. */
2523
static DERTemplate SECAlgorithmIDTemplate[] = {
2524
    { DER_SEQUENCE,
2525
      0, NULL, sizeof(SECAlgorithmID) },
2526
    { DER_OBJECT_ID,
2527
      offsetof(SECAlgorithmID, algorithm) },
2528
    { DER_OPTIONAL | DER_ANY,
2529
      offsetof(SECAlgorithmID, parameters) },
2530
    { 0 }
2531
};
2532
2533
/*
2534
 * XXX OLD Template.  Once all uses have been switched over to new one,
2535
 * remove this.
2536
 */
2537
static DERTemplate SGNDigestInfoTemplate[] = {
2538
    { DER_SEQUENCE,
2539
      0, NULL, sizeof(SGNDigestInfo) },
2540
    { DER_INLINE,
2541
      offsetof(SGNDigestInfo, digestAlgorithm),
2542
      SECAlgorithmIDTemplate },
2543
    { DER_OCTET_STRING,
2544
      offsetof(SGNDigestInfo, digest) },
2545
    { 0 }
2546
};
2547
2548
/*
2549
 * encode RSA PKCS #1 Signature data before signing...
2550
 */
2551
SECStatus
2552
RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key,
2553
             unsigned char *sig, unsigned int *sigLen, unsigned int maxLen,
2554
             const unsigned char *hash, unsigned int hashLen)
2555
0
{
2556
0
    SECStatus rv = SECFailure;
2557
0
    SECItem digder;
2558
0
    PLArenaPool *arena = NULL;
2559
0
    SGNDigestInfo *di = NULL;
2560
2561
0
    digder.data = NULL;
2562
2563
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2564
0
    if (!arena) {
2565
0
        goto loser;
2566
0
    }
2567
2568
    /* Construct digest info */
2569
0
    di = SGN_CreateDigestInfo(hashOid, hash, hashLen);
2570
0
    if (!di) {
2571
0
        goto loser;
2572
0
    }
2573
2574
    /* Der encode the digest as a DigestInfo */
2575
0
    rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di);
2576
0
    if (rv != SECSuccess) {
2577
0
        goto loser;
2578
0
    }
2579
2580
    /*
2581
    ** Encrypt signature after constructing appropriate PKCS#1 signature
2582
    ** block
2583
    */
2584
0
    rv = RSA_Sign(&key->u.rsa, sig, sigLen, maxLen, digder.data,
2585
0
                  digder.len);
2586
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2587
0
        sftk_fatalError = PR_TRUE;
2588
0
    }
2589
2590
0
loser:
2591
0
    SGN_DestroyDigestInfo(di);
2592
0
    if (arena != NULL) {
2593
0
        PORT_FreeArena(arena, PR_TRUE);
2594
0
    }
2595
0
    return rv;
2596
0
}
2597
2598
static SECStatus
2599
sftk_RSASign(NSSLOWKEYPrivateKey *key, unsigned char *output,
2600
             unsigned int *outputLen, unsigned int maxOutputLen,
2601
             const unsigned char *input, unsigned int inputLen)
2602
12.0k
{
2603
12.0k
    SECStatus rv = SECFailure;
2604
2605
12.0k
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
2606
12.0k
    if (key->keyType != NSSLOWKEYRSAKey) {
2607
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
2608
0
        return SECFailure;
2609
0
    }
2610
2611
12.0k
    rv = RSA_Sign(&key->u.rsa, output, outputLen, maxOutputLen, input,
2612
12.0k
                  inputLen);
2613
12.0k
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2614
0
        sftk_fatalError = PR_TRUE;
2615
0
    }
2616
12.0k
    return rv;
2617
12.0k
}
2618
2619
static SECStatus
2620
sftk_RSASignRaw(NSSLOWKEYPrivateKey *key, unsigned char *output,
2621
                unsigned int *outputLen, unsigned int maxOutputLen,
2622
                const unsigned char *input, unsigned int inputLen)
2623
0
{
2624
0
    SECStatus rv = SECFailure;
2625
2626
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
2627
0
    if (key->keyType != NSSLOWKEYRSAKey) {
2628
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
2629
0
        return SECFailure;
2630
0
    }
2631
2632
0
    rv = RSA_SignRaw(&key->u.rsa, output, outputLen, maxOutputLen, input,
2633
0
                     inputLen);
2634
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2635
0
        sftk_fatalError = PR_TRUE;
2636
0
    }
2637
0
    return rv;
2638
0
}
2639
2640
static SECStatus
2641
sftk_RSASignPSS(SFTKPSSSignInfo *info, unsigned char *sig,
2642
                unsigned int *sigLen, unsigned int maxLen,
2643
                const unsigned char *hash, unsigned int hashLen)
2644
939
{
2645
939
    SECStatus rv = SECFailure;
2646
939
    HASH_HashType hashAlg;
2647
939
    HASH_HashType maskHashAlg;
2648
939
    CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
2649
2650
939
    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
2651
939
    if (info->key->keyType != NSSLOWKEYRSAKey) {
2652
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
2653
0
        return SECFailure;
2654
0
    }
2655
2656
939
    hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg);
2657
939
    maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf);
2658
2659
939
    rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL,
2660
939
                     params->sLen, sig, sigLen, maxLen, hash, hashLen);
2661
939
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2662
0
        sftk_fatalError = PR_TRUE;
2663
0
    }
2664
939
    return rv;
2665
939
}
2666
2667
static SECStatus
2668
nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen,
2669
                    void *dataBuf, unsigned int dataLen)
2670
10
{
2671
10
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen };
2672
10
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2673
10
    NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx;
2674
10
    return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest);
2675
10
}
2676
2677
static SECStatus
2678
nsc_DSA_Sign_Stub(void *ctx, void *sigBuf,
2679
                  unsigned int *sigLen, unsigned int maxSigLen,
2680
                  void *dataBuf, unsigned int dataLen)
2681
0
{
2682
0
    NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
2683
0
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen };
2684
0
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2685
0
    SECStatus rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest);
2686
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2687
0
        sftk_fatalError = PR_TRUE;
2688
0
    }
2689
0
    *sigLen = signature.len;
2690
0
    return rv;
2691
0
}
2692
2693
static SECStatus
2694
nsc_ECDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen,
2695
                    void *dataBuf, unsigned int dataLen)
2696
1.37k
{
2697
1.37k
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen };
2698
1.37k
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2699
1.37k
    NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx;
2700
1.37k
    return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest);
2701
1.37k
}
2702
2703
static SECStatus
2704
nsc_ECDSASignStub(void *ctx, void *sigBuf,
2705
                  unsigned int *sigLen, unsigned int maxSigLen,
2706
                  void *dataBuf, unsigned int dataLen)
2707
1.30k
{
2708
1.30k
    NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
2709
1.30k
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen };
2710
1.30k
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2711
2712
1.30k
    SECStatus rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest);
2713
1.30k
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2714
0
        sftk_fatalError = PR_TRUE;
2715
0
    }
2716
1.30k
    *sigLen = signature.len;
2717
1.30k
    return rv;
2718
1.30k
}
2719
2720
static SECStatus
2721
nsc_EDDSAVerifyStub(void *ctx, void *sigBuf, unsigned int sigLen,
2722
                    void *dataBuf, unsigned int dataLen)
2723
0
{
2724
0
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen };
2725
0
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2726
0
    NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx;
2727
0
    return ED_VerifyMessage(&(key->u.ec), &signature, &digest);
2728
0
}
2729
2730
static SECStatus
2731
nsc_EDDSASignStub(void *ctx, void *sigBuf,
2732
                  unsigned int *sigLen, unsigned int maxSigLen,
2733
                  void *dataBuf, unsigned int dataLen)
2734
0
{
2735
0
    NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx;
2736
0
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen };
2737
0
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2738
2739
0
    SECStatus rv = ED_SignMessage(&(key->u.ec), &signature, &digest);
2740
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2741
0
        sftk_fatalError = PR_TRUE;
2742
0
    }
2743
0
    *sigLen = signature.len;
2744
0
    return rv;
2745
0
}
2746
2747
/* NSC_SignInit setups up the signing operations. There are three basic
2748
 * types of signing:
2749
 *      (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied
2750
 *  to data in a single Sign operation (which often looks a lot like an
2751
 *  encrypt, with data coming in and data going out).
2752
 *      (2) Hash based signing, where we continually hash the data, then apply
2753
 *  some sort of signature to the end.
2754
 *      (3) Block Encryption CBC MAC's, where the Data is encrypted with a key,
2755
 *  and only the final block is part of the mac.
2756
 *
2757
 *  For case number 3, we initialize a context much like the Encryption Context
2758
 *  (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and
2759
 *  C_Final by the following method... if it's not multi-part, and it's doesn't
2760
 *  have a hash context, it must be a block Encryption CBC MAC.
2761
 *
2762
 *  For case number 2, we initialize a hash structure, as well as make it
2763
 *  multi-part. Updates are simple calls to the hash update function. Final
2764
 *  calls the hashend, then passes the result to the 'update' function (which
2765
 *  operates as a final signature function). In some hash based MAC'ing (as
2766
 *  opposed to hash base signatures), the update function is can be simply a
2767
 *  copy (as is the case with HMAC).
2768
 */
2769
CK_RV
2770
NSC_SignInit(CK_SESSION_HANDLE hSession,
2771
             CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2772
60.4k
{
2773
60.4k
    SFTKSession *session;
2774
60.4k
    SFTKObject *key;
2775
60.4k
    SFTKSessionContext *context;
2776
60.4k
    CK_KEY_TYPE key_type;
2777
60.4k
    CK_RV crv = CKR_OK;
2778
60.4k
    NSSLOWKEYPrivateKey *privKey;
2779
60.4k
    SFTKHashSignInfo *info = NULL;
2780
60.4k
    SFTKPSSSignInfo *pinfo = NULL;
2781
2782
60.4k
    CHECK_FORK();
2783
2784
    /* Block Cipher MACing Algorithms use a different Context init method..*/
2785
60.4k
    crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN);
2786
60.4k
    if (crv != CKR_FUNCTION_NOT_SUPPORTED)
2787
0
        return crv;
2788
2789
    /* we're not using a block cipher mac */
2790
60.4k
    session = sftk_SessionFromHandle(hSession);
2791
60.4k
    if (session == NULL)
2792
0
        return CKR_SESSION_HANDLE_INVALID;
2793
60.4k
    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_SIGN, &key,
2794
60.4k
                           hKey, &key_type, CKO_PRIVATE_KEY, CKA_SIGN);
2795
60.4k
    if (crv != CKR_OK) {
2796
0
        sftk_FreeSession(session);
2797
0
        return crv;
2798
0
    }
2799
2800
60.4k
    context->multi = PR_FALSE;
2801
2802
60.4k
#define INIT_RSA_SIGN_MECH(mmm)                         \
2803
60.4k
    case CKM_##mmm##_RSA_PKCS:                          \
2804
0
        context->multi = PR_TRUE;                       \
2805
0
        crv = sftk_doSub##mmm(context);                 \
2806
0
        if (crv != CKR_OK)                              \
2807
0
            break;                                      \
2808
0
        context->update = (SFTKCipher)sftk_RSAHashSign; \
2809
0
        info = PORT_New(SFTKHashSignInfo);              \
2810
0
        if (info == NULL) {                             \
2811
0
            crv = CKR_HOST_MEMORY;                      \
2812
0
            break;                                      \
2813
0
        }                                               \
2814
0
        info->hashOid = SEC_OID_##mmm;                  \
2815
0
        goto finish_rsa;
2816
2817
60.4k
    switch (pMechanism->mechanism) {
2818
0
        INIT_RSA_SIGN_MECH(MD5)
2819
0
        INIT_RSA_SIGN_MECH(MD2)
2820
0
        INIT_RSA_SIGN_MECH(SHA1)
2821
0
        INIT_RSA_SIGN_MECH(SHA224)
2822
0
        INIT_RSA_SIGN_MECH(SHA256)
2823
0
        INIT_RSA_SIGN_MECH(SHA384)
2824
0
        INIT_RSA_SIGN_MECH(SHA512)
2825
2826
12.0k
        case CKM_RSA_PKCS:
2827
12.0k
            context->update = (SFTKCipher)sftk_RSASign;
2828
12.0k
            goto finish_rsa;
2829
0
        case CKM_RSA_X_509:
2830
0
            context->update = (SFTKCipher)sftk_RSASignRaw;
2831
12.0k
        finish_rsa:
2832
12.0k
            if (key_type != CKK_RSA) {
2833
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
2834
0
                break;
2835
0
            }
2836
12.0k
            context->rsa = PR_TRUE;
2837
12.0k
            privKey = sftk_GetPrivKey(key, CKK_RSA, &crv);
2838
12.0k
            if (privKey == NULL) {
2839
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
2840
0
                break;
2841
0
            }
2842
            /* OK, info is allocated only if we're doing hash and sign mechanism.
2843
             * It's necessary to be able to set the correct OID in the final
2844
             * signature.
2845
             */
2846
12.0k
            if (info) {
2847
0
                info->key = privKey;
2848
0
                context->cipherInfo = info;
2849
0
                context->destroy = (SFTKDestroy)sftk_Space;
2850
12.0k
            } else {
2851
12.0k
                context->cipherInfo = privKey;
2852
12.0k
                context->destroy = (SFTKDestroy)sftk_Null;
2853
12.0k
            }
2854
12.0k
            context->maxLen = nsslowkey_PrivateModulusLen(privKey);
2855
12.0k
            break;
2856
2857
0
#define INIT_RSA_PSS_SIG_MECH(mmm)                                                            \
2858
0
    case CKM_##mmm##_RSA_PKCS_PSS:                                                            \
2859
0
        context->multi = PR_TRUE;                                                             \
2860
0
        crv = sftk_doSub##mmm(context);                                                       \
2861
0
        if (crv != CKR_OK)                                                                    \
2862
0
            break;                                                                            \
2863
0
        if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) {                   \
2864
0
            crv = CKR_MECHANISM_PARAM_INVALID;                                                \
2865
0
            break;                                                                            \
2866
0
        }                                                                                     \
2867
0
        if (((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)->hashAlg != CKM_##mmm) { \
2868
0
            crv = CKR_MECHANISM_PARAM_INVALID;                                                \
2869
0
            break;                                                                            \
2870
0
        }                                                                                     \
2871
0
        goto finish_rsa_pss;
2872
0
            INIT_RSA_PSS_SIG_MECH(SHA1)
2873
0
            INIT_RSA_PSS_SIG_MECH(SHA224)
2874
0
            INIT_RSA_PSS_SIG_MECH(SHA256)
2875
0
            INIT_RSA_PSS_SIG_MECH(SHA384)
2876
0
            INIT_RSA_PSS_SIG_MECH(SHA512)
2877
939
        case CKM_RSA_PKCS_PSS:
2878
939
        finish_rsa_pss:
2879
939
            if (key_type != CKK_RSA) {
2880
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
2881
0
                break;
2882
0
            }
2883
939
            context->rsa = PR_TRUE;
2884
939
            if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
2885
939
                !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) {
2886
0
                crv = CKR_MECHANISM_PARAM_INVALID;
2887
0
                break;
2888
0
            }
2889
939
            pinfo = PORT_New(SFTKPSSSignInfo);
2890
939
            if (pinfo == NULL) {
2891
0
                crv = CKR_HOST_MEMORY;
2892
0
                break;
2893
0
            }
2894
939
            pinfo->size = sizeof(SFTKPSSSignInfo);
2895
939
            pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter;
2896
939
            pinfo->key = sftk_GetPrivKey(key, CKK_RSA, &crv);
2897
939
            if (pinfo->key == NULL) {
2898
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
2899
0
                break;
2900
0
            }
2901
939
            context->cipherInfo = pinfo;
2902
939
            context->destroy = (SFTKDestroy)sftk_ZSpace;
2903
939
            context->update = (SFTKCipher)sftk_RSASignPSS;
2904
939
            context->maxLen = nsslowkey_PrivateModulusLen(pinfo->key);
2905
939
            break;
2906
2907
0
#define INIT_DSA_SIG_MECH(mmm)          \
2908
0
    case CKM_DSA_##mmm:                 \
2909
0
        context->multi = PR_TRUE;       \
2910
0
        crv = sftk_doSub##mmm(context); \
2911
0
        if (crv != CKR_OK)              \
2912
0
            break;                      \
2913
0
        goto finish_dsa;
2914
0
            INIT_DSA_SIG_MECH(SHA1)
2915
0
            INIT_DSA_SIG_MECH(SHA224)
2916
0
            INIT_DSA_SIG_MECH(SHA256)
2917
0
            INIT_DSA_SIG_MECH(SHA384)
2918
0
            INIT_DSA_SIG_MECH(SHA512)
2919
0
        case CKM_DSA:
2920
0
        finish_dsa:
2921
0
            if (key_type != CKK_DSA) {
2922
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
2923
0
                break;
2924
0
            }
2925
0
            privKey = sftk_GetPrivKey(key, CKK_DSA, &crv);
2926
0
            if (privKey == NULL) {
2927
0
                break;
2928
0
            }
2929
0
            context->cipherInfo = privKey;
2930
0
            context->update = (SFTKCipher)nsc_DSA_Sign_Stub;
2931
0
            context->destroy = (privKey == key->objectInfo) ? (SFTKDestroy)sftk_Null : (SFTKDestroy)sftk_FreePrivKey;
2932
0
            context->maxLen = DSA_MAX_SIGNATURE_LEN;
2933
2934
0
            break;
2935
2936
0
#define INIT_ECDSA_SIG_MECH(mmm)        \
2937
3
    case CKM_ECDSA_##mmm:               \
2938
3
        context->multi = PR_TRUE;       \
2939
3
        crv = sftk_doSub##mmm(context); \
2940
3
        if (crv != CKR_OK)              \
2941
3
            break;                      \
2942
3
        goto finish_ecdsa;
2943
0
            INIT_ECDSA_SIG_MECH(SHA1)
2944
0
            INIT_ECDSA_SIG_MECH(SHA224)
2945
0
            INIT_ECDSA_SIG_MECH(SHA256)
2946
0
            INIT_ECDSA_SIG_MECH(SHA384)
2947
0
            INIT_ECDSA_SIG_MECH(SHA512)
2948
1.30k
        case CKM_ECDSA:
2949
1.30k
        finish_ecdsa:
2950
1.30k
            if (key_type != CKK_EC) {
2951
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
2952
0
                break;
2953
0
            }
2954
1.30k
            privKey = sftk_GetPrivKey(key, CKK_EC, &crv);
2955
1.30k
            if (privKey == NULL) {
2956
0
                crv = CKR_HOST_MEMORY;
2957
0
                break;
2958
0
            }
2959
1.30k
            context->cipherInfo = privKey;
2960
1.30k
            context->update = (SFTKCipher)nsc_ECDSASignStub;
2961
1.30k
            context->destroy = (privKey == key->objectInfo) ? (SFTKDestroy)sftk_Null : (SFTKDestroy)sftk_FreePrivKey;
2962
1.30k
            context->maxLen = MAX_ECKEY_LEN * 2;
2963
2964
1.30k
            break;
2965
2966
0
        case CKM_EDDSA:
2967
0
            if (key_type != CKK_EC_EDWARDS) {
2968
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
2969
0
                break;
2970
0
            }
2971
2972
0
            if (pMechanism->pParameter) {
2973
0
                crv = CKR_MECHANISM_PARAM_INVALID;
2974
0
                break;
2975
0
            }
2976
2977
0
            privKey = sftk_GetPrivKey(key, CKK_EC_EDWARDS, &crv);
2978
0
            if (privKey == NULL) {
2979
0
                crv = CKR_HOST_MEMORY;
2980
0
                break;
2981
0
            }
2982
0
            context->cipherInfo = privKey;
2983
0
            context->update = (SFTKCipher)nsc_EDDSASignStub;
2984
0
            context->destroy = (privKey == key->objectInfo) ? (SFTKDestroy)sftk_Null : (SFTKDestroy)sftk_FreePrivKey;
2985
0
            context->maxLen = MAX_ECKEY_LEN * 2;
2986
2987
0
            break;
2988
2989
0
#define INIT_HMAC_MECH(mmm)                                        \
2990
0
    case CKM_##mmm##_HMAC_GENERAL:                                 \
2991
0
        PORT_Assert(pMechanism->pParameter);                       \
2992
0
        if (!pMechanism->pParameter) {                             \
2993
0
            crv = CKR_MECHANISM_PARAM_INVALID;                     \
2994
0
            break;                                                 \
2995
0
        }                                                          \
2996
0
        crv = sftk_doMACInit(pMechanism->mechanism, context, key,  \
2997
0
                             *(CK_ULONG *)pMechanism->pParameter); \
2998
0
        break;                                                     \
2999
28.1k
    case CKM_##mmm##_HMAC:                                         \
3000
28.1k
        crv = sftk_doMACInit(pMechanism->mechanism, context, key,  \
3001
28.1k
                             mmm##_LENGTH);                        \
3002
28.1k
        break;
3003
3004
0
            INIT_HMAC_MECH(MD2)
3005
0
            INIT_HMAC_MECH(MD5)
3006
0
            INIT_HMAC_MECH(SHA1)
3007
0
            INIT_HMAC_MECH(SHA224)
3008
0
            INIT_HMAC_MECH(SHA256)
3009
0
            INIT_HMAC_MECH(SHA384)
3010
0
            INIT_HMAC_MECH(SHA512)
3011
0
            INIT_HMAC_MECH(SHA3_224)
3012
0
            INIT_HMAC_MECH(SHA3_256)
3013
0
            INIT_HMAC_MECH(SHA3_384)
3014
0
            INIT_HMAC_MECH(SHA3_512)
3015
3016
0
        case CKM_AES_CMAC_GENERAL:
3017
0
            PORT_Assert(pMechanism->pParameter);
3018
0
            if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) {
3019
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3020
0
                break;
3021
0
            }
3022
0
            crv = sftk_doMACInit(pMechanism->mechanism, context, key, *(CK_ULONG *)pMechanism->pParameter);
3023
0
            break;
3024
0
        case CKM_AES_CMAC:
3025
0
            crv = sftk_doMACInit(pMechanism->mechanism, context, key, AES_BLOCK_SIZE);
3026
0
            break;
3027
0
        case CKM_SSL3_MD5_MAC:
3028
0
            PORT_Assert(pMechanism->pParameter);
3029
0
            if (!pMechanism->pParameter) {
3030
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3031
0
                break;
3032
0
            }
3033
0
            crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key,
3034
0
                                    *(CK_ULONG *)pMechanism->pParameter);
3035
0
            break;
3036
0
        case CKM_SSL3_SHA1_MAC:
3037
0
            PORT_Assert(pMechanism->pParameter);
3038
0
            if (!pMechanism->pParameter) {
3039
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3040
0
                break;
3041
0
            }
3042
0
            crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key,
3043
0
                                    *(CK_ULONG *)pMechanism->pParameter);
3044
0
            break;
3045
0
        case CKM_TLS_PRF_GENERAL:
3046
0
            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0);
3047
0
            break;
3048
11.2k
        case CKM_TLS_MAC: {
3049
11.2k
            CK_TLS_MAC_PARAMS *tls12_mac_params;
3050
11.2k
            HASH_HashType tlsPrfHash;
3051
11.2k
            const char *label;
3052
3053
11.2k
            if (pMechanism->ulParameterLen != sizeof(CK_TLS_MAC_PARAMS)) {
3054
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3055
0
                break;
3056
0
            }
3057
11.2k
            tls12_mac_params = (CK_TLS_MAC_PARAMS *)pMechanism->pParameter;
3058
11.2k
            if (tls12_mac_params->prfHashMechanism == CKM_TLS_PRF) {
3059
                /* The TLS 1.0 and 1.1 PRF */
3060
6.29k
                tlsPrfHash = HASH_AlgNULL;
3061
6.29k
                if (tls12_mac_params->ulMacLength != 12) {
3062
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
3063
0
                    break;
3064
0
                }
3065
6.29k
            } else {
3066
                /* The hash function for the TLS 1.2 PRF */
3067
4.98k
                tlsPrfHash =
3068
4.98k
                    sftk_GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism);
3069
4.98k
                if (tlsPrfHash == HASH_AlgNULL ||
3070
4.98k
                    tls12_mac_params->ulMacLength < 12) {
3071
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
3072
0
                    break;
3073
0
                }
3074
4.98k
            }
3075
11.2k
            if (tls12_mac_params->ulServerOrClient == 1) {
3076
4.40k
                label = "server finished";
3077
6.86k
            } else if (tls12_mac_params->ulServerOrClient == 2) {
3078
6.86k
                label = "client finished";
3079
6.86k
            } else {
3080
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3081
0
                break;
3082
0
            }
3083
11.2k
            crv = sftk_TLSPRFInit(context, key, key_type, tlsPrfHash,
3084
11.2k
                                  tls12_mac_params->ulMacLength);
3085
11.2k
            if (crv == CKR_OK) {
3086
11.2k
                context->hashUpdate(context->hashInfo, label, 15);
3087
11.2k
            }
3088
11.2k
            break;
3089
11.2k
        }
3090
0
        case CKM_NSS_TLS_PRF_GENERAL_SHA256:
3091
0
            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0);
3092
0
            break;
3093
3094
6.80k
        case CKM_NSS_HMAC_CONSTANT_TIME: {
3095
6.80k
            sftk_MACConstantTimeCtx *ctx =
3096
6.80k
                sftk_HMACConstantTime_New(pMechanism, key);
3097
6.80k
            CK_ULONG *intpointer;
3098
3099
6.80k
            if (ctx == NULL) {
3100
0
                crv = CKR_ARGUMENTS_BAD;
3101
0
                break;
3102
0
            }
3103
6.80k
            intpointer = PORT_New(CK_ULONG);
3104
6.80k
            if (intpointer == NULL) {
3105
0
                PORT_Free(ctx);
3106
0
                crv = CKR_HOST_MEMORY;
3107
0
                break;
3108
0
            }
3109
6.80k
            *intpointer = ctx->hash->length;
3110
3111
6.80k
            context->cipherInfo = intpointer;
3112
6.80k
            context->hashInfo = ctx;
3113
6.80k
            context->currentMech = pMechanism->mechanism;
3114
6.80k
            context->hashUpdate = sftk_HMACConstantTime_Update;
3115
6.80k
            context->hashdestroy = sftk_MACConstantTime_DestroyContext;
3116
6.80k
            context->end = sftk_MACConstantTime_EndHash;
3117
6.80k
            context->update = (SFTKCipher)sftk_SignCopy;
3118
6.80k
            context->destroy = sftk_Space;
3119
6.80k
            context->maxLen = 64;
3120
6.80k
            context->multi = PR_TRUE;
3121
6.80k
            break;
3122
6.80k
        }
3123
3124
0
        case CKM_NSS_SSL3_MAC_CONSTANT_TIME: {
3125
0
            sftk_MACConstantTimeCtx *ctx =
3126
0
                sftk_SSLv3MACConstantTime_New(pMechanism, key);
3127
0
            CK_ULONG *intpointer;
3128
3129
0
            if (ctx == NULL) {
3130
0
                crv = CKR_ARGUMENTS_BAD;
3131
0
                break;
3132
0
            }
3133
0
            intpointer = PORT_New(CK_ULONG);
3134
0
            if (intpointer == NULL) {
3135
0
                PORT_Free(ctx);
3136
0
                crv = CKR_HOST_MEMORY;
3137
0
                break;
3138
0
            }
3139
0
            *intpointer = ctx->hash->length;
3140
3141
0
            context->cipherInfo = intpointer;
3142
0
            context->hashInfo = ctx;
3143
0
            context->currentMech = pMechanism->mechanism;
3144
0
            context->hashUpdate = sftk_SSLv3MACConstantTime_Update;
3145
0
            context->hashdestroy = sftk_MACConstantTime_DestroyContext;
3146
0
            context->end = sftk_MACConstantTime_EndHash;
3147
0
            context->update = (SFTKCipher)sftk_SignCopy;
3148
0
            context->destroy = sftk_Space;
3149
0
            context->maxLen = 64;
3150
0
            context->multi = PR_TRUE;
3151
0
            break;
3152
0
        }
3153
3154
0
        default:
3155
0
            crv = CKR_MECHANISM_INVALID;
3156
0
            break;
3157
60.4k
    }
3158
3159
60.4k
    if (crv != CKR_OK) {
3160
0
        if (info)
3161
0
            PORT_Free(info);
3162
0
        if (pinfo)
3163
0
            PORT_ZFree(pinfo, pinfo->size);
3164
0
        sftk_FreeContext(context);
3165
0
        sftk_FreeSession(session);
3166
0
        return crv;
3167
0
    }
3168
60.4k
    sftk_SetContextByType(session, SFTK_SIGN, context);
3169
60.4k
    sftk_FreeSession(session);
3170
60.4k
    return CKR_OK;
3171
60.4k
}
3172
3173
/** MAC one block of data by block cipher
3174
 */
3175
static CK_RV
3176
sftk_MACBlock(SFTKSessionContext *ctx, void *blk)
3177
0
{
3178
0
    unsigned int outlen;
3179
0
    return (SECSuccess == (ctx->update)(ctx->cipherInfo, ctx->macBuf, &outlen,
3180
0
                                        SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize))
3181
0
               ? CKR_OK
3182
0
               : sftk_MapCryptError(PORT_GetError());
3183
0
}
3184
3185
/** MAC last (incomplete) block of data by block cipher
3186
 *
3187
 *  Call once, then terminate MACing operation.
3188
 */
3189
static CK_RV
3190
sftk_MACFinal(SFTKSessionContext *ctx)
3191
0
{
3192
0
    unsigned int padLen = ctx->padDataLength;
3193
    /* pad and proceed the residual */
3194
0
    if (ctx->isXCBC) {
3195
0
        CK_RV crv = sftk_xcbc_mac_pad(ctx->padBuf, padLen, ctx->blockSize,
3196
0
                                      ctx->k2, ctx->k3);
3197
0
        if (crv != CKR_OK)
3198
0
            return crv;
3199
0
        return sftk_MACBlock(ctx, ctx->padBuf);
3200
0
    }
3201
0
    if (padLen) {
3202
        /* shd clr ctx->padLen to make sftk_MACFinal idempotent */
3203
0
        PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen);
3204
0
        return sftk_MACBlock(ctx, ctx->padBuf);
3205
0
    } else
3206
0
        return CKR_OK;
3207
0
}
3208
3209
/** The common implementation for {Sign,Verify}Update. (S/V only vary in their
3210
 * setup and final operations).
3211
 *
3212
 * A call which results in an error terminates the operation [PKCS#11,v2.11]
3213
 */
3214
static CK_RV
3215
sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
3216
               CK_ULONG ulPartLen, SFTKContextType type)
3217
41.2k
{
3218
41.2k
    SFTKSession *session;
3219
41.2k
    SFTKSessionContext *context;
3220
41.2k
    CK_RV crv;
3221
3222
    /* make sure we're legal */
3223
41.2k
    crv = sftk_GetContext(hSession, &context, type, PR_TRUE, &session);
3224
41.2k
    if (crv != CKR_OK)
3225
0
        return crv;
3226
3227
41.2k
    if (context->hashInfo) {
3228
41.2k
#if (ULONG_MAX > UINT_MAX)
3229
41.2k
        while (ulPartLen > UINT_MAX) {
3230
0
            (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX);
3231
0
            pPart += UINT_MAX;
3232
0
            ulPartLen -= UINT_MAX;
3233
0
        }
3234
41.2k
#endif
3235
41.2k
        (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen);
3236
41.2k
    } else {
3237
        /* must be block cipher MACing */
3238
3239
0
        unsigned int blkSize = context->blockSize;
3240
0
        unsigned char *residual = /* free room in context->padBuf */
3241
0
            context->padBuf + context->padDataLength;
3242
0
        unsigned int minInput = /* min input for MACing at least one block */
3243
0
            blkSize - context->padDataLength;
3244
3245
        /* not enough data even for one block */
3246
0
        if (ulPartLen <= minInput) {
3247
0
            PORT_Memcpy(residual, pPart, ulPartLen);
3248
0
            context->padDataLength += ulPartLen;
3249
0
            goto cleanup;
3250
0
        }
3251
        /* MACing residual */
3252
0
        if (context->padDataLength) {
3253
0
            PORT_Memcpy(residual, pPart, minInput);
3254
0
            ulPartLen -= minInput;
3255
0
            pPart += minInput;
3256
0
            if (CKR_OK != (crv = sftk_MACBlock(context, context->padBuf)))
3257
0
                goto terminate;
3258
0
        }
3259
        /* MACing full blocks */
3260
0
        while (ulPartLen > blkSize) {
3261
0
            if (CKR_OK != (crv = sftk_MACBlock(context, pPart)))
3262
0
                goto terminate;
3263
0
            ulPartLen -= blkSize;
3264
0
            pPart += blkSize;
3265
0
        }
3266
        /* save the residual */
3267
0
        if ((context->padDataLength = ulPartLen))
3268
0
            PORT_Memcpy(context->padBuf, pPart, ulPartLen);
3269
0
    } /* blk cipher MACing */
3270
3271
41.2k
    goto cleanup;
3272
3273
41.2k
terminate:
3274
0
    sftk_TerminateOp(session, type, context);
3275
41.2k
cleanup:
3276
41.2k
    sftk_FreeSession(session);
3277
41.2k
    return crv;
3278
0
}
3279
3280
/* NSC_SignUpdate continues a multiple-part signature operation,
3281
 * where the signature is (will be) an appendix to the data,
3282
 * and plaintext cannot be recovered from the signature
3283
 *
3284
 * A call which results in an error terminates the operation [PKCS#11,v2.11]
3285
 */
3286
CK_RV
3287
NSC_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
3288
               CK_ULONG ulPartLen)
3289
41.2k
{
3290
41.2k
    CHECK_FORK();
3291
41.2k
    return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN);
3292
41.2k
}
3293
3294
struct SFTK_SESSION_FLAGS {
3295
    CK_FLAGS flag;
3296
    SFTKContextType type;
3297
};
3298
3299
const static struct SFTK_SESSION_FLAGS sftk_session_flags[] = {
3300
    { CKF_ENCRYPT, SFTK_ENCRYPT },
3301
    { CKF_DECRYPT, SFTK_DECRYPT },
3302
    { CKF_DIGEST, SFTK_HASH },
3303
    { CKF_SIGN, SFTK_SIGN },
3304
    { CKF_SIGN_RECOVER, SFTK_SIGN_RECOVER },
3305
    { CKF_VERIFY, SFTK_VERIFY },
3306
    { CKF_VERIFY_RECOVER, SFTK_VERIFY_RECOVER },
3307
    { CKF_MESSAGE_ENCRYPT, SFTK_MESSAGE_ENCRYPT },
3308
    { CKF_MESSAGE_DECRYPT, SFTK_MESSAGE_DECRYPT },
3309
    { CKF_MESSAGE_SIGN, SFTK_MESSAGE_SIGN },
3310
    { CKF_MESSAGE_VERIFY, SFTK_MESSAGE_VERIFY },
3311
};
3312
const static int sftk_flag_count = PR_ARRAY_SIZE(sftk_session_flags);
3313
3314
/*
3315
 * Cancel one or more operations running on the existing session.
3316
 */
3317
CK_RV
3318
NSC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags)
3319
0
{
3320
0
    SFTKSession *session;
3321
0
    SFTKSessionContext *context;
3322
0
    CK_RV gcrv = CKR_OK;
3323
0
    CK_RV crv;
3324
0
    int i;
3325
3326
0
    for (i = 0; i < sftk_flag_count; i++) {
3327
0
        if (flags & sftk_session_flags[i].flag) {
3328
0
            flags &= ~sftk_session_flags[i].flag;
3329
0
            crv = sftk_GetContext(hSession, &context, sftk_session_flags[i].type, PR_TRUE, &session);
3330
0
            if (crv != CKR_OK) {
3331
0
                gcrv = CKR_OPERATION_CANCEL_FAILED;
3332
0
                continue;
3333
0
            }
3334
0
            sftk_TerminateOp(session, sftk_session_flags[i].type, context);
3335
0
        }
3336
0
    }
3337
0
    if (flags & CKF_FIND_OBJECTS) {
3338
0
        flags &= ~CKF_FIND_OBJECTS;
3339
0
        crv = NSC_FindObjectsFinal(hSession);
3340
0
        if (crv != CKR_OK) {
3341
0
            gcrv = CKR_OPERATION_CANCEL_FAILED;
3342
0
        }
3343
0
    }
3344
0
    if (flags) {
3345
0
        gcrv = CKR_OPERATION_CANCEL_FAILED;
3346
0
    }
3347
0
    return gcrv;
3348
0
}
3349
3350
/* NSC_SignFinal finishes a multiple-part signature operation,
3351
 * returning the signature. */
3352
CK_RV
3353
NSC_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
3354
              CK_ULONG_PTR pulSignatureLen)
3355
50.1k
{
3356
50.1k
    SFTKSession *session;
3357
50.1k
    SFTKSessionContext *context;
3358
50.1k
    unsigned int outlen;
3359
50.1k
    unsigned int maxoutlen = *pulSignatureLen;
3360
50.1k
    CK_RV crv;
3361
3362
50.1k
    CHECK_FORK();
3363
3364
    /* make sure we're legal */
3365
50.1k
    crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_TRUE, &session);
3366
50.1k
    if (crv != CKR_OK)
3367
14.6k
        return crv;
3368
3369
35.4k
    if (context->hashInfo) {
3370
35.4k
        unsigned int digestLen;
3371
35.4k
        unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
3372
3373
35.4k
        if (!pSignature) {
3374
0
            outlen = context->maxLen;
3375
0
            goto finish;
3376
0
        }
3377
35.4k
        (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
3378
35.4k
        if (SECSuccess != (context->update)(context->cipherInfo, pSignature,
3379
35.4k
                                            &outlen, maxoutlen, tmpbuf, digestLen))
3380
0
            crv = sftk_MapCryptError(PORT_GetError());
3381
        /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate.
3382
         * Keeping "too small" CK_RV intact is a standard violation, but allows
3383
         * application read EXACT signature length */
3384
35.4k
        PORT_Memset(tmpbuf, 0, sizeof tmpbuf);
3385
35.4k
    } else {
3386
        /* must be block cipher MACing */
3387
0
        outlen = context->macSize;
3388
        /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/
3389
0
        if (!pSignature || maxoutlen < outlen) {
3390
0
            if (pSignature)
3391
0
                crv = CKR_BUFFER_TOO_SMALL;
3392
0
            goto finish;
3393
0
        }
3394
0
        if (CKR_OK == (crv = sftk_MACFinal(context)))
3395
0
            PORT_Memcpy(pSignature, context->macBuf, outlen);
3396
0
    }
3397
3398
35.4k
    sftk_TerminateOp(session, SFTK_SIGN, context);
3399
35.4k
finish:
3400
35.4k
    *pulSignatureLen = outlen;
3401
35.4k
    sftk_FreeSession(session);
3402
35.4k
    return crv;
3403
35.4k
}
3404
3405
/* NSC_Sign signs (encrypts with private key) data in a single part,
3406
 * where the signature is (will be) an appendix to the data,
3407
 * and plaintext cannot be recovered from the signature */
3408
CK_RV
3409
NSC_Sign(CK_SESSION_HANDLE hSession,
3410
         CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
3411
         CK_ULONG_PTR pulSignatureLen)
3412
21.0k
{
3413
21.0k
    SFTKSession *session;
3414
21.0k
    SFTKSessionContext *context;
3415
21.0k
    CK_RV crv;
3416
3417
21.0k
    CHECK_FORK();
3418
3419
    /* make sure we're legal */
3420
21.0k
    crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_FALSE, &session);
3421
21.0k
    if (crv != CKR_OK)
3422
0
        return crv;
3423
3424
21.0k
    if (!pSignature) {
3425
        /* see also how C_SignUpdate implements this */
3426
0
        *pulSignatureLen = (!context->multi || context->hashInfo)
3427
0
                               ? context->maxLen
3428
0
                               : context->macSize; /* must be block cipher MACing */
3429
0
        goto finish;
3430
0
    }
3431
3432
    /* multi part Signing are completely implemented by SignUpdate and
3433
     * sign Final */
3434
21.0k
    if (context->multi) {
3435
        /* SignFinal can't follow failed SignUpdate */
3436
6.80k
        if (CKR_OK == (crv = NSC_SignUpdate(hSession, pData, ulDataLen)))
3437
6.80k
            crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen);
3438
14.2k
    } else {
3439
        /* single-part PKC signature (e.g. CKM_ECDSA) */
3440
14.2k
        unsigned int outlen;
3441
14.2k
        unsigned int maxoutlen = *pulSignatureLen;
3442
14.2k
        if (SECSuccess != (*context->update)(context->cipherInfo, pSignature,
3443
14.2k
                                             &outlen, maxoutlen, pData, ulDataLen))
3444
0
            crv = sftk_MapCryptError(PORT_GetError());
3445
14.2k
        *pulSignatureLen = (CK_ULONG)outlen;
3446
        /*  "too small" here is certainly continuable */
3447
14.2k
        if (crv != CKR_BUFFER_TOO_SMALL)
3448
14.2k
            sftk_TerminateOp(session, SFTK_SIGN, context);
3449
14.2k
    } /* single-part */
3450
3451
21.0k
finish:
3452
21.0k
    sftk_FreeSession(session);
3453
21.0k
    return crv;
3454
21.0k
}
3455
3456
/*
3457
 ************** Crypto Functions:     Sign Recover  ************************
3458
 */
3459
/* NSC_SignRecoverInit initializes a signature operation,
3460
 * where the (digest) data can be recovered from the signature.
3461
 * E.g. encryption with the user's private key */
3462
CK_RV
3463
NSC_SignRecoverInit(CK_SESSION_HANDLE hSession,
3464
                    CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3465
0
{
3466
0
    CHECK_FORK();
3467
3468
0
    switch (pMechanism->mechanism) {
3469
0
        case CKM_RSA_PKCS:
3470
0
        case CKM_RSA_X_509:
3471
0
            return NSC_SignInit(hSession, pMechanism, hKey);
3472
0
        default:
3473
0
            break;
3474
0
    }
3475
0
    return CKR_MECHANISM_INVALID;
3476
0
}
3477
3478
/* NSC_SignRecover signs data in a single operation
3479
 * where the (digest) data can be recovered from the signature.
3480
 * E.g. encryption with the user's private key */
3481
CK_RV
3482
NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
3483
                CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
3484
0
{
3485
0
    CHECK_FORK();
3486
3487
0
    return NSC_Sign(hSession, pData, ulDataLen, pSignature, pulSignatureLen);
3488
0
}
3489
3490
/*
3491
 ************** Crypto Functions:     verify  ************************
3492
 */
3493
3494
/* Handle RSA Signature formatting */
3495
static SECStatus
3496
sftk_hashCheckSign(SFTKHashVerifyInfo *info, const unsigned char *sig,
3497
                   unsigned int sigLen, const unsigned char *digest,
3498
                   unsigned int digestLen)
3499
4
{
3500
4
    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
3501
4
    if (info->key->keyType != NSSLOWKEYRSAKey) {
3502
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
3503
0
        return SECFailure;
3504
0
    }
3505
3506
4
    return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, digest,
3507
4
                             digestLen);
3508
4
}
3509
3510
SECStatus
3511
RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key,
3512
                  const unsigned char *sig, unsigned int sigLen,
3513
                  const unsigned char *digestData, unsigned int digestLen)
3514
4
{
3515
4
    unsigned char *pkcs1DigestInfoData;
3516
4
    SECItem pkcs1DigestInfo;
3517
4
    SECItem digest;
3518
4
    unsigned int bufferSize;
3519
4
    SECStatus rv;
3520
3521
    /* pkcs1DigestInfo.data must be less than key->u.rsa.modulus.len */
3522
4
    bufferSize = key->u.rsa.modulus.len;
3523
4
    pkcs1DigestInfoData = PORT_ZAlloc(bufferSize);
3524
4
    if (!pkcs1DigestInfoData) {
3525
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
3526
0
        return SECFailure;
3527
0
    }
3528
3529
4
    pkcs1DigestInfo.data = pkcs1DigestInfoData;
3530
4
    pkcs1DigestInfo.len = bufferSize;
3531
3532
    /* decrypt the block */
3533
4
    rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data,
3534
4
                              &pkcs1DigestInfo.len, pkcs1DigestInfo.len,
3535
4
                              sig, sigLen);
3536
4
    if (rv != SECSuccess) {
3537
4
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
3538
4
    } else {
3539
0
        digest.data = (PRUint8 *)digestData;
3540
0
        digest.len = digestLen;
3541
0
        rv = _SGN_VerifyPKCS1DigestInfo(
3542
0
            digestOid, &digest, &pkcs1DigestInfo,
3543
0
            PR_FALSE /*XXX: unsafeAllowMissingParameters*/);
3544
0
    }
3545
3546
4
    PORT_ZFree(pkcs1DigestInfoData, bufferSize);
3547
4
    return rv;
3548
4
}
3549
3550
static SECStatus
3551
sftk_RSACheckSign(NSSLOWKEYPublicKey *key, const unsigned char *sig,
3552
                  unsigned int sigLen, const unsigned char *digest,
3553
                  unsigned int digestLen)
3554
673
{
3555
673
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
3556
673
    if (key->keyType != NSSLOWKEYRSAKey) {
3557
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
3558
0
        return SECFailure;
3559
0
    }
3560
3561
673
    return RSA_CheckSign(&key->u.rsa, sig, sigLen, digest, digestLen);
3562
673
}
3563
3564
static SECStatus
3565
sftk_RSACheckSignRaw(NSSLOWKEYPublicKey *key, const unsigned char *sig,
3566
                     unsigned int sigLen, const unsigned char *digest,
3567
                     unsigned int digestLen)
3568
0
{
3569
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
3570
0
    if (key->keyType != NSSLOWKEYRSAKey) {
3571
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
3572
0
        return SECFailure;
3573
0
    }
3574
3575
0
    return RSA_CheckSignRaw(&key->u.rsa, sig, sigLen, digest, digestLen);
3576
0
}
3577
3578
static SECStatus
3579
sftk_RSACheckSignPSS(SFTKPSSVerifyInfo *info, const unsigned char *sig,
3580
                     unsigned int sigLen, const unsigned char *digest,
3581
                     unsigned int digestLen)
3582
1.92k
{
3583
1.92k
    HASH_HashType hashAlg;
3584
1.92k
    HASH_HashType maskHashAlg;
3585
1.92k
    CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
3586
3587
1.92k
    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
3588
1.92k
    if (info->key->keyType != NSSLOWKEYRSAKey) {
3589
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
3590
0
        return SECFailure;
3591
0
    }
3592
3593
1.92k
    hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg);
3594
1.92k
    maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf);
3595
3596
1.92k
    return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg,
3597
1.92k
                            params->sLen, sig, sigLen, digest, digestLen);
3598
1.92k
}
3599
3600
/* NSC_VerifyInit initializes a verification operation,
3601
 * where the signature is an appendix to the data,
3602
 * and plaintext cannot be recovered from the signature (e.g. DSA) */
3603
CK_RV
3604
NSC_VerifyInit(CK_SESSION_HANDLE hSession,
3605
               CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3606
3.98k
{
3607
3.98k
    SFTKSession *session;
3608
3.98k
    SFTKObject *key;
3609
3.98k
    SFTKSessionContext *context;
3610
3.98k
    CK_KEY_TYPE key_type;
3611
3.98k
    CK_RV crv = CKR_OK;
3612
3.98k
    NSSLOWKEYPublicKey *pubKey;
3613
3.98k
    SFTKHashVerifyInfo *info = NULL;
3614
3.98k
    SFTKPSSVerifyInfo *pinfo = NULL;
3615
3616
3.98k
    CHECK_FORK();
3617
3618
    /* Block Cipher MACing Algorithms use a different Context init method..*/
3619
3.98k
    crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY);
3620
3.98k
    if (crv != CKR_FUNCTION_NOT_SUPPORTED)
3621
0
        return crv;
3622
3623
3.98k
    session = sftk_SessionFromHandle(hSession);
3624
3.98k
    if (session == NULL)
3625
0
        return CKR_SESSION_HANDLE_INVALID;
3626
3.98k
    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY, &key,
3627
3.98k
                           hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY);
3628
3.98k
    if (crv != CKR_OK) {
3629
0
        sftk_FreeSession(session);
3630
0
        return crv;
3631
0
    }
3632
3633
3.98k
    context->multi = PR_FALSE;
3634
3635
3.98k
#define INIT_RSA_VFY_MECH(mmm)                            \
3636
3.98k
    case CKM_##mmm##_RSA_PKCS:                            \
3637
4
        context->multi = PR_TRUE;                         \
3638
4
        crv = sftk_doSub##mmm(context);                   \
3639
4
        if (crv != CKR_OK)                                \
3640
4
            break;                                        \
3641
4
        context->verify = (SFTKVerify)sftk_hashCheckSign; \
3642
4
        info = PORT_New(SFTKHashVerifyInfo);              \
3643
4
        if (info == NULL) {                               \
3644
0
            crv = CKR_HOST_MEMORY;                        \
3645
0
            break;                                        \
3646
0
        }                                                 \
3647
4
        info->hashOid = SEC_OID_##mmm;                    \
3648
4
        goto finish_rsa;
3649
3650
3.98k
    switch (pMechanism->mechanism) {
3651
0
        INIT_RSA_VFY_MECH(MD5)
3652
0
        INIT_RSA_VFY_MECH(MD2)
3653
0
        INIT_RSA_VFY_MECH(SHA1)
3654
0
        INIT_RSA_VFY_MECH(SHA224)
3655
8
        INIT_RSA_VFY_MECH(SHA256)
3656
0
        INIT_RSA_VFY_MECH(SHA384)
3657
0
        INIT_RSA_VFY_MECH(SHA512)
3658
3659
673
        case CKM_RSA_PKCS:
3660
673
            context->verify = (SFTKVerify)sftk_RSACheckSign;
3661
673
            goto finish_rsa;
3662
0
        case CKM_RSA_X_509:
3663
0
            context->verify = (SFTKVerify)sftk_RSACheckSignRaw;
3664
677
        finish_rsa:
3665
677
            if (key_type != CKK_RSA) {
3666
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3667
0
                break;
3668
0
            }
3669
677
            context->rsa = PR_TRUE;
3670
677
            pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
3671
677
            if (pubKey == NULL) {
3672
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3673
0
                break;
3674
0
            }
3675
677
            if (info) {
3676
4
                info->key = pubKey;
3677
4
                context->cipherInfo = info;
3678
4
                context->destroy = sftk_Space;
3679
673
            } else {
3680
673
                context->cipherInfo = pubKey;
3681
673
                context->destroy = sftk_Null;
3682
673
            }
3683
677
            break;
3684
3685
0
            INIT_RSA_PSS_SIG_MECH(SHA1)
3686
0
            INIT_RSA_PSS_SIG_MECH(SHA224)
3687
0
            INIT_RSA_PSS_SIG_MECH(SHA256)
3688
0
            INIT_RSA_PSS_SIG_MECH(SHA384)
3689
0
            INIT_RSA_PSS_SIG_MECH(SHA512)
3690
1.92k
        case CKM_RSA_PKCS_PSS:
3691
1.92k
        finish_rsa_pss:
3692
1.92k
            if (key_type != CKK_RSA) {
3693
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3694
0
                break;
3695
0
            }
3696
1.92k
            context->rsa = PR_TRUE;
3697
1.92k
            if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
3698
1.92k
                !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) {
3699
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3700
0
                break;
3701
0
            }
3702
1.92k
            pinfo = PORT_New(SFTKPSSVerifyInfo);
3703
1.92k
            if (pinfo == NULL) {
3704
0
                crv = CKR_HOST_MEMORY;
3705
0
                break;
3706
0
            }
3707
1.92k
            pinfo->size = sizeof(SFTKPSSVerifyInfo);
3708
1.92k
            pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter;
3709
1.92k
            pinfo->key = sftk_GetPubKey(key, CKK_RSA, &crv);
3710
1.92k
            if (pinfo->key == NULL) {
3711
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3712
0
                break;
3713
0
            }
3714
1.92k
            context->cipherInfo = pinfo;
3715
1.92k
            context->destroy = (SFTKDestroy)sftk_ZSpace;
3716
1.92k
            context->verify = (SFTKVerify)sftk_RSACheckSignPSS;
3717
1.92k
            break;
3718
3719
0
            INIT_DSA_SIG_MECH(SHA1)
3720
0
            INIT_DSA_SIG_MECH(SHA224)
3721
0
            INIT_DSA_SIG_MECH(SHA256)
3722
0
            INIT_DSA_SIG_MECH(SHA384)
3723
0
            INIT_DSA_SIG_MECH(SHA512)
3724
10
        case CKM_DSA:
3725
10
        finish_dsa:
3726
10
            if (key_type != CKK_DSA) {
3727
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3728
0
                break;
3729
0
            }
3730
10
            pubKey = sftk_GetPubKey(key, CKK_DSA, &crv);
3731
10
            if (pubKey == NULL) {
3732
0
                break;
3733
0
            }
3734
10
            context->cipherInfo = pubKey;
3735
10
            context->verify = (SFTKVerify)nsc_DSA_Verify_Stub;
3736
10
            context->destroy = sftk_Null;
3737
10
            break;
3738
3739
0
            INIT_ECDSA_SIG_MECH(SHA1)
3740
0
            INIT_ECDSA_SIG_MECH(SHA224)
3741
1
            INIT_ECDSA_SIG_MECH(SHA256)
3742
1
            INIT_ECDSA_SIG_MECH(SHA384)
3743
2
            INIT_ECDSA_SIG_MECH(SHA512)
3744
1.37k
        case CKM_ECDSA:
3745
1.37k
        finish_ecdsa:
3746
1.37k
            if (key_type != CKK_EC) {
3747
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3748
0
                break;
3749
0
            }
3750
1.37k
            pubKey = sftk_GetPubKey(key, CKK_EC, &crv);
3751
1.37k
            if (pubKey == NULL) {
3752
0
                crv = CKR_HOST_MEMORY;
3753
0
                break;
3754
0
            }
3755
1.37k
            context->cipherInfo = pubKey;
3756
1.37k
            context->verify = (SFTKVerify)nsc_ECDSAVerifyStub;
3757
1.37k
            context->destroy = sftk_Null;
3758
1.37k
            break;
3759
3760
0
            INIT_HMAC_MECH(MD2)
3761
0
            INIT_HMAC_MECH(MD5)
3762
0
            INIT_HMAC_MECH(SHA1)
3763
0
            INIT_HMAC_MECH(SHA224)
3764
0
            INIT_HMAC_MECH(SHA256)
3765
0
            INIT_HMAC_MECH(SHA384)
3766
0
            INIT_HMAC_MECH(SHA512)
3767
0
            INIT_HMAC_MECH(SHA3_224)
3768
0
            INIT_HMAC_MECH(SHA3_256)
3769
0
            INIT_HMAC_MECH(SHA3_384)
3770
0
            INIT_HMAC_MECH(SHA3_512)
3771
3772
0
        case CKM_EDDSA:
3773
0
            if (key_type != CKK_EC_EDWARDS) {
3774
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3775
0
                break;
3776
0
            }
3777
0
            pubKey = sftk_GetPubKey(key, CKK_EC_EDWARDS, &crv);
3778
0
            if (pubKey == NULL) {
3779
0
                crv = CKR_HOST_MEMORY;
3780
0
                break;
3781
0
            }
3782
3783
0
            if (pMechanism->pParameter) {
3784
0
                crv = CKR_FUNCTION_NOT_SUPPORTED;
3785
0
                break;
3786
0
            }
3787
3788
0
            context->cipherInfo = pubKey;
3789
0
            context->verify = (SFTKVerify)nsc_EDDSAVerifyStub;
3790
0
            context->destroy = sftk_Null;
3791
0
            break;
3792
3793
0
        case CKM_SSL3_MD5_MAC:
3794
0
            PORT_Assert(pMechanism->pParameter);
3795
0
            if (!pMechanism->pParameter) {
3796
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3797
0
                break;
3798
0
            }
3799
0
            crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key,
3800
0
                                    *(CK_ULONG *)pMechanism->pParameter);
3801
0
            break;
3802
0
        case CKM_SSL3_SHA1_MAC:
3803
0
            PORT_Assert(pMechanism->pParameter);
3804
0
            if (!pMechanism->pParameter) {
3805
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3806
0
                break;
3807
0
            }
3808
0
            crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key,
3809
0
                                    *(CK_ULONG *)pMechanism->pParameter);
3810
0
            break;
3811
0
        case CKM_TLS_PRF_GENERAL:
3812
0
            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0);
3813
0
            break;
3814
0
        case CKM_NSS_TLS_PRF_GENERAL_SHA256:
3815
0
            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0);
3816
0
            break;
3817
3818
0
        default:
3819
0
            crv = CKR_MECHANISM_INVALID;
3820
0
            break;
3821
3.98k
    }
3822
3823
3.98k
    if (crv != CKR_OK) {
3824
0
        if (info)
3825
0
            PORT_Free(info);
3826
0
        if (pinfo)
3827
0
            PORT_ZFree(pinfo, pinfo->size);
3828
0
        sftk_FreeContext(context);
3829
0
        sftk_FreeSession(session);
3830
0
        return crv;
3831
0
    }
3832
3.98k
    sftk_SetContextByType(session, SFTK_VERIFY, context);
3833
3.98k
    sftk_FreeSession(session);
3834
3.98k
    return CKR_OK;
3835
3.98k
}
3836
3837
/* NSC_Verify verifies a signature in a single-part operation,
3838
 * where the signature is an appendix to the data,
3839
 * and plaintext cannot be recovered from the signature */
3840
CK_RV
3841
NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
3842
           CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
3843
3.98k
{
3844
3.98k
    SFTKSession *session;
3845
3.98k
    SFTKSessionContext *context;
3846
3.98k
    CK_RV crv;
3847
3848
3.98k
    CHECK_FORK();
3849
3850
    /* make sure we're legal */
3851
3.98k
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session);
3852
3.98k
    if (crv != CKR_OK)
3853
0
        return crv;
3854
3855
    /* multi part Verifying are completely implemented by VerifyUpdate and
3856
     * VerifyFinal */
3857
3.98k
    if (context->multi) {
3858
        /* VerifyFinal can't follow failed VerifyUpdate */
3859
7
        if (CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen)))
3860
7
            crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen);
3861
3.97k
    } else {
3862
3.97k
        if (SECSuccess != (*context->verify)(context->cipherInfo, pSignature,
3863
3.97k
                                             ulSignatureLen, pData, ulDataLen))
3864
3.97k
            crv = sftk_MapCryptError(PORT_GetError());
3865
3866
3.97k
        sftk_TerminateOp(session, SFTK_VERIFY, context);
3867
3.97k
    }
3868
3.98k
    sftk_FreeSession(session);
3869
3.98k
    return crv;
3870
3.98k
}
3871
3872
/* NSC_VerifyUpdate continues a multiple-part verification operation,
3873
 * where the signature is an appendix to the data,
3874
 * and plaintext cannot be recovered from the signature
3875
 *
3876
 * A call which results in an error terminates the operation [PKCS#11,v2.11]
3877
 */
3878
CK_RV
3879
NSC_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
3880
                 CK_ULONG ulPartLen)
3881
7
{
3882
7
    CHECK_FORK();
3883
7
    return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY);
3884
7
}
3885
3886
/* NSC_VerifyFinal finishes a multiple-part verification operation,
3887
 * checking the signature. */
3888
CK_RV
3889
NSC_VerifyFinal(CK_SESSION_HANDLE hSession,
3890
                CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
3891
7
{
3892
7
    SFTKSession *session;
3893
7
    SFTKSessionContext *context;
3894
7
    CK_RV crv;
3895
3896
7
    CHECK_FORK();
3897
3898
7
    if (!pSignature)
3899
0
        return CKR_ARGUMENTS_BAD;
3900
3901
    /* make sure we're legal */
3902
7
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session);
3903
7
    if (crv != CKR_OK)
3904
0
        return crv;
3905
3906
7
    if (context->hashInfo) {
3907
7
        unsigned int digestLen;
3908
7
        unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
3909
3910
7
        (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
3911
7
        if (SECSuccess != (context->verify)(context->cipherInfo, pSignature,
3912
7
                                            ulSignatureLen, tmpbuf, digestLen))
3913
7
            crv = sftk_MapCryptError(PORT_GetError());
3914
7
        PORT_Memset(tmpbuf, 0, sizeof tmpbuf);
3915
7
    } else if (ulSignatureLen != context->macSize) {
3916
        /* must be block cipher MACing */
3917
0
        crv = CKR_SIGNATURE_LEN_RANGE;
3918
0
    } else if (CKR_OK == (crv = sftk_MACFinal(context))) {
3919
0
        if (NSS_SecureMemcmp(pSignature, context->macBuf, ulSignatureLen))
3920
0
            crv = CKR_SIGNATURE_INVALID;
3921
0
    }
3922
3923
7
    sftk_TerminateOp(session, SFTK_VERIFY, context);
3924
7
    sftk_FreeSession(session);
3925
7
    return crv;
3926
7
}
3927
3928
/*
3929
 ************** Crypto Functions:     Verify  Recover ************************
3930
 */
3931
static SECStatus
3932
sftk_RSACheckSignRecover(NSSLOWKEYPublicKey *key, unsigned char *data,
3933
                         unsigned int *dataLen, unsigned int maxDataLen,
3934
                         const unsigned char *sig, unsigned int sigLen)
3935
804
{
3936
804
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
3937
804
    if (key->keyType != NSSLOWKEYRSAKey) {
3938
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
3939
0
        return SECFailure;
3940
0
    }
3941
3942
804
    return RSA_CheckSignRecover(&key->u.rsa, data, dataLen, maxDataLen,
3943
804
                                sig, sigLen);
3944
804
}
3945
3946
static SECStatus
3947
sftk_RSACheckSignRecoverRaw(NSSLOWKEYPublicKey *key, unsigned char *data,
3948
                            unsigned int *dataLen, unsigned int maxDataLen,
3949
                            const unsigned char *sig, unsigned int sigLen)
3950
0
{
3951
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
3952
0
    if (key->keyType != NSSLOWKEYRSAKey) {
3953
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
3954
0
        return SECFailure;
3955
0
    }
3956
3957
0
    return RSA_CheckSignRecoverRaw(&key->u.rsa, data, dataLen, maxDataLen,
3958
0
                                   sig, sigLen);
3959
0
}
3960
3961
/* NSC_VerifyRecoverInit initializes a signature verification operation,
3962
 * where the data is recovered from the signature.
3963
 * E.g. Decryption with the user's public key */
3964
CK_RV
3965
NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
3966
                      CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3967
804
{
3968
804
    SFTKSession *session;
3969
804
    SFTKObject *key;
3970
804
    SFTKSessionContext *context;
3971
804
    CK_KEY_TYPE key_type;
3972
804
    CK_RV crv = CKR_OK;
3973
804
    NSSLOWKEYPublicKey *pubKey;
3974
3975
804
    CHECK_FORK();
3976
3977
804
    session = sftk_SessionFromHandle(hSession);
3978
804
    if (session == NULL)
3979
0
        return CKR_SESSION_HANDLE_INVALID;
3980
804
    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY_RECOVER,
3981
804
                           &key, hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY_RECOVER);
3982
804
    if (crv != CKR_OK) {
3983
0
        sftk_FreeSession(session);
3984
0
        return crv;
3985
0
    }
3986
3987
804
    context->multi = PR_TRUE;
3988
3989
804
    switch (pMechanism->mechanism) {
3990
804
        case CKM_RSA_PKCS:
3991
804
        case CKM_RSA_X_509:
3992
804
            if (key_type != CKK_RSA) {
3993
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3994
0
                break;
3995
0
            }
3996
804
            context->multi = PR_FALSE;
3997
804
            context->rsa = PR_TRUE;
3998
804
            pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
3999
804
            if (pubKey == NULL) {
4000
0
                break;
4001
0
            }
4002
804
            context->cipherInfo = pubKey;
4003
804
            context->update = (SFTKCipher)(pMechanism->mechanism == CKM_RSA_X_509
4004
804
                                               ? sftk_RSACheckSignRecoverRaw
4005
804
                                               : sftk_RSACheckSignRecover);
4006
804
            context->destroy = sftk_Null;
4007
804
            break;
4008
0
        default:
4009
0
            crv = CKR_MECHANISM_INVALID;
4010
0
            break;
4011
804
    }
4012
4013
804
    if (crv != CKR_OK) {
4014
0
        PORT_Free(context);
4015
0
        sftk_FreeSession(session);
4016
0
        return crv;
4017
0
    }
4018
804
    sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context);
4019
804
    sftk_FreeSession(session);
4020
804
    return CKR_OK;
4021
804
}
4022
4023
/* NSC_VerifyRecover verifies a signature in a single-part operation,
4024
 * where the data is recovered from the signature.
4025
 * E.g. Decryption with the user's public key */
4026
CK_RV
4027
NSC_VerifyRecover(CK_SESSION_HANDLE hSession,
4028
                  CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen,
4029
                  CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
4030
804
{
4031
804
    SFTKSession *session;
4032
804
    SFTKSessionContext *context;
4033
804
    unsigned int outlen;
4034
804
    unsigned int maxoutlen = *pulDataLen;
4035
804
    CK_RV crv;
4036
804
    SECStatus rv;
4037
4038
804
    CHECK_FORK();
4039
4040
    /* make sure we're legal */
4041
804
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY_RECOVER,
4042
804
                          PR_FALSE, &session);
4043
804
    if (crv != CKR_OK)
4044
0
        return crv;
4045
804
    if (pData == NULL) {
4046
        /* to return the actual size, we need  to do the decrypt, just return
4047
         * the max size, which is the size of the input signature. */
4048
0
        *pulDataLen = ulSignatureLen;
4049
0
        rv = SECSuccess;
4050
0
        goto finish;
4051
0
    }
4052
4053
804
    rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
4054
804
                            pSignature, ulSignatureLen);
4055
804
    *pulDataLen = (CK_ULONG)outlen;
4056
4057
804
    sftk_TerminateOp(session, SFTK_VERIFY_RECOVER, context);
4058
804
finish:
4059
804
    sftk_FreeSession(session);
4060
804
    return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError());
4061
804
}
4062
4063
/*
4064
 **************************** Random Functions:  ************************
4065
 */
4066
4067
/* NSC_SeedRandom mixes additional seed material into the token's random number
4068
 * generator. */
4069
CK_RV
4070
NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
4071
               CK_ULONG ulSeedLen)
4072
0
{
4073
0
    SECStatus rv;
4074
4075
0
    CHECK_FORK();
4076
4077
0
    rv = RNG_RandomUpdate(pSeed, ulSeedLen);
4078
0
    return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
4079
0
}
4080
4081
/* NSC_GenerateRandom generates random data. */
4082
CK_RV
4083
NSC_GenerateRandom(CK_SESSION_HANDLE hSession,
4084
                   CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
4085
81.2k
{
4086
81.2k
    SECStatus rv;
4087
4088
81.2k
    CHECK_FORK();
4089
4090
81.2k
    rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen);
4091
    /*
4092
     * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't
4093
     * seeded with enough entropy.
4094
     */
4095
81.2k
    return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
4096
81.2k
}
4097
4098
/*
4099
 **************************** Key Functions:  ************************
4100
 */
4101
4102
/*
4103
 * generate a password based encryption key. This code uses
4104
 * PKCS5 to do the work.
4105
 */
4106
static CK_RV
4107
nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism,
4108
                void *buf, CK_ULONG *key_length, PRBool faulty3DES)
4109
0
{
4110
0
    SECItem *pbe_key = NULL, iv, pwitem;
4111
0
    CK_PBE_PARAMS *pbe_params = NULL;
4112
0
    CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL;
4113
4114
0
    *key_length = 0;
4115
0
    iv.data = NULL;
4116
0
    iv.len = 0;
4117
4118
0
    if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
4119
0
        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PKCS5_PBKD2_PARAMS))) {
4120
0
            return CKR_MECHANISM_PARAM_INVALID;
4121
0
        }
4122
0
        pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
4123
0
        pwitem.data = (unsigned char *)pbkd2_params->pPassword;
4124
        /* was this a typo in the PKCS #11 spec? */
4125
0
        pwitem.len = *pbkd2_params->ulPasswordLen;
4126
0
    } else {
4127
0
        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
4128
0
            return CKR_MECHANISM_PARAM_INVALID;
4129
0
        }
4130
0
        pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
4131
0
        pwitem.data = (unsigned char *)pbe_params->pPassword;
4132
0
        pwitem.len = pbe_params->ulPasswordLen;
4133
0
    }
4134
0
    pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES);
4135
0
    if (pbe_key == NULL) {
4136
0
        return CKR_HOST_MEMORY;
4137
0
    }
4138
4139
0
    PORT_Memcpy(buf, pbe_key->data, pbe_key->len);
4140
0
    *key_length = pbe_key->len;
4141
0
    SECITEM_ZfreeItem(pbe_key, PR_TRUE);
4142
0
    pbe_key = NULL;
4143
4144
0
    if (iv.data) {
4145
0
        if (pbe_params && pbe_params->pInitVector != NULL) {
4146
0
            PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len);
4147
0
        }
4148
0
        PORT_Free(iv.data);
4149
0
    }
4150
4151
0
    return CKR_OK;
4152
0
}
4153
4154
/*
4155
 * this is coded for "full" support. These selections will be limitted to
4156
 * the official subset by freebl.
4157
 */
4158
static unsigned int
4159
sftk_GetSubPrimeFromPrime(unsigned int primeBits)
4160
0
{
4161
0
    if (primeBits <= 1024) {
4162
0
        return 160;
4163
0
    } else if (primeBits <= 2048) {
4164
0
        return 224;
4165
0
    } else if (primeBits <= 3072) {
4166
0
        return 256;
4167
0
    } else if (primeBits <= 7680) {
4168
0
        return 384;
4169
0
    } else {
4170
0
        return 512;
4171
0
    }
4172
0
}
4173
4174
static CK_RV
4175
nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key)
4176
0
{
4177
0
    SFTKAttribute *attribute;
4178
0
    CK_ULONG counter;
4179
0
    unsigned int seedBits = 0;
4180
0
    unsigned int subprimeBits = 0;
4181
0
    unsigned int primeBits;
4182
0
    unsigned int j = 8; /* default to 1024 bits */
4183
0
    CK_RV crv = CKR_OK;
4184
0
    PQGParams *params = NULL;
4185
0
    PQGVerify *vfy = NULL;
4186
0
    SECStatus rv;
4187
4188
0
    attribute = sftk_FindAttribute(key, CKA_PRIME_BITS);
4189
0
    if (attribute == NULL) {
4190
0
        attribute = sftk_FindAttribute(key, CKA_PRIME);
4191
0
        if (attribute == NULL) {
4192
0
            return CKR_TEMPLATE_INCOMPLETE;
4193
0
        } else {
4194
0
            primeBits = attribute->attrib.ulValueLen;
4195
0
            sftk_FreeAttribute(attribute);
4196
0
        }
4197
0
    } else {
4198
0
        primeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
4199
0
        sftk_FreeAttribute(attribute);
4200
0
    }
4201
0
    if (primeBits < 1024) {
4202
0
        j = PQG_PBITS_TO_INDEX(primeBits);
4203
0
        if (j == (unsigned int)-1) {
4204
0
            return CKR_ATTRIBUTE_VALUE_INVALID;
4205
0
        }
4206
0
    }
4207
4208
0
    attribute = sftk_FindAttribute(key, CKA_NSS_PQG_SEED_BITS);
4209
0
    if (attribute != NULL) {
4210
0
        seedBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
4211
0
        sftk_FreeAttribute(attribute);
4212
0
    }
4213
4214
0
    attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS);
4215
0
    if (attribute != NULL) {
4216
0
        subprimeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
4217
0
        sftk_FreeAttribute(attribute);
4218
0
    }
4219
4220
    /* if P and Q are supplied, we want to generate a new G */
4221
0
    attribute = sftk_FindAttribute(key, CKA_PRIME);
4222
0
    if (attribute != NULL) {
4223
0
        PLArenaPool *arena;
4224
4225
0
        sftk_FreeAttribute(attribute);
4226
0
        arena = PORT_NewArena(1024);
4227
0
        if (arena == NULL) {
4228
0
            crv = CKR_HOST_MEMORY;
4229
0
            goto loser;
4230
0
        }
4231
0
        params = PORT_ArenaAlloc(arena, sizeof(*params));
4232
0
        if (params == NULL) {
4233
0
            crv = CKR_HOST_MEMORY;
4234
0
            goto loser;
4235
0
        }
4236
0
        params->arena = arena;
4237
0
        crv = sftk_Attribute2SSecItem(arena, &params->prime, key, CKA_PRIME);
4238
0
        if (crv != CKR_OK) {
4239
0
            goto loser;
4240
0
        }
4241
0
        crv = sftk_Attribute2SSecItem(arena, &params->subPrime,
4242
0
                                      key, CKA_SUBPRIME);
4243
0
        if (crv != CKR_OK) {
4244
0
            goto loser;
4245
0
        }
4246
4247
0
        arena = PORT_NewArena(1024);
4248
0
        if (arena == NULL) {
4249
0
            crv = CKR_HOST_MEMORY;
4250
0
            goto loser;
4251
0
        }
4252
0
        vfy = PORT_ArenaAlloc(arena, sizeof(*vfy));
4253
0
        if (vfy == NULL) {
4254
0
            crv = CKR_HOST_MEMORY;
4255
0
            goto loser;
4256
0
        }
4257
0
        vfy->arena = arena;
4258
0
        crv = sftk_Attribute2SSecItem(arena, &vfy->seed, key, CKA_NSS_PQG_SEED);
4259
0
        if (crv != CKR_OK) {
4260
0
            goto loser;
4261
0
        }
4262
0
        crv = sftk_Attribute2SSecItem(arena, &vfy->h, key, CKA_NSS_PQG_H);
4263
0
        if (crv != CKR_OK) {
4264
0
            goto loser;
4265
0
        }
4266
0
        sftk_DeleteAttributeType(key, CKA_PRIME);
4267
0
        sftk_DeleteAttributeType(key, CKA_SUBPRIME);
4268
0
        sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED);
4269
0
        sftk_DeleteAttributeType(key, CKA_NSS_PQG_H);
4270
0
    }
4271
4272
0
    sftk_DeleteAttributeType(key, CKA_PRIME_BITS);
4273
0
    sftk_DeleteAttributeType(key, CKA_SUBPRIME_BITS);
4274
0
    sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED_BITS);
4275
4276
    /* use the old PQG interface if we have old input data */
4277
0
    if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) {
4278
0
        if (seedBits == 0) {
4279
0
            rv = PQG_ParamGen(j, &params, &vfy);
4280
0
        } else {
4281
0
            rv = PQG_ParamGenSeedLen(j, seedBits / 8, &params, &vfy);
4282
0
        }
4283
0
    } else {
4284
0
        if (subprimeBits == 0) {
4285
0
            subprimeBits = sftk_GetSubPrimeFromPrime(primeBits);
4286
0
        }
4287
0
        if (seedBits == 0) {
4288
0
            seedBits = primeBits;
4289
0
        }
4290
0
        rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits / 8, &params, &vfy);
4291
0
    }
4292
4293
0
    if (rv != SECSuccess) {
4294
0
        if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
4295
0
            sftk_fatalError = PR_TRUE;
4296
0
        }
4297
0
        return sftk_MapCryptError(PORT_GetError());
4298
0
    }
4299
0
    crv = sftk_AddAttributeType(key, CKA_PRIME,
4300
0
                                params->prime.data, params->prime.len);
4301
0
    if (crv != CKR_OK)
4302
0
        goto loser;
4303
0
    crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
4304
0
                                params->subPrime.data, params->subPrime.len);
4305
0
    if (crv != CKR_OK)
4306
0
        goto loser;
4307
0
    crv = sftk_AddAttributeType(key, CKA_BASE,
4308
0
                                params->base.data, params->base.len);
4309
0
    if (crv != CKR_OK)
4310
0
        goto loser;
4311
0
    counter = vfy->counter;
4312
0
    crv = sftk_AddAttributeType(key, CKA_NSS_PQG_COUNTER,
4313
0
                                &counter, sizeof(counter));
4314
0
    crv = sftk_AddAttributeType(key, CKA_NSS_PQG_SEED,
4315
0
                                vfy->seed.data, vfy->seed.len);
4316
0
    if (crv != CKR_OK)
4317
0
        goto loser;
4318
0
    crv = sftk_AddAttributeType(key, CKA_NSS_PQG_H,
4319
0
                                vfy->h.data, vfy->h.len);
4320
0
    if (crv != CKR_OK)
4321
0
        goto loser;
4322
4323
0
loser:
4324
0
    if (params) {
4325
0
        PQG_DestroyParams(params);
4326
0
    }
4327
4328
0
    if (vfy) {
4329
0
        PQG_DestroyVerify(vfy);
4330
0
    }
4331
0
    return crv;
4332
0
}
4333
4334
static CK_RV
4335
nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type,
4336
                    CK_ULONG *key_length)
4337
289
{
4338
289
    CK_RV crv = CKR_OK;
4339
4340
289
    switch (mechanism) {
4341
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
4342
0
        case CKM_RC2_KEY_GEN:
4343
0
            *key_type = CKK_RC2;
4344
0
            if (*key_length == 0)
4345
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4346
0
            break;
4347
0
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
4348
#if NSS_SOFTOKEN_DOES_RC5
4349
        case CKM_RC5_KEY_GEN:
4350
            *key_type = CKK_RC5;
4351
            if (*key_length == 0)
4352
                crv = CKR_TEMPLATE_INCOMPLETE;
4353
            break;
4354
#endif
4355
0
        case CKM_RC4_KEY_GEN:
4356
0
            *key_type = CKK_RC4;
4357
0
            if (*key_length == 0)
4358
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4359
0
            break;
4360
2
        case CKM_GENERIC_SECRET_KEY_GEN:
4361
2
            *key_type = CKK_GENERIC_SECRET;
4362
2
            if (*key_length == 0)
4363
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4364
2
            break;
4365
0
        case CKM_CDMF_KEY_GEN:
4366
0
            *key_type = CKK_CDMF;
4367
0
            *key_length = 8;
4368
0
            break;
4369
0
        case CKM_DES_KEY_GEN:
4370
0
            *key_type = CKK_DES;
4371
0
            *key_length = 8;
4372
0
            break;
4373
0
        case CKM_DES2_KEY_GEN:
4374
0
            *key_type = CKK_DES2;
4375
0
            *key_length = 16;
4376
0
            break;
4377
285
        case CKM_DES3_KEY_GEN:
4378
285
            *key_type = CKK_DES3;
4379
285
            *key_length = 24;
4380
285
            break;
4381
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
4382
0
        case CKM_SEED_KEY_GEN:
4383
0
            *key_type = CKK_SEED;
4384
0
            *key_length = 16;
4385
0
            break;
4386
0
#endif /* NSS_DISABLE_DEPRECATED_SEED */
4387
0
        case CKM_CAMELLIA_KEY_GEN:
4388
0
            *key_type = CKK_CAMELLIA;
4389
0
            if (*key_length == 0)
4390
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4391
0
            break;
4392
2
        case CKM_AES_KEY_GEN:
4393
2
            *key_type = CKK_AES;
4394
2
            if (*key_length == 0)
4395
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4396
2
            break;
4397
0
        case CKM_NSS_CHACHA20_KEY_GEN:
4398
0
            *key_type = CKK_NSS_CHACHA20;
4399
0
            *key_length = 32;
4400
0
            break;
4401
0
        case CKM_CHACHA20_KEY_GEN:
4402
0
            *key_type = CKK_CHACHA20;
4403
0
            *key_length = 32;
4404
0
            break;
4405
0
        case CKM_HKDF_KEY_GEN:
4406
0
            *key_type = CKK_HKDF;
4407
0
            if (*key_length == 0)
4408
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4409
0
            break;
4410
0
        default:
4411
0
            PORT_Assert(0);
4412
0
            crv = CKR_MECHANISM_INVALID;
4413
0
            break;
4414
289
    }
4415
4416
289
    return crv;
4417
289
}
4418
4419
CK_RV
4420
nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe)
4421
0
{
4422
0
    SECItem salt;
4423
0
    CK_PBE_PARAMS *pbe_params = NULL;
4424
0
    NSSPKCS5PBEParameter *params;
4425
0
    PLArenaPool *arena = NULL;
4426
0
    SECStatus rv;
4427
4428
0
    *pbe = NULL;
4429
4430
0
    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
4431
0
    if (arena == NULL) {
4432
0
        return CKR_HOST_MEMORY;
4433
0
    }
4434
4435
0
    params = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena,
4436
0
                                                      sizeof(NSSPKCS5PBEParameter));
4437
0
    if (params == NULL) {
4438
0
        PORT_FreeArena(arena, PR_TRUE);
4439
0
        return CKR_HOST_MEMORY;
4440
0
    }
4441
0
    if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
4442
0
        PORT_FreeArena(arena, PR_TRUE);
4443
0
        return CKR_MECHANISM_PARAM_INVALID;
4444
0
    }
4445
4446
0
    params->poolp = arena;
4447
0
    params->ivLen = 0;
4448
0
    params->pbeType = NSSPKCS5_PKCS12_V2;
4449
0
    params->hashType = HASH_AlgSHA1;
4450
0
    params->encAlg = SEC_OID_SHA1; /* any invalid value */
4451
0
    params->is2KeyDES = PR_FALSE;
4452
0
    params->keyID = pbeBitGenIntegrityKey;
4453
0
    pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
4454
0
    params->iter = pbe_params->ulIteration;
4455
4456
0
    salt.data = (unsigned char *)pbe_params->pSalt;
4457
0
    salt.len = (unsigned int)pbe_params->ulSaltLen;
4458
0
    salt.type = siBuffer;
4459
0
    rv = SECITEM_CopyItem(arena, &params->salt, &salt);
4460
0
    if (rv != SECSuccess) {
4461
0
        PORT_FreeArena(arena, PR_TRUE);
4462
0
        return CKR_HOST_MEMORY;
4463
0
    }
4464
0
    switch (pMechanism->mechanism) {
4465
0
        case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN:
4466
0
        case CKM_PBA_SHA1_WITH_SHA1_HMAC:
4467
0
            params->hashType = HASH_AlgSHA1;
4468
0
            params->keyLen = 20;
4469
0
            break;
4470
0
        case CKM_NSS_PBE_MD5_HMAC_KEY_GEN:
4471
0
            params->hashType = HASH_AlgMD5;
4472
0
            params->keyLen = 16;
4473
0
            break;
4474
0
        case CKM_NSS_PBE_MD2_HMAC_KEY_GEN:
4475
0
            params->hashType = HASH_AlgMD2;
4476
0
            params->keyLen = 16;
4477
0
            break;
4478
0
        case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
4479
0
            params->hashType = HASH_AlgSHA224;
4480
0
            params->keyLen = 28;
4481
0
            break;
4482
0
        case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
4483
0
            params->hashType = HASH_AlgSHA256;
4484
0
            params->keyLen = 32;
4485
0
            break;
4486
0
        case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
4487
0
            params->hashType = HASH_AlgSHA384;
4488
0
            params->keyLen = 48;
4489
0
            break;
4490
0
        case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
4491
0
            params->hashType = HASH_AlgSHA512;
4492
0
            params->keyLen = 64;
4493
0
            break;
4494
0
        default:
4495
0
            PORT_FreeArena(arena, PR_TRUE);
4496
0
            return CKR_MECHANISM_INVALID;
4497
0
    }
4498
0
    *pbe = params;
4499
0
    return CKR_OK;
4500
0
}
4501
4502
/* maybe this should be table driven? */
4503
static CK_RV
4504
nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
4505
                   CK_KEY_TYPE *key_type, CK_ULONG *key_length)
4506
0
{
4507
0
    CK_RV crv = CKR_OK;
4508
0
    SECOidData *oid;
4509
0
    CK_PBE_PARAMS *pbe_params = NULL;
4510
0
    NSSPKCS5PBEParameter *params = NULL;
4511
0
    HASH_HashType hashType = HASH_AlgSHA1;
4512
0
    CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL;
4513
0
    SECItem salt;
4514
0
    CK_ULONG iteration = 0;
4515
4516
0
    *pbe = NULL;
4517
4518
0
    oid = SECOID_FindOIDByMechanism(pMechanism->mechanism);
4519
0
    if (oid == NULL) {
4520
0
        return CKR_MECHANISM_INVALID;
4521
0
    }
4522
4523
0
    if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
4524
0
        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PKCS5_PBKD2_PARAMS))) {
4525
0
            return CKR_MECHANISM_PARAM_INVALID;
4526
0
        }
4527
0
        pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
4528
0
        switch (pbkd2_params->prf) {
4529
0
            case CKP_PKCS5_PBKD2_HMAC_SHA1:
4530
0
                hashType = HASH_AlgSHA1;
4531
0
                break;
4532
0
            case CKP_PKCS5_PBKD2_HMAC_SHA224:
4533
0
                hashType = HASH_AlgSHA224;
4534
0
                break;
4535
0
            case CKP_PKCS5_PBKD2_HMAC_SHA256:
4536
0
                hashType = HASH_AlgSHA256;
4537
0
                break;
4538
0
            case CKP_PKCS5_PBKD2_HMAC_SHA384:
4539
0
                hashType = HASH_AlgSHA384;
4540
0
                break;
4541
0
            case CKP_PKCS5_PBKD2_HMAC_SHA512:
4542
0
                hashType = HASH_AlgSHA512;
4543
0
                break;
4544
0
            default:
4545
0
                return CKR_MECHANISM_PARAM_INVALID;
4546
0
        }
4547
0
        if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) {
4548
0
            return CKR_MECHANISM_PARAM_INVALID;
4549
0
        }
4550
0
        salt.data = (unsigned char *)pbkd2_params->pSaltSourceData;
4551
0
        salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen;
4552
0
        iteration = pbkd2_params->iterations;
4553
0
    } else {
4554
0
        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
4555
0
            return CKR_MECHANISM_PARAM_INVALID;
4556
0
        }
4557
0
        pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
4558
0
        salt.data = (unsigned char *)pbe_params->pSalt;
4559
0
        salt.len = (unsigned int)pbe_params->ulSaltLen;
4560
0
        iteration = pbe_params->ulIteration;
4561
0
    }
4562
0
    params = nsspkcs5_NewParam(oid->offset, hashType, &salt, iteration);
4563
0
    if (params == NULL) {
4564
0
        return CKR_MECHANISM_INVALID;
4565
0
    }
4566
4567
0
    switch (params->encAlg) {
4568
0
        case SEC_OID_DES_CBC:
4569
0
            *key_type = CKK_DES;
4570
0
            *key_length = params->keyLen;
4571
0
            break;
4572
0
        case SEC_OID_DES_EDE3_CBC:
4573
0
            *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3;
4574
0
            *key_length = params->keyLen;
4575
0
            break;
4576
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
4577
0
        case SEC_OID_RC2_CBC:
4578
0
            *key_type = CKK_RC2;
4579
0
            *key_length = params->keyLen;
4580
0
            break;
4581
0
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
4582
0
        case SEC_OID_RC4:
4583
0
            *key_type = CKK_RC4;
4584
0
            *key_length = params->keyLen;
4585
0
            break;
4586
0
        case SEC_OID_PKCS5_PBKDF2:
4587
            /* key type must already be set */
4588
0
            if (*key_type == CKK_INVALID_KEY_TYPE) {
4589
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4590
0
                break;
4591
0
            }
4592
            /* PBKDF2 needs to calculate the key length from the other parameters
4593
             */
4594
0
            if (*key_length == 0) {
4595
0
                *key_length = sftk_MapKeySize(*key_type);
4596
0
            }
4597
0
            if (*key_length == 0) {
4598
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4599
0
                break;
4600
0
            }
4601
0
            params->keyLen = *key_length;
4602
0
            break;
4603
0
        default:
4604
0
            crv = CKR_MECHANISM_INVALID;
4605
0
            break;
4606
0
    }
4607
0
    if (crv == CKR_OK) {
4608
0
        *pbe = params;
4609
0
    } else {
4610
0
        nsspkcs5_DestroyPBEParameter(params);
4611
0
    }
4612
0
    return crv;
4613
0
}
4614
4615
/* NSC_GenerateKey generates a secret key, creating a new key object. */
4616
CK_RV
4617
NSC_GenerateKey(CK_SESSION_HANDLE hSession,
4618
                CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
4619
                CK_OBJECT_HANDLE_PTR phKey)
4620
5.52k
{
4621
5.52k
    SFTKObject *key;
4622
5.52k
    SFTKSession *session;
4623
5.52k
    PRBool checkWeak = PR_FALSE;
4624
5.52k
    CK_ULONG key_length = 0;
4625
5.52k
    CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE;
4626
5.52k
    CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
4627
5.52k
    CK_RV crv = CKR_OK;
4628
5.52k
    CK_BBOOL cktrue = CK_TRUE;
4629
5.52k
    NSSPKCS5PBEParameter *pbe_param = NULL;
4630
5.52k
    int i;
4631
5.52k
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
4632
5.52k
    unsigned char buf[MAX_KEY_LEN];
4633
5.52k
    enum { nsc_pbe,
4634
5.52k
           nsc_ssl,
4635
5.52k
           nsc_bulk,
4636
5.52k
           nsc_param,
4637
5.52k
           nsc_jpake } key_gen_type;
4638
5.52k
    SSL3RSAPreMasterSecret *rsa_pms;
4639
5.52k
    CK_VERSION *version;
4640
    /* in very old versions of NSS, there were implementation errors with key
4641
     * generation methods.  We want to beable to read these, but not
4642
     * produce them any more.  The affected algorithm was 3DES.
4643
     */
4644
5.52k
    PRBool faultyPBE3DES = PR_FALSE;
4645
5.52k
    HASH_HashType hashType = HASH_AlgNULL;
4646
4647
5.52k
    CHECK_FORK();
4648
4649
5.52k
    if (!slot) {
4650
0
        return CKR_SESSION_HANDLE_INVALID;
4651
0
    }
4652
    /*
4653
     * now lets create an object to hang the attributes off of
4654
     */
4655
5.52k
    key = sftk_NewObject(slot); /* fill in the handle later */
4656
5.52k
    if (key == NULL) {
4657
0
        return CKR_HOST_MEMORY;
4658
0
    }
4659
4660
    /*
4661
     * load the template values into the object
4662
     */
4663
16.5k
    for (i = 0; i < (int)ulCount; i++) {
4664
11.0k
        if (pTemplate[i].type == CKA_VALUE_LEN) {
4665
4
            key_length = *(CK_ULONG *)pTemplate[i].pValue;
4666
4
            continue;
4667
4
        }
4668
        /* some algorithms need keytype specified */
4669
11.0k
        if (pTemplate[i].type == CKA_KEY_TYPE) {
4670
0
            key_type = *(CK_ULONG *)pTemplate[i].pValue;
4671
0
            continue;
4672
0
        }
4673
4674
11.0k
        crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
4675
11.0k
        if (crv != CKR_OK) {
4676
0
            break;
4677
0
        }
4678
11.0k
    }
4679
5.52k
    if (crv != CKR_OK) {
4680
0
        goto loser;
4681
0
    }
4682
4683
    /* make sure we don't have any class, key_type, or value fields */
4684
5.52k
    sftk_DeleteAttributeType(key, CKA_CLASS);
4685
5.52k
    sftk_DeleteAttributeType(key, CKA_KEY_TYPE);
4686
5.52k
    sftk_DeleteAttributeType(key, CKA_VALUE);
4687
4688
    /* Now Set up the parameters to generate the key (based on mechanism) */
4689
5.52k
    key_gen_type = nsc_bulk; /* bulk key by default */
4690
5.52k
    switch (pMechanism->mechanism) {
4691
0
        case CKM_CDMF_KEY_GEN:
4692
0
        case CKM_DES_KEY_GEN:
4693
0
        case CKM_DES2_KEY_GEN:
4694
285
        case CKM_DES3_KEY_GEN:
4695
285
            checkWeak = PR_TRUE;
4696
/* fall through */
4697
285
#ifndef NSS_DISABLE_DEPRECATED_RC2
4698
285
        case CKM_RC2_KEY_GEN:
4699
285
#endif
4700
285
        case CKM_RC4_KEY_GEN:
4701
287
        case CKM_GENERIC_SECRET_KEY_GEN:
4702
287
#ifndef NSS_DISABLE_DEPRECATED_SEED
4703
287
        case CKM_SEED_KEY_GEN:
4704
287
#endif
4705
287
        case CKM_CAMELLIA_KEY_GEN:
4706
289
        case CKM_AES_KEY_GEN:
4707
289
        case CKM_NSS_CHACHA20_KEY_GEN:
4708
289
        case CKM_CHACHA20_KEY_GEN:
4709
#if NSS_SOFTOKEN_DOES_RC5
4710
        case CKM_RC5_KEY_GEN:
4711
#endif
4712
289
            crv = nsc_SetupBulkKeyGen(pMechanism->mechanism, &key_type, &key_length);
4713
289
            break;
4714
5.23k
        case CKM_SSL3_PRE_MASTER_KEY_GEN:
4715
5.23k
            key_type = CKK_GENERIC_SECRET;
4716
5.23k
            key_length = 48;
4717
5.23k
            key_gen_type = nsc_ssl;
4718
5.23k
            break;
4719
0
        case CKM_PBA_SHA1_WITH_SHA1_HMAC:
4720
0
        case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN:
4721
0
        case CKM_NSS_PBE_MD5_HMAC_KEY_GEN:
4722
0
        case CKM_NSS_PBE_MD2_HMAC_KEY_GEN:
4723
0
        case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
4724
0
        case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
4725
0
        case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
4726
0
        case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
4727
0
            key_gen_type = nsc_pbe;
4728
0
            key_type = CKK_GENERIC_SECRET;
4729
0
            crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param);
4730
0
            break;
4731
0
        case CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC:
4732
0
            faultyPBE3DES = PR_TRUE;
4733
        /* fall through */
4734
0
        case CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC:
4735
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
4736
0
        case CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC:
4737
0
        case CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC:
4738
0
        case CKM_PBE_SHA1_RC2_128_CBC:
4739
0
        case CKM_PBE_SHA1_RC2_40_CBC:
4740
0
#endif
4741
0
        case CKM_NSS_PBE_SHA1_DES_CBC:
4742
0
        case CKM_NSS_PBE_SHA1_40_BIT_RC4:
4743
0
        case CKM_NSS_PBE_SHA1_128_BIT_RC4:
4744
0
        case CKM_PBE_SHA1_DES3_EDE_CBC:
4745
0
        case CKM_PBE_SHA1_DES2_EDE_CBC:
4746
0
        case CKM_PBE_SHA1_RC4_128:
4747
0
        case CKM_PBE_SHA1_RC4_40:
4748
0
        case CKM_PBE_MD5_DES_CBC:
4749
0
        case CKM_PBE_MD2_DES_CBC:
4750
0
        case CKM_PKCS5_PBKD2:
4751
0
            key_gen_type = nsc_pbe;
4752
0
            crv = nsc_SetupPBEKeyGen(pMechanism, &pbe_param, &key_type, &key_length);
4753
0
            break;
4754
0
        case CKM_DSA_PARAMETER_GEN:
4755
0
            key_gen_type = nsc_param;
4756
0
            key_type = CKK_DSA;
4757
0
            objclass = CKO_DOMAIN_PARAMETERS;
4758
0
            crv = CKR_OK;
4759
0
            break;
4760
0
        case CKM_NSS_JPAKE_ROUND1_SHA1:
4761
0
            hashType = HASH_AlgSHA1;
4762
0
            goto jpake1;
4763
0
        case CKM_NSS_JPAKE_ROUND1_SHA256:
4764
0
            hashType = HASH_AlgSHA256;
4765
0
            goto jpake1;
4766
0
        case CKM_NSS_JPAKE_ROUND1_SHA384:
4767
0
            hashType = HASH_AlgSHA384;
4768
0
            goto jpake1;
4769
0
        case CKM_NSS_JPAKE_ROUND1_SHA512:
4770
0
            hashType = HASH_AlgSHA512;
4771
0
            goto jpake1;
4772
0
        jpake1:
4773
0
            key_gen_type = nsc_jpake;
4774
0
            key_type = CKK_NSS_JPAKE_ROUND1;
4775
0
            objclass = CKO_PRIVATE_KEY;
4776
0
            if (pMechanism->pParameter == NULL ||
4777
0
                pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) {
4778
0
                crv = CKR_MECHANISM_PARAM_INVALID;
4779
0
                break;
4780
0
            }
4781
0
            if (sftk_isTrue(key, CKA_TOKEN)) {
4782
0
                crv = CKR_TEMPLATE_INCONSISTENT;
4783
0
                break;
4784
0
            }
4785
0
            crv = CKR_OK;
4786
0
            break;
4787
0
        default:
4788
0
            crv = CKR_MECHANISM_INVALID;
4789
0
            break;
4790
5.52k
    }
4791
4792
    /* make sure we aren't going to overflow the buffer */
4793
5.52k
    if (sizeof(buf) < key_length) {
4794
        /* someone is getting pretty optimistic about how big their key can
4795
         * be... */
4796
0
        crv = CKR_TEMPLATE_INCONSISTENT;
4797
0
    }
4798
4799
5.52k
    if (crv != CKR_OK) {
4800
0
        if (pbe_param) {
4801
0
            nsspkcs5_DestroyPBEParameter(pbe_param);
4802
0
        }
4803
0
        goto loser;
4804
0
    }
4805
4806
    /* if there was no error,
4807
     * key_type *MUST* be set in the switch statement above */
4808
5.52k
    PORT_Assert(key_type != CKK_INVALID_KEY_TYPE);
4809
4810
    /*
4811
     * now to the actual key gen.
4812
     */
4813
5.52k
    switch (key_gen_type) {
4814
0
        case nsc_pbe:
4815
0
            crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length,
4816
0
                                  faultyPBE3DES);
4817
0
            nsspkcs5_DestroyPBEParameter(pbe_param);
4818
0
            break;
4819
5.23k
        case nsc_ssl:
4820
5.23k
            rsa_pms = (SSL3RSAPreMasterSecret *)buf;
4821
5.23k
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_VERSION))) {
4822
0
                crv = CKR_MECHANISM_PARAM_INVALID;
4823
0
                goto loser;
4824
0
            }
4825
5.23k
            version = (CK_VERSION *)pMechanism->pParameter;
4826
5.23k
            rsa_pms->client_version[0] = version->major;
4827
5.23k
            rsa_pms->client_version[1] = version->minor;
4828
5.23k
            crv =
4829
5.23k
                NSC_GenerateRandom(0, &rsa_pms->random[0], sizeof(rsa_pms->random));
4830
5.23k
            break;
4831
289
        case nsc_bulk:
4832
            /* get the key, check for weak keys and repeat if found */
4833
289
            do {
4834
289
                crv = NSC_GenerateRandom(0, buf, key_length);
4835
289
            } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf, key_type));
4836
289
            break;
4837
0
        case nsc_param:
4838
            /* generate parameters */
4839
0
            *buf = 0;
4840
0
            crv = nsc_parameter_gen(key_type, key);
4841
0
            break;
4842
0
        case nsc_jpake:
4843
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_NSS_JPAKERound1Params))) {
4844
0
                crv = CKR_MECHANISM_PARAM_INVALID;
4845
0
                goto loser;
4846
0
            }
4847
0
            crv = jpake_Round1(hashType,
4848
0
                               (CK_NSS_JPAKERound1Params *)pMechanism->pParameter,
4849
0
                               key);
4850
0
            break;
4851
5.52k
    }
4852
4853
5.52k
    if (crv != CKR_OK) {
4854
0
        goto loser;
4855
0
    }
4856
4857
    /* Add the class, key_type, and value */
4858
5.52k
    crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS));
4859
5.52k
    if (crv != CKR_OK) {
4860
0
        goto loser;
4861
0
    }
4862
5.52k
    crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE));
4863
5.52k
    if (crv != CKR_OK) {
4864
0
        goto loser;
4865
0
    }
4866
5.52k
    if (key_length != 0) {
4867
5.52k
        crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length);
4868
5.52k
        if (crv != CKR_OK) {
4869
0
            goto loser;
4870
0
        }
4871
5.52k
    }
4872
4873
    /* get the session */
4874
5.52k
    session = sftk_SessionFromHandle(hSession);
4875
5.52k
    if (session == NULL) {
4876
0
        crv = CKR_SESSION_HANDLE_INVALID;
4877
0
        goto loser;
4878
0
    }
4879
4880
    /*
4881
     * handle the base object stuff
4882
     */
4883
5.52k
    crv = sftk_handleObject(key, session);
4884
5.52k
    sftk_FreeSession(session);
4885
5.52k
    if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) {
4886
0
        crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL));
4887
0
    }
4888
5.52k
    if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) {
4889
0
        crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL));
4890
0
    }
4891
5.52k
    if (crv == CKR_OK) {
4892
5.52k
        *phKey = key->handle;
4893
5.52k
    }
4894
5.52k
loser:
4895
5.52k
    PORT_Memset(buf, 0, sizeof buf);
4896
5.52k
    sftk_FreeObject(key);
4897
5.52k
    return crv;
4898
5.52k
}
4899
4900
40.3k
#define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */
4901
0
#define PAIRWISE_MESSAGE_LENGTH 20         /* 160-bits */
4902
4903
/*
4904
 * FIPS 140-2 pairwise consistency check utilized to validate key pair.
4905
 *
4906
 * This function returns
4907
 *   CKR_OK               if pairwise consistency check passed
4908
 *   CKR_GENERAL_ERROR    if pairwise consistency check failed
4909
 *   other error codes    if paiswise consistency check could not be
4910
 *                        performed, for example, CKR_HOST_MEMORY.
4911
 */
4912
static CK_RV
4913
sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, SFTKSlot *slot,
4914
                              SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType)
4915
40.3k
{
4916
    /*
4917
     *                      Key type    Mechanism type
4918
     *                      --------------------------------
4919
     * For encrypt/decrypt: CKK_RSA  => CKM_RSA_PKCS
4920
     *                      others   => CKM_INVALID_MECHANISM
4921
     *
4922
     * For sign/verify:     CKK_RSA  => CKM_RSA_PKCS
4923
     *                      CKK_DSA  => CKM_DSA
4924
     *                      CKK_EC   => CKM_ECDSA
4925
     *                      others   => CKM_INVALID_MECHANISM
4926
     *
4927
     * None of these mechanisms has a parameter.
4928
     *
4929
     * For derive           CKK_DH   => CKM_DH_PKCS_DERIVE
4930
     *                      CKK_EC   => CKM_ECDH1_DERIVE
4931
     *                      others   => CKM_INVALID_MECHANISM
4932
     *
4933
     * The parameters for these mechanisms is the public key.
4934
     */
4935
40.3k
    CK_MECHANISM mech = { 0, NULL, 0 };
4936
4937
40.3k
    CK_ULONG modulusLen = 0;
4938
40.3k
    CK_ULONG subPrimeLen = 0;
4939
40.3k
    PRBool isEncryptable = PR_FALSE;
4940
40.3k
    PRBool canSignVerify = PR_FALSE;
4941
40.3k
    PRBool isDerivable = PR_FALSE;
4942
40.3k
    CK_RV crv;
4943
4944
    /* Variables used for Encrypt/Decrypt functions. */
4945
40.3k
    unsigned char *known_message = (unsigned char *)"Known Crypto Message";
4946
40.3k
    unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH];
4947
40.3k
    CK_ULONG bytes_decrypted;
4948
40.3k
    unsigned char *ciphertext;
4949
40.3k
    unsigned char *text_compared;
4950
40.3k
    CK_ULONG bytes_encrypted;
4951
40.3k
    CK_ULONG bytes_compared;
4952
40.3k
    CK_ULONG pairwise_digest_length = PAIRWISE_DIGEST_LENGTH;
4953
4954
    /* Variables used for Signature/Verification functions. */
4955
    /* Must be at least 256 bits for DSA2 digest */
4956
40.3k
    unsigned char *known_digest = (unsigned char *)"Mozilla Rules the World through NSS!";
4957
40.3k
    unsigned char *signature;
4958
40.3k
    CK_ULONG signature_length;
4959
4960
40.3k
    if (keyType == CKK_RSA) {
4961
0
        SFTKAttribute *attribute;
4962
4963
        /* Get modulus length of private key. */
4964
0
        attribute = sftk_FindAttribute(privateKey, CKA_MODULUS);
4965
0
        if (attribute == NULL) {
4966
0
            return CKR_DEVICE_ERROR;
4967
0
        }
4968
0
        modulusLen = attribute->attrib.ulValueLen;
4969
0
        if (*(unsigned char *)attribute->attrib.pValue == 0) {
4970
0
            modulusLen--;
4971
0
        }
4972
0
        sftk_FreeAttribute(attribute);
4973
40.3k
    } else if (keyType == CKK_DSA) {
4974
0
        SFTKAttribute *attribute;
4975
4976
        /* Get subprime length of private key. */
4977
0
        attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME);
4978
0
        if (attribute == NULL) {
4979
0
            return CKR_DEVICE_ERROR;
4980
0
        }
4981
0
        subPrimeLen = attribute->attrib.ulValueLen;
4982
0
        if (subPrimeLen > 1 && *(unsigned char *)attribute->attrib.pValue == 0) {
4983
0
            subPrimeLen--;
4984
0
        }
4985
0
        sftk_FreeAttribute(attribute);
4986
0
    }
4987
4988
    /**************************************************/
4989
    /* Pairwise Consistency Check of Encrypt/Decrypt. */
4990
    /**************************************************/
4991
4992
40.3k
    isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT);
4993
4994
    /*
4995
     * If the decryption attribute is set, attempt to encrypt
4996
     * with the public key and decrypt with the private key.
4997
     */
4998
40.3k
    if (isEncryptable) {
4999
0
        if (keyType != CKK_RSA) {
5000
0
            return CKR_DEVICE_ERROR;
5001
0
        }
5002
0
        bytes_encrypted = modulusLen;
5003
0
        mech.mechanism = CKM_RSA_PKCS;
5004
5005
        /* Allocate space for ciphertext. */
5006
0
        ciphertext = (unsigned char *)PORT_ZAlloc(bytes_encrypted);
5007
0
        if (ciphertext == NULL) {
5008
0
            return CKR_HOST_MEMORY;
5009
0
        }
5010
5011
        /* Prepare for encryption using the public key. */
5012
0
        crv = NSC_EncryptInit(hSession, &mech, publicKey->handle);
5013
0
        if (crv != CKR_OK) {
5014
0
            PORT_Free(ciphertext);
5015
0
            return crv;
5016
0
        }
5017
5018
        /* Encrypt using the public key. */
5019
0
        crv = NSC_Encrypt(hSession,
5020
0
                          known_message,
5021
0
                          PAIRWISE_MESSAGE_LENGTH,
5022
0
                          ciphertext,
5023
0
                          &bytes_encrypted);
5024
0
        if (crv != CKR_OK) {
5025
0
            PORT_Free(ciphertext);
5026
0
            return crv;
5027
0
        }
5028
5029
        /* Always use the smaller of these two values . . . */
5030
0
        bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH);
5031
5032
        /*
5033
         * If there was a failure, the plaintext
5034
         * goes at the end, therefore . . .
5035
         */
5036
0
        text_compared = ciphertext + bytes_encrypted - bytes_compared;
5037
5038
        /*
5039
         * Check to ensure that ciphertext does
5040
         * NOT EQUAL known input message text
5041
         * per FIPS PUB 140-2 directive.
5042
         */
5043
0
        if (PORT_Memcmp(text_compared, known_message,
5044
0
                        bytes_compared) == 0) {
5045
            /* Set error to Invalid PRIVATE Key. */
5046
0
            PORT_SetError(SEC_ERROR_INVALID_KEY);
5047
0
            PORT_Free(ciphertext);
5048
0
            return CKR_GENERAL_ERROR;
5049
0
        }
5050
5051
        /* Prepare for decryption using the private key. */
5052
0
        crv = NSC_DecryptInit(hSession, &mech, privateKey->handle);
5053
0
        if (crv != CKR_OK) {
5054
0
            PORT_Free(ciphertext);
5055
0
            return crv;
5056
0
        }
5057
5058
0
        memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH);
5059
5060
        /*
5061
         * Initialize bytes decrypted to be the
5062
         * expected PAIRWISE_MESSAGE_LENGTH.
5063
         */
5064
0
        bytes_decrypted = PAIRWISE_MESSAGE_LENGTH;
5065
5066
        /*
5067
         * Decrypt using the private key.
5068
         * NOTE:  No need to reset the
5069
         *        value of bytes_encrypted.
5070
         */
5071
0
        crv = NSC_Decrypt(hSession,
5072
0
                          ciphertext,
5073
0
                          bytes_encrypted,
5074
0
                          plaintext,
5075
0
                          &bytes_decrypted);
5076
5077
        /* Finished with ciphertext; free it. */
5078
0
        PORT_Free(ciphertext);
5079
5080
0
        if (crv != CKR_OK) {
5081
0
            return crv;
5082
0
        }
5083
5084
        /*
5085
         * Check to ensure that the output plaintext
5086
         * does EQUAL known input message text.
5087
         */
5088
0
        if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) ||
5089
0
            (PORT_Memcmp(plaintext, known_message,
5090
0
                         PAIRWISE_MESSAGE_LENGTH) != 0)) {
5091
            /* Set error to Bad PUBLIC Key. */
5092
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
5093
0
            return CKR_GENERAL_ERROR;
5094
0
        }
5095
0
    }
5096
5097
    /**********************************************/
5098
    /* Pairwise Consistency Check of Sign/Verify. */
5099
    /**********************************************/
5100
5101
40.3k
    canSignVerify = sftk_isTrue(privateKey, CKA_SIGN);
5102
    /* Unfortunately CKA_SIGN is always true in lg dbs. We have to check the
5103
     * actual curve to determine if we can do sign/verify. */
5104
40.3k
    if (canSignVerify && keyType == CKK_EC) {
5105
0
        NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(privateKey, CKK_EC, &crv);
5106
0
        if (privKey && privKey->u.ec.ecParams.name == ECCurve25519) {
5107
0
            canSignVerify = PR_FALSE;
5108
0
        }
5109
0
    }
5110
5111
40.3k
    if (canSignVerify) {
5112
        /* Determine length of signature. */
5113
0
        switch (keyType) {
5114
0
            case CKK_RSA:
5115
0
                signature_length = modulusLen;
5116
0
                mech.mechanism = CKM_RSA_PKCS;
5117
0
                break;
5118
0
            case CKK_DSA:
5119
0
                signature_length = DSA_MAX_SIGNATURE_LEN;
5120
0
                pairwise_digest_length = subPrimeLen;
5121
0
                mech.mechanism = CKM_DSA;
5122
0
                break;
5123
0
            case CKK_EC:
5124
0
                signature_length = MAX_ECKEY_LEN * 2;
5125
0
                mech.mechanism = CKM_ECDSA;
5126
0
                break;
5127
0
            case CKK_EC_EDWARDS:
5128
0
                signature_length = ED25519_SIGN_LEN;
5129
0
                mech.mechanism = CKM_EDDSA;
5130
0
                break;
5131
0
            default:
5132
0
                return CKR_DEVICE_ERROR;
5133
0
        }
5134
5135
        /* Allocate space for signature data. */
5136
0
        signature = (unsigned char *)PORT_ZAlloc(signature_length);
5137
0
        if (signature == NULL) {
5138
0
            return CKR_HOST_MEMORY;
5139
0
        }
5140
5141
        /* Sign the known hash using the private key. */
5142
0
        crv = NSC_SignInit(hSession, &mech, privateKey->handle);
5143
0
        if (crv != CKR_OK) {
5144
0
            PORT_Free(signature);
5145
0
            return crv;
5146
0
        }
5147
5148
0
        crv = NSC_Sign(hSession,
5149
0
                       known_digest,
5150
0
                       pairwise_digest_length,
5151
0
                       signature,
5152
0
                       &signature_length);
5153
0
        if (crv != CKR_OK) {
5154
0
            PORT_Free(signature);
5155
0
            return crv;
5156
0
        }
5157
5158
        /* detect trivial signing transforms */
5159
0
        if ((signature_length >= pairwise_digest_length) &&
5160
0
            (PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) {
5161
0
            PORT_Free(signature);
5162
0
            return CKR_DEVICE_ERROR;
5163
0
        }
5164
5165
        /* Verify the known hash using the public key. */
5166
0
        crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
5167
0
        if (crv != CKR_OK) {
5168
0
            PORT_Free(signature);
5169
0
            return crv;
5170
0
        }
5171
5172
0
        crv = NSC_Verify(hSession,
5173
0
                         known_digest,
5174
0
                         pairwise_digest_length,
5175
0
                         signature,
5176
0
                         signature_length);
5177
5178
        /* Free signature data. */
5179
0
        PORT_Free(signature);
5180
5181
0
        if ((crv == CKR_SIGNATURE_LEN_RANGE) ||
5182
0
            (crv == CKR_SIGNATURE_INVALID)) {
5183
0
            return CKR_GENERAL_ERROR;
5184
0
        }
5185
0
        if (crv != CKR_OK) {
5186
0
            return crv;
5187
0
        }
5188
0
    }
5189
5190
    /**********************************************/
5191
    /* Pairwise Consistency Check for Derivation  */
5192
    /**********************************************/
5193
5194
40.3k
    isDerivable = sftk_isTrue(privateKey, CKA_DERIVE);
5195
5196
40.3k
    if (isDerivable) {
5197
40.3k
        SFTKAttribute *pubAttribute = NULL;
5198
40.3k
        CK_OBJECT_HANDLE newKey;
5199
40.3k
        PRBool isFIPS = sftk_isFIPS(slot->slotID);
5200
40.3k
        CK_RV crv2;
5201
40.3k
        CK_OBJECT_CLASS secret = CKO_SECRET_KEY;
5202
40.3k
        CK_KEY_TYPE generic = CKK_GENERIC_SECRET;
5203
40.3k
        CK_ULONG keyLen = 128;
5204
40.3k
        CK_BBOOL ckTrue = CK_TRUE;
5205
40.3k
        CK_ATTRIBUTE template[] = {
5206
40.3k
            { CKA_CLASS, &secret, sizeof(secret) },
5207
40.3k
            { CKA_KEY_TYPE, &generic, sizeof(generic) },
5208
40.3k
            { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) },
5209
40.3k
            { CKA_DERIVE, &ckTrue, sizeof(ckTrue) }
5210
40.3k
        };
5211
40.3k
        CK_ULONG templateCount = PR_ARRAY_SIZE(template);
5212
40.3k
        CK_ECDH1_DERIVE_PARAMS ecParams;
5213
5214
40.3k
        crv = CKR_OK; /*paranoia, already get's set before we drop to the end */
5215
        /* FIPS 140-2 requires we verify that the resulting key is a valid key.
5216
         * The easiest way to do this is to do a derive operation, which checks
5217
         * the validity of the key */
5218
5219
40.3k
        switch (keyType) {
5220
5.53k
            case CKK_DH:
5221
5.53k
                mech.mechanism = CKM_DH_PKCS_DERIVE;
5222
5.53k
                pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE);
5223
5.53k
                if (pubAttribute == NULL) {
5224
0
                    return CKR_DEVICE_ERROR;
5225
0
                }
5226
5.53k
                mech.pParameter = pubAttribute->attrib.pValue;
5227
5.53k
                mech.ulParameterLen = pubAttribute->attrib.ulValueLen;
5228
5.53k
                break;
5229
34.8k
            case CKK_EC:
5230
34.8k
                mech.mechanism = CKM_ECDH1_DERIVE;
5231
34.8k
                pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT);
5232
34.8k
                if (pubAttribute == NULL) {
5233
0
                    return CKR_DEVICE_ERROR;
5234
0
                }
5235
34.8k
                ecParams.kdf = CKD_NULL;
5236
34.8k
                ecParams.ulSharedDataLen = 0;
5237
34.8k
                ecParams.pSharedData = NULL;
5238
34.8k
                ecParams.ulPublicDataLen = pubAttribute->attrib.ulValueLen;
5239
34.8k
                ecParams.pPublicData = pubAttribute->attrib.pValue;
5240
34.8k
                mech.pParameter = &ecParams;
5241
34.8k
                mech.ulParameterLen = sizeof(ecParams);
5242
34.8k
                break;
5243
0
            default:
5244
0
                return CKR_DEVICE_ERROR;
5245
40.3k
        }
5246
5247
40.3k
        crv = NSC_DeriveKey(hSession, &mech, privateKey->handle, template, templateCount, &newKey);
5248
40.3k
        if (crv != CKR_OK) {
5249
0
            sftk_FreeAttribute(pubAttribute);
5250
0
            return crv;
5251
0
        }
5252
        /* FIPS requires full validation, but in fipx mode NSC_Derive
5253
         * only does partial validation with approved primes, now handle
5254
         * full validation */
5255
40.3k
        if (isFIPS && keyType == CKK_DH) {
5256
0
            SECItem pubKey;
5257
0
            SECItem prime;
5258
0
            SECItem subPrime;
5259
0
            const SECItem *subPrimePtr = &subPrime;
5260
5261
0
            pubKey.data = pubAttribute->attrib.pValue;
5262
0
            pubKey.len = pubAttribute->attrib.ulValueLen;
5263
0
            prime.data = subPrime.data = NULL;
5264
0
            prime.len = subPrime.len = 0;
5265
0
            crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
5266
0
            if (crv != CKR_OK) {
5267
0
                goto done;
5268
0
            }
5269
0
            crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
5270
            /* we ignore the return code an only look at the length */
5271
0
            if (subPrime.len == 0) {
5272
                /* subprime not supplied, In this case look it up.
5273
                 * This only works with approved primes, but in FIPS mode
5274
                 * that's the only kine of prime that will get here */
5275
0
                subPrimePtr = sftk_VerifyDH_Prime(&prime, isFIPS);
5276
0
                if (subPrimePtr == NULL) {
5277
0
                    crv = CKR_GENERAL_ERROR;
5278
0
                    goto done;
5279
0
                }
5280
0
            }
5281
0
            if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) {
5282
0
                crv = CKR_GENERAL_ERROR;
5283
0
            }
5284
0
        done:
5285
0
            SECITEM_ZfreeItem(&subPrime, PR_FALSE);
5286
0
            SECITEM_ZfreeItem(&prime, PR_FALSE);
5287
0
        }
5288
        /* clean up before we return */
5289
40.3k
        sftk_FreeAttribute(pubAttribute);
5290
40.3k
        crv2 = NSC_DestroyObject(hSession, newKey);
5291
40.3k
        if (crv != CKR_OK) {
5292
0
            return crv;
5293
0
        }
5294
40.3k
        if (crv2 != CKR_OK) {
5295
0
            return crv2;
5296
0
        }
5297
40.3k
    }
5298
5299
40.3k
    return CKR_OK;
5300
40.3k
}
5301
5302
/* NSC_GenerateKeyPair generates a public-key/private-key pair,
5303
 * creating new key objects. */
5304
CK_RV
5305
NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
5306
                    CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
5307
                    CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
5308
                    CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,
5309
                    CK_OBJECT_HANDLE_PTR phPrivateKey)
5310
40.8k
{
5311
40.8k
    SFTKObject *publicKey, *privateKey;
5312
40.8k
    SFTKSession *session;
5313
40.8k
    CK_KEY_TYPE key_type;
5314
40.8k
    CK_RV crv = CKR_OK;
5315
40.8k
    CK_BBOOL cktrue = CK_TRUE;
5316
40.8k
    SECStatus rv;
5317
40.8k
    CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
5318
40.8k
    CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
5319
40.8k
    int i;
5320
40.8k
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
5321
40.8k
    unsigned int bitSize;
5322
5323
    /* RSA */
5324
40.8k
    int public_modulus_bits = 0;
5325
40.8k
    SECItem pubExp;
5326
40.8k
    RSAPrivateKey *rsaPriv;
5327
5328
    /* DSA */
5329
40.8k
    PQGParams pqgParam;
5330
40.8k
    DHParams dhParam;
5331
40.8k
    DSAPrivateKey *dsaPriv;
5332
5333
    /* Diffie Hellman */
5334
40.8k
    DHPrivateKey *dhPriv;
5335
5336
    /* Elliptic Curve Cryptography */
5337
40.8k
    SECItem ecEncodedParams; /* DER Encoded parameters */
5338
40.8k
    ECPrivateKey *ecPriv;
5339
40.8k
    ECParams *ecParams;
5340
5341
    /* Kyber */
5342
40.8k
    CK_NSS_KEM_PARAMETER_SET_TYPE ckKyberParamSet;
5343
5344
40.8k
    CHECK_FORK();
5345
5346
40.8k
    if (!slot) {
5347
0
        return CKR_SESSION_HANDLE_INVALID;
5348
0
    }
5349
    /*
5350
     * now lets create an object to hang the attributes off of
5351
     */
5352
40.8k
    publicKey = sftk_NewObject(slot); /* fill in the handle later */
5353
40.8k
    if (publicKey == NULL) {
5354
0
        return CKR_HOST_MEMORY;
5355
0
    }
5356
5357
    /*
5358
     * load the template values into the publicKey
5359
     */
5360
332k
    for (i = 0; i < (int)ulPublicKeyAttributeCount; i++) {
5361
291k
        if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) {
5362
0
            public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;
5363
0
            continue;
5364
0
        }
5365
5366
291k
        if (pPublicKeyTemplate[i].type == CKA_NSS_PARAMETER_SET) {
5367
0
            ckKyberParamSet = *(CK_NSS_KEM_PARAMETER_SET_TYPE *)pPublicKeyTemplate[i].pValue;
5368
0
            continue;
5369
0
        }
5370
5371
291k
        crv = sftk_AddAttributeType(publicKey,
5372
291k
                                    sftk_attr_expand(&pPublicKeyTemplate[i]));
5373
291k
        if (crv != CKR_OK)
5374
0
            break;
5375
291k
    }
5376
5377
40.8k
    if (crv != CKR_OK) {
5378
0
        sftk_FreeObject(publicKey);
5379
0
        return CKR_HOST_MEMORY;
5380
0
    }
5381
5382
40.8k
    privateKey = sftk_NewObject(slot); /* fill in the handle later */
5383
40.8k
    if (privateKey == NULL) {
5384
0
        sftk_FreeObject(publicKey);
5385
0
        return CKR_HOST_MEMORY;
5386
0
    }
5387
    /*
5388
     * now load the private key template
5389
     */
5390
327k
    for (i = 0; i < (int)ulPrivateKeyAttributeCount; i++) {
5391
286k
        if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) {
5392
0
            continue;
5393
0
        }
5394
5395
286k
        crv = sftk_AddAttributeType(privateKey,
5396
286k
                                    sftk_attr_expand(&pPrivateKeyTemplate[i]));
5397
286k
        if (crv != CKR_OK)
5398
0
            break;
5399
286k
    }
5400
5401
40.8k
    if (crv != CKR_OK) {
5402
0
        sftk_FreeObject(publicKey);
5403
0
        sftk_FreeObject(privateKey);
5404
0
        return CKR_HOST_MEMORY;
5405
0
    }
5406
40.8k
    sftk_DeleteAttributeType(privateKey, CKA_CLASS);
5407
40.8k
    sftk_DeleteAttributeType(privateKey, CKA_KEY_TYPE);
5408
40.8k
    sftk_DeleteAttributeType(privateKey, CKA_VALUE);
5409
40.8k
    sftk_DeleteAttributeType(publicKey, CKA_CLASS);
5410
40.8k
    sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE);
5411
40.8k
    sftk_DeleteAttributeType(publicKey, CKA_VALUE);
5412
5413
    /* Now Set up the parameters to generate the key (based on mechanism) */
5414
40.8k
    switch (pMechanism->mechanism) {
5415
0
        case CKM_RSA_PKCS_KEY_PAIR_GEN:
5416
            /* format the keys */
5417
0
            sftk_DeleteAttributeType(publicKey, CKA_MODULUS);
5418
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5419
0
            sftk_DeleteAttributeType(privateKey, CKA_MODULUS);
5420
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIVATE_EXPONENT);
5421
0
            sftk_DeleteAttributeType(privateKey, CKA_PUBLIC_EXPONENT);
5422
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIME_1);
5423
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIME_2);
5424
0
            sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_1);
5425
0
            sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_2);
5426
0
            sftk_DeleteAttributeType(privateKey, CKA_COEFFICIENT);
5427
0
            key_type = CKK_RSA;
5428
0
            if (public_modulus_bits == 0) {
5429
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5430
0
                break;
5431
0
            }
5432
0
            if (public_modulus_bits < RSA_MIN_MODULUS_BITS) {
5433
0
                crv = CKR_ATTRIBUTE_VALUE_INVALID;
5434
0
                break;
5435
0
            }
5436
0
            if (public_modulus_bits % 2 != 0) {
5437
0
                crv = CKR_ATTRIBUTE_VALUE_INVALID;
5438
0
                break;
5439
0
            }
5440
5441
            /* extract the exponent */
5442
0
            crv = sftk_Attribute2SSecItem(NULL, &pubExp, publicKey, CKA_PUBLIC_EXPONENT);
5443
0
            if (crv != CKR_OK)
5444
0
                break;
5445
0
            bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len);
5446
0
            if (bitSize < 2) {
5447
0
                crv = CKR_ATTRIBUTE_VALUE_INVALID;
5448
0
                SECITEM_ZfreeItem(&pubExp, PR_FALSE);
5449
0
                break;
5450
0
            }
5451
0
            crv = sftk_AddAttributeType(privateKey, CKA_PUBLIC_EXPONENT,
5452
0
                                        sftk_item_expand(&pubExp));
5453
0
            if (crv != CKR_OK) {
5454
0
                SECITEM_ZfreeItem(&pubExp, PR_FALSE);
5455
0
                break;
5456
0
            }
5457
5458
0
            rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp);
5459
0
            SECITEM_ZfreeItem(&pubExp, PR_FALSE);
5460
0
            if (rsaPriv == NULL) {
5461
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5462
0
                    sftk_fatalError = PR_TRUE;
5463
0
                }
5464
0
                crv = sftk_MapCryptError(PORT_GetError());
5465
0
                break;
5466
0
            }
5467
            /* now fill in the RSA dependent paramenters in the public key */
5468
0
            crv = sftk_AddAttributeType(publicKey, CKA_MODULUS,
5469
0
                                        sftk_item_expand(&rsaPriv->modulus));
5470
0
            if (crv != CKR_OK)
5471
0
                goto kpg_done;
5472
            /* now fill in the RSA dependent paramenters in the private key */
5473
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5474
0
                                        sftk_item_expand(&rsaPriv->modulus));
5475
0
            if (crv != CKR_OK)
5476
0
                goto kpg_done;
5477
0
            crv = sftk_AddAttributeType(privateKey, CKA_MODULUS,
5478
0
                                        sftk_item_expand(&rsaPriv->modulus));
5479
0
            if (crv != CKR_OK)
5480
0
                goto kpg_done;
5481
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIVATE_EXPONENT,
5482
0
                                        sftk_item_expand(&rsaPriv->privateExponent));
5483
0
            if (crv != CKR_OK)
5484
0
                goto kpg_done;
5485
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIME_1,
5486
0
                                        sftk_item_expand(&rsaPriv->prime1));
5487
0
            if (crv != CKR_OK)
5488
0
                goto kpg_done;
5489
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIME_2,
5490
0
                                        sftk_item_expand(&rsaPriv->prime2));
5491
0
            if (crv != CKR_OK)
5492
0
                goto kpg_done;
5493
0
            crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_1,
5494
0
                                        sftk_item_expand(&rsaPriv->exponent1));
5495
0
            if (crv != CKR_OK)
5496
0
                goto kpg_done;
5497
0
            crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_2,
5498
0
                                        sftk_item_expand(&rsaPriv->exponent2));
5499
0
            if (crv != CKR_OK)
5500
0
                goto kpg_done;
5501
0
            crv = sftk_AddAttributeType(privateKey, CKA_COEFFICIENT,
5502
0
                                        sftk_item_expand(&rsaPriv->coefficient));
5503
0
        kpg_done:
5504
            /* Should zeroize the contents first, since this func doesn't. */
5505
0
            PORT_FreeArena(rsaPriv->arena, PR_TRUE);
5506
0
            break;
5507
0
        case CKM_DSA_KEY_PAIR_GEN:
5508
0
            sftk_DeleteAttributeType(publicKey, CKA_VALUE);
5509
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5510
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIME);
5511
0
            sftk_DeleteAttributeType(privateKey, CKA_SUBPRIME);
5512
0
            sftk_DeleteAttributeType(privateKey, CKA_BASE);
5513
0
            key_type = CKK_DSA;
5514
5515
            /* extract the necessary parameters and copy them to the private key */
5516
0
            crv = sftk_Attribute2SSecItem(NULL, &pqgParam.prime, publicKey, CKA_PRIME);
5517
0
            if (crv != CKR_OK)
5518
0
                break;
5519
0
            crv = sftk_Attribute2SSecItem(NULL, &pqgParam.subPrime, publicKey,
5520
0
                                          CKA_SUBPRIME);
5521
0
            if (crv != CKR_OK) {
5522
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5523
0
                break;
5524
0
            }
5525
0
            crv = sftk_Attribute2SSecItem(NULL, &pqgParam.base, publicKey, CKA_BASE);
5526
0
            if (crv != CKR_OK) {
5527
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5528
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5529
0
                break;
5530
0
            }
5531
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
5532
0
                                        sftk_item_expand(&pqgParam.prime));
5533
0
            if (crv != CKR_OK) {
5534
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5535
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5536
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5537
0
                break;
5538
0
            }
5539
0
            crv = sftk_AddAttributeType(privateKey, CKA_SUBPRIME,
5540
0
                                        sftk_item_expand(&pqgParam.subPrime));
5541
0
            if (crv != CKR_OK) {
5542
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5543
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5544
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5545
0
                break;
5546
0
            }
5547
0
            crv = sftk_AddAttributeType(privateKey, CKA_BASE,
5548
0
                                        sftk_item_expand(&pqgParam.base));
5549
0
            if (crv != CKR_OK) {
5550
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5551
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5552
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5553
0
                break;
5554
0
            }
5555
5556
            /*
5557
             * these are checked by DSA_NewKey
5558
             */
5559
0
            bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data,
5560
0
                                           pqgParam.subPrime.len);
5561
0
            if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) {
5562
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5563
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5564
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5565
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5566
0
                break;
5567
0
            }
5568
0
            bitSize = sftk_GetLengthInBits(pqgParam.prime.data, pqgParam.prime.len);
5569
0
            if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) {
5570
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5571
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5572
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5573
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5574
0
                break;
5575
0
            }
5576
0
            bitSize = sftk_GetLengthInBits(pqgParam.base.data, pqgParam.base.len);
5577
0
            if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) {
5578
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5579
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5580
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5581
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5582
0
                break;
5583
0
            }
5584
5585
            /* Generate the key */
5586
0
            rv = DSA_NewKey(&pqgParam, &dsaPriv);
5587
5588
0
            SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5589
0
            SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5590
0
            SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5591
5592
0
            if (rv != SECSuccess) {
5593
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5594
0
                    sftk_fatalError = PR_TRUE;
5595
0
                }
5596
0
                crv = sftk_MapCryptError(PORT_GetError());
5597
0
                break;
5598
0
            }
5599
5600
            /* store the generated key into the attributes */
5601
0
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
5602
0
                                        sftk_item_expand(&dsaPriv->publicValue));
5603
0
            if (crv != CKR_OK)
5604
0
                goto dsagn_done;
5605
5606
            /* now fill in the RSA dependent paramenters in the private key */
5607
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5608
0
                                        sftk_item_expand(&dsaPriv->publicValue));
5609
0
            if (crv != CKR_OK)
5610
0
                goto dsagn_done;
5611
0
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5612
0
                                        sftk_item_expand(&dsaPriv->privateValue));
5613
5614
0
        dsagn_done:
5615
            /* should zeroize, since this function doesn't. */
5616
0
            PORT_FreeArena(dsaPriv->params.arena, PR_TRUE);
5617
0
            break;
5618
5619
5.53k
        case CKM_DH_PKCS_KEY_PAIR_GEN:
5620
5.53k
            sftk_DeleteAttributeType(privateKey, CKA_PRIME);
5621
5.53k
            sftk_DeleteAttributeType(privateKey, CKA_BASE);
5622
5.53k
            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
5623
5.53k
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5624
5.53k
            key_type = CKK_DH;
5625
5626
            /* extract the necessary parameters and copy them to private keys */
5627
5.53k
            crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey,
5628
5.53k
                                          CKA_PRIME);
5629
5.53k
            if (crv != CKR_OK)
5630
0
                break;
5631
5.53k
            crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);
5632
5.53k
            if (crv != CKR_OK) {
5633
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5634
0
                break;
5635
0
            }
5636
5.53k
            crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
5637
5.53k
                                        sftk_item_expand(&dhParam.prime));
5638
5.53k
            if (crv != CKR_OK) {
5639
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5640
0
                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5641
0
                break;
5642
0
            }
5643
5.53k
            crv = sftk_AddAttributeType(privateKey, CKA_BASE,
5644
5.53k
                                        sftk_item_expand(&dhParam.base));
5645
5.53k
            if (crv != CKR_OK) {
5646
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5647
0
                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5648
0
                break;
5649
0
            }
5650
5.53k
            bitSize = sftk_GetLengthInBits(dhParam.prime.data, dhParam.prime.len);
5651
5.53k
            if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) {
5652
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5653
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5654
0
                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5655
0
                break;
5656
0
            }
5657
5.53k
            bitSize = sftk_GetLengthInBits(dhParam.base.data, dhParam.base.len);
5658
5.53k
            if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) {
5659
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5660
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5661
0
                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5662
0
                break;
5663
0
            }
5664
5665
5.53k
            rv = DH_NewKey(&dhParam, &dhPriv);
5666
5.53k
            SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5667
5.53k
            SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5668
5.53k
            if (rv != SECSuccess) {
5669
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5670
0
                    sftk_fatalError = PR_TRUE;
5671
0
                }
5672
0
                crv = sftk_MapCryptError(PORT_GetError());
5673
0
                break;
5674
0
            }
5675
5676
5.53k
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
5677
5.53k
                                        sftk_item_expand(&dhPriv->publicValue));
5678
5.53k
            if (crv != CKR_OK)
5679
0
                goto dhgn_done;
5680
5681
5.53k
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5682
5.53k
                                        sftk_item_expand(&dhPriv->publicValue));
5683
5.53k
            if (crv != CKR_OK)
5684
0
                goto dhgn_done;
5685
5686
5.53k
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5687
5.53k
                                        sftk_item_expand(&dhPriv->privateValue));
5688
5689
5.53k
        dhgn_done:
5690
            /* should zeroize, since this function doesn't. */
5691
5.53k
            PORT_FreeArena(dhPriv->arena, PR_TRUE);
5692
5.53k
            break;
5693
5694
35.3k
        case CKM_EC_KEY_PAIR_GEN:
5695
35.3k
            sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS);
5696
35.3k
            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
5697
35.3k
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5698
35.3k
            key_type = CKK_EC;
5699
5700
            /* extract the necessary parameters and copy them to private keys */
5701
35.3k
            crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey,
5702
35.3k
                                          CKA_EC_PARAMS);
5703
35.3k
            if (crv != CKR_OK)
5704
0
                break;
5705
5706
35.3k
            crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS,
5707
35.3k
                                        sftk_item_expand(&ecEncodedParams));
5708
35.3k
            if (crv != CKR_OK) {
5709
0
                SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
5710
0
                break;
5711
0
            }
5712
5713
            /* Decode ec params before calling EC_NewKey */
5714
35.3k
            rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
5715
35.3k
            SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
5716
35.3k
            if (rv != SECSuccess) {
5717
562
                crv = sftk_MapCryptError(PORT_GetError());
5718
562
                break;
5719
562
            }
5720
34.8k
            rv = EC_NewKey(ecParams, &ecPriv);
5721
34.8k
            if (rv != SECSuccess) {
5722
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5723
0
                    sftk_fatalError = PR_TRUE;
5724
0
                }
5725
0
                PORT_FreeArena(ecParams->arena, PR_TRUE);
5726
0
                crv = sftk_MapCryptError(PORT_GetError());
5727
0
                break;
5728
0
            }
5729
5730
34.8k
            if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") ||
5731
34.8k
                ecParams->type != ec_params_named) {
5732
20.8k
                PORT_FreeArena(ecParams->arena, PR_TRUE);
5733
20.8k
                crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
5734
20.8k
                                            sftk_item_expand(&ecPriv->publicValue));
5735
20.8k
            } else {
5736
13.9k
                PORT_FreeArena(ecParams->arena, PR_TRUE);
5737
13.9k
                SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
5738
13.9k
                                                       &ecPriv->publicValue,
5739
13.9k
                                                       SEC_ASN1_GET(SEC_OctetStringTemplate));
5740
13.9k
                if (!pubValue) {
5741
0
                    crv = CKR_ARGUMENTS_BAD;
5742
0
                    goto ecgn_done;
5743
0
                }
5744
13.9k
                crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
5745
13.9k
                                            sftk_item_expand(pubValue));
5746
13.9k
                SECITEM_ZfreeItem(pubValue, PR_TRUE);
5747
13.9k
            }
5748
34.8k
            if (crv != CKR_OK)
5749
0
                goto ecgn_done;
5750
5751
34.8k
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5752
34.8k
                                        sftk_item_expand(&ecPriv->privateValue));
5753
34.8k
            if (crv != CKR_OK)
5754
0
                goto ecgn_done;
5755
5756
34.8k
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5757
34.8k
                                        sftk_item_expand(&ecPriv->publicValue));
5758
34.8k
        ecgn_done:
5759
            /* should zeroize, since this function doesn't. */
5760
34.8k
            PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
5761
34.8k
            break;
5762
5763
0
        case CKM_NSS_KYBER_KEY_PAIR_GEN:
5764
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5765
0
            key_type = CKK_NSS_KYBER;
5766
5767
0
            SECItem privKey = { siBuffer, NULL, 0 };
5768
0
            SECItem pubKey = { siBuffer, NULL, 0 };
5769
0
            KyberParams kyberParams = sftk_kyber_PK11ParamToInternal(ckKyberParamSet);
5770
0
            if (!sftk_kyber_AllocPrivKeyItem(kyberParams, &privKey)) {
5771
0
                crv = CKR_HOST_MEMORY;
5772
0
                goto kyber_done;
5773
0
            }
5774
0
            if (!sftk_kyber_AllocPubKeyItem(kyberParams, &pubKey)) {
5775
0
                crv = CKR_HOST_MEMORY;
5776
0
                goto kyber_done;
5777
0
            }
5778
0
            rv = Kyber_NewKey(kyberParams, NULL, &privKey, &pubKey);
5779
0
            if (rv != SECSuccess) {
5780
0
                crv = sftk_MapCryptError(PORT_GetError());
5781
0
                goto kyber_done;
5782
0
            }
5783
5784
0
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE, sftk_item_expand(&pubKey));
5785
0
            if (crv != CKR_OK) {
5786
0
                goto kyber_done;
5787
0
            }
5788
0
            crv = sftk_AddAttributeType(publicKey, CKA_NSS_PARAMETER_SET,
5789
0
                                        &ckKyberParamSet, sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE));
5790
0
            if (crv != CKR_OK) {
5791
0
                goto kyber_done;
5792
0
            }
5793
0
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5794
0
                                        sftk_item_expand(&privKey));
5795
0
            if (crv != CKR_OK) {
5796
0
                goto kyber_done;
5797
0
            }
5798
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_PARAMETER_SET,
5799
0
                                        &ckKyberParamSet, sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE));
5800
0
            if (crv != CKR_OK) {
5801
0
                goto kyber_done;
5802
0
            }
5803
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5804
0
                                        sftk_item_expand(&pubKey));
5805
0
        kyber_done:
5806
0
            SECITEM_ZfreeItem(&privKey, PR_FALSE);
5807
0
            SECITEM_FreeItem(&pubKey, PR_FALSE);
5808
0
            break;
5809
5810
0
        case CKM_EC_EDWARDS_KEY_PAIR_GEN:
5811
0
            sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS);
5812
0
            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
5813
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5814
0
            key_type = CKK_EC_EDWARDS;
5815
5816
            /* extract the necessary parameters and copy them to private keys */
5817
0
            crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey,
5818
0
                                          CKA_EC_PARAMS);
5819
0
            if (crv != CKR_OK) {
5820
0
                break;
5821
0
            }
5822
5823
0
            crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS,
5824
0
                                        sftk_item_expand(&ecEncodedParams));
5825
0
            if (crv != CKR_OK) {
5826
0
                SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
5827
0
                break;
5828
0
            }
5829
5830
            /* Decode ec params before calling EC_NewKey */
5831
0
            rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
5832
0
            SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
5833
0
            if (rv != SECSuccess) {
5834
0
                crv = sftk_MapCryptError(PORT_GetError());
5835
0
                break;
5836
0
            }
5837
5838
0
            rv = EC_NewKey(ecParams, &ecPriv);
5839
0
            if (rv != SECSuccess) {
5840
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5841
0
                    sftk_fatalError = PR_TRUE;
5842
0
                }
5843
0
                PORT_FreeArena(ecParams->arena, PR_TRUE);
5844
0
                crv = sftk_MapCryptError(PORT_GetError());
5845
0
                break;
5846
0
            }
5847
0
            PORT_FreeArena(ecParams->arena, PR_TRUE);
5848
0
            crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
5849
0
                                        sftk_item_expand(&ecPriv->publicValue));
5850
0
            if (crv != CKR_OK)
5851
0
                goto edgn_done;
5852
5853
0
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5854
0
                                        sftk_item_expand(&ecPriv->privateValue));
5855
0
            if (crv != CKR_OK)
5856
0
                goto edgn_done;
5857
5858
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5859
0
                                        sftk_item_expand(&ecPriv->publicValue));
5860
0
        edgn_done:
5861
            /* should zeroize, since this function doesn't. */
5862
0
            PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
5863
0
            break;
5864
5865
0
        default:
5866
0
            crv = CKR_MECHANISM_INVALID;
5867
40.8k
    }
5868
5869
40.8k
    if (crv != CKR_OK) {
5870
562
        sftk_FreeObject(privateKey);
5871
562
        sftk_FreeObject(publicKey);
5872
562
        return crv;
5873
562
    }
5874
5875
    /* Add the class, key_type The loop lets us check errors blow out
5876
     *  on errors and clean up at the bottom */
5877
40.3k
    session = NULL; /* make pedtantic happy... session cannot leave the*/
5878
                    /* loop below NULL unless an error is set... */
5879
40.3k
    do {
5880
40.3k
        crv = sftk_AddAttributeType(privateKey, CKA_CLASS, &privClass,
5881
40.3k
                                    sizeof(CK_OBJECT_CLASS));
5882
40.3k
        if (crv != CKR_OK)
5883
0
            break;
5884
40.3k
        crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &pubClass,
5885
40.3k
                                    sizeof(CK_OBJECT_CLASS));
5886
40.3k
        if (crv != CKR_OK)
5887
0
            break;
5888
40.3k
        crv = sftk_AddAttributeType(privateKey, CKA_KEY_TYPE, &key_type,
5889
40.3k
                                    sizeof(CK_KEY_TYPE));
5890
40.3k
        if (crv != CKR_OK)
5891
0
            break;
5892
40.3k
        crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &key_type,
5893
40.3k
                                    sizeof(CK_KEY_TYPE));
5894
40.3k
        if (crv != CKR_OK)
5895
0
            break;
5896
40.3k
        session = sftk_SessionFromHandle(hSession);
5897
40.3k
        if (session == NULL)
5898
0
            crv = CKR_SESSION_HANDLE_INVALID;
5899
40.3k
    } while (0);
5900
5901
40.3k
    if (crv != CKR_OK) {
5902
0
        sftk_FreeObject(privateKey);
5903
0
        sftk_FreeObject(publicKey);
5904
0
        return crv;
5905
0
    }
5906
5907
    /*
5908
     * handle the base object cleanup for the public Key
5909
     */
5910
40.3k
    crv = sftk_handleObject(privateKey, session);
5911
40.3k
    if (crv != CKR_OK) {
5912
0
        sftk_FreeSession(session);
5913
0
        sftk_FreeObject(privateKey);
5914
0
        sftk_FreeObject(publicKey);
5915
0
        return crv;
5916
0
    }
5917
5918
    /*
5919
     * handle the base object cleanup for the private Key
5920
     * If we have any problems, we destroy the public Key we've
5921
     * created and linked.
5922
     */
5923
40.3k
    crv = sftk_handleObject(publicKey, session);
5924
40.3k
    sftk_FreeSession(session);
5925
40.3k
    if (crv != CKR_OK) {
5926
0
        sftk_FreeObject(publicKey);
5927
0
        NSC_DestroyObject(hSession, privateKey->handle);
5928
0
        sftk_FreeObject(privateKey);
5929
0
        return crv;
5930
0
    }
5931
40.3k
    if (sftk_isTrue(privateKey, CKA_SENSITIVE)) {
5932
0
        crv = sftk_forceAttribute(privateKey, CKA_ALWAYS_SENSITIVE,
5933
0
                                  &cktrue, sizeof(CK_BBOOL));
5934
0
    }
5935
40.3k
    if (crv == CKR_OK && sftk_isTrue(publicKey, CKA_SENSITIVE)) {
5936
0
        crv = sftk_forceAttribute(publicKey, CKA_ALWAYS_SENSITIVE,
5937
0
                                  &cktrue, sizeof(CK_BBOOL));
5938
0
    }
5939
40.3k
    if (crv == CKR_OK && !sftk_isTrue(privateKey, CKA_EXTRACTABLE)) {
5940
0
        crv = sftk_forceAttribute(privateKey, CKA_NEVER_EXTRACTABLE,
5941
0
                                  &cktrue, sizeof(CK_BBOOL));
5942
0
    }
5943
40.3k
    if (crv == CKR_OK && !sftk_isTrue(publicKey, CKA_EXTRACTABLE)) {
5944
40.3k
        crv = sftk_forceAttribute(publicKey, CKA_NEVER_EXTRACTABLE,
5945
40.3k
                                  &cktrue, sizeof(CK_BBOOL));
5946
40.3k
    }
5947
5948
40.3k
    if (crv == CKR_OK && key_type != CKK_NSS_KYBER) {
5949
        /* Perform FIPS 140-2 pairwise consistency check. */
5950
40.3k
        crv = sftk_PairwiseConsistencyCheck(hSession, slot,
5951
40.3k
                                            publicKey, privateKey, key_type);
5952
40.3k
        if (crv != CKR_OK) {
5953
0
            if (sftk_audit_enabled) {
5954
0
                char msg[128];
5955
0
                PR_snprintf(msg, sizeof msg,
5956
0
                            "C_GenerateKeyPair(hSession=0x%08lX, "
5957
0
                            "pMechanism->mechanism=0x%08lX)=0x%08lX "
5958
0
                            "self-test: pair-wise consistency test failed",
5959
0
                            (PRUint32)hSession, (PRUint32)pMechanism->mechanism,
5960
0
                            (PRUint32)crv);
5961
0
                sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg);
5962
0
            }
5963
0
        }
5964
40.3k
    }
5965
5966
40.3k
    if (crv != CKR_OK) {
5967
0
        NSC_DestroyObject(hSession, publicKey->handle);
5968
0
        sftk_FreeObject(publicKey);
5969
0
        NSC_DestroyObject(hSession, privateKey->handle);
5970
0
        sftk_FreeObject(privateKey);
5971
0
        return crv;
5972
0
    }
5973
5974
40.3k
    *phPrivateKey = privateKey->handle;
5975
40.3k
    *phPublicKey = publicKey->handle;
5976
40.3k
    sftk_FreeObject(publicKey);
5977
40.3k
    sftk_FreeObject(privateKey);
5978
5979
40.3k
    return CKR_OK;
5980
40.3k
}
5981
5982
static SECItem *
5983
sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp)
5984
0
{
5985
0
    NSSLOWKEYPrivateKey *lk = NULL;
5986
0
    NSSLOWKEYPrivateKeyInfo *pki = NULL;
5987
0
    SFTKAttribute *attribute = NULL;
5988
0
    PLArenaPool *arena = NULL;
5989
0
    SECOidTag algorithm = SEC_OID_UNKNOWN;
5990
0
    void *dummy, *param = NULL;
5991
0
    SECStatus rv = SECSuccess;
5992
0
    SECItem *encodedKey = NULL;
5993
#ifdef EC_DEBUG
5994
    SECItem *fordebug;
5995
#endif
5996
0
    int savelen;
5997
5998
0
    if (!key) {
5999
0
        *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */
6000
0
        return NULL;
6001
0
    }
6002
6003
0
    attribute = sftk_FindAttribute(key, CKA_KEY_TYPE);
6004
0
    if (!attribute) {
6005
0
        *crvp = CKR_KEY_TYPE_INCONSISTENT;
6006
0
        return NULL;
6007
0
    }
6008
6009
0
    lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp);
6010
0
    sftk_FreeAttribute(attribute);
6011
0
    if (!lk) {
6012
0
        return NULL;
6013
0
    }
6014
6015
0
    arena = PORT_NewArena(2048); /* XXX different size? */
6016
0
    if (!arena) {
6017
0
        *crvp = CKR_HOST_MEMORY;
6018
0
        rv = SECFailure;
6019
0
        goto loser;
6020
0
    }
6021
6022
0
    pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena,
6023
0
                                                      sizeof(NSSLOWKEYPrivateKeyInfo));
6024
0
    if (!pki) {
6025
0
        *crvp = CKR_HOST_MEMORY;
6026
0
        rv = SECFailure;
6027
0
        goto loser;
6028
0
    }
6029
0
    pki->arena = arena;
6030
6031
0
    param = NULL;
6032
0
    switch (lk->keyType) {
6033
0
        case NSSLOWKEYRSAKey:
6034
0
            prepare_low_rsa_priv_key_for_asn1(lk);
6035
0
            dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
6036
0
                                       nsslowkey_RSAPrivateKeyTemplate);
6037
6038
            /* determine RSA key type from the CKA_PUBLIC_KEY_INFO if present */
6039
0
            attribute = sftk_FindAttribute(key, CKA_PUBLIC_KEY_INFO);
6040
0
            if (attribute) {
6041
0
                NSSLOWKEYSubjectPublicKeyInfo *publicKeyInfo;
6042
0
                SECItem spki;
6043
6044
0
                spki.data = attribute->attrib.pValue;
6045
0
                spki.len = attribute->attrib.ulValueLen;
6046
6047
0
                publicKeyInfo = PORT_ArenaZAlloc(arena,
6048
0
                                                 sizeof(NSSLOWKEYSubjectPublicKeyInfo));
6049
0
                if (!publicKeyInfo) {
6050
0
                    sftk_FreeAttribute(attribute);
6051
0
                    *crvp = CKR_HOST_MEMORY;
6052
0
                    rv = SECFailure;
6053
0
                    goto loser;
6054
0
                }
6055
0
                rv = SEC_QuickDERDecodeItem(arena, publicKeyInfo,
6056
0
                                            nsslowkey_SubjectPublicKeyInfoTemplate,
6057
0
                                            &spki);
6058
0
                if (rv != SECSuccess) {
6059
0
                    sftk_FreeAttribute(attribute);
6060
0
                    *crvp = CKR_KEY_TYPE_INCONSISTENT;
6061
0
                    goto loser;
6062
0
                }
6063
0
                algorithm = SECOID_GetAlgorithmTag(&publicKeyInfo->algorithm);
6064
0
                if (algorithm != SEC_OID_PKCS1_RSA_ENCRYPTION &&
6065
0
                    algorithm != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
6066
0
                    sftk_FreeAttribute(attribute);
6067
0
                    rv = SECFailure;
6068
0
                    *crvp = CKR_KEY_TYPE_INCONSISTENT;
6069
0
                    goto loser;
6070
0
                }
6071
0
                param = SECITEM_DupItem(&publicKeyInfo->algorithm.parameters);
6072
0
                if (!param) {
6073
0
                    sftk_FreeAttribute(attribute);
6074
0
                    rv = SECFailure;
6075
0
                    *crvp = CKR_HOST_MEMORY;
6076
0
                    goto loser;
6077
0
                }
6078
0
                sftk_FreeAttribute(attribute);
6079
0
            } else {
6080
                /* default to PKCS #1 */
6081
0
                algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
6082
0
            }
6083
0
            break;
6084
0
        case NSSLOWKEYDSAKey:
6085
0
            prepare_low_dsa_priv_key_export_for_asn1(lk);
6086
0
            dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
6087
0
                                       nsslowkey_DSAPrivateKeyExportTemplate);
6088
0
            prepare_low_pqg_params_for_asn1(&lk->u.dsa.params);
6089
0
            param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params),
6090
0
                                       nsslowkey_PQGParamsTemplate);
6091
0
            algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE;
6092
0
            break;
6093
0
        case NSSLOWKEYECKey:
6094
0
            prepare_low_ec_priv_key_for_asn1(lk);
6095
            /* Public value is encoded as a bit string so adjust length
6096
             * to be in bits before ASN encoding and readjust
6097
             * immediately after.
6098
             *
6099
             * Since the SECG specification recommends not including the
6100
             * parameters as part of ECPrivateKey, we zero out the curveOID
6101
             * length before encoding and restore it later.
6102
             */
6103
0
            lk->u.ec.publicValue.len <<= 3;
6104
0
            savelen = lk->u.ec.ecParams.curveOID.len;
6105
0
            lk->u.ec.ecParams.curveOID.len = 0;
6106
0
            dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
6107
0
                                       nsslowkey_ECPrivateKeyTemplate);
6108
0
            lk->u.ec.ecParams.curveOID.len = savelen;
6109
0
            lk->u.ec.publicValue.len >>= 3;
6110
6111
#ifdef EC_DEBUG
6112
            fordebug = &pki->privateKey;
6113
            SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType,
6114
                      fordebug);
6115
#endif
6116
6117
0
            param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding);
6118
6119
0
            algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
6120
0
            break;
6121
0
        case NSSLOWKEYDHKey:
6122
0
        default:
6123
0
            dummy = NULL;
6124
0
            break;
6125
0
    }
6126
6127
0
    if (!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) {
6128
0
        *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
6129
0
        rv = SECFailure;
6130
0
        goto loser;
6131
0
    }
6132
6133
0
    rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm,
6134
0
                               (SECItem *)param);
6135
0
    if (rv != SECSuccess) {
6136
0
        *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
6137
0
        rv = SECFailure;
6138
0
        goto loser;
6139
0
    }
6140
6141
0
    dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
6142
0
                                  NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
6143
0
    if (!dummy) {
6144
0
        *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
6145
0
        rv = SECFailure;
6146
0
        goto loser;
6147
0
    }
6148
6149
0
    encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki,
6150
0
                                    nsslowkey_PrivateKeyInfoTemplate);
6151
0
    *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR;
6152
6153
#ifdef EC_DEBUG
6154
    fordebug = encodedKey;
6155
    SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType,
6156
              fordebug);
6157
#endif
6158
0
loser:
6159
0
    if (arena) {
6160
0
        PORT_FreeArena(arena, PR_TRUE);
6161
0
    }
6162
6163
0
    if (lk && (lk != key->objectInfo)) {
6164
0
        nsslowkey_DestroyPrivateKey(lk);
6165
0
    }
6166
6167
0
    if (param) {
6168
0
        SECITEM_ZfreeItem((SECItem *)param, PR_TRUE);
6169
0
    }
6170
6171
0
    if (rv != SECSuccess) {
6172
0
        return NULL;
6173
0
    }
6174
6175
0
    return encodedKey;
6176
0
}
6177
6178
/* it doesn't matter yet, since we colapse error conditions in the
6179
 * level above, but we really should map those few key error differences */
6180
static CK_RV
6181
sftk_mapWrap(CK_RV crv)
6182
4.50k
{
6183
4.50k
    switch (crv) {
6184
0
        case CKR_ENCRYPTED_DATA_INVALID:
6185
0
            crv = CKR_WRAPPED_KEY_INVALID;
6186
0
            break;
6187
4.50k
    }
6188
4.50k
    return crv;
6189
4.50k
}
6190
6191
/* NSC_WrapKey wraps (i.e., encrypts) a key. */
6192
CK_RV
6193
NSC_WrapKey(CK_SESSION_HANDLE hSession,
6194
            CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
6195
            CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
6196
            CK_ULONG_PTR pulWrappedKeyLen)
6197
4.48k
{
6198
4.48k
    SFTKSession *session;
6199
4.48k
    SFTKAttribute *attribute;
6200
4.48k
    SFTKObject *key;
6201
4.48k
    CK_RV crv;
6202
6203
4.48k
    CHECK_FORK();
6204
6205
4.48k
    session = sftk_SessionFromHandle(hSession);
6206
4.48k
    if (session == NULL) {
6207
0
        return CKR_SESSION_HANDLE_INVALID;
6208
0
    }
6209
6210
4.48k
    key = sftk_ObjectFromHandle(hKey, session);
6211
4.48k
    if (key == NULL) {
6212
0
        sftk_FreeSession(session);
6213
0
        return CKR_KEY_HANDLE_INVALID;
6214
0
    }
6215
6216
4.48k
    switch (key->objclass) {
6217
4.48k
        case CKO_SECRET_KEY: {
6218
4.48k
            SFTKSessionContext *context = NULL;
6219
4.48k
            SECItem pText;
6220
6221
4.48k
            attribute = sftk_FindAttribute(key, CKA_VALUE);
6222
6223
4.48k
            if (attribute == NULL) {
6224
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
6225
0
                break;
6226
0
            }
6227
4.48k
            crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
6228
4.48k
                                 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
6229
4.48k
            if (crv != CKR_OK) {
6230
18
                sftk_FreeAttribute(attribute);
6231
18
                break;
6232
18
            }
6233
6234
4.46k
            pText.type = siBuffer;
6235
4.46k
            pText.data = (unsigned char *)attribute->attrib.pValue;
6236
4.46k
            pText.len = attribute->attrib.ulValueLen;
6237
6238
            /* Find out if this is a block cipher. */
6239
4.46k
            crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, NULL);
6240
4.46k
            if (crv != CKR_OK || !context)
6241
0
                break;
6242
4.46k
            if (context->blockSize > 1) {
6243
1.73k
                unsigned int remainder = pText.len % context->blockSize;
6244
1.73k
                if (!context->doPad && remainder) {
6245
                    /* When wrapping secret keys with unpadded block ciphers,
6246
                    ** the keys are zero padded, if necessary, to fill out
6247
                    ** a full block.
6248
                    */
6249
0
                    pText.len += context->blockSize - remainder;
6250
0
                    pText.data = PORT_ZAlloc(pText.len);
6251
0
                    if (pText.data)
6252
0
                        memcpy(pText.data, attribute->attrib.pValue,
6253
0
                               attribute->attrib.ulValueLen);
6254
0
                    else {
6255
0
                        crv = CKR_HOST_MEMORY;
6256
0
                        break;
6257
0
                    }
6258
0
                }
6259
1.73k
            }
6260
6261
4.46k
            crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data,
6262
4.46k
                              pText.len, pWrappedKey, pulWrappedKeyLen);
6263
            /* always force a finalize, both on errors and when
6264
             * we are just getting the size */
6265
4.46k
            if (crv != CKR_OK || pWrappedKey == NULL) {
6266
0
                CK_RV lcrv;
6267
0
                lcrv = sftk_GetContext(hSession, &context,
6268
0
                                       SFTK_ENCRYPT, PR_FALSE, NULL);
6269
0
                sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
6270
0
                if (lcrv == CKR_OK && context) {
6271
0
                    sftk_FreeContext(context);
6272
0
                }
6273
0
            }
6274
6275
4.46k
            if (pText.data != (unsigned char *)attribute->attrib.pValue)
6276
0
                PORT_ZFree(pText.data, pText.len);
6277
4.46k
            sftk_FreeAttribute(attribute);
6278
4.46k
            break;
6279
4.46k
        }
6280
6281
0
        case CKO_PRIVATE_KEY: {
6282
0
            SECItem *bpki = sftk_PackagePrivateKey(key, &crv);
6283
0
            SFTKSessionContext *context = NULL;
6284
6285
0
            if (!bpki) {
6286
0
                break;
6287
0
            }
6288
6289
0
            crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
6290
0
                                 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
6291
0
            if (crv != CKR_OK) {
6292
0
                SECITEM_ZfreeItem(bpki, PR_TRUE);
6293
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
6294
0
                break;
6295
0
            }
6296
6297
0
            crv = NSC_Encrypt(hSession, bpki->data, bpki->len,
6298
0
                              pWrappedKey, pulWrappedKeyLen);
6299
            /* always force a finalize */
6300
0
            if (crv != CKR_OK || pWrappedKey == NULL) {
6301
0
                CK_RV lcrv;
6302
0
                lcrv = sftk_GetContext(hSession, &context,
6303
0
                                       SFTK_ENCRYPT, PR_FALSE, NULL);
6304
0
                sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
6305
0
                if (lcrv == CKR_OK && context) {
6306
0
                    sftk_FreeContext(context);
6307
0
                }
6308
0
            }
6309
0
            SECITEM_ZfreeItem(bpki, PR_TRUE);
6310
0
            break;
6311
0
        }
6312
6313
0
        default:
6314
0
            crv = CKR_KEY_TYPE_INCONSISTENT;
6315
0
            break;
6316
4.48k
    }
6317
4.48k
    sftk_FreeObject(key);
6318
4.48k
    sftk_FreeSession(session);
6319
4.48k
    return sftk_mapWrap(crv);
6320
4.48k
}
6321
6322
/*
6323
 * import a pprivate key info into the desired slot
6324
 */
6325
static SECStatus
6326
sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki)
6327
0
{
6328
0
    CK_BBOOL cktrue = CK_TRUE;
6329
0
    CK_KEY_TYPE keyType = CKK_RSA;
6330
0
    SECStatus rv = SECFailure;
6331
0
    const SEC_ASN1Template *keyTemplate, *paramTemplate;
6332
0
    void *paramDest = NULL;
6333
0
    PLArenaPool *arena;
6334
0
    NSSLOWKEYPrivateKey *lpk = NULL;
6335
0
    NSSLOWKEYPrivateKeyInfo *pki = NULL;
6336
0
    CK_RV crv = CKR_KEY_TYPE_INCONSISTENT;
6337
6338
0
    arena = PORT_NewArena(2048);
6339
0
    if (!arena) {
6340
0
        return SECFailure;
6341
0
    }
6342
6343
0
    pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena,
6344
0
                                                      sizeof(NSSLOWKEYPrivateKeyInfo));
6345
0
    if (!pki) {
6346
0
        PORT_FreeArena(arena, PR_FALSE);
6347
0
        return SECFailure;
6348
0
    }
6349
6350
0
    if (SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) != SECSuccess) {
6351
0
        PORT_FreeArena(arena, PR_TRUE);
6352
0
        return SECFailure;
6353
0
    }
6354
6355
0
    lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena,
6356
0
                                                  sizeof(NSSLOWKEYPrivateKey));
6357
0
    if (lpk == NULL) {
6358
0
        goto loser;
6359
0
    }
6360
0
    lpk->arena = arena;
6361
6362
0
    switch (SECOID_GetAlgorithmTag(&pki->algorithm)) {
6363
0
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
6364
0
        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
6365
0
            keyTemplate = nsslowkey_RSAPrivateKeyTemplate;
6366
0
            paramTemplate = NULL;
6367
0
            paramDest = NULL;
6368
0
            lpk->keyType = NSSLOWKEYRSAKey;
6369
0
            prepare_low_rsa_priv_key_for_asn1(lpk);
6370
0
            break;
6371
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
6372
0
            keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate;
6373
0
            paramTemplate = nsslowkey_PQGParamsTemplate;
6374
0
            paramDest = &(lpk->u.dsa.params);
6375
0
            lpk->keyType = NSSLOWKEYDSAKey;
6376
0
            prepare_low_dsa_priv_key_export_for_asn1(lpk);
6377
0
            prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params);
6378
0
            break;
6379
        /* case NSSLOWKEYDHKey: */
6380
0
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
6381
0
            keyTemplate = nsslowkey_ECPrivateKeyTemplate;
6382
0
            paramTemplate = NULL;
6383
0
            paramDest = &(lpk->u.ec.ecParams.DEREncoding);
6384
0
            lpk->keyType = NSSLOWKEYECKey;
6385
0
            prepare_low_ec_priv_key_for_asn1(lpk);
6386
0
            prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams);
6387
0
            break;
6388
0
        default:
6389
0
            keyTemplate = NULL;
6390
0
            paramTemplate = NULL;
6391
0
            paramDest = NULL;
6392
0
            break;
6393
0
    }
6394
6395
0
    if (!keyTemplate) {
6396
0
        goto loser;
6397
0
    }
6398
6399
    /* decode the private key and any algorithm parameters */
6400
0
    rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
6401
6402
0
    if (lpk->keyType == NSSLOWKEYECKey) {
6403
        /* convert length in bits to length in bytes */
6404
0
        lpk->u.ec.publicValue.len >>= 3;
6405
0
        rv = SECITEM_CopyItem(arena,
6406
0
                              &(lpk->u.ec.ecParams.DEREncoding),
6407
0
                              &(pki->algorithm.parameters));
6408
0
        if (rv != SECSuccess) {
6409
0
            goto loser;
6410
0
        }
6411
0
    }
6412
6413
0
    if (rv != SECSuccess) {
6414
0
        goto loser;
6415
0
    }
6416
0
    if (paramDest && paramTemplate) {
6417
0
        rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate,
6418
0
                                    &(pki->algorithm.parameters));
6419
0
        if (rv != SECSuccess) {
6420
0
            goto loser;
6421
0
        }
6422
0
    }
6423
6424
0
    rv = SECFailure;
6425
6426
0
    switch (lpk->keyType) {
6427
0
        case NSSLOWKEYRSAKey:
6428
0
            keyType = CKK_RSA;
6429
0
            if (sftk_hasAttribute(key, CKA_NSS_DB)) {
6430
0
                sftk_DeleteAttributeType(key, CKA_NSS_DB);
6431
0
            }
6432
0
            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
6433
0
                                        sizeof(keyType));
6434
0
            if (crv != CKR_OK)
6435
0
                break;
6436
0
            crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue,
6437
0
                                        sizeof(CK_BBOOL));
6438
0
            if (crv != CKR_OK)
6439
0
                break;
6440
0
            crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue,
6441
0
                                        sizeof(CK_BBOOL));
6442
0
            if (crv != CKR_OK)
6443
0
                break;
6444
0
            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
6445
0
                                        sizeof(CK_BBOOL));
6446
0
            if (crv != CKR_OK)
6447
0
                break;
6448
0
            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
6449
0
                                        sizeof(CK_BBOOL));
6450
0
            if (crv != CKR_OK)
6451
0
                break;
6452
0
            crv = sftk_AddAttributeType(key, CKA_MODULUS,
6453
0
                                        sftk_item_expand(&lpk->u.rsa.modulus));
6454
0
            if (crv != CKR_OK)
6455
0
                break;
6456
0
            crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT,
6457
0
                                        sftk_item_expand(&lpk->u.rsa.publicExponent));
6458
0
            if (crv != CKR_OK)
6459
0
                break;
6460
0
            crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT,
6461
0
                                        sftk_item_expand(&lpk->u.rsa.privateExponent));
6462
0
            if (crv != CKR_OK)
6463
0
                break;
6464
0
            crv = sftk_AddAttributeType(key, CKA_PRIME_1,
6465
0
                                        sftk_item_expand(&lpk->u.rsa.prime1));
6466
0
            if (crv != CKR_OK)
6467
0
                break;
6468
0
            crv = sftk_AddAttributeType(key, CKA_PRIME_2,
6469
0
                                        sftk_item_expand(&lpk->u.rsa.prime2));
6470
0
            if (crv != CKR_OK)
6471
0
                break;
6472
0
            crv = sftk_AddAttributeType(key, CKA_EXPONENT_1,
6473
0
                                        sftk_item_expand(&lpk->u.rsa.exponent1));
6474
0
            if (crv != CKR_OK)
6475
0
                break;
6476
0
            crv = sftk_AddAttributeType(key, CKA_EXPONENT_2,
6477
0
                                        sftk_item_expand(&lpk->u.rsa.exponent2));
6478
0
            if (crv != CKR_OK)
6479
0
                break;
6480
0
            crv = sftk_AddAttributeType(key, CKA_COEFFICIENT,
6481
0
                                        sftk_item_expand(&lpk->u.rsa.coefficient));
6482
0
            break;
6483
0
        case NSSLOWKEYDSAKey:
6484
0
            keyType = CKK_DSA;
6485
0
            crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
6486
0
            if (crv != CKR_OK)
6487
0
                break;
6488
0
            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
6489
0
                                        sizeof(keyType));
6490
0
            if (crv != CKR_OK)
6491
0
                break;
6492
0
            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
6493
0
                                        sizeof(CK_BBOOL));
6494
0
            if (crv != CKR_OK)
6495
0
                break;
6496
0
            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
6497
0
                                        sizeof(CK_BBOOL));
6498
0
            if (crv != CKR_OK)
6499
0
                break;
6500
0
            crv = sftk_AddAttributeType(key, CKA_PRIME,
6501
0
                                        sftk_item_expand(&lpk->u.dsa.params.prime));
6502
0
            if (crv != CKR_OK)
6503
0
                break;
6504
0
            crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
6505
0
                                        sftk_item_expand(&lpk->u.dsa.params.subPrime));
6506
0
            if (crv != CKR_OK)
6507
0
                break;
6508
0
            crv = sftk_AddAttributeType(key, CKA_BASE,
6509
0
                                        sftk_item_expand(&lpk->u.dsa.params.base));
6510
0
            if (crv != CKR_OK)
6511
0
                break;
6512
0
            crv = sftk_AddAttributeType(key, CKA_VALUE,
6513
0
                                        sftk_item_expand(&lpk->u.dsa.privateValue));
6514
0
            if (crv != CKR_OK)
6515
0
                break;
6516
0
            break;
6517
#ifdef notdef
6518
        case NSSLOWKEYDHKey:
6519
            template = dhTemplate;
6520
            templateCount = sizeof(dhTemplate) / sizeof(CK_ATTRIBUTE);
6521
            keyType = CKK_DH;
6522
            break;
6523
#endif
6524
        /* what about fortezza??? */
6525
0
        case NSSLOWKEYECKey:
6526
0
            keyType = CKK_EC;
6527
0
            crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
6528
0
            if (crv != CKR_OK)
6529
0
                break;
6530
0
            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
6531
0
                                        sizeof(keyType));
6532
0
            if (crv != CKR_OK)
6533
0
                break;
6534
0
            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
6535
0
                                        sizeof(CK_BBOOL));
6536
0
            if (crv != CKR_OK)
6537
0
                break;
6538
0
            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
6539
0
                                        sizeof(CK_BBOOL));
6540
0
            if (crv != CKR_OK)
6541
0
                break;
6542
0
            crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue,
6543
0
                                        sizeof(CK_BBOOL));
6544
0
            if (crv != CKR_OK)
6545
0
                break;
6546
0
            crv = sftk_AddAttributeType(key, CKA_EC_PARAMS,
6547
0
                                        sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding));
6548
0
            if (crv != CKR_OK)
6549
0
                break;
6550
0
            crv = sftk_AddAttributeType(key, CKA_VALUE,
6551
0
                                        sftk_item_expand(&lpk->u.ec.privateValue));
6552
0
            if (crv != CKR_OK)
6553
0
                break;
6554
            /* XXX Do we need to decode the EC Params here ?? */
6555
0
            break;
6556
0
        default:
6557
0
            crv = CKR_KEY_TYPE_INCONSISTENT;
6558
0
            break;
6559
0
    }
6560
6561
0
    if (crv != CKR_OK) {
6562
0
        goto loser;
6563
0
    }
6564
6565
    /* For RSA-PSS, record the original algorithm parameters so
6566
     * they can be encrypted altoghether when wrapping */
6567
0
    if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
6568
0
        NSSLOWKEYSubjectPublicKeyInfo spki;
6569
0
        NSSLOWKEYPublicKey pubk;
6570
0
        SECItem *publicKeyInfo;
6571
6572
0
        memset(&spki, 0, sizeof(NSSLOWKEYSubjectPublicKeyInfo));
6573
0
        rv = SECOID_CopyAlgorithmID(arena, &spki.algorithm, &pki->algorithm);
6574
0
        if (rv != SECSuccess) {
6575
0
            crv = CKR_HOST_MEMORY;
6576
0
            goto loser;
6577
0
        }
6578
6579
0
        prepare_low_rsa_pub_key_for_asn1(&pubk);
6580
6581
0
        rv = SECITEM_CopyItem(arena, &pubk.u.rsa.modulus, &lpk->u.rsa.modulus);
6582
0
        if (rv != SECSuccess) {
6583
0
            crv = CKR_HOST_MEMORY;
6584
0
            goto loser;
6585
0
        }
6586
0
        rv = SECITEM_CopyItem(arena, &pubk.u.rsa.publicExponent, &lpk->u.rsa.publicExponent);
6587
0
        if (rv != SECSuccess) {
6588
0
            crv = CKR_HOST_MEMORY;
6589
0
            goto loser;
6590
0
        }
6591
6592
0
        if (SEC_ASN1EncodeItem(arena, &spki.subjectPublicKey,
6593
0
                               &pubk, nsslowkey_RSAPublicKeyTemplate) == NULL) {
6594
0
            crv = CKR_HOST_MEMORY;
6595
0
            goto loser;
6596
0
        }
6597
6598
0
        publicKeyInfo = SEC_ASN1EncodeItem(arena, NULL,
6599
0
                                           &spki, nsslowkey_SubjectPublicKeyInfoTemplate);
6600
0
        if (!publicKeyInfo) {
6601
0
            crv = CKR_HOST_MEMORY;
6602
0
            goto loser;
6603
0
        }
6604
0
        crv = sftk_AddAttributeType(key, CKA_PUBLIC_KEY_INFO,
6605
0
                                    sftk_item_expand(publicKeyInfo));
6606
0
    }
6607
6608
0
loser:
6609
0
    if (lpk) {
6610
0
        nsslowkey_DestroyPrivateKey(lpk);
6611
0
    }
6612
6613
0
    if (crv != CKR_OK) {
6614
0
        return SECFailure;
6615
0
    }
6616
6617
0
    return SECSuccess;
6618
0
}
6619
6620
/* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
6621
CK_RV
6622
NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
6623
              CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
6624
              CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
6625
              CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
6626
              CK_OBJECT_HANDLE_PTR phKey)
6627
27
{
6628
27
    SFTKObject *key = NULL;
6629
27
    SFTKSession *session;
6630
27
    CK_ULONG key_length = 0;
6631
27
    unsigned char *buf = NULL;
6632
27
    CK_RV crv = CKR_OK;
6633
27
    int i;
6634
27
    CK_ULONG bsize = ulWrappedKeyLen;
6635
27
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
6636
27
    SECItem bpki;
6637
27
    CK_OBJECT_CLASS target_type = CKO_SECRET_KEY;
6638
6639
27
    CHECK_FORK();
6640
6641
27
    if (!slot) {
6642
0
        return CKR_SESSION_HANDLE_INVALID;
6643
0
    }
6644
    /*
6645
     * now lets create an object to hang the attributes off of
6646
     */
6647
27
    key = sftk_NewObject(slot); /* fill in the handle later */
6648
27
    if (key == NULL) {
6649
0
        return CKR_HOST_MEMORY;
6650
0
    }
6651
6652
    /*
6653
     * load the template values into the object
6654
     */
6655
108
    for (i = 0; i < (int)ulAttributeCount; i++) {
6656
81
        if (pTemplate[i].type == CKA_VALUE_LEN) {
6657
0
            key_length = *(CK_ULONG *)pTemplate[i].pValue;
6658
0
            continue;
6659
0
        }
6660
81
        if (pTemplate[i].type == CKA_CLASS) {
6661
27
            target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
6662
27
        }
6663
81
        crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
6664
81
        if (crv != CKR_OK)
6665
0
            break;
6666
81
    }
6667
27
    if (crv != CKR_OK) {
6668
0
        sftk_FreeObject(key);
6669
0
        return crv;
6670
0
    }
6671
6672
27
    crv = sftk_CryptInit(hSession, pMechanism, hUnwrappingKey, CKA_UNWRAP,
6673
27
                         CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE);
6674
27
    if (crv != CKR_OK) {
6675
0
        sftk_FreeObject(key);
6676
0
        return sftk_mapWrap(crv);
6677
0
    }
6678
6679
    /* allocate the buffer to decrypt into
6680
     * this assumes the unwrapped key is never larger than the
6681
     * wrapped key. For all the mechanisms we support this is true */
6682
27
    buf = (unsigned char *)PORT_Alloc(ulWrappedKeyLen);
6683
27
    bsize = ulWrappedKeyLen;
6684
6685
27
    crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize);
6686
27
    if (crv != CKR_OK) {
6687
20
        sftk_FreeObject(key);
6688
20
        PORT_Free(buf);
6689
20
        return sftk_mapWrap(crv);
6690
20
    }
6691
6692
7
    switch (target_type) {
6693
7
        case CKO_SECRET_KEY:
6694
7
            if (!sftk_hasAttribute(key, CKA_KEY_TYPE)) {
6695
0
                crv = CKR_TEMPLATE_INCOMPLETE;
6696
0
                break;
6697
0
            }
6698
6699
7
            if (key_length == 0 || key_length > bsize) {
6700
7
                key_length = bsize;
6701
7
            }
6702
7
            if (key_length > MAX_KEY_LEN) {
6703
0
                crv = CKR_TEMPLATE_INCONSISTENT;
6704
0
                break;
6705
0
            }
6706
6707
            /* add the value */
6708
7
            crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length);
6709
7
            break;
6710
0
        case CKO_PRIVATE_KEY:
6711
0
            bpki.data = (unsigned char *)buf;
6712
0
            bpki.len = bsize;
6713
0
            crv = CKR_OK;
6714
0
            if (sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) {
6715
0
                crv = CKR_TEMPLATE_INCOMPLETE;
6716
0
            }
6717
0
            break;
6718
0
        default:
6719
0
            crv = CKR_TEMPLATE_INCONSISTENT;
6720
0
            break;
6721
7
    }
6722
6723
7
    PORT_ZFree(buf, bsize);
6724
7
    if (crv != CKR_OK) {
6725
0
        sftk_FreeObject(key);
6726
0
        return crv;
6727
0
    }
6728
6729
    /* get the session */
6730
7
    session = sftk_SessionFromHandle(hSession);
6731
7
    if (session == NULL) {
6732
0
        sftk_FreeObject(key);
6733
0
        return CKR_SESSION_HANDLE_INVALID;
6734
0
    }
6735
6736
    /* mark the key as FIPS if the previous operation was all FIPS */
6737
7
    key->isFIPS = session->lastOpWasFIPS;
6738
6739
    /*
6740
     * handle the base object stuff
6741
     */
6742
7
    crv = sftk_handleObject(key, session);
6743
7
    *phKey = key->handle;
6744
7
    sftk_FreeSession(session);
6745
7
    sftk_FreeObject(key);
6746
6747
7
    return crv;
6748
7
}
6749
6750
/*
6751
 * The SSL key gen mechanism create's lots of keys. This function handles the
6752
 * details of each of these key creation.
6753
 */
6754
static CK_RV
6755
sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey,
6756
                 PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize,
6757
                 CK_OBJECT_HANDLE *keyHandle)
6758
25.4k
{
6759
25.4k
    SFTKObject *key;
6760
25.4k
    SFTKSession *session;
6761
25.4k
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
6762
25.4k
    CK_BBOOL cktrue = CK_TRUE;
6763
25.4k
    CK_BBOOL ckfalse = CK_FALSE;
6764
25.4k
    CK_RV crv = CKR_HOST_MEMORY;
6765
6766
    /*
6767
     * now lets create an object to hang the attributes off of
6768
     */
6769
25.4k
    *keyHandle = CK_INVALID_HANDLE;
6770
25.4k
    key = sftk_NewObject(baseKey->slot);
6771
25.4k
    if (key == NULL)
6772
0
        return CKR_HOST_MEMORY;
6773
25.4k
    sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE;
6774
6775
25.4k
    crv = sftk_CopyObject(key, baseKey);
6776
25.4k
    if (crv != CKR_OK)
6777
0
        goto loser;
6778
25.4k
    if (isMacKey) {
6779
13.8k
        crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType));
6780
13.8k
        if (crv != CKR_OK)
6781
0
            goto loser;
6782
13.8k
        crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
6783
13.8k
        if (crv != CKR_OK)
6784
0
            goto loser;
6785
13.8k
        crv = sftk_forceAttribute(key, CKA_ENCRYPT, &ckfalse, sizeof(CK_BBOOL));
6786
13.8k
        if (crv != CKR_OK)
6787
0
            goto loser;
6788
13.8k
        crv = sftk_forceAttribute(key, CKA_DECRYPT, &ckfalse, sizeof(CK_BBOOL));
6789
13.8k
        if (crv != CKR_OK)
6790
0
            goto loser;
6791
13.8k
        crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
6792
13.8k
        if (crv != CKR_OK)
6793
0
            goto loser;
6794
13.8k
        crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
6795
13.8k
        if (crv != CKR_OK)
6796
0
            goto loser;
6797
13.8k
        crv = sftk_forceAttribute(key, CKA_WRAP, &ckfalse, sizeof(CK_BBOOL));
6798
13.8k
        if (crv != CKR_OK)
6799
0
            goto loser;
6800
13.8k
        crv = sftk_forceAttribute(key, CKA_UNWRAP, &ckfalse, sizeof(CK_BBOOL));
6801
13.8k
        if (crv != CKR_OK)
6802
0
            goto loser;
6803
13.8k
    }
6804
25.4k
    crv = sftk_forceAttribute(key, CKA_VALUE, keyBlock, keySize);
6805
25.4k
    if (crv != CKR_OK)
6806
0
        goto loser;
6807
6808
    /* get the session */
6809
25.4k
    crv = CKR_HOST_MEMORY;
6810
25.4k
    session = sftk_SessionFromHandle(hSession);
6811
25.4k
    if (session == NULL) {
6812
0
        goto loser;
6813
0
    }
6814
6815
25.4k
    crv = sftk_handleObject(key, session);
6816
25.4k
    sftk_FreeSession(session);
6817
25.4k
    *keyHandle = key->handle;
6818
25.4k
loser:
6819
25.4k
    if (key)
6820
25.4k
        sftk_FreeObject(key);
6821
25.4k
    return crv;
6822
25.4k
}
6823
6824
/*
6825
 * if there is an error, we need to free the keys we already created in SSL
6826
 * This is the routine that will do it..
6827
 */
6828
static void
6829
sftk_freeSSLKeys(CK_SESSION_HANDLE session,
6830
                 CK_SSL3_KEY_MAT_OUT *returnedMaterial)
6831
0
{
6832
0
    if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) {
6833
0
        NSC_DestroyObject(session, returnedMaterial->hClientMacSecret);
6834
0
    }
6835
0
    if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) {
6836
0
        NSC_DestroyObject(session, returnedMaterial->hServerMacSecret);
6837
0
    }
6838
0
    if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) {
6839
0
        NSC_DestroyObject(session, returnedMaterial->hClientKey);
6840
0
    }
6841
0
    if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) {
6842
0
        NSC_DestroyObject(session, returnedMaterial->hServerKey);
6843
0
    }
6844
0
}
6845
6846
/*
6847
 * when deriving from sensitive and extractable keys, we need to preserve some
6848
 * of the semantics in the derived key. This helper routine maintains these
6849
 * semantics.
6850
 */
6851
static CK_RV
6852
sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey,
6853
                          PRBool canBeData)
6854
28.2k
{
6855
28.2k
    PRBool hasSensitive;
6856
28.2k
    PRBool sensitive = PR_FALSE;
6857
28.2k
    CK_BBOOL bFalse = CK_FALSE;
6858
28.2k
    PRBool hasExtractable;
6859
28.2k
    PRBool extractable = PR_TRUE;
6860
28.2k
    CK_BBOOL bTrue = CK_TRUE;
6861
28.2k
    CK_RV crv = CKR_OK;
6862
28.2k
    SFTKAttribute *att;
6863
28.2k
    PRBool isData = PR_TRUE;
6864
6865
28.2k
    if (canBeData) {
6866
21.3k
        CK_OBJECT_CLASS objClass;
6867
6868
        /* if the target key is actually data, don't set the unexpected
6869
         * attributes */
6870
21.3k
        crv = sftk_GetULongAttribute(destKey, CKA_CLASS, &objClass);
6871
21.3k
        if (crv != CKR_OK) {
6872
0
            return crv;
6873
0
        }
6874
21.3k
        if (objClass == CKO_DATA) {
6875
3.29k
            return CKR_OK;
6876
3.29k
        }
6877
6878
        /* if the base key is data, it doesn't have sensitive attributes,
6879
         * allow the destKey to get it's own */
6880
18.0k
        crv = sftk_GetULongAttribute(baseKey, CKA_CLASS, &objClass);
6881
18.0k
        if (crv != CKR_OK) {
6882
0
            return crv;
6883
0
        }
6884
18.0k
        if (objClass == CKO_DATA) {
6885
3.36k
            isData = PR_TRUE;
6886
3.36k
        }
6887
18.0k
    }
6888
6889
24.9k
    hasSensitive = PR_FALSE;
6890
24.9k
    att = sftk_FindAttribute(destKey, CKA_SENSITIVE);
6891
24.9k
    if (att) {
6892
0
        hasSensitive = PR_TRUE;
6893
0
        sensitive = (PRBool) * (CK_BBOOL *)att->attrib.pValue;
6894
0
        sftk_FreeAttribute(att);
6895
0
    }
6896
6897
24.9k
    hasExtractable = PR_FALSE;
6898
24.9k
    att = sftk_FindAttribute(destKey, CKA_EXTRACTABLE);
6899
24.9k
    if (att) {
6900
0
        hasExtractable = PR_TRUE;
6901
0
        extractable = (PRBool) * (CK_BBOOL *)att->attrib.pValue;
6902
0
        sftk_FreeAttribute(att);
6903
0
    }
6904
6905
    /* don't make a key more accessible */
6906
24.9k
    if (sftk_isTrue(baseKey, CKA_SENSITIVE) && hasSensitive &&
6907
24.9k
        (sensitive == PR_FALSE)) {
6908
0
        return CKR_KEY_FUNCTION_NOT_PERMITTED;
6909
0
    }
6910
24.9k
    if (!sftk_isTrue(baseKey, CKA_EXTRACTABLE) && hasExtractable &&
6911
24.9k
        (extractable == PR_TRUE)) {
6912
0
        return CKR_KEY_FUNCTION_NOT_PERMITTED;
6913
0
    }
6914
6915
    /* inherit parent's sensitivity */
6916
24.9k
    if (!hasSensitive) {
6917
24.9k
        att = sftk_FindAttribute(baseKey, CKA_SENSITIVE);
6918
24.9k
        if (att != NULL) {
6919
21.5k
            crv = sftk_defaultAttribute(destKey,
6920
21.5k
                                        sftk_attr_expand(&att->attrib));
6921
21.5k
            sftk_FreeAttribute(att);
6922
21.5k
        } else if (isData) {
6923
3.36k
            crv = sftk_defaultAttribute(destKey, CKA_SENSITIVE,
6924
3.36k
                                        &bFalse, sizeof(bFalse));
6925
3.36k
        } else {
6926
0
            return CKR_KEY_TYPE_INCONSISTENT;
6927
0
        }
6928
24.9k
        if (crv != CKR_OK)
6929
0
            return crv;
6930
24.9k
    }
6931
24.9k
    if (!hasExtractable) {
6932
24.9k
        att = sftk_FindAttribute(baseKey, CKA_EXTRACTABLE);
6933
24.9k
        if (att != NULL) {
6934
21.5k
            crv = sftk_defaultAttribute(destKey,
6935
21.5k
                                        sftk_attr_expand(&att->attrib));
6936
21.5k
            sftk_FreeAttribute(att);
6937
21.5k
        } else if (isData) {
6938
3.36k
            crv = sftk_defaultAttribute(destKey, CKA_EXTRACTABLE,
6939
3.36k
                                        &bTrue, sizeof(bTrue));
6940
3.36k
        } else {
6941
0
            return CKR_KEY_TYPE_INCONSISTENT;
6942
0
        }
6943
24.9k
        if (crv != CKR_OK)
6944
0
            return crv;
6945
24.9k
    }
6946
6947
    /* we should inherit the parent's always extractable/ never sensitive info,
6948
     * but handleObject always forces this attributes, so we would need to do
6949
     * something special. */
6950
24.9k
    return CKR_OK;
6951
24.9k
}
6952
6953
/*
6954
 * make known fixed PKCS #11 key types to their sizes in bytes
6955
 */
6956
unsigned long
6957
sftk_MapKeySize(CK_KEY_TYPE keyType)
6958
15.3k
{
6959
15.3k
    switch (keyType) {
6960
0
        case CKK_CDMF:
6961
0
            return 8;
6962
356
        case CKK_DES:
6963
356
            return 8;
6964
0
        case CKK_DES2:
6965
0
            return 16;
6966
1.89k
        case CKK_DES3:
6967
1.89k
            return 24;
6968
        /* IDEA and CAST need to be added */
6969
13.1k
        default:
6970
13.1k
            break;
6971
15.3k
    }
6972
13.1k
    return 0;
6973
15.3k
}
6974
6975
/* Inputs:
6976
 *  key_len: Length of derived key to be generated.
6977
 *  SharedSecret: a shared secret that is the output of a key agreement primitive.
6978
 *  SharedInfo: (Optional) some data shared by the entities computing the secret key.
6979
 *  SharedInfoLen: the length in octets of SharedInfo
6980
 *  Hash: The hash function to be used in the KDF
6981
 *  HashLen: the length in octets of the output of Hash
6982
 * Output:
6983
 *  key: Pointer to a buffer containing derived key, if return value is SECSuccess.
6984
 */
6985
static CK_RV
6986
sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret,
6987
                            CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
6988
                            SECStatus Hash(unsigned char *, const unsigned char *, PRUint32),
6989
                            CK_ULONG HashLen)
6990
0
{
6991
0
    unsigned char *buffer = NULL, *output_buffer = NULL;
6992
0
    PRUint32 buffer_len, max_counter, i;
6993
0
    SECStatus rv;
6994
0
    CK_RV crv;
6995
6996
    /* Check that key_len isn't too long.  The maximum key length could be
6997
     * greatly increased if the code below did not limit the 4-byte counter
6998
     * to a maximum value of 255. */
6999
0
    if (key_len > 254 * HashLen)
7000
0
        return CKR_ARGUMENTS_BAD;
7001
7002
0
    if (SharedInfo == NULL)
7003
0
        SharedInfoLen = 0;
7004
7005
0
    buffer_len = SharedSecret->len + 4 + SharedInfoLen;
7006
0
    buffer = (CK_BYTE *)PORT_Alloc(buffer_len);
7007
0
    if (buffer == NULL) {
7008
0
        crv = CKR_HOST_MEMORY;
7009
0
        goto loser;
7010
0
    }
7011
7012
0
    max_counter = key_len / HashLen;
7013
0
    if (key_len > max_counter * HashLen)
7014
0
        max_counter++;
7015
7016
0
    output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen);
7017
0
    if (output_buffer == NULL) {
7018
0
        crv = CKR_HOST_MEMORY;
7019
0
        goto loser;
7020
0
    }
7021
7022
    /* Populate buffer with SharedSecret || Counter || [SharedInfo]
7023
     * where Counter is 0x00000001 */
7024
0
    PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len);
7025
0
    buffer[SharedSecret->len] = 0;
7026
0
    buffer[SharedSecret->len + 1] = 0;
7027
0
    buffer[SharedSecret->len + 2] = 0;
7028
0
    buffer[SharedSecret->len + 3] = 1;
7029
0
    if (SharedInfo) {
7030
0
        PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen);
7031
0
    }
7032
7033
0
    for (i = 0; i < max_counter; i++) {
7034
0
        rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len);
7035
0
        if (rv != SECSuccess) {
7036
            /* 'Hash' should not fail. */
7037
0
            crv = CKR_FUNCTION_FAILED;
7038
0
            goto loser;
7039
0
        }
7040
7041
        /* Increment counter (assumes max_counter < 255) */
7042
0
        buffer[SharedSecret->len + 3]++;
7043
0
    }
7044
7045
0
    PORT_ZFree(buffer, buffer_len);
7046
0
    if (key_len < max_counter * HashLen) {
7047
0
        PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len);
7048
0
    }
7049
0
    *key = output_buffer;
7050
7051
0
    return CKR_OK;
7052
7053
0
loser:
7054
0
    if (buffer) {
7055
0
        PORT_ZFree(buffer, buffer_len);
7056
0
    }
7057
0
    if (output_buffer) {
7058
0
        PORT_ZFree(output_buffer, max_counter * HashLen);
7059
0
    }
7060
0
    return crv;
7061
0
}
7062
7063
static CK_RV
7064
sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len,
7065
                    SECItem *SharedSecret,
7066
                    CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
7067
                    CK_EC_KDF_TYPE kdf)
7068
0
{
7069
0
    if (kdf == CKD_SHA1_KDF)
7070
0
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
7071
0
                                           SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH);
7072
0
    else if (kdf == CKD_SHA224_KDF)
7073
0
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
7074
0
                                           SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH);
7075
0
    else if (kdf == CKD_SHA256_KDF)
7076
0
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
7077
0
                                           SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH);
7078
0
    else if (kdf == CKD_SHA384_KDF)
7079
0
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
7080
0
                                           SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH);
7081
0
    else if (kdf == CKD_SHA512_KDF)
7082
0
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
7083
0
                                           SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH);
7084
0
    else
7085
0
        return CKR_MECHANISM_INVALID;
7086
0
}
7087
7088
/*
7089
 *  Handle the derive from a block encryption cipher
7090
 */
7091
CK_RV
7092
sftk_DeriveEncrypt(SFTKCipher encrypt, void *cipherInfo,
7093
                   int blockSize, SFTKObject *key, CK_ULONG keySize,
7094
                   unsigned char *data, CK_ULONG len)
7095
0
{
7096
    /* large enough for a 512-bit key */
7097
0
    unsigned char tmpdata[SFTK_MAX_DERIVE_KEY_SIZE];
7098
0
    SECStatus rv;
7099
0
    unsigned int outLen;
7100
0
    CK_RV crv;
7101
7102
0
    if ((len % blockSize) != 0) {
7103
0
        return CKR_MECHANISM_PARAM_INVALID;
7104
0
    }
7105
0
    if (len > SFTK_MAX_DERIVE_KEY_SIZE) {
7106
0
        return CKR_MECHANISM_PARAM_INVALID;
7107
0
    }
7108
0
    if (keySize && (len < keySize)) {
7109
0
        return CKR_MECHANISM_PARAM_INVALID;
7110
0
    }
7111
0
    if (keySize == 0) {
7112
0
        keySize = len;
7113
0
    }
7114
7115
0
    rv = (*encrypt)(cipherInfo, &tmpdata, &outLen, len, data, len);
7116
0
    if (rv != SECSuccess) {
7117
0
        crv = sftk_MapCryptError(PORT_GetError());
7118
0
        return crv;
7119
0
    }
7120
7121
0
    crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize);
7122
0
    PORT_Memset(tmpdata, 0, sizeof tmpdata);
7123
0
    return crv;
7124
0
}
7125
7126
CK_RV
7127
sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession,
7128
          SFTKObject *sourceKey, const unsigned char *sourceKeyBytes,
7129
          int sourceKeyLen, SFTKObject *key, unsigned char *outKeyBytes,
7130
          int keySize, PRBool canBeData, PRBool isFIPS)
7131
21.3k
{
7132
21.3k
    SFTKSession *session;
7133
21.3k
    SFTKAttribute *saltKey_att = NULL;
7134
21.3k
    const SECHashObject *rawHash;
7135
21.3k
    unsigned hashLen;
7136
21.3k
    unsigned genLen = 0;
7137
21.3k
    unsigned char hashbuf[HASH_LENGTH_MAX];
7138
21.3k
    unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH];
7139
21.3k
    unsigned char *keyBlockAlloc = NULL;    /* allocated keyBlock */
7140
21.3k
    unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */
7141
21.3k
    const unsigned char *prk;               /* psuedo-random key */
7142
21.3k
    CK_ULONG prkLen;
7143
21.3k
    const unsigned char *okm; /* output keying material */
7144
21.3k
    HASH_HashType hashType = sftk_GetHashTypeFromMechanism(params->prfHashMechanism);
7145
21.3k
    SFTKObject *saltKey = NULL;
7146
21.3k
    CK_RV crv = CKR_OK;
7147
7148
    /* Spec says it should be the base hash, but also accept the HMAC */
7149
21.3k
    if (hashType == HASH_AlgNULL) {
7150
0
        hashType = sftk_HMACMechanismToHash(params->prfHashMechanism);
7151
0
    }
7152
21.3k
    rawHash = HASH_GetRawHashObject(hashType);
7153
21.3k
    if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) {
7154
0
        return CKR_MECHANISM_INVALID;
7155
0
    }
7156
21.3k
    hashLen = rawHash->length;
7157
7158
21.3k
    if ((!params->bExpand && !params->bExtract) ||
7159
21.3k
        (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) ||
7160
21.3k
        (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) {
7161
0
        return CKR_MECHANISM_PARAM_INVALID;
7162
0
    }
7163
21.3k
    if ((params->bExpand && keySize == 0) ||
7164
21.3k
        (!params->bExpand && keySize > hashLen) ||
7165
21.3k
        (params->bExpand && keySize > 255 * hashLen)) {
7166
0
        return CKR_TEMPLATE_INCONSISTENT;
7167
0
    }
7168
7169
    /* sourceKey is NULL if we are called from the POST, skip the
7170
     * sensitiveCheck */
7171
21.3k
    if (sourceKey != NULL) {
7172
21.3k
        crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData);
7173
21.3k
        if (crv != CKR_OK)
7174
0
            return crv;
7175
21.3k
    }
7176
7177
    /* HKDF-Extract(salt, base key value) */
7178
21.3k
    if (params->bExtract) {
7179
5.04k
        CK_BYTE *salt;
7180
5.04k
        CK_ULONG saltLen;
7181
5.04k
        HMACContext *hmac;
7182
5.04k
        unsigned int bufLen;
7183
7184
5.04k
        switch (params->ulSaltType) {
7185
1.68k
            case CKF_HKDF_SALT_NULL:
7186
1.68k
                saltLen = hashLen;
7187
1.68k
                salt = hashbuf;
7188
1.68k
                memset(salt, 0, saltLen);
7189
1.68k
                break;
7190
0
            case CKF_HKDF_SALT_DATA:
7191
0
                salt = params->pSalt;
7192
0
                saltLen = params->ulSaltLen;
7193
0
                if ((salt == NULL) || (params->ulSaltLen == 0)) {
7194
0
                    return CKR_MECHANISM_PARAM_INVALID;
7195
0
                }
7196
0
                break;
7197
3.36k
            case CKF_HKDF_SALT_KEY:
7198
                /* lookup key */
7199
3.36k
                session = sftk_SessionFromHandle(hSession);
7200
3.36k
                if (session == NULL) {
7201
0
                    return CKR_SESSION_HANDLE_INVALID;
7202
0
                }
7203
7204
3.36k
                saltKey = sftk_ObjectFromHandle(params->hSaltKey, session);
7205
3.36k
                sftk_FreeSession(session);
7206
3.36k
                if (saltKey == NULL) {
7207
0
                    return CKR_KEY_HANDLE_INVALID;
7208
0
                }
7209
                /* if the base key is not fips, but the salt key is, the
7210
                 * resulting key can be fips */
7211
3.36k
                if (isFIPS && (key->isFIPS == 0) && (saltKey->isFIPS == 1)) {
7212
0
                    CK_MECHANISM mech;
7213
0
                    mech.mechanism = CKM_HKDF_DERIVE;
7214
0
                    mech.pParameter = params;
7215
0
                    mech.ulParameterLen = sizeof(*params);
7216
0
                    key->isFIPS = sftk_operationIsFIPS(saltKey->slot, &mech,
7217
0
                                                       CKA_DERIVE, saltKey);
7218
0
                }
7219
3.36k
                saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE);
7220
3.36k
                if (saltKey_att == NULL) {
7221
0
                    sftk_FreeObject(saltKey);
7222
0
                    return CKR_KEY_HANDLE_INVALID;
7223
0
                }
7224
                /* save the resulting salt */
7225
3.36k
                salt = saltKey_att->attrib.pValue;
7226
3.36k
                saltLen = saltKey_att->attrib.ulValueLen;
7227
3.36k
                break;
7228
0
            default:
7229
0
                return CKR_MECHANISM_PARAM_INVALID;
7230
0
                break;
7231
5.04k
        }
7232
7233
5.04k
        hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
7234
5.04k
        if (saltKey_att) {
7235
3.36k
            sftk_FreeAttribute(saltKey_att);
7236
3.36k
        }
7237
5.04k
        if (saltKey) {
7238
3.36k
            sftk_FreeObject(saltKey);
7239
3.36k
        }
7240
5.04k
        if (!hmac) {
7241
0
            return CKR_HOST_MEMORY;
7242
0
        }
7243
5.04k
        HMAC_Begin(hmac);
7244
5.04k
        HMAC_Update(hmac, sourceKeyBytes, sourceKeyLen);
7245
5.04k
        HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf));
7246
5.04k
        HMAC_Destroy(hmac, PR_TRUE);
7247
5.04k
        PORT_Assert(bufLen == rawHash->length);
7248
5.04k
        prk = hashbuf;
7249
5.04k
        prkLen = bufLen;
7250
16.2k
    } else {
7251
        /* PRK = base key value */
7252
16.2k
        prk = sourceKeyBytes;
7253
16.2k
        prkLen = sourceKeyLen;
7254
16.2k
    }
7255
7256
    /* HKDF-Expand */
7257
21.3k
    if (!params->bExpand) {
7258
5.04k
        okm = prk;
7259
5.04k
        keySize = genLen = hashLen;
7260
16.2k
    } else {
7261
        /* T(1) = HMAC-Hash(prk, "" | info | 0x01)
7262
         * T(n) = HMAC-Hash(prk, T(n-1) | info | n
7263
         * key material = T(1) | ... | T(n)
7264
         */
7265
16.2k
        HMACContext *hmac;
7266
16.2k
        CK_BYTE bi;
7267
16.2k
        unsigned iterations;
7268
7269
16.2k
        genLen = PR_ROUNDUP(keySize, hashLen);
7270
16.2k
        iterations = genLen / hashLen;
7271
7272
16.2k
        if (genLen > sizeof(keyBlock)) {
7273
0
            keyBlockAlloc = PORT_Alloc(genLen);
7274
0
            if (keyBlockAlloc == NULL) {
7275
0
                return CKR_HOST_MEMORY;
7276
0
            }
7277
0
            keyBlockData = keyBlockAlloc;
7278
0
        }
7279
16.2k
        hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS);
7280
16.2k
        if (hmac == NULL) {
7281
0
            PORT_Free(keyBlockAlloc);
7282
0
            return CKR_HOST_MEMORY;
7283
0
        }
7284
32.5k
        for (bi = 1; bi <= iterations && bi > 0; ++bi) {
7285
16.2k
            unsigned len;
7286
16.2k
            HMAC_Begin(hmac);
7287
16.2k
            if (bi > 1) {
7288
0
                HMAC_Update(hmac, &keyBlockData[(bi - 2) * hashLen], hashLen);
7289
0
            }
7290
16.2k
            if (params->ulInfoLen != 0) {
7291
16.2k
                HMAC_Update(hmac, params->pInfo, params->ulInfoLen);
7292
16.2k
            }
7293
16.2k
            HMAC_Update(hmac, &bi, 1);
7294
16.2k
            HMAC_Finish(hmac, &keyBlockData[(bi - 1) * hashLen], &len,
7295
16.2k
                        hashLen);
7296
16.2k
            PORT_Assert(len == hashLen);
7297
16.2k
        }
7298
16.2k
        HMAC_Destroy(hmac, PR_TRUE);
7299
16.2k
        okm = &keyBlockData[0];
7300
16.2k
    }
7301
    /* key material = okm */
7302
21.3k
    crv = CKR_OK;
7303
21.3k
    if (key) {
7304
21.3k
        crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize);
7305
21.3k
    } else {
7306
0
        PORT_Assert(outKeyBytes != NULL);
7307
0
        PORT_Memcpy(outKeyBytes, okm, keySize);
7308
0
    }
7309
21.3k
    PORT_Memset(keyBlockData, 0, genLen);
7310
21.3k
    PORT_Memset(hashbuf, 0, sizeof(hashbuf));
7311
21.3k
    PORT_Free(keyBlockAlloc);
7312
21.3k
    return crv;
7313
21.3k
}
7314
7315
/*
7316
 * SSL Key generation given pre master secret
7317
 */
7318
0
#define NUM_MIXERS 9
7319
static const char *const mixers[NUM_MIXERS] = {
7320
    "A",
7321
    "BB",
7322
    "CCC",
7323
    "DDDD",
7324
    "EEEEE",
7325
    "FFFFFF",
7326
    "GGGGGGG",
7327
    "HHHHHHHH",
7328
    "IIIIIIIII"
7329
};
7330
2.78k
#define SSL3_PMS_LENGTH 48
7331
20.7k
#define SSL3_MASTER_SECRET_LENGTH 48
7332
55.2k
#define SSL3_RANDOM_LENGTH 32
7333
7334
/* NSC_DeriveKey derives a key from a base key, creating a new key object. */
7335
CK_RV
7336
NSC_DeriveKey(CK_SESSION_HANDLE hSession,
7337
              CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
7338
              CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
7339
              CK_OBJECT_HANDLE_PTR phKey)
7340
84.6k
{
7341
84.6k
    SFTKSession *session;
7342
84.6k
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
7343
84.6k
    SFTKObject *key;
7344
84.6k
    SFTKObject *sourceKey;
7345
84.6k
    SFTKAttribute *att = NULL;
7346
84.6k
    SFTKAttribute *att2 = NULL;
7347
84.6k
    unsigned char *buf;
7348
84.6k
    SHA1Context *sha;
7349
84.6k
    MD5Context *md5;
7350
84.6k
    MD2Context *md2;
7351
84.6k
    CK_ULONG macSize;
7352
84.6k
    CK_ULONG tmpKeySize;
7353
84.6k
    CK_ULONG IVSize;
7354
84.6k
    CK_ULONG keySize = 0;
7355
84.6k
    CK_RV crv = CKR_OK;
7356
84.6k
    CK_BBOOL cktrue = CK_TRUE;
7357
84.6k
    CK_BBOOL ckfalse = CK_FALSE;
7358
84.6k
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
7359
84.6k
    CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
7360
84.6k
    CK_KEY_DERIVATION_STRING_DATA *stringPtr;
7361
84.6k
    PRBool isTLS = PR_FALSE;
7362
84.6k
    PRBool isDH = PR_FALSE;
7363
84.6k
    HASH_HashType tlsPrfHash = HASH_AlgNULL;
7364
84.6k
    SECStatus rv;
7365
84.6k
    int i;
7366
84.6k
    unsigned int outLen;
7367
84.6k
    unsigned char sha_out[SHA1_LENGTH];
7368
84.6k
    unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH];
7369
84.6k
    PRBool isFIPS;
7370
84.6k
    HASH_HashType hashType;
7371
84.6k
    CK_MECHANISM_TYPE hashMech;
7372
84.6k
    PRBool extractValue = PR_TRUE;
7373
84.6k
    CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS ikeAppB;
7374
84.6k
    CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *pIkeAppB;
7375
7376
84.6k
    CHECK_FORK();
7377
7378
84.6k
    if (!slot) {
7379
0
        return CKR_SESSION_HANDLE_INVALID;
7380
0
    }
7381
84.6k
    if (!pMechanism) {
7382
0
        return CKR_MECHANISM_PARAM_INVALID;
7383
0
    }
7384
84.6k
    CK_MECHANISM_TYPE mechanism = pMechanism->mechanism;
7385
7386
    /*
7387
     * now lets create an object to hang the attributes off of
7388
     */
7389
84.6k
    if (phKey)
7390
84.6k
        *phKey = CK_INVALID_HANDLE;
7391
7392
84.6k
    key = sftk_NewObject(slot); /* fill in the handle later */
7393
84.6k
    if (key == NULL) {
7394
0
        return CKR_HOST_MEMORY;
7395
0
    }
7396
84.6k
    isFIPS = sftk_isFIPS(slot->slotID);
7397
7398
    /*
7399
     * load the template values into the object
7400
     */
7401
456k
    for (i = 0; i < (int)ulAttributeCount; i++) {
7402
372k
        crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
7403
372k
        if (crv != CKR_OK)
7404
0
            break;
7405
7406
372k
        if (pTemplate[i].type == CKA_KEY_TYPE) {
7407
84.6k
            keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue;
7408
84.6k
        }
7409
372k
        if (pTemplate[i].type == CKA_VALUE_LEN) {
7410
71.5k
            keySize = *(CK_ULONG *)pTemplate[i].pValue;
7411
71.5k
        }
7412
372k
    }
7413
84.6k
    if (crv != CKR_OK) {
7414
0
        sftk_FreeObject(key);
7415
0
        return crv;
7416
0
    }
7417
7418
84.6k
    if (keySize == 0) {
7419
13.1k
        keySize = sftk_MapKeySize(keyType);
7420
13.1k
    }
7421
7422
84.6k
    switch (mechanism) {
7423
0
        case CKM_NSS_JPAKE_ROUND2_SHA1:   /* fall through */
7424
0
        case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */
7425
0
        case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */
7426
0
        case CKM_NSS_JPAKE_ROUND2_SHA512:
7427
0
            extractValue = PR_FALSE;
7428
0
            classType = CKO_PRIVATE_KEY;
7429
0
            break;
7430
0
        case CKM_NSS_PUB_FROM_PRIV:
7431
0
            extractValue = PR_FALSE;
7432
0
            classType = CKO_PUBLIC_KEY;
7433
0
            break;
7434
3.29k
        case CKM_HKDF_DATA:                              /* fall through */
7435
3.29k
        case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA:  /* fall through */
7436
3.29k
        case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */
7437
3.29k
        case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA:
7438
3.29k
            classType = CKO_DATA;
7439
3.29k
            break;
7440
0
        case CKM_NSS_JPAKE_FINAL_SHA1:   /* fall through */
7441
0
        case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
7442
0
        case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
7443
0
        case CKM_NSS_JPAKE_FINAL_SHA512:
7444
0
            extractValue = PR_FALSE;
7445
        /* fall through */
7446
81.3k
        default:
7447
81.3k
            classType = CKO_SECRET_KEY;
7448
84.6k
    }
7449
7450
84.6k
    crv = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType));
7451
84.6k
    if (crv != CKR_OK) {
7452
0
        sftk_FreeObject(key);
7453
0
        return crv;
7454
0
    }
7455
7456
    /* look up the base key we're deriving with */
7457
84.6k
    session = sftk_SessionFromHandle(hSession);
7458
84.6k
    if (session == NULL) {
7459
0
        sftk_FreeObject(key);
7460
0
        return CKR_SESSION_HANDLE_INVALID;
7461
0
    }
7462
7463
84.6k
    sourceKey = sftk_ObjectFromHandle(hBaseKey, session);
7464
84.6k
    sftk_FreeSession(session);
7465
    /* is this eventually succeeds, lastOpWasFIPS will be set the resulting key's
7466
     * FIPS state below. */
7467
84.6k
    session->lastOpWasFIPS = PR_FALSE;
7468
84.6k
    if (sourceKey == NULL) {
7469
0
        sftk_FreeObject(key);
7470
0
        return CKR_KEY_HANDLE_INVALID;
7471
0
    }
7472
7473
84.6k
    if (extractValue) {
7474
        /* get the value of the base key */
7475
84.6k
        att = sftk_FindAttribute(sourceKey, CKA_VALUE);
7476
84.6k
        if (att == NULL) {
7477
0
            sftk_FreeObject(key);
7478
0
            sftk_FreeObject(sourceKey);
7479
0
            return CKR_KEY_HANDLE_INVALID;
7480
0
        }
7481
84.6k
    }
7482
84.6k
    key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DERIVE, sourceKey);
7483
7484
84.6k
    switch (mechanism) {
7485
        /* get a public key from a private key. nsslowkey_ConvertToPublickey()
7486
         * will generate the public portion if it doesn't already exist. */
7487
0
        case CKM_NSS_PUB_FROM_PRIV: {
7488
0
            NSSLOWKEYPrivateKey *privKey;
7489
0
            NSSLOWKEYPublicKey *pubKey;
7490
0
            int error;
7491
7492
0
            crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType);
7493
0
            if (crv != CKR_OK) {
7494
0
                break;
7495
0
            }
7496
7497
            /* privKey is stored in sourceKey and will be destroyed when
7498
             * the sourceKey is freed. */
7499
0
            privKey = sftk_GetPrivKey(sourceKey, keyType, &crv);
7500
0
            if (privKey == NULL) {
7501
0
                break;
7502
0
            }
7503
0
            pubKey = nsslowkey_ConvertToPublicKey(privKey);
7504
0
            if (pubKey == NULL) {
7505
0
                error = PORT_GetError();
7506
0
                crv = sftk_MapCryptError(error);
7507
0
                break;
7508
0
            }
7509
0
            crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey);
7510
0
            nsslowkey_DestroyPublicKey(pubKey);
7511
0
            break;
7512
0
        }
7513
0
        case CKM_NSS_IKE_PRF_DERIVE:
7514
0
            if (pMechanism->ulParameterLen !=
7515
0
                sizeof(CK_NSS_IKE_PRF_DERIVE_PARAMS)) {
7516
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7517
0
                break;
7518
0
            }
7519
0
            crv = sftk_ike_prf(hSession, att,
7520
0
                               (CK_NSS_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key);
7521
0
            break;
7522
0
        case CKM_NSS_IKE1_PRF_DERIVE:
7523
0
            if (pMechanism->ulParameterLen !=
7524
0
                sizeof(CK_NSS_IKE1_PRF_DERIVE_PARAMS)) {
7525
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7526
0
                break;
7527
0
            }
7528
0
            crv = sftk_ike1_prf(hSession, att,
7529
0
                                (CK_NSS_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter,
7530
0
                                key, keySize);
7531
0
            break;
7532
0
        case CKM_NSS_IKE1_APP_B_PRF_DERIVE:
7533
0
            pIkeAppB = (CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *)pMechanism->pParameter;
7534
0
            if (pMechanism->ulParameterLen ==
7535
0
                sizeof(CK_MECHANISM_TYPE)) {
7536
0
                ikeAppB.prfMechanism = *(CK_MECHANISM_TYPE *)pMechanism->pParameter;
7537
0
                ikeAppB.bHasKeygxy = PR_FALSE;
7538
0
                ikeAppB.hKeygxy = CK_INVALID_HANDLE;
7539
0
                ikeAppB.pExtraData = NULL;
7540
0
                ikeAppB.ulExtraDataLen = 0;
7541
0
                pIkeAppB = &ikeAppB;
7542
0
            } else if (pMechanism->ulParameterLen !=
7543
0
                       sizeof(CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS)) {
7544
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7545
0
                break;
7546
0
            }
7547
0
            crv = sftk_ike1_appendix_b_prf(hSession, att, pIkeAppB, key,
7548
0
                                           keySize);
7549
0
            break;
7550
0
        case CKM_NSS_IKE_PRF_PLUS_DERIVE:
7551
0
            if (pMechanism->ulParameterLen !=
7552
0
                sizeof(CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS)) {
7553
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7554
0
                break;
7555
0
            }
7556
0
            crv = sftk_ike_prf_plus(hSession, att,
7557
0
                                    (CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter,
7558
0
                                    key, keySize);
7559
0
            break;
7560
        /*
7561
         * generate the master secret
7562
         */
7563
2.31k
        case CKM_TLS12_MASTER_KEY_DERIVE:
7564
3.51k
        case CKM_TLS12_MASTER_KEY_DERIVE_DH:
7565
3.51k
        case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256:
7566
3.51k
        case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256:
7567
3.95k
        case CKM_TLS_MASTER_KEY_DERIVE:
7568
6.90k
        case CKM_TLS_MASTER_KEY_DERIVE_DH:
7569
6.90k
        case CKM_SSL3_MASTER_KEY_DERIVE:
7570
6.90k
        case CKM_SSL3_MASTER_KEY_DERIVE_DH: {
7571
6.90k
            CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master;
7572
6.90k
            SSL3RSAPreMasterSecret *rsa_pms;
7573
6.90k
            unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
7574
7575
6.90k
            if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) ||
7576
6.90k
                (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
7577
3.51k
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) {
7578
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
7579
0
                    break;
7580
0
                }
7581
3.51k
                CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master =
7582
3.51k
                    (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter;
7583
3.51k
                tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_master->prfHashMechanism);
7584
3.51k
                if (tlsPrfHash == HASH_AlgNULL) {
7585
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
7586
0
                    break;
7587
0
                }
7588
3.51k
            } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) ||
7589
3.38k
                       (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) {
7590
0
                tlsPrfHash = HASH_AlgSHA256;
7591
0
            }
7592
7593
6.90k
            if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) &&
7594
6.90k
                (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) {
7595
6.90k
                isTLS = PR_TRUE;
7596
6.90k
            }
7597
6.90k
            if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) ||
7598
6.90k
                (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) ||
7599
6.90k
                (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) ||
7600
6.90k
                (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
7601
4.14k
                isDH = PR_TRUE;
7602
4.14k
            }
7603
7604
            /* first do the consistency checks */
7605
6.90k
            if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
7606
6
                crv = CKR_KEY_TYPE_INCONSISTENT;
7607
6
                break;
7608
6
            }
7609
6.89k
            att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
7610
6.89k
            if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
7611
6.89k
                                   CKK_GENERIC_SECRET)) {
7612
0
                if (att2)
7613
0
                    sftk_FreeAttribute(att2);
7614
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7615
0
                break;
7616
0
            }
7617
6.89k
            sftk_FreeAttribute(att2);
7618
6.89k
            if (keyType != CKK_GENERIC_SECRET) {
7619
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7620
0
                break;
7621
0
            }
7622
6.89k
            if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
7623
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7624
0
                break;
7625
0
            }
7626
7627
            /* finally do the key gen */
7628
6.89k
            ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)
7629
6.89k
                              pMechanism->pParameter;
7630
7631
6.89k
            if (ssl3_master->pVersion) {
7632
2.74k
                SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
7633
2.74k
                rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue;
7634
                /* don't leak more key material then necessary for SSL to work */
7635
2.74k
                if ((sessKey == NULL) || sessKey->wasDerived) {
7636
0
                    ssl3_master->pVersion->major = 0xff;
7637
0
                    ssl3_master->pVersion->minor = 0xff;
7638
2.74k
                } else {
7639
2.74k
                    ssl3_master->pVersion->major = rsa_pms->client_version[0];
7640
2.74k
                    ssl3_master->pVersion->minor = rsa_pms->client_version[1];
7641
2.74k
                }
7642
2.74k
            }
7643
6.89k
            if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) {
7644
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7645
0
                break;
7646
0
            }
7647
6.89k
            if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) {
7648
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7649
0
                break;
7650
0
            }
7651
6.89k
            PORT_Memcpy(crsrdata,
7652
6.89k
                        ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
7653
6.89k
            PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
7654
6.89k
                        ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
7655
7656
6.89k
            if (isTLS) {
7657
6.89k
                SECStatus status;
7658
6.89k
                SECItem crsr = { siBuffer, NULL, 0 };
7659
6.89k
                SECItem master = { siBuffer, NULL, 0 };
7660
6.89k
                SECItem pms = { siBuffer, NULL, 0 };
7661
7662
6.89k
                crsr.data = crsrdata;
7663
6.89k
                crsr.len = sizeof crsrdata;
7664
6.89k
                master.data = key_block;
7665
6.89k
                master.len = SSL3_MASTER_SECRET_LENGTH;
7666
6.89k
                pms.data = (unsigned char *)att->attrib.pValue;
7667
6.89k
                pms.len = att->attrib.ulValueLen;
7668
7669
6.89k
                if (tlsPrfHash != HASH_AlgNULL) {
7670
3.51k
                    status = TLS_P_hash(tlsPrfHash, &pms, "master secret",
7671
3.51k
                                        &crsr, &master, isFIPS);
7672
3.51k
                } else {
7673
3.38k
                    status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS);
7674
3.38k
                }
7675
6.89k
                if (status != SECSuccess) {
7676
0
                    PORT_Memset(crsrdata, 0, sizeof crsrdata);
7677
0
                    crv = CKR_FUNCTION_FAILED;
7678
0
                    break;
7679
0
                }
7680
6.89k
            } else {
7681
                /* now allocate the hash contexts */
7682
0
                md5 = MD5_NewContext();
7683
0
                if (md5 == NULL) {
7684
0
                    PORT_Memset(crsrdata, 0, sizeof crsrdata);
7685
0
                    crv = CKR_HOST_MEMORY;
7686
0
                    break;
7687
0
                }
7688
0
                sha = SHA1_NewContext();
7689
0
                if (sha == NULL) {
7690
0
                    PORT_Memset(crsrdata, 0, sizeof crsrdata);
7691
0
                    PORT_Free(md5);
7692
0
                    crv = CKR_HOST_MEMORY;
7693
0
                    break;
7694
0
                }
7695
0
                for (i = 0; i < 3; i++) {
7696
0
                    SHA1_Begin(sha);
7697
0
                    SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i]));
7698
0
                    SHA1_Update(sha, (const unsigned char *)att->attrib.pValue,
7699
0
                                att->attrib.ulValueLen);
7700
0
                    SHA1_Update(sha, crsrdata, sizeof crsrdata);
7701
0
                    SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
7702
0
                    PORT_Assert(outLen == SHA1_LENGTH);
7703
7704
0
                    MD5_Begin(md5);
7705
0
                    MD5_Update(md5, (const unsigned char *)att->attrib.pValue,
7706
0
                               att->attrib.ulValueLen);
7707
0
                    MD5_Update(md5, sha_out, outLen);
7708
0
                    MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH);
7709
0
                    PORT_Assert(outLen == MD5_LENGTH);
7710
0
                }
7711
0
                PORT_Free(md5);
7712
0
                PORT_Free(sha);
7713
0
                PORT_Memset(crsrdata, 0, sizeof crsrdata);
7714
0
                PORT_Memset(sha_out, 0, sizeof sha_out);
7715
0
            }
7716
7717
            /* store the results */
7718
6.89k
            crv = sftk_forceAttribute(key, CKA_VALUE, key_block, SSL3_MASTER_SECRET_LENGTH);
7719
6.89k
            PORT_Memset(key_block, 0, sizeof key_block);
7720
6.89k
            if (crv != CKR_OK)
7721
0
                break;
7722
6.89k
            keyType = CKK_GENERIC_SECRET;
7723
6.89k
            crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType));
7724
6.89k
            if (isTLS) {
7725
                /* TLS's master secret is used to "sign" finished msgs with PRF. */
7726
                /* XXX This seems like a hack.   But SFTK_Derive only accepts
7727
                 * one "operation" argument. */
7728
6.89k
                crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
7729
6.89k
                if (crv != CKR_OK)
7730
0
                    break;
7731
6.89k
                crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
7732
6.89k
                if (crv != CKR_OK)
7733
0
                    break;
7734
                /* While we're here, we might as well force this, too. */
7735
6.89k
                crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
7736
6.89k
                if (crv != CKR_OK)
7737
0
                    break;
7738
6.89k
            }
7739
6.89k
            break;
7740
6.89k
        }
7741
7742
        /* Extended master key derivation [draft-ietf-tls-session-hash] */
7743
6.89k
        case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE:
7744
38
        case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: {
7745
38
            CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params;
7746
38
            SSL3RSAPreMasterSecret *rsa_pms;
7747
38
            SECStatus status;
7748
38
            SECItem pms = { siBuffer, NULL, 0 };
7749
38
            SECItem seed = { siBuffer, NULL, 0 };
7750
38
            SECItem master = { siBuffer, NULL, 0 };
7751
7752
38
            ems_params = (CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *)
7753
38
                             pMechanism->pParameter;
7754
7755
            /* First do the consistency checks */
7756
38
            if ((mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE) &&
7757
38
                (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
7758
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
7759
0
                break;
7760
0
            }
7761
38
            att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
7762
38
            if ((att2 == NULL) ||
7763
38
                (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) {
7764
0
                if (att2)
7765
0
                    sftk_FreeAttribute(att2);
7766
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7767
0
                break;
7768
0
            }
7769
38
            sftk_FreeAttribute(att2);
7770
38
            if (keyType != CKK_GENERIC_SECRET) {
7771
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7772
0
                break;
7773
0
            }
7774
38
            if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
7775
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7776
0
                break;
7777
0
            }
7778
7779
            /* Do the key derivation */
7780
38
            pms.data = (unsigned char *)att->attrib.pValue;
7781
38
            pms.len = att->attrib.ulValueLen;
7782
38
            seed.data = ems_params->pSessionHash;
7783
38
            seed.len = ems_params->ulSessionHashLen;
7784
38
            master.data = key_block;
7785
38
            master.len = SSL3_MASTER_SECRET_LENGTH;
7786
38
            if (ems_params->prfHashMechanism == CKM_TLS_PRF) {
7787
                /*
7788
                 * In this case, the session hash is the concatenation of SHA-1
7789
                 * and MD5, so it should be 36 bytes long.
7790
                 */
7791
0
                if (seed.len != MD5_LENGTH + SHA1_LENGTH) {
7792
0
                    crv = CKR_TEMPLATE_INCONSISTENT;
7793
0
                    break;
7794
0
                }
7795
7796
0
                status = TLS_PRF(&pms, "extended master secret",
7797
0
                                 &seed, &master, isFIPS);
7798
38
            } else {
7799
38
                const SECHashObject *hashObj;
7800
7801
38
                tlsPrfHash = sftk_GetHashTypeFromMechanism(ems_params->prfHashMechanism);
7802
38
                if (tlsPrfHash == HASH_AlgNULL) {
7803
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
7804
0
                    break;
7805
0
                }
7806
7807
38
                hashObj = HASH_GetRawHashObject(tlsPrfHash);
7808
38
                if (seed.len != hashObj->length) {
7809
0
                    crv = CKR_TEMPLATE_INCONSISTENT;
7810
0
                    break;
7811
0
                }
7812
7813
38
                status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret",
7814
38
                                    &seed, &master, isFIPS);
7815
38
            }
7816
38
            if (status != SECSuccess) {
7817
0
                crv = CKR_FUNCTION_FAILED;
7818
0
                break;
7819
0
            }
7820
7821
            /* Reflect the version if required */
7822
38
            if (ems_params->pVersion) {
7823
26
                SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
7824
26
                rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue;
7825
                /* don't leak more key material than necessary for SSL to work */
7826
26
                if ((sessKey == NULL) || sessKey->wasDerived) {
7827
0
                    ems_params->pVersion->major = 0xff;
7828
0
                    ems_params->pVersion->minor = 0xff;
7829
26
                } else {
7830
26
                    ems_params->pVersion->major = rsa_pms->client_version[0];
7831
26
                    ems_params->pVersion->minor = rsa_pms->client_version[1];
7832
26
                }
7833
26
            }
7834
7835
            /* Store the results */
7836
38
            crv = sftk_forceAttribute(key, CKA_VALUE, key_block,
7837
38
                                      SSL3_MASTER_SECRET_LENGTH);
7838
38
            PORT_Memset(key_block, 0, sizeof key_block);
7839
38
            break;
7840
38
        }
7841
7842
3.52k
        case CKM_TLS12_KEY_AND_MAC_DERIVE:
7843
3.52k
        case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256:
7844
6.91k
        case CKM_TLS_KEY_AND_MAC_DERIVE:
7845
6.91k
        case CKM_SSL3_KEY_AND_MAC_DERIVE: {
7846
6.91k
            CK_SSL3_KEY_MAT_PARAMS *ssl3_keys;
7847
6.91k
            CK_SSL3_KEY_MAT_OUT *ssl3_keys_out;
7848
6.91k
            CK_ULONG effKeySize;
7849
6.91k
            unsigned int block_needed;
7850
6.91k
            unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
7851
7852
6.91k
            if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) {
7853
3.52k
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) {
7854
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
7855
0
                    break;
7856
0
                }
7857
3.52k
                CK_TLS12_KEY_MAT_PARAMS *tls12_keys =
7858
3.52k
                    (CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter;
7859
3.52k
                tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_keys->prfHashMechanism);
7860
3.52k
                if (tlsPrfHash == HASH_AlgNULL) {
7861
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
7862
0
                    break;
7863
0
                }
7864
3.52k
            } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) {
7865
0
                tlsPrfHash = HASH_AlgSHA256;
7866
0
            }
7867
7868
6.91k
            if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) {
7869
6.91k
                isTLS = PR_TRUE;
7870
6.91k
            }
7871
7872
6.91k
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
7873
6.91k
            if (crv != CKR_OK)
7874
0
                break;
7875
7876
6.91k
            if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) {
7877
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7878
0
                break;
7879
0
            }
7880
6.91k
            att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
7881
6.91k
            if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
7882
6.91k
                                   CKK_GENERIC_SECRET)) {
7883
0
                if (att2)
7884
0
                    sftk_FreeAttribute(att2);
7885
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7886
0
                break;
7887
0
            }
7888
6.91k
            sftk_FreeAttribute(att2);
7889
6.91k
            md5 = MD5_NewContext();
7890
6.91k
            if (md5 == NULL) {
7891
0
                crv = CKR_HOST_MEMORY;
7892
0
                break;
7893
0
            }
7894
6.91k
            sha = SHA1_NewContext();
7895
6.91k
            if (sha == NULL) {
7896
0
                MD5_DestroyContext(md5, PR_TRUE);
7897
0
                crv = CKR_HOST_MEMORY;
7898
0
                break;
7899
0
            }
7900
7901
6.91k
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_SSL3_KEY_MAT_PARAMS))) {
7902
0
                MD5_DestroyContext(md5, PR_TRUE);
7903
0
                SHA1_DestroyContext(sha, PR_TRUE);
7904
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7905
0
                break;
7906
0
            }
7907
6.91k
            ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter;
7908
7909
6.91k
            PORT_Memcpy(srcrdata,
7910
6.91k
                        ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
7911
6.91k
            PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH,
7912
6.91k
                        ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
7913
7914
            /*
7915
             * clear out our returned keys so we can recover on failure
7916
             */
7917
6.91k
            ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;
7918
6.91k
            ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE;
7919
6.91k
            ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE;
7920
6.91k
            ssl3_keys_out->hClientKey = CK_INVALID_HANDLE;
7921
6.91k
            ssl3_keys_out->hServerKey = CK_INVALID_HANDLE;
7922
7923
            /*
7924
             * How much key material do we need?
7925
             */
7926
6.91k
            macSize = ssl3_keys->ulMacSizeInBits / 8;
7927
6.91k
            effKeySize = ssl3_keys->ulKeySizeInBits / 8;
7928
6.91k
            IVSize = ssl3_keys->ulIVSizeInBits / 8;
7929
6.91k
            if (keySize == 0) {
7930
1.11k
                effKeySize = keySize;
7931
1.11k
            }
7932
7933
            /* bIsExport must be false. */
7934
6.91k
            if (ssl3_keys->bIsExport) {
7935
0
                MD5_DestroyContext(md5, PR_TRUE);
7936
0
                SHA1_DestroyContext(sha, PR_TRUE);
7937
0
                PORT_Memset(srcrdata, 0, sizeof srcrdata);
7938
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7939
0
                break;
7940
0
            }
7941
7942
6.91k
            block_needed = 2 * (macSize + effKeySize + IVSize);
7943
6.91k
            PORT_Assert(block_needed <= sizeof key_block);
7944
6.91k
            if (block_needed > sizeof key_block)
7945
0
                block_needed = sizeof key_block;
7946
7947
            /*
7948
             * generate the key material: This looks amazingly similar to the
7949
             * PMS code, and is clearly crying out for a function to provide it.
7950
             */
7951
6.91k
            if (isTLS) {
7952
6.91k
                SECStatus status;
7953
6.91k
                SECItem srcr = { siBuffer, NULL, 0 };
7954
6.91k
                SECItem keyblk = { siBuffer, NULL, 0 };
7955
6.91k
                SECItem master = { siBuffer, NULL, 0 };
7956
7957
6.91k
                srcr.data = srcrdata;
7958
6.91k
                srcr.len = sizeof srcrdata;
7959
6.91k
                keyblk.data = key_block;
7960
6.91k
                keyblk.len = block_needed;
7961
6.91k
                master.data = (unsigned char *)att->attrib.pValue;
7962
6.91k
                master.len = att->attrib.ulValueLen;
7963
7964
6.91k
                if (tlsPrfHash != HASH_AlgNULL) {
7965
3.52k
                    status = TLS_P_hash(tlsPrfHash, &master, "key expansion",
7966
3.52k
                                        &srcr, &keyblk, isFIPS);
7967
3.52k
                } else {
7968
3.38k
                    status = TLS_PRF(&master, "key expansion", &srcr, &keyblk,
7969
3.38k
                                     isFIPS);
7970
3.38k
                }
7971
6.91k
                if (status != SECSuccess) {
7972
0
                    goto key_and_mac_derive_fail;
7973
0
                }
7974
6.91k
            } else {
7975
0
                unsigned int block_bytes = 0;
7976
                /* key_block =
7977
                 *     MD5(master_secret + SHA('A' + master_secret +
7978
                 *                      ServerHello.random + ClientHello.random)) +
7979
                 *     MD5(master_secret + SHA('BB' + master_secret +
7980
                 *                      ServerHello.random + ClientHello.random)) +
7981
                 *     MD5(master_secret + SHA('CCC' + master_secret +
7982
                 *                      ServerHello.random + ClientHello.random)) +
7983
                 *     [...];
7984
                 */
7985
0
                for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) {
7986
0
                    SHA1_Begin(sha);
7987
0
                    SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i]));
7988
0
                    SHA1_Update(sha, (const unsigned char *)att->attrib.pValue,
7989
0
                                att->attrib.ulValueLen);
7990
0
                    SHA1_Update(sha, srcrdata, sizeof srcrdata);
7991
0
                    SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
7992
0
                    PORT_Assert(outLen == SHA1_LENGTH);
7993
0
                    MD5_Begin(md5);
7994
0
                    MD5_Update(md5, (const unsigned char *)att->attrib.pValue,
7995
0
                               att->attrib.ulValueLen);
7996
0
                    MD5_Update(md5, sha_out, outLen);
7997
0
                    MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH);
7998
0
                    PORT_Assert(outLen == MD5_LENGTH);
7999
0
                    block_bytes += outLen;
8000
0
                }
8001
0
                PORT_Memset(sha_out, 0, sizeof sha_out);
8002
0
            }
8003
8004
            /*
8005
             * Put the key material where it goes.
8006
             */
8007
6.91k
            i = 0; /* now shows how much consumed */
8008
8009
            /*
8010
             * The key_block is partitioned as follows:
8011
             * client_write_MAC_secret[CipherSpec.hash_size]
8012
             */
8013
6.91k
            crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
8014
6.91k
                                   &ssl3_keys_out->hClientMacSecret);
8015
6.91k
            if (crv != CKR_OK)
8016
0
                goto key_and_mac_derive_fail;
8017
8018
6.91k
            i += macSize;
8019
8020
            /*
8021
             * server_write_MAC_secret[CipherSpec.hash_size]
8022
             */
8023
6.91k
            crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
8024
6.91k
                                   &ssl3_keys_out->hServerMacSecret);
8025
6.91k
            if (crv != CKR_OK) {
8026
0
                goto key_and_mac_derive_fail;
8027
0
            }
8028
6.91k
            i += macSize;
8029
8030
6.91k
            if (keySize) {
8031
                /*
8032
                ** Generate Domestic write keys and IVs.
8033
                ** client_write_key[CipherSpec.key_material]
8034
                */
8035
5.79k
                crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
8036
5.79k
                                       keySize, &ssl3_keys_out->hClientKey);
8037
5.79k
                if (crv != CKR_OK) {
8038
0
                    goto key_and_mac_derive_fail;
8039
0
                }
8040
5.79k
                i += keySize;
8041
8042
                /*
8043
                ** server_write_key[CipherSpec.key_material]
8044
                */
8045
5.79k
                crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
8046
5.79k
                                       keySize, &ssl3_keys_out->hServerKey);
8047
5.79k
                if (crv != CKR_OK) {
8048
0
                    goto key_and_mac_derive_fail;
8049
0
                }
8050
5.79k
                i += keySize;
8051
8052
                /*
8053
                ** client_write_IV[CipherSpec.IV_size]
8054
                */
8055
5.79k
                if (IVSize > 0) {
8056
5.54k
                    PORT_Memcpy(ssl3_keys_out->pIVClient,
8057
5.54k
                                &key_block[i], IVSize);
8058
5.54k
                    i += IVSize;
8059
5.54k
                }
8060
8061
                /*
8062
                ** server_write_IV[CipherSpec.IV_size]
8063
                */
8064
5.79k
                if (IVSize > 0) {
8065
5.54k
                    PORT_Memcpy(ssl3_keys_out->pIVServer,
8066
5.54k
                                &key_block[i], IVSize);
8067
5.54k
                    i += IVSize;
8068
5.54k
                }
8069
5.79k
                PORT_Assert(i <= sizeof key_block);
8070
5.79k
            }
8071
8072
6.91k
            crv = CKR_OK;
8073
8074
6.91k
            if (0) {
8075
0
            key_and_mac_derive_fail:
8076
0
                if (crv == CKR_OK)
8077
0
                    crv = CKR_FUNCTION_FAILED;
8078
0
                sftk_freeSSLKeys(hSession, ssl3_keys_out);
8079
0
            }
8080
6.91k
            PORT_Memset(srcrdata, 0, sizeof srcrdata);
8081
6.91k
            PORT_Memset(key_block, 0, sizeof key_block);
8082
6.91k
            MD5_DestroyContext(md5, PR_TRUE);
8083
6.91k
            SHA1_DestroyContext(sha, PR_TRUE);
8084
6.91k
            sftk_FreeObject(key);
8085
6.91k
            key = NULL;
8086
6.91k
            break;
8087
6.91k
        }
8088
8089
0
        case CKM_DES3_ECB_ENCRYPT_DATA:
8090
0
        case CKM_DES3_CBC_ENCRYPT_DATA: {
8091
0
            void *cipherInfo;
8092
0
            unsigned char des3key[MAX_DES3_KEY_SIZE];
8093
0
            CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr;
8094
0
            int mode;
8095
0
            unsigned char *iv;
8096
0
            unsigned char *data;
8097
0
            CK_ULONG len;
8098
8099
0
            if (mechanism == CKM_DES3_ECB_ENCRYPT_DATA) {
8100
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8101
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8102
0
                    break;
8103
0
                }
8104
0
                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
8105
0
                                pMechanism->pParameter;
8106
0
                mode = NSS_DES_EDE3;
8107
0
                iv = NULL;
8108
0
                data = stringPtr->pData;
8109
0
                len = stringPtr->ulLen;
8110
0
            } else {
8111
0
                mode = NSS_DES_EDE3_CBC;
8112
0
                desEncryptPtr =
8113
0
                    (CK_DES_CBC_ENCRYPT_DATA_PARAMS *)
8114
0
                        pMechanism->pParameter;
8115
0
                iv = desEncryptPtr->iv;
8116
0
                data = desEncryptPtr->pData;
8117
0
                len = desEncryptPtr->length;
8118
0
            }
8119
0
            if (att->attrib.ulValueLen == 16) {
8120
0
                PORT_Memcpy(des3key, att->attrib.pValue, 16);
8121
0
                PORT_Memcpy(des3key + 16, des3key, 8);
8122
0
            } else if (att->attrib.ulValueLen == 24) {
8123
0
                PORT_Memcpy(des3key, att->attrib.pValue, 24);
8124
0
            } else {
8125
0
                crv = CKR_KEY_SIZE_RANGE;
8126
0
                break;
8127
0
            }
8128
0
            cipherInfo = DES_CreateContext(des3key, iv, mode, PR_TRUE);
8129
0
            PORT_Memset(des3key, 0, 24);
8130
0
            if (cipherInfo == NULL) {
8131
0
                crv = CKR_HOST_MEMORY;
8132
0
                break;
8133
0
            }
8134
0
            crv = sftk_DeriveEncrypt((SFTKCipher)DES_Encrypt,
8135
0
                                     cipherInfo, 8, key, keySize,
8136
0
                                     data, len);
8137
0
            DES_DestroyContext(cipherInfo, PR_TRUE);
8138
0
            break;
8139
0
        }
8140
8141
0
        case CKM_AES_ECB_ENCRYPT_DATA:
8142
0
        case CKM_AES_CBC_ENCRYPT_DATA: {
8143
0
            void *cipherInfo;
8144
0
            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
8145
0
            int mode;
8146
0
            unsigned char *iv;
8147
0
            unsigned char *data;
8148
0
            CK_ULONG len;
8149
8150
0
            if (mechanism == CKM_AES_ECB_ENCRYPT_DATA) {
8151
0
                mode = NSS_AES;
8152
0
                iv = NULL;
8153
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8154
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8155
0
                    break;
8156
0
                }
8157
0
                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8158
0
                data = stringPtr->pData;
8159
0
                len = stringPtr->ulLen;
8160
0
            } else {
8161
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
8162
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8163
0
                    break;
8164
0
                }
8165
0
                aesEncryptPtr =
8166
0
                    (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)pMechanism->pParameter;
8167
0
                mode = NSS_AES_CBC;
8168
0
                iv = aesEncryptPtr->iv;
8169
0
                data = aesEncryptPtr->pData;
8170
0
                len = aesEncryptPtr->length;
8171
0
            }
8172
8173
0
            cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue,
8174
0
                                           iv, mode, PR_TRUE,
8175
0
                                           att->attrib.ulValueLen, 16);
8176
0
            if (cipherInfo == NULL) {
8177
0
                crv = CKR_HOST_MEMORY;
8178
0
                break;
8179
0
            }
8180
0
            crv = sftk_DeriveEncrypt((SFTKCipher)AES_Encrypt,
8181
0
                                     cipherInfo, 16, key, keySize,
8182
0
                                     data, len);
8183
0
            AES_DestroyContext(cipherInfo, PR_TRUE);
8184
0
            break;
8185
0
        }
8186
8187
0
        case CKM_CAMELLIA_ECB_ENCRYPT_DATA:
8188
0
        case CKM_CAMELLIA_CBC_ENCRYPT_DATA: {
8189
0
            void *cipherInfo;
8190
0
            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
8191
0
            int mode;
8192
0
            unsigned char *iv;
8193
0
            unsigned char *data;
8194
0
            CK_ULONG len;
8195
8196
0
            if (mechanism == CKM_CAMELLIA_ECB_ENCRYPT_DATA) {
8197
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8198
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8199
0
                    break;
8200
0
                }
8201
0
                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
8202
0
                                pMechanism->pParameter;
8203
0
                aesEncryptPtr = NULL;
8204
0
                mode = NSS_CAMELLIA;
8205
0
                data = stringPtr->pData;
8206
0
                len = stringPtr->ulLen;
8207
0
                iv = NULL;
8208
0
            } else {
8209
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
8210
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8211
0
                    break;
8212
0
                }
8213
0
                stringPtr = NULL;
8214
0
                aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
8215
0
                                    pMechanism->pParameter;
8216
0
                mode = NSS_CAMELLIA_CBC;
8217
0
                iv = aesEncryptPtr->iv;
8218
0
                data = aesEncryptPtr->pData;
8219
0
                len = aesEncryptPtr->length;
8220
0
            }
8221
8222
0
            cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue,
8223
0
                                                iv, mode, PR_TRUE,
8224
0
                                                att->attrib.ulValueLen);
8225
0
            if (cipherInfo == NULL) {
8226
0
                crv = CKR_HOST_MEMORY;
8227
0
                break;
8228
0
            }
8229
0
            crv = sftk_DeriveEncrypt((SFTKCipher)Camellia_Encrypt,
8230
0
                                     cipherInfo, 16, key, keySize,
8231
0
                                     data, len);
8232
0
            Camellia_DestroyContext(cipherInfo, PR_TRUE);
8233
0
            break;
8234
0
        }
8235
8236
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
8237
0
        case CKM_SEED_ECB_ENCRYPT_DATA:
8238
0
        case CKM_SEED_CBC_ENCRYPT_DATA: {
8239
0
            void *cipherInfo;
8240
0
            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
8241
0
            int mode;
8242
0
            unsigned char *iv;
8243
0
            unsigned char *data;
8244
0
            CK_ULONG len;
8245
8246
0
            if (mechanism == CKM_SEED_ECB_ENCRYPT_DATA) {
8247
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8248
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8249
0
                    break;
8250
0
                }
8251
0
                mode = NSS_SEED;
8252
0
                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
8253
0
                                pMechanism->pParameter;
8254
0
                aesEncryptPtr = NULL;
8255
0
                data = stringPtr->pData;
8256
0
                len = stringPtr->ulLen;
8257
0
                iv = NULL;
8258
0
            } else {
8259
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
8260
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8261
0
                    break;
8262
0
                }
8263
0
                mode = NSS_SEED_CBC;
8264
0
                aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
8265
0
                                    pMechanism->pParameter;
8266
0
                iv = aesEncryptPtr->iv;
8267
0
                data = aesEncryptPtr->pData;
8268
0
                len = aesEncryptPtr->length;
8269
0
            }
8270
8271
0
            cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue,
8272
0
                                            iv, mode, PR_TRUE);
8273
0
            if (cipherInfo == NULL) {
8274
0
                crv = CKR_HOST_MEMORY;
8275
0
                break;
8276
0
            }
8277
0
            crv = sftk_DeriveEncrypt((SFTKCipher)SEED_Encrypt,
8278
0
                                     cipherInfo, 16, key, keySize,
8279
0
                                     data, len);
8280
0
            SEED_DestroyContext(cipherInfo, PR_TRUE);
8281
0
            break;
8282
0
        }
8283
0
#endif /* NSS_DISABLE_DEPRECATED_SEED */
8284
8285
0
        case CKM_CONCATENATE_BASE_AND_KEY: {
8286
0
            SFTKObject *paramKey;
8287
8288
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8289
0
            if (crv != CKR_OK)
8290
0
                break;
8291
8292
0
            session = sftk_SessionFromHandle(hSession);
8293
0
            if (session == NULL) {
8294
0
                crv = CKR_SESSION_HANDLE_INVALID;
8295
0
                break;
8296
0
            }
8297
8298
0
            paramKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *)
8299
0
                                                  pMechanism->pParameter,
8300
0
                                             session);
8301
0
            sftk_FreeSession(session);
8302
0
            if (paramKey == NULL) {
8303
0
                crv = CKR_KEY_HANDLE_INVALID;
8304
0
                break;
8305
0
            }
8306
8307
0
            if (sftk_isTrue(paramKey, CKA_SENSITIVE)) {
8308
0
                crv = sftk_forceAttribute(key, CKA_SENSITIVE, &cktrue,
8309
0
                                          sizeof(CK_BBOOL));
8310
0
                if (crv != CKR_OK) {
8311
0
                    sftk_FreeObject(paramKey);
8312
0
                    break;
8313
0
                }
8314
0
            }
8315
8316
0
            if (sftk_hasAttribute(paramKey, CKA_EXTRACTABLE) && !sftk_isTrue(paramKey, CKA_EXTRACTABLE)) {
8317
0
                crv = sftk_forceAttribute(key, CKA_EXTRACTABLE, &ckfalse, sizeof(CK_BBOOL));
8318
0
                if (crv != CKR_OK) {
8319
0
                    sftk_FreeObject(paramKey);
8320
0
                    break;
8321
0
                }
8322
0
            }
8323
8324
0
            att2 = sftk_FindAttribute(paramKey, CKA_VALUE);
8325
0
            if (att2 == NULL) {
8326
0
                sftk_FreeObject(paramKey);
8327
0
                crv = CKR_KEY_HANDLE_INVALID;
8328
0
                break;
8329
0
            }
8330
0
            tmpKeySize = att->attrib.ulValueLen + att2->attrib.ulValueLen;
8331
0
            if (keySize == 0)
8332
0
                keySize = tmpKeySize;
8333
0
            if (keySize > tmpKeySize) {
8334
0
                sftk_FreeObject(paramKey);
8335
0
                sftk_FreeAttribute(att2);
8336
0
                crv = CKR_TEMPLATE_INCONSISTENT;
8337
0
                break;
8338
0
            }
8339
0
            buf = (unsigned char *)PORT_Alloc(tmpKeySize);
8340
0
            if (buf == NULL) {
8341
0
                sftk_FreeAttribute(att2);
8342
0
                sftk_FreeObject(paramKey);
8343
0
                crv = CKR_HOST_MEMORY;
8344
0
                break;
8345
0
            }
8346
8347
0
            PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
8348
0
            PORT_Memcpy(buf + att->attrib.ulValueLen,
8349
0
                        att2->attrib.pValue, att2->attrib.ulValueLen);
8350
8351
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8352
0
            PORT_ZFree(buf, tmpKeySize);
8353
0
            sftk_FreeAttribute(att2);
8354
0
            sftk_FreeObject(paramKey);
8355
0
            break;
8356
0
        }
8357
8358
0
        case CKM_CONCATENATE_BASE_AND_DATA:
8359
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8360
0
            if (crv != CKR_OK)
8361
0
                break;
8362
8363
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8364
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8365
0
                break;
8366
0
            }
8367
0
            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8368
0
            tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
8369
0
            if (keySize == 0)
8370
0
                keySize = tmpKeySize;
8371
0
            if (keySize > tmpKeySize) {
8372
0
                crv = CKR_TEMPLATE_INCONSISTENT;
8373
0
                break;
8374
0
            }
8375
0
            buf = (unsigned char *)PORT_Alloc(tmpKeySize);
8376
0
            if (buf == NULL) {
8377
0
                crv = CKR_HOST_MEMORY;
8378
0
                break;
8379
0
            }
8380
8381
0
            PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
8382
0
            PORT_Memcpy(buf + att->attrib.ulValueLen, stringPtr->pData,
8383
0
                        stringPtr->ulLen);
8384
8385
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8386
0
            PORT_ZFree(buf, tmpKeySize);
8387
0
            break;
8388
0
        case CKM_CONCATENATE_DATA_AND_BASE:
8389
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8390
0
            if (crv != CKR_OK)
8391
0
                break;
8392
8393
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8394
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8395
0
                break;
8396
0
            }
8397
0
            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8398
0
            tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
8399
0
            if (keySize == 0)
8400
0
                keySize = tmpKeySize;
8401
0
            if (keySize > tmpKeySize) {
8402
0
                crv = CKR_TEMPLATE_INCONSISTENT;
8403
0
                break;
8404
0
            }
8405
0
            buf = (unsigned char *)PORT_Alloc(tmpKeySize);
8406
0
            if (buf == NULL) {
8407
0
                crv = CKR_HOST_MEMORY;
8408
0
                break;
8409
0
            }
8410
8411
0
            PORT_Memcpy(buf, stringPtr->pData, stringPtr->ulLen);
8412
0
            PORT_Memcpy(buf + stringPtr->ulLen, att->attrib.pValue,
8413
0
                        att->attrib.ulValueLen);
8414
8415
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8416
0
            PORT_ZFree(buf, tmpKeySize);
8417
0
            break;
8418
0
        case CKM_XOR_BASE_AND_DATA:
8419
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8420
0
            if (crv != CKR_OK)
8421
0
                break;
8422
8423
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8424
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8425
0
                break;
8426
0
            }
8427
0
            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8428
0
            tmpKeySize = PR_MIN(att->attrib.ulValueLen, stringPtr->ulLen);
8429
0
            if (keySize == 0)
8430
0
                keySize = tmpKeySize;
8431
0
            if (keySize > tmpKeySize) {
8432
0
                crv = CKR_TEMPLATE_INCONSISTENT;
8433
0
                break;
8434
0
            }
8435
0
            buf = (unsigned char *)PORT_Alloc(keySize);
8436
0
            if (buf == NULL) {
8437
0
                crv = CKR_HOST_MEMORY;
8438
0
                break;
8439
0
            }
8440
8441
0
            PORT_Memcpy(buf, att->attrib.pValue, keySize);
8442
0
            for (i = 0; i < (int)keySize; i++) {
8443
0
                buf[i] ^= stringPtr->pData[i];
8444
0
            }
8445
8446
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8447
0
            PORT_ZFree(buf, keySize);
8448
0
            break;
8449
8450
0
        case CKM_EXTRACT_KEY_FROM_KEY: {
8451
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_EXTRACT_PARAMS))) {
8452
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8453
0
                break;
8454
0
            }
8455
            /* the following assumes 8 bits per byte */
8456
0
            CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;
8457
0
            CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */
8458
0
            CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */
8459
8460
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8461
0
            if (crv != CKR_OK)
8462
0
                break;
8463
8464
0
            if (keySize == 0) {
8465
0
                crv = CKR_TEMPLATE_INCOMPLETE;
8466
0
                break;
8467
0
            }
8468
            /* make sure we have enough bits in the original key */
8469
0
            if (att->attrib.ulValueLen <
8470
0
                (offset + keySize + ((shift != 0) ? 1 : 0))) {
8471
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8472
0
                break;
8473
0
            }
8474
0
            buf = (unsigned char *)PORT_Alloc(keySize);
8475
0
            if (buf == NULL) {
8476
0
                crv = CKR_HOST_MEMORY;
8477
0
                break;
8478
0
            }
8479
8480
            /* copy the bits we need into the new key */
8481
0
            for (i = 0; i < (int)keySize; i++) {
8482
0
                unsigned char *value =
8483
0
                    ((unsigned char *)att->attrib.pValue) + offset + i;
8484
0
                if (shift) {
8485
0
                    buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift));
8486
0
                } else {
8487
0
                    buf[i] = value[0];
8488
0
                }
8489
0
            }
8490
8491
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8492
0
            PORT_ZFree(buf, keySize);
8493
0
            break;
8494
0
        }
8495
0
        case CKM_MD2_KEY_DERIVATION:
8496
0
            if (keySize == 0)
8497
0
                keySize = MD2_LENGTH;
8498
0
            if (keySize > MD2_LENGTH) {
8499
0
                crv = CKR_TEMPLATE_INCONSISTENT;
8500
0
                break;
8501
0
            }
8502
            /* now allocate the hash contexts */
8503
0
            md2 = MD2_NewContext();
8504
0
            if (md2 == NULL) {
8505
0
                crv = CKR_HOST_MEMORY;
8506
0
                break;
8507
0
            }
8508
0
            MD2_Begin(md2);
8509
0
            MD2_Update(md2, (const unsigned char *)att->attrib.pValue,
8510
0
                       att->attrib.ulValueLen);
8511
0
            MD2_End(md2, key_block, &outLen, MD2_LENGTH);
8512
0
            MD2_DestroyContext(md2, PR_TRUE);
8513
8514
0
            crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);
8515
0
            PORT_Memset(key_block, 0, MD2_LENGTH);
8516
0
            break;
8517
0
#define DERIVE_KEY_HASH(hash)                                                \
8518
0
    case CKM_##hash##_KEY_DERIVATION:                                        \
8519
0
        if (keySize == 0)                                                    \
8520
0
            keySize = hash##_LENGTH;                                         \
8521
0
        if (keySize > hash##_LENGTH) {                                       \
8522
0
            crv = CKR_TEMPLATE_INCONSISTENT;                                 \
8523
0
            break;                                                           \
8524
0
        }                                                                    \
8525
0
        hash##_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, \
8526
0
                       att->attrib.ulValueLen);                              \
8527
0
        crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);       \
8528
0
        PORT_Memset(key_block, 0, hash##_LENGTH);                            \
8529
0
        break;
8530
0
            DERIVE_KEY_HASH(MD5)
8531
0
            DERIVE_KEY_HASH(SHA1)
8532
0
            DERIVE_KEY_HASH(SHA224)
8533
0
            DERIVE_KEY_HASH(SHA256)
8534
0
            DERIVE_KEY_HASH(SHA384)
8535
0
            DERIVE_KEY_HASH(SHA512)
8536
0
            DERIVE_KEY_HASH(SHA3_224)
8537
0
            DERIVE_KEY_HASH(SHA3_256)
8538
0
            DERIVE_KEY_HASH(SHA3_384)
8539
0
            DERIVE_KEY_HASH(SHA3_512)
8540
8541
6.60k
        case CKM_DH_PKCS_DERIVE: {
8542
6.60k
            SECItem derived, dhPublic;
8543
6.60k
            SECItem dhPrime, dhValue;
8544
6.60k
            const SECItem *subPrime;
8545
            /* sourceKey - values for the local existing low key */
8546
            /* get prime and value attributes */
8547
6.60k
            crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
8548
6.60k
            if (crv != CKR_OK)
8549
0
                break;
8550
8551
6.60k
            dhPublic.data = pMechanism->pParameter;
8552
6.60k
            dhPublic.len = pMechanism->ulParameterLen;
8553
8554
            /* if the prime is an approved prime, we can skip all the other
8555
             * checks. */
8556
6.60k
            subPrime = sftk_VerifyDH_Prime(&dhPrime, isFIPS);
8557
6.60k
            if (subPrime == NULL) {
8558
0
                SECItem dhSubPrime;
8559
                /* If the caller set the subprime value, it means that
8560
                 * either the caller knows the subprime value and wants us
8561
                 * to validate the key against the subprime, or that the
8562
                 * caller wants us to verify that the prime is a safe prime
8563
                 * by passing in subprime = (prime-1)/2 */
8564
0
                dhSubPrime.data = NULL;
8565
0
                dhSubPrime.len = 0;
8566
0
                crv = sftk_Attribute2SecItem(NULL, &dhSubPrime,
8567
0
                                             sourceKey, CKA_SUBPRIME);
8568
                /* we ignore the value of crv here, We treat a valid
8569
                * return of len = 0 and a failure to find a subrime the same
8570
                * NOTE: we free the subprime in both cases depending on
8571
                * PORT_Free of NULL to be a noop */
8572
0
                if (dhSubPrime.len != 0) {
8573
0
                    PRBool isSafe = PR_FALSE;
8574
8575
                    /* Callers can set dhSubPrime to q=(p-1)/2 to force
8576
                     * checks for safe primes. If so we only need to check
8577
                     * q and p for primality and skip the group test.  */
8578
0
                    rv = sftk_IsSafePrime(&dhPrime, &dhSubPrime, &isSafe);
8579
0
                    if (rv != SECSuccess) {
8580
                        /* either p or q was even and therefore not prime,
8581
                         * we can stop processing here and fail now */
8582
0
                        crv = CKR_ARGUMENTS_BAD;
8583
0
                        SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8584
0
                        SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8585
0
                        break;
8586
0
                    }
8587
8588
                    /* first make sure the primes are really prime */
8589
0
                    if (!KEA_PrimeCheck(&dhPrime)) {
8590
0
                        crv = CKR_ARGUMENTS_BAD;
8591
0
                        SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8592
0
                        SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8593
0
                        break;
8594
0
                    }
8595
0
                    if (!KEA_PrimeCheck(&dhSubPrime)) {
8596
0
                        crv = CKR_ARGUMENTS_BAD;
8597
0
                        SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8598
0
                        SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8599
0
                        break;
8600
0
                    }
8601
0
                    if (isFIPS || !isSafe) {
8602
                        /* With safe primes, there is only one other small
8603
                         * subgroup. As long as y isn't 0, 1, or -1 mod p,
8604
                         * any other y is safe. Only do the full check for
8605
                         * non-safe primes, except in FIPS mode we need
8606
                         * to do this check on all primes in which
8607
                         * we receive the subprime value */
8608
0
                        if (!KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime)) {
8609
0
                            crv = CKR_ARGUMENTS_BAD;
8610
0
                            SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8611
0
                            SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8612
0
                            break;
8613
0
                        }
8614
0
                    }
8615
0
                } else if (isFIPS) {
8616
                    /* In FIPS mode we only accept approved primes, or
8617
                     * primes with the full subprime value */
8618
0
                    crv = CKR_ARGUMENTS_BAD;
8619
0
                    SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8620
0
                    break;
8621
0
                }
8622
                /* checks are complete, no need for the subPrime any longer */
8623
0
                SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8624
0
            }
8625
8626
            /* now that the prime is validated, get the private value */
8627
6.60k
            crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
8628
6.60k
            if (crv != CKR_OK) {
8629
0
                SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8630
0
                break;
8631
0
            }
8632
8633
            /* calculate private value - oct */
8634
6.60k
            rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
8635
8636
6.60k
            SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8637
6.60k
            SECITEM_ZfreeItem(&dhValue, PR_FALSE);
8638
8639
6.60k
            if (rv == SECSuccess) {
8640
6.60k
                sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
8641
6.60k
                SECITEM_ZfreeItem(&derived, PR_FALSE);
8642
6.60k
                crv = CKR_OK;
8643
6.60k
            } else
8644
0
                crv = CKR_HOST_MEMORY;
8645
8646
6.60k
            break;
8647
6.60k
        }
8648
8649
42.9k
        case CKM_ECDH1_DERIVE:
8650
42.9k
        case CKM_ECDH1_COFACTOR_DERIVE: {
8651
42.9k
            SECItem ecScalar, ecPoint;
8652
42.9k
            SECItem tmp;
8653
42.9k
            PRBool withCofactor = PR_FALSE;
8654
42.9k
            unsigned char *secret;
8655
42.9k
            unsigned char *keyData = NULL;
8656
42.9k
            unsigned int secretlen, pubKeyLen;
8657
42.9k
            CK_ECDH1_DERIVE_PARAMS *mechParams;
8658
42.9k
            NSSLOWKEYPrivateKey *privKey;
8659
42.9k
            PLArenaPool *arena = NULL;
8660
8661
            /* Check mechanism parameters */
8662
42.9k
            mechParams = (CK_ECDH1_DERIVE_PARAMS *)pMechanism->pParameter;
8663
42.9k
            if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) ||
8664
42.9k
                ((mechParams->kdf == CKD_NULL) &&
8665
42.9k
                 ((mechParams->ulSharedDataLen != 0) ||
8666
42.9k
                  (mechParams->pSharedData != NULL)))) {
8667
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8668
0
                break;
8669
0
            }
8670
8671
42.9k
            privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv);
8672
42.9k
            if (privKey == NULL) {
8673
0
                break;
8674
0
            }
8675
8676
            /* Now we are working with a non-NULL private key */
8677
42.9k
            SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue);
8678
8679
42.9k
            ecPoint.data = mechParams->pPublicData;
8680
42.9k
            ecPoint.len = mechParams->ulPublicDataLen;
8681
8682
42.9k
            pubKeyLen = EC_GetPointSize(&privKey->u.ec.ecParams);
8683
8684
            /* if the len is too large, might be an encoded point */
8685
42.9k
            if (ecPoint.len > pubKeyLen) {
8686
15.6k
                SECItem newPoint;
8687
8688
15.6k
                arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
8689
15.6k
                if (arena == NULL) {
8690
0
                    goto ec_loser;
8691
0
                }
8692
8693
15.6k
                rv = SEC_QuickDERDecodeItem(arena, &newPoint,
8694
15.6k
                                            SEC_ASN1_GET(SEC_OctetStringTemplate),
8695
15.6k
                                            &ecPoint);
8696
15.6k
                if (rv != SECSuccess) {
8697
135
                    goto ec_loser;
8698
135
                }
8699
15.5k
                ecPoint = newPoint;
8700
15.5k
            }
8701
8702
42.7k
            if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) {
8703
0
                withCofactor = PR_TRUE;
8704
0
            }
8705
8706
42.7k
            rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
8707
42.7k
                             withCofactor, &tmp);
8708
42.7k
            SECITEM_ZfreeItem(&ecScalar, PR_FALSE);
8709
42.7k
            ecScalar.data = NULL;
8710
42.7k
            if (privKey != sourceKey->objectInfo) {
8711
0
                nsslowkey_DestroyPrivateKey(privKey);
8712
0
                privKey = NULL;
8713
0
            }
8714
42.7k
            if (arena) {
8715
15.5k
                PORT_FreeArena(arena, PR_FALSE);
8716
15.5k
                arena = NULL;
8717
15.5k
            }
8718
8719
42.7k
            if (rv != SECSuccess) {
8720
3.20k
                crv = sftk_MapCryptError(PORT_GetError());
8721
3.20k
                break;
8722
3.20k
            }
8723
8724
            /*
8725
             * apply the kdf function.
8726
             */
8727
39.5k
            if (mechParams->kdf == CKD_NULL) {
8728
                /*
8729
             * tmp is the raw data created by ECDH_Derive,
8730
             * secret and secretlen are the values we will
8731
             * eventually pass as our generated key.
8732
             */
8733
39.5k
                secret = tmp.data;
8734
39.5k
                secretlen = tmp.len;
8735
39.5k
            } else {
8736
0
                secretlen = keySize;
8737
0
                crv = sftk_ANSI_X9_63_kdf(&secret, keySize,
8738
0
                                          &tmp, mechParams->pSharedData,
8739
0
                                          mechParams->ulSharedDataLen, mechParams->kdf);
8740
0
                PORT_ZFree(tmp.data, tmp.len);
8741
0
                if (crv != CKR_OK) {
8742
0
                    break;
8743
0
                }
8744
0
                tmp.data = secret;
8745
0
                tmp.len = secretlen;
8746
0
            }
8747
8748
            /*
8749
             * if keySize is supplied, then we are generating a key of a specific
8750
             * length. This is done by taking the least significant 'keySize'
8751
             * bytes from the unsigned value calculated by ECDH. Note: this may
8752
             * mean padding temp with extra leading zeros from what ECDH_Derive
8753
             * already returned (which itself may contain leading zeros).
8754
             */
8755
39.5k
            if (keySize) {
8756
39.5k
                if (secretlen < keySize) {
8757
34.8k
                    keyData = PORT_ZAlloc(keySize);
8758
34.8k
                    if (!keyData) {
8759
0
                        PORT_ZFree(tmp.data, tmp.len);
8760
0
                        crv = CKR_HOST_MEMORY;
8761
0
                        break;
8762
0
                    }
8763
34.8k
                    PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen);
8764
34.8k
                    secret = keyData;
8765
34.8k
                } else {
8766
4.76k
                    secret += (secretlen - keySize);
8767
4.76k
                }
8768
39.5k
                secretlen = keySize;
8769
39.5k
            }
8770
8771
39.5k
            sftk_forceAttribute(key, CKA_VALUE, secret, secretlen);
8772
39.5k
            PORT_ZFree(tmp.data, tmp.len);
8773
39.5k
            if (keyData) {
8774
34.8k
                PORT_ZFree(keyData, keySize);
8775
34.8k
            }
8776
39.5k
            break;
8777
8778
135
        ec_loser:
8779
135
            crv = CKR_ARGUMENTS_BAD;
8780
135
            SECITEM_ZfreeItem(&ecScalar, PR_FALSE);
8781
135
            if (privKey != sourceKey->objectInfo)
8782
0
                nsslowkey_DestroyPrivateKey(privKey);
8783
135
            if (arena) {
8784
135
                PORT_FreeArena(arena, PR_TRUE);
8785
135
            }
8786
135
            break;
8787
39.5k
        }
8788
        /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */
8789
0
        case CKM_NSS_HKDF_SHA1:
8790
0
            hashMech = CKM_SHA_1;
8791
0
            goto hkdf;
8792
0
        case CKM_NSS_HKDF_SHA256:
8793
0
            hashMech = CKM_SHA256;
8794
0
            goto hkdf;
8795
0
        case CKM_NSS_HKDF_SHA384:
8796
0
            hashMech = CKM_SHA384;
8797
0
            goto hkdf;
8798
0
        case CKM_NSS_HKDF_SHA512:
8799
0
            hashMech = CKM_SHA512;
8800
0
            goto hkdf;
8801
0
        hkdf : {
8802
0
            const CK_NSS_HKDFParams *params =
8803
0
                (const CK_NSS_HKDFParams *)pMechanism->pParameter;
8804
0
            CK_HKDF_PARAMS hkdfParams;
8805
8806
0
            if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams)) {
8807
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8808
0
                break;
8809
0
            }
8810
0
            hkdfParams.bExtract = params->bExtract;
8811
0
            hkdfParams.bExpand = params->bExpand;
8812
0
            if (params->pSalt) {
8813
0
                hkdfParams.ulSaltType = CKF_HKDF_SALT_DATA;
8814
0
            } else {
8815
0
                hkdfParams.ulSaltType = CKF_HKDF_SALT_NULL;
8816
0
            }
8817
0
            hkdfParams.pSalt = params->pSalt;
8818
0
            hkdfParams.ulSaltLen = params->ulSaltLen;
8819
0
            hkdfParams.hSaltKey = CK_INVALID_HANDLE;
8820
0
            hkdfParams.pInfo = params->pInfo;
8821
0
            hkdfParams.ulInfoLen = params->ulInfoLen;
8822
0
            hkdfParams.prfHashMechanism = hashMech;
8823
8824
0
            crv = sftk_HKDF(&hkdfParams, hSession, sourceKey,
8825
0
                            att->attrib.pValue, att->attrib.ulValueLen,
8826
0
                            key, NULL, keySize, PR_FALSE, isFIPS);
8827
0
        } break;
8828
18.0k
        case CKM_HKDF_DERIVE:
8829
21.3k
        case CKM_HKDF_DATA: /* only difference is the class of key */
8830
21.3k
            if ((pMechanism->pParameter == NULL) ||
8831
21.3k
                (pMechanism->ulParameterLen != sizeof(CK_HKDF_PARAMS))) {
8832
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8833
0
                break;
8834
0
            }
8835
21.3k
            crv = sftk_HKDF((CK_HKDF_PARAMS_PTR)pMechanism->pParameter,
8836
21.3k
                            hSession, sourceKey, att->attrib.pValue,
8837
21.3k
                            att->attrib.ulValueLen, key, NULL, keySize, PR_TRUE,
8838
21.3k
                            isFIPS);
8839
21.3k
            break;
8840
0
        case CKM_NSS_JPAKE_ROUND2_SHA1:
8841
0
            hashType = HASH_AlgSHA1;
8842
0
            goto jpake2;
8843
0
        case CKM_NSS_JPAKE_ROUND2_SHA256:
8844
0
            hashType = HASH_AlgSHA256;
8845
0
            goto jpake2;
8846
0
        case CKM_NSS_JPAKE_ROUND2_SHA384:
8847
0
            hashType = HASH_AlgSHA384;
8848
0
            goto jpake2;
8849
0
        case CKM_NSS_JPAKE_ROUND2_SHA512:
8850
0
            hashType = HASH_AlgSHA512;
8851
0
            goto jpake2;
8852
0
        jpake2:
8853
0
            if (pMechanism->pParameter == NULL ||
8854
0
                pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params))
8855
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8856
0
            if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN))
8857
0
                crv = CKR_TEMPLATE_INCONSISTENT;
8858
0
            if (crv == CKR_OK)
8859
0
                crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8860
0
            if (crv == CKR_OK)
8861
0
                crv = jpake_Round2(hashType,
8862
0
                                   (CK_NSS_JPAKERound2Params *)pMechanism->pParameter,
8863
0
                                   sourceKey, key);
8864
0
            break;
8865
8866
0
        case CKM_NSS_JPAKE_FINAL_SHA1:
8867
0
            hashType = HASH_AlgSHA1;
8868
0
            goto jpakeFinal;
8869
0
        case CKM_NSS_JPAKE_FINAL_SHA256:
8870
0
            hashType = HASH_AlgSHA256;
8871
0
            goto jpakeFinal;
8872
0
        case CKM_NSS_JPAKE_FINAL_SHA384:
8873
0
            hashType = HASH_AlgSHA384;
8874
0
            goto jpakeFinal;
8875
0
        case CKM_NSS_JPAKE_FINAL_SHA512:
8876
0
            hashType = HASH_AlgSHA512;
8877
0
            goto jpakeFinal;
8878
0
        jpakeFinal:
8879
0
            if (pMechanism->pParameter == NULL ||
8880
0
                pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams))
8881
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8882
            /* We purposely do not do the derive sensitivity check; we want to be
8883
               able to derive non-sensitive keys while allowing the ROUND1 and
8884
               ROUND2 keys to be sensitive (which they always are, since they are
8885
               in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE
8886
               in the template in order for the resultant keyblock key to be
8887
               sensitive.
8888
             */
8889
0
            if (crv == CKR_OK)
8890
0
                crv = jpake_Final(hashType,
8891
0
                                  (CK_NSS_JPAKEFinalParams *)pMechanism->pParameter,
8892
0
                                  sourceKey, key);
8893
0
            break;
8894
8895
0
        case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA:         /* fall through */
8896
0
        case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA:        /* fall through */
8897
0
        case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */
8898
0
        case CKM_SP800_108_COUNTER_KDF:                         /* fall through */
8899
0
        case CKM_SP800_108_FEEDBACK_KDF:                        /* fall through */
8900
0
        case CKM_SP800_108_DOUBLE_PIPELINE_KDF:
8901
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8902
0
            if (crv != CKR_OK) {
8903
0
                break;
8904
0
            }
8905
8906
0
            crv = kbkdf_Dispatch(mechanism, hSession, pMechanism, sourceKey, key, keySize);
8907
0
            break;
8908
0
        default:
8909
0
            crv = CKR_MECHANISM_INVALID;
8910
84.6k
    }
8911
84.6k
    if (att) {
8912
84.6k
        sftk_FreeAttribute(att);
8913
84.6k
    }
8914
84.6k
    sftk_FreeObject(sourceKey);
8915
84.6k
    if (crv != CKR_OK) {
8916
3.34k
        if (key)
8917
3.34k
            sftk_FreeObject(key);
8918
3.34k
        return crv;
8919
3.34k
    }
8920
8921
    /* link the key object into the list */
8922
81.3k
    if (key) {
8923
74.4k
        SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
8924
74.4k
        PORT_Assert(sessKey);
8925
        /* get the session */
8926
74.4k
        sessKey->wasDerived = PR_TRUE;
8927
74.4k
        session = sftk_SessionFromHandle(hSession);
8928
74.4k
        if (session == NULL) {
8929
0
            sftk_FreeObject(key);
8930
0
            return CKR_HOST_MEMORY;
8931
0
        }
8932
8933
74.4k
        crv = sftk_handleObject(key, session);
8934
74.4k
        session->lastOpWasFIPS = key->isFIPS;
8935
74.4k
        sftk_FreeSession(session);
8936
74.4k
        *phKey = key->handle;
8937
74.4k
        sftk_FreeObject(key);
8938
74.4k
    }
8939
81.3k
    return crv;
8940
81.3k
}
8941
8942
/* NSC_GetFunctionStatus obtains an updated status of a function running
8943
 * in parallel with an application. */
8944
CK_RV
8945
NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)
8946
0
{
8947
0
    CHECK_FORK();
8948
8949
0
    return CKR_FUNCTION_NOT_PARALLEL;
8950
0
}
8951
8952
/* NSC_CancelFunction cancels a function running in parallel */
8953
CK_RV
8954
NSC_CancelFunction(CK_SESSION_HANDLE hSession)
8955
0
{
8956
0
    CHECK_FORK();
8957
8958
0
    return CKR_FUNCTION_NOT_PARALLEL;
8959
0
}
8960
8961
/* NSC_GetOperationState saves the state of the cryptographic
8962
 * operation in a session.
8963
 * NOTE: This code only works for digest functions for now. eventually need
8964
 * to add full flatten/resurect to our state stuff so that all types of state
8965
 * can be saved */
8966
CK_RV
8967
NSC_GetOperationState(CK_SESSION_HANDLE hSession,
8968
                      CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
8969
26.7k
{
8970
26.7k
    SFTKSessionContext *context;
8971
26.7k
    SFTKSession *session;
8972
26.7k
    CK_RV crv;
8973
26.7k
    CK_ULONG pOSLen = *pulOperationStateLen;
8974
8975
26.7k
    CHECK_FORK();
8976
8977
    /* make sure we're legal */
8978
26.7k
    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
8979
26.7k
    if (crv != CKR_OK)
8980
0
        return crv;
8981
8982
    /* a zero cipherInfoLen signals that this context cannot be serialized */
8983
26.7k
    if (context->cipherInfoLen == 0) {
8984
0
        return CKR_STATE_UNSAVEABLE;
8985
0
    }
8986
8987
26.7k
    *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) + sizeof(SFTKContextType);
8988
26.7k
    if (pOperationState == NULL) {
8989
7.06k
        sftk_FreeSession(session);
8990
7.06k
        return CKR_OK;
8991
19.6k
    } else {
8992
19.6k
        if (pOSLen < *pulOperationStateLen) {
8993
0
            return CKR_BUFFER_TOO_SMALL;
8994
0
        }
8995
19.6k
    }
8996
19.6k
    PORT_Memcpy(pOperationState, &context->type, sizeof(SFTKContextType));
8997
19.6k
    pOperationState += sizeof(SFTKContextType);
8998
19.6k
    PORT_Memcpy(pOperationState, &context->currentMech,
8999
19.6k
                sizeof(CK_MECHANISM_TYPE));
9000
19.6k
    pOperationState += sizeof(CK_MECHANISM_TYPE);
9001
19.6k
    PORT_Memcpy(pOperationState, context->cipherInfo, context->cipherInfoLen);
9002
19.6k
    sftk_FreeSession(session);
9003
19.6k
    return CKR_OK;
9004
26.7k
}
9005
9006
#define sftk_Decrement(stateSize, len) \
9007
58.9k
    stateSize = ((stateSize) > (CK_ULONG)(len)) ? ((stateSize) - (CK_ULONG)(len)) : 0;
9008
9009
/* NSC_SetOperationState restores the state of the cryptographic
9010
 * operation in a session. This is coded like it can restore lots of
9011
 * states, but it only works for truly flat cipher structures. */
9012
CK_RV
9013
NSC_SetOperationState(CK_SESSION_HANDLE hSession,
9014
                      CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen,
9015
                      CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
9016
19.6k
{
9017
19.6k
    SFTKSessionContext *context;
9018
19.6k
    SFTKSession *session;
9019
19.6k
    SFTKContextType type;
9020
19.6k
    CK_MECHANISM mech;
9021
19.6k
    CK_RV crv = CKR_OK;
9022
9023
19.6k
    CHECK_FORK();
9024
9025
39.2k
    while (ulOperationStateLen != 0) {
9026
        /* get what type of state we're dealing with... */
9027
19.6k
        PORT_Memcpy(&type, pOperationState, sizeof(SFTKContextType));
9028
9029
        /* fix up session contexts based on type */
9030
19.6k
        session = sftk_SessionFromHandle(hSession);
9031
19.6k
        if (session == NULL)
9032
0
            return CKR_SESSION_HANDLE_INVALID;
9033
19.6k
        context = sftk_ReturnContextByType(session, type);
9034
19.6k
        sftk_SetContextByType(session, type, NULL);
9035
19.6k
        if (context) {
9036
7.06k
            sftk_FreeContext(context);
9037
7.06k
        }
9038
19.6k
        pOperationState += sizeof(SFTKContextType);
9039
19.6k
        sftk_Decrement(ulOperationStateLen, sizeof(SFTKContextType));
9040
9041
        /* get the mechanism structure */
9042
19.6k
        PORT_Memcpy(&mech.mechanism, pOperationState, sizeof(CK_MECHANISM_TYPE));
9043
19.6k
        pOperationState += sizeof(CK_MECHANISM_TYPE);
9044
19.6k
        sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE));
9045
        /* should be filled in... but not necessary for hash */
9046
19.6k
        mech.pParameter = NULL;
9047
19.6k
        mech.ulParameterLen = 0;
9048
19.6k
        switch (type) {
9049
19.6k
            case SFTK_HASH:
9050
19.6k
                crv = NSC_DigestInit(hSession, &mech);
9051
19.6k
                if (crv != CKR_OK)
9052
0
                    break;
9053
19.6k
                crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE,
9054
19.6k
                                      NULL);
9055
19.6k
                if (crv != CKR_OK)
9056
0
                    break;
9057
19.6k
                if (context->cipherInfoLen == 0) {
9058
0
                    crv = CKR_SAVED_STATE_INVALID;
9059
0
                    break;
9060
0
                }
9061
19.6k
                PORT_Memcpy(context->cipherInfo, pOperationState,
9062
19.6k
                            context->cipherInfoLen);
9063
19.6k
                pOperationState += context->cipherInfoLen;
9064
19.6k
                sftk_Decrement(ulOperationStateLen, context->cipherInfoLen);
9065
19.6k
                break;
9066
0
            default:
9067
                /* do sign/encrypt/decrypt later */
9068
0
                crv = CKR_SAVED_STATE_INVALID;
9069
19.6k
        }
9070
19.6k
        sftk_FreeSession(session);
9071
19.6k
        if (crv != CKR_OK)
9072
0
            break;
9073
19.6k
    }
9074
19.6k
    return crv;
9075
19.6k
}
9076
9077
/* Dual-function cryptographic operations */
9078
9079
/* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption
9080
 * operation. */
9081
CK_RV
9082
NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
9083
                        CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
9084
                        CK_ULONG_PTR pulEncryptedPartLen)
9085
0
{
9086
0
    CK_RV crv;
9087
9088
0
    CHECK_FORK();
9089
9090
0
    crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
9091
0
                            pulEncryptedPartLen);
9092
0
    if (crv != CKR_OK)
9093
0
        return crv;
9094
0
    crv = NSC_DigestUpdate(hSession, pPart, ulPartLen);
9095
9096
0
    return crv;
9097
0
}
9098
9099
/* NSC_DecryptDigestUpdate continues a multiple-part decryption and
9100
 * digesting operation. */
9101
CK_RV
9102
NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
9103
                        CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
9104
                        CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
9105
0
{
9106
0
    CK_RV crv;
9107
9108
0
    CHECK_FORK();
9109
9110
0
    crv = NSC_DecryptUpdate(hSession, pEncryptedPart, ulEncryptedPartLen,
9111
0
                            pPart, pulPartLen);
9112
0
    if (crv != CKR_OK)
9113
0
        return crv;
9114
0
    crv = NSC_DigestUpdate(hSession, pPart, *pulPartLen);
9115
9116
0
    return crv;
9117
0
}
9118
9119
/* NSC_SignEncryptUpdate continues a multiple-part signing and
9120
 * encryption operation. */
9121
CK_RV
9122
NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
9123
                      CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
9124
                      CK_ULONG_PTR pulEncryptedPartLen)
9125
0
{
9126
0
    CK_RV crv;
9127
9128
0
    CHECK_FORK();
9129
9130
0
    crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
9131
0
                            pulEncryptedPartLen);
9132
0
    if (crv != CKR_OK)
9133
0
        return crv;
9134
0
    crv = NSC_SignUpdate(hSession, pPart, ulPartLen);
9135
9136
0
    return crv;
9137
0
}
9138
9139
/* NSC_DecryptVerifyUpdate continues a multiple-part decryption
9140
 * and verify operation. */
9141
CK_RV
9142
NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
9143
                        CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
9144
                        CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
9145
0
{
9146
0
    CK_RV crv;
9147
9148
0
    CHECK_FORK();
9149
9150
0
    crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
9151
0
                            pData, pulDataLen);
9152
0
    if (crv != CKR_OK)
9153
0
        return crv;
9154
0
    crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen);
9155
9156
0
    return crv;
9157
0
}
9158
9159
/* NSC_DigestKey continues a multi-part message-digesting operation,
9160
 * by digesting the value of a secret key as part of the data already digested.
9161
 */
9162
CK_RV
9163
NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
9164
0
{
9165
0
    SFTKSession *session = NULL;
9166
0
    SFTKObject *key = NULL;
9167
0
    SFTKAttribute *att;
9168
0
    CK_RV crv;
9169
9170
0
    CHECK_FORK();
9171
9172
0
    session = sftk_SessionFromHandle(hSession);
9173
0
    if (session == NULL)
9174
0
        return CKR_SESSION_HANDLE_INVALID;
9175
9176
0
    key = sftk_ObjectFromHandle(hKey, session);
9177
0
    sftk_FreeSession(session);
9178
0
    if (key == NULL)
9179
0
        return CKR_KEY_HANDLE_INVALID;
9180
9181
    /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */
9182
9183
    /* make sure it's a valid  key for this operation */
9184
0
    if (key->objclass != CKO_SECRET_KEY) {
9185
0
        sftk_FreeObject(key);
9186
0
        return CKR_KEY_TYPE_INCONSISTENT;
9187
0
    }
9188
    /* get the key value */
9189
0
    att = sftk_FindAttribute(key, CKA_VALUE);
9190
0
    sftk_FreeObject(key);
9191
0
    if (!att) {
9192
0
        return CKR_KEY_HANDLE_INVALID;
9193
0
    }
9194
0
    crv = NSC_DigestUpdate(hSession, (CK_BYTE_PTR)att->attrib.pValue,
9195
0
                           att->attrib.ulValueLen);
9196
0
    sftk_FreeAttribute(att);
9197
0
    return crv;
9198
0
}