Coverage Report

Created: 2025-04-22 06:14

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