Coverage Report

Created: 2025-07-01 06:25

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