Coverage Report

Created: 2025-08-18 06:34

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