Coverage Report

Created: 2026-08-18 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nss/lib/softoken/pkcs11.c
Line
Count
Source
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
#include "seccomon.h"
21
#include "secitem.h"
22
/* we need to use the deprecated mechanisms values for backward compatibility */
23
#include "pkcs11.h"
24
#include "pkcs11i.h"
25
#include "softoken.h"
26
#include "lowkeyi.h"
27
#include "blapi.h"
28
#include "secder.h"
29
#include "secport.h"
30
#include "secrng.h"
31
#include "prlock.h"
32
#include "prtypes.h"
33
#include "nspr.h"
34
#include "softkver.h"
35
#include "secoid.h"
36
#include "sftkdb.h"
37
#include "utilpars.h"
38
#include "ec.h"
39
#include "secasn1.h"
40
#include "secerr.h"
41
#include "lgglue.h"
42
#include "kem.h"
43
44
PRBool parentForkedAfterC_Initialize;
45
46
#ifndef NO_FORK_CHECK
47
48
PRBool sftkForkCheckDisabled;
49
50
#if defined(CHECK_FORK_PTHREAD) || defined(CHECK_FORK_MIXED)
51
PRBool forked = PR_FALSE;
52
#endif
53
54
#if defined(CHECK_FORK_GETPID) || defined(CHECK_FORK_MIXED)
55
#include <unistd.h>
56
pid_t myPid;
57
#endif
58
59
#ifdef CHECK_FORK_MIXED
60
#include <sys/systeminfo.h>
61
PRBool usePthread_atfork;
62
#endif
63
64
#endif
65
66
#ifdef XP_UNIX
67
0
#define LIB_PARAM_DEFAULT_FILE_LOCATION "/etc/nss/params.config"
68
#endif
69
70
0
#define LIB_PARAM_DEFAULT " configdir='' certPrefix='' keyPrefix='' secmod='' flags=noCertDB,noModDB "
71
/*
72
 * ******************** Static data *******************************
73
 */
74
75
/* The next three strings must be exactly 32 characters long */
76
static char *manufacturerID = "Mozilla Foundation              ";
77
static char manufacturerID_space[33];
78
static char *libraryDescription = "NSS Internal Crypto Services    ";
79
static char libraryDescription_space[33];
80
81
/*
82
 * In FIPS mode, we disallow login attempts for 1 second after a login
83
 * failure so that there are at most 60 login attempts per minute.
84
 */
85
static PRIntervalTime loginWaitTime;
86
87
#undef __PASTE
88
#define __PASTE(x, y) x##y
89
90
/*
91
 * we renamed all our internal functions, get the correct
92
 * definitions for them...
93
 */
94
#undef CK_PKCS11_FUNCTION_INFO
95
#undef CK_NEED_ARG_LIST
96
97
#define CK_PKCS11_3_2 1
98
#define CK_PKCS11_3_0 1
99
#define CK_EXTERN extern
100
#define CK_PKCS11_FUNCTION_INFO(func) \
101
    CK_RV __PASTE(NS, func)
102
#define CK_NEED_ARG_LIST 1
103
104
#include "pkcs11f.h"
105
106
#ifndef NSS_FIPS_DISABLE
107
/* ------------- forward declare all the FIPS functions ------------- */
108
#undef CK_NEED_ARG_LIST
109
#undef CK_PKCS11_FUNCTION_INFO
110
111
#define CK_PKCS11_FUNCTION_INFO(name) CK_RV __PASTE(F, name)
112
#define CK_NEED_ARG_LIST 1
113
114
#include "pkcs11f.h"
115
#endif
116
117
/* build the crypto module table */
118
static CK_FUNCTION_LIST_3_2 sftk_funcList_v32 = {
119
    { 3, 2 },
120
121
#undef CK_PKCS11_FUNCTION_INFO
122
#undef CK_NEED_ARG_LIST
123
124
#define CK_PKCS11_3_2_ONLY 1
125
#define CK_PKCS11_FUNCTION_INFO(func) \
126
    __PASTE(NS, func)                 \
127
    ,
128
#include "pkcs11f.h"
129
130
};
131
#undef CK_PKCS11_3_2_ONLY
132
133
/* build the crypto module table */
134
static CK_FUNCTION_LIST_3_0 sftk_funcList_v30 = {
135
    { 3, 0 },
136
137
#undef CK_PKCS11_FUNCTION_INFO
138
#undef CK_NEED_ARG_LIST
139
140
#define CK_PKCS11_3_0_ONLY 1
141
#define CK_PKCS11_FUNCTION_INFO(func) \
142
    __PASTE(NS, func)                 \
143
    ,
144
#include "pkcs11f.h"
145
146
};
147
#undef CK_PKCS11_3_0_ONLY
148
149
/* need a special version of get info for version 2 which returns the version
150
 * 2.4 version number */
151
CK_RV NSC_GetInfoV2(CK_INFO_PTR pInfo);
152
CK_RV NSC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
153
                             CK_MECHANISM_INFO_PTR pInfo);
154
155
/* build the crypto module table */
156
static CK_FUNCTION_LIST sftk_funcList_v2 = {
157
    { 2, 40 },
158
159
#define CK_PKCS11_2_0_ONLY 1
160
#undef CK_PKCS11_FUNCTION_INFO
161
#undef CK_NEED_ARG_LIST
162
#define C_GetInfo C_GetInfoV2
163
#define C_GetMechanismInfo C_GetMechanismInfoV2
164
165
#define CK_PKCS11_FUNCTION_INFO(func) \
166
    __PASTE(NS, func)                 \
167
    ,
168
#include "pkcs11f.h"
169
170
};
171
172
#undef C_GetInfo
173
#undef C_GetMechanismInfo
174
#undef CK_PKCS_11_2_0_ONLY
175
#undef CK_PKCS11_FUNCTION_INFO
176
#undef CK_NEED_ARG_LIST
177
178
#undef __PASTE
179
180
CK_NSS_MODULE_FUNCTIONS sftk_module_funcList = {
181
    { 1, 0 },
182
    NSC_ModuleDBFunc
183
};
184
185
static CK_RV
186
nsc_NSSGetFIPSStatus(CK_SESSION_HANDLE hSession,
187
                     CK_OBJECT_HANDLE hObject,
188
                     CK_ULONG ulOperationType,
189
                     CK_ULONG *pulFIPSStatus);
190
CK_NSS_FIPS_FUNCTIONS sftk_fips_funcList = {
191
    { 1, 0 },
192
    nsc_NSSGetFIPSStatus
193
};
194
195
CK_NSS_KEM_FUNCTIONS sftk_kem_funcList = {
196
    { 1, 0 },
197
    NSC_Encapsulate,
198
    NSC_Decapsulate
199
};
200
201
/*
202
 * Array is orderd by default first
203
 */
204
static CK_INTERFACE nss_interfaces[] = {
205
    { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_funcList_v32, NSS_INTERFACE_FLAGS },
206
    { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_funcList_v30, NSS_INTERFACE_FLAGS },
207
    { (CK_UTF8CHAR_PTR) "PKCS 11", &sftk_funcList_v2, NSS_INTERFACE_FLAGS },
208
    { (CK_UTF8CHAR_PTR) "Vendor NSS Module Interface", &sftk_module_funcList, NSS_INTERFACE_FLAGS },
209
    { (CK_UTF8CHAR_PTR) "Vendor NSS FIPS Interface", &sftk_fips_funcList, NSS_INTERFACE_FLAGS },
210
    { (CK_UTF8CHAR_PTR) "Vendor NSS KEM Interface", &sftk_kem_funcList, NSS_INTERFACE_FLAGS }
211
};
212
/* must match the count of interfaces in nss_interfaces above */
213
96
#define NSS_INTERFACE_COUNT PR_ARRAY_SIZE(nss_interfaces)
214
215
/* List of DES Weak Keys */
216
typedef unsigned char desKey[8];
217
static const desKey sftk_desWeakTable[] = {
218
#ifdef noParity
219
    /* weak */
220
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
221
    { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e },
222
    { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 },
223
    { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
224
    /* semi-weak */
225
    { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe },
226
    { 0xfe, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0xfe },
227
228
    { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 },
229
    { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e },
230
231
    { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0x0f, 0x00, 0x0f },
232
    { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 },
233
234
    { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe },
235
    { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e },
236
237
    { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e },
238
    { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 },
239
240
    { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe },
241
    { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 },
242
#else
243
    /* weak */
244
    { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
245
    { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e },
246
    { 0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xf1, 0xf1, 0xf1 },
247
    { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
248
249
    /* semi-weak */
250
    { 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe },
251
    { 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01 },
252
253
    { 0x1f, 0xe0, 0x1f, 0xe0, 0x0e, 0xf1, 0x0e, 0xf1 },
254
    { 0xe0, 0x1f, 0xe0, 0x1f, 0xf1, 0x0e, 0xf1, 0x0e },
255
256
    { 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1 },
257
    { 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1, 0x01 },
258
259
    { 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe },
260
    { 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e },
261
262
    { 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e },
263
    { 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e, 0x01 },
264
265
    { 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1, 0xfe },
266
    { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1 }
267
#endif
268
};
269
270
static const int sftk_desWeakTableSize = sizeof(sftk_desWeakTable) /
271
                                         sizeof(sftk_desWeakTable[0]);
272
273
/* DES KEY Parity conversion table. Takes each byte/2 as an index, returns
274
 * that byte with the proper parity bit set */
275
static const unsigned char parityTable[256] = {
276
    /* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */
277
    /* E */ 0x01, 0x02, 0x04, 0x07, 0x08, 0x0b, 0x0d, 0x0e,
278
    /* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */
279
    /* O */ 0x10, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, 0x1f,
280
    /* Odd....0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e */
281
    /* O */ 0x20, 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x2f,
282
    /* Even...0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e */
283
    /* E */ 0x31, 0x32, 0x34, 0x37, 0x38, 0x3b, 0x3d, 0x3e,
284
    /* Odd....0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e */
285
    /* O */ 0x40, 0x43, 0x45, 0x46, 0x49, 0x4a, 0x4c, 0x4f,
286
    /* Even...0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e */
287
    /* E */ 0x51, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d, 0x5e,
288
    /* Even...0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e */
289
    /* E */ 0x61, 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x6e,
290
    /* Odd....0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e */
291
    /* O */ 0x70, 0x73, 0x75, 0x76, 0x79, 0x7a, 0x7c, 0x7f,
292
    /* Odd....0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e */
293
    /* O */ 0x80, 0x83, 0x85, 0x86, 0x89, 0x8a, 0x8c, 0x8f,
294
    /* Even...0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e */
295
    /* E */ 0x91, 0x92, 0x94, 0x97, 0x98, 0x9b, 0x9d, 0x9e,
296
    /* Even...0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae */
297
    /* E */ 0xa1, 0xa2, 0xa4, 0xa7, 0xa8, 0xab, 0xad, 0xae,
298
    /* Odd....0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe */
299
    /* O */ 0xb0, 0xb3, 0xb5, 0xb6, 0xb9, 0xba, 0xbc, 0xbf,
300
    /* Even...0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce */
301
    /* E */ 0xc1, 0xc2, 0xc4, 0xc7, 0xc8, 0xcb, 0xcd, 0xce,
302
    /* Odd....0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde */
303
    /* O */ 0xd0, 0xd3, 0xd5, 0xd6, 0xd9, 0xda, 0xdc, 0xdf,
304
    /* Odd....0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee */
305
    /* O */ 0xe0, 0xe3, 0xe5, 0xe6, 0xe9, 0xea, 0xec, 0xef,
306
    /* Even...0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe */
307
    /* E */ 0xf1, 0xf2, 0xf4, 0xf7, 0xf8, 0xfb, 0xfd, 0xfe
308
};
309
310
/* Mechanisms */
311
struct mechanismList {
312
    CK_MECHANISM_TYPE type;
313
    CK_MECHANISM_INFO info;
314
    PRBool privkey;
315
};
316
317
/*
318
 * the following table includes a complete list of mechanism defined by
319
 * PKCS #11 version 2.01. Those Mechanisms not supported by this PKCS #11
320
 * module are ifdef'ed out.
321
 */
322
#define CKF_EN_DE CKF_ENCRYPT | CKF_DECRYPT
323
#define CKF_WR_UN CKF_WRAP | CKF_UNWRAP
324
#define CKF_SN_VR CKF_SIGN | CKF_VERIFY
325
#define CKF_SN_RE CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER
326
#define CKF_EN_DE_MSG CKF_ENCRYPT | CKF_DECRYPT | CKF_MESSAGE_ENCRYPT | CKF_MESSAGE_DECRYPT
327
#define CKF_KEM CKF_ENCAPSULATE | CKF_DECAPSULATE
328
329
#define CKF_EN_DE_WR_UN CKF_EN_DE | CKF_WR_UN
330
#define CKF_SN_VR_RE CKF_SN_VR | CKF_SN_RE
331
#define CKF_DUZ_IT_ALL CKF_EN_DE_WR_UN | CKF_SN_VR_RE
332
333
#define CKF_EC_PNU CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS
334
335
#define CKF_EC_BPNU CKF_EC_F_2M | CKF_EC_PNU
336
#define CKF_EC_POC CKF_EC_F_P | CKF_EC_OID | CKF_EC_COMPRESS
337
338
#define CK_MAX 0xffffffff
339
340
static const struct mechanismList mechanisms[] = {
341
342
    /*
343
     * PKCS #11 Mechanism List.
344
     *
345
     * The first argument is the PKCS #11 Mechanism we support.
346
     * The second argument is Mechanism info structure. It includes:
347
     *    The minimum key size,
348
     *       in bits for RSA, DSA, DH, EC*, KEA, RC2 and RC4 * algs.
349
     *       in bytes for RC5, AES, Camellia, and CAST*
350
     *       ignored for DES*, IDEA and FORTEZZA based
351
     *    The maximum key size,
352
     *       in bits for RSA, DSA, DH, EC*, KEA, RC2 and RC4 * algs.
353
     *       in bytes for RC5, AES, Camellia, and CAST*
354
     *       ignored for DES*, IDEA and FORTEZZA based
355
     *     Flags
356
     *       What operations are supported by this mechanism.
357
     *  The third argument is a bool which tells if this mechanism is
358
     *    supported in the database token.
359
     *
360
     */
361
362
    /* ------------------------- RSA Operations ---------------------------*/
363
    { CKM_RSA_PKCS_KEY_PAIR_GEN, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
364
    { CKM_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_DUZ_IT_ALL }, PR_TRUE },
365
    { CKM_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
366
    { CKM_RSA_PKCS_OAEP, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_EN_DE_WR_UN }, PR_TRUE },
367
#ifdef SFTK_RSA9796_SUPPORTED
368
    { CKM_RSA_9796, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_DUZ_IT_ALL }, PR_TRUE },
369
#endif
370
    { CKM_RSA_X_509, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_DUZ_IT_ALL }, PR_TRUE },
371
    /* -------------- RSA Multipart Signing Operations -------------------- */
372
    { CKM_MD2_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
373
    { CKM_MD5_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
374
    { CKM_SHA1_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
375
    { CKM_SHA224_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
376
    { CKM_SHA256_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
377
    { CKM_SHA384_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
378
    { CKM_SHA512_RSA_PKCS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
379
    { CKM_SHA1_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
380
    { CKM_SHA224_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
381
    { CKM_SHA256_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
382
    { CKM_SHA384_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
383
    { CKM_SHA512_RSA_PKCS_PSS, { RSA_MIN_MODULUS_BITS, CK_MAX, CKF_SN_VR }, PR_TRUE },
384
/* ------------------------- DSA Operations --------------------------- */
385
#ifndef NSS_DISABLE_DSA
386
    { CKM_DSA_KEY_PAIR_GEN, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
387
    { CKM_DSA, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
388
    { CKM_DSA_PARAMETER_GEN, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_GENERATE }, PR_TRUE },
389
    { CKM_DSA_SHA1, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
390
    { CKM_DSA_SHA224, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
391
    { CKM_DSA_SHA256, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
392
    { CKM_DSA_SHA384, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
393
    { CKM_DSA_SHA512, { DSA_MIN_P_BITS, DSA_MAX_P_BITS, CKF_SN_VR }, PR_TRUE },
394
#endif
395
    /* -------------------- Diffie Hellman Operations --------------------- */
396
    /* no diffie hellman yet */
397
    { CKM_DH_PKCS_KEY_PAIR_GEN, { DH_MIN_P_BITS, DH_MAX_P_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
398
    { CKM_DH_PKCS_DERIVE, { DH_MIN_P_BITS, DH_MAX_P_BITS, CKF_DERIVE }, PR_TRUE },
399
    /* -------------------- Elliptic Curve Operations --------------------- */
400
    { CKM_EC_KEY_PAIR_GEN, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_GENERATE_KEY_PAIR | CKF_EC_BPNU }, PR_TRUE },
401
    { CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_GENERATE_KEY_PAIR | CKF_EC_BPNU }, PR_TRUE },
402
    { CKM_ECDH1_DERIVE, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_DERIVE | CKF_EC_BPNU }, PR_TRUE },
403
    { CKM_ECDSA, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
404
    { CKM_ECDSA_SHA1, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
405
    { CKM_ECDSA_SHA224, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
406
    { CKM_ECDSA_SHA256, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
407
    { CKM_ECDSA_SHA384, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
408
    { CKM_ECDSA_SHA512, { EC_MIN_KEY_BITS, EC_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_BPNU }, PR_TRUE },
409
    { CKM_EC_EDWARDS_KEY_PAIR_GEN, { ECD_MIN_KEY_BITS, ECD_MAX_KEY_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
410
    { CKM_EC_MONTGOMERY_KEY_PAIR_GEN, { ECD_MIN_KEY_BITS, ECD_MAX_KEY_BITS, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
411
    { CKM_EDDSA, { ECD_MIN_KEY_BITS, ECD_MAX_KEY_BITS, CKF_SN_VR | CKF_EC_POC }, PR_TRUE },
412
    /* ------------------------- RC2 Operations --------------------------- */
413
    { CKM_RC2_KEY_GEN, { 1, 128, CKF_GENERATE }, PR_TRUE },
414
    { CKM_RC2_ECB, { 1, 128, CKF_EN_DE_WR_UN }, PR_TRUE },
415
    { CKM_RC2_CBC, { 1, 128, CKF_EN_DE_WR_UN }, PR_TRUE },
416
    { CKM_RC2_MAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
417
    { CKM_RC2_MAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
418
    { CKM_RC2_CBC_PAD, { 1, 128, CKF_EN_DE_WR_UN }, PR_TRUE },
419
    /* ------------------------- RC4 Operations --------------------------- */
420
    { CKM_RC4_KEY_GEN, { 1, 256, CKF_GENERATE }, PR_FALSE },
421
    { CKM_RC4, { 1, 256, CKF_EN_DE_WR_UN }, PR_FALSE },
422
    /* ------------------------- DES Operations --------------------------- */
423
    { CKM_DES_KEY_GEN, { 8, 8, CKF_GENERATE }, PR_TRUE },
424
    { CKM_DES_ECB, { 8, 8, CKF_EN_DE_WR_UN }, PR_TRUE },
425
    { CKM_DES_CBC, { 8, 8, CKF_EN_DE_WR_UN }, PR_TRUE },
426
    { CKM_DES_MAC, { 8, 8, CKF_SN_VR }, PR_TRUE },
427
    { CKM_DES_MAC_GENERAL, { 8, 8, CKF_SN_VR }, PR_TRUE },
428
    { CKM_DES_CBC_PAD, { 8, 8, CKF_EN_DE_WR_UN }, PR_TRUE },
429
    { CKM_DES2_KEY_GEN, { 24, 24, CKF_GENERATE }, PR_TRUE },
430
    { CKM_DES3_KEY_GEN, { 24, 24, CKF_GENERATE }, PR_TRUE },
431
    { CKM_DES3_ECB, { 24, 24, CKF_EN_DE_WR_UN }, PR_TRUE },
432
    { CKM_DES3_CBC, { 24, 24, CKF_EN_DE_WR_UN }, PR_TRUE },
433
    { CKM_DES3_MAC, { 24, 24, CKF_SN_VR }, PR_TRUE },
434
    { CKM_DES3_MAC_GENERAL, { 24, 24, CKF_SN_VR }, PR_TRUE },
435
    { CKM_DES3_CBC_PAD, { 24, 24, CKF_EN_DE_WR_UN }, PR_TRUE },
436
    /* ------------------------- CDMF Operations --------------------------- */
437
    { CKM_CDMF_KEY_GEN, { 8, 8, CKF_GENERATE }, PR_TRUE },
438
    { CKM_CDMF_ECB, { 8, 8, CKF_EN_DE_WR_UN }, PR_TRUE },
439
    { CKM_CDMF_CBC, { 8, 8, CKF_EN_DE_WR_UN }, PR_TRUE },
440
    { CKM_CDMF_MAC, { 8, 8, CKF_SN_VR }, PR_TRUE },
441
    { CKM_CDMF_MAC_GENERAL, { 8, 8, CKF_SN_VR }, PR_TRUE },
442
    { CKM_CDMF_CBC_PAD, { 8, 8, CKF_EN_DE_WR_UN }, PR_TRUE },
443
    /* ------------------------- AES Operations --------------------------- */
444
    { CKM_AES_KEY_GEN, { 16, 32, CKF_GENERATE }, PR_TRUE },
445
    { CKM_AES_ECB, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
446
    { CKM_AES_CBC, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
447
    { CKM_AES_MAC, { 16, 32, CKF_SN_VR }, PR_TRUE },
448
    { CKM_AES_MAC_GENERAL, { 16, 32, CKF_SN_VR }, PR_TRUE },
449
    { CKM_AES_CMAC, { 16, 32, CKF_SN_VR }, PR_TRUE },
450
    { CKM_AES_CMAC_GENERAL, { 16, 32, CKF_SN_VR }, PR_TRUE },
451
    { CKM_AES_CBC_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
452
    { CKM_AES_CTS, { 16, 32, CKF_EN_DE }, PR_TRUE },
453
    { CKM_AES_CTR, { 16, 32, CKF_EN_DE }, PR_TRUE },
454
    { CKM_AES_GCM, { 16, 32, CKF_EN_DE_MSG }, PR_TRUE },
455
    { CKM_AES_XCBC_MAC_96, { 12, 12, CKF_SN_VR }, PR_TRUE },
456
    { CKM_AES_XCBC_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE },
457
    /* ------------------------- Camellia Operations --------------------- */
458
    { CKM_CAMELLIA_KEY_GEN, { 16, 32, CKF_GENERATE }, PR_TRUE },
459
    { CKM_CAMELLIA_ECB, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
460
    { CKM_CAMELLIA_CBC, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
461
    { CKM_CAMELLIA_MAC, { 16, 32, CKF_SN_VR }, PR_TRUE },
462
    { CKM_CAMELLIA_MAC_GENERAL, { 16, 32, CKF_SN_VR }, PR_TRUE },
463
    { CKM_CAMELLIA_CBC_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
464
/* ------------------------- SEED Operations --------------------------- */
465
#ifndef NSS_DISABLE_DEPRECATED_SEED
466
    { CKM_SEED_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE },
467
    { CKM_SEED_ECB, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
468
    { CKM_SEED_CBC, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
469
    { CKM_SEED_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE },
470
    { CKM_SEED_MAC_GENERAL, { 16, 16, CKF_SN_VR }, PR_TRUE },
471
    { CKM_SEED_CBC_PAD, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
472
#endif
473
/* ------------------------- ChaCha20 Operations ---------------------- */
474
#ifndef NSS_DISABLE_CHACHAPOLY
475
    { CKM_NSS_CHACHA20_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE },
476
    { CKM_NSS_CHACHA20_POLY1305, { 32, 32, CKF_EN_DE }, PR_TRUE },
477
    { CKM_NSS_CHACHA20_CTR, { 32, 32, CKF_EN_DE }, PR_TRUE },
478
    { CKM_CHACHA20_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE },
479
    { CKM_CHACHA20, { 32, 32, CKF_EN_DE }, PR_TRUE },
480
    { CKM_CHACHA20_POLY1305, { 32, 32, CKF_EN_DE_MSG }, PR_TRUE },
481
#endif /* NSS_DISABLE_CHACHAPOLY */
482
    /* ------------------------- Hashing Operations ----------------------- */
483
    { CKM_MD2, { 0, 0, CKF_DIGEST }, PR_FALSE },
484
    { CKM_MD2_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
485
    { CKM_MD2_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
486
    { CKM_MD5, { 0, 0, CKF_DIGEST }, PR_FALSE },
487
    { CKM_MD5_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
488
    { CKM_MD5_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
489
    { CKM_SHA_1, { 0, 0, CKF_DIGEST }, PR_FALSE },
490
    { CKM_SHA_1_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
491
    { CKM_SHA_1_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
492
    { CKM_SHA224, { 0, 0, CKF_DIGEST }, PR_FALSE },
493
    { CKM_SHA224_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
494
    { CKM_SHA224_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
495
    { CKM_SHA256, { 0, 0, CKF_DIGEST }, PR_FALSE },
496
    { CKM_SHA256_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
497
    { CKM_SHA256_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
498
    { CKM_SHA384, { 0, 0, CKF_DIGEST }, PR_FALSE },
499
    { CKM_SHA384_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
500
    { CKM_SHA384_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
501
    { CKM_SHA512, { 0, 0, CKF_DIGEST }, PR_FALSE },
502
    { CKM_SHA512_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
503
    { CKM_SHA512_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
504
    { CKM_SHA3_224, { 0, 0, CKF_DIGEST }, PR_FALSE },
505
    { CKM_SHA3_224_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
506
    { CKM_SHA3_224_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
507
    { CKM_SHA3_256, { 0, 0, CKF_DIGEST }, PR_FALSE },
508
    { CKM_SHA3_256_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
509
    { CKM_SHA3_256_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
510
    { CKM_SHA3_384, { 0, 0, CKF_DIGEST }, PR_FALSE },
511
    { CKM_SHA3_384_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
512
    { CKM_SHA3_384_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
513
    { CKM_SHA3_512, { 0, 0, CKF_DIGEST }, PR_FALSE },
514
    { CKM_SHA3_512_HMAC, { 1, 128, CKF_SN_VR }, PR_TRUE },
515
    { CKM_SHA3_512_HMAC_GENERAL, { 1, 128, CKF_SN_VR }, PR_TRUE },
516
    { CKM_TLS_PRF_GENERAL, { 0, 512, CKF_SN_VR }, PR_FALSE },
517
    { CKM_TLS_MAC, { 0, 512, CKF_SN_VR }, PR_FALSE },
518
    { CKM_NSS_TLS_PRF_GENERAL_SHA256,
519
      { 0, 512, CKF_SN_VR },
520
      PR_FALSE },
521
    /* ------------------------- HKDF Operations -------------------------- */
522
    { CKM_HKDF_DERIVE, { 1, 255 * 64, CKF_DERIVE }, PR_TRUE },
523
    { CKM_HKDF_DATA, { 1, 255 * 64, CKF_DERIVE }, PR_TRUE },
524
    { CKM_HKDF_KEY_GEN, { 20, 64, CKF_GENERATE }, PR_TRUE },
525
    { CKM_NSS_HKDF_SHA1, { 1, 128, CKF_DERIVE }, PR_TRUE },
526
    { CKM_NSS_HKDF_SHA256, { 1, 128, CKF_DERIVE }, PR_TRUE },
527
    { CKM_NSS_HKDF_SHA384, { 1, 128, CKF_DERIVE }, PR_TRUE },
528
    { CKM_NSS_HKDF_SHA512, { 1, 128, CKF_DERIVE }, PR_TRUE },
529
/* ------------------------- CAST Operations --------------------------- */
530
#ifdef NSS_SOFTOKEN_DOES_CAST
531
    /* Cast operations are not supported ( yet? ) */
532
    { CKM_CAST_KEY_GEN, { 1, 8, CKF_GENERATE }, PR_TRUE },
533
    { CKM_CAST_ECB, { 1, 8, CKF_EN_DE_WR_UN }, PR_TRUE },
534
    { CKM_CAST_CBC, { 1, 8, CKF_EN_DE_WR_UN }, PR_TRUE },
535
    { CKM_CAST_MAC, { 1, 8, CKF_SN_VR }, PR_TRUE },
536
    { CKM_CAST_MAC_GENERAL, { 1, 8, CKF_SN_VR }, PR_TRUE },
537
    { CKM_CAST_CBC_PAD, { 1, 8, CKF_EN_DE_WR_UN }, PR_TRUE },
538
    { CKM_CAST3_KEY_GEN, { 1, 16, CKF_GENERATE }, PR_TRUE },
539
    { CKM_CAST3_ECB, { 1, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
540
    { CKM_CAST3_CBC, { 1, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
541
    { CKM_CAST3_MAC, { 1, 16, CKF_SN_VR }, PR_TRUE },
542
    { CKM_CAST3_MAC_GENERAL, { 1, 16, CKF_SN_VR }, PR_TRUE },
543
    { CKM_CAST3_CBC_PAD, { 1, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
544
    { CKM_CAST5_KEY_GEN, { 1, 16, CKF_GENERATE }, PR_TRUE },
545
    { CKM_CAST5_ECB, { 1, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
546
    { CKM_CAST5_CBC, { 1, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
547
    { CKM_CAST5_MAC, { 1, 16, CKF_SN_VR }, PR_TRUE },
548
    { CKM_CAST5_MAC_GENERAL, { 1, 16, CKF_SN_VR }, PR_TRUE },
549
    { CKM_CAST5_CBC_PAD, { 1, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
550
#endif
551
#if NSS_SOFTOKEN_DOES_RC5
552
    /* ------------------------- RC5 Operations --------------------------- */
553
    { CKM_RC5_KEY_GEN, { 1, 32, CKF_GENERATE }, PR_TRUE },
554
    { CKM_RC5_ECB, { 1, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
555
    { CKM_RC5_CBC, { 1, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
556
    { CKM_RC5_MAC, { 1, 32, CKF_SN_VR }, PR_TRUE },
557
    { CKM_RC5_MAC_GENERAL, { 1, 32, CKF_SN_VR }, PR_TRUE },
558
    { CKM_RC5_CBC_PAD, { 1, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
559
#endif
560
#ifdef NSS_SOFTOKEN_DOES_IDEA
561
    /* ------------------------- IDEA Operations -------------------------- */
562
    { CKM_IDEA_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE },
563
    { CKM_IDEA_ECB, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
564
    { CKM_IDEA_CBC, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
565
    { CKM_IDEA_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE },
566
    { CKM_IDEA_MAC_GENERAL, { 16, 16, CKF_SN_VR }, PR_TRUE },
567
    { CKM_IDEA_CBC_PAD, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
568
#endif
569
    /* --------------------- Secret Key Operations ------------------------ */
570
    { CKM_GENERIC_SECRET_KEY_GEN, { 1, 32, CKF_GENERATE }, PR_TRUE },
571
    { CKM_CONCATENATE_BASE_AND_KEY, { 1, 32, CKF_DERIVE }, PR_FALSE },
572
    { CKM_CONCATENATE_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
573
    { CKM_CONCATENATE_DATA_AND_BASE, { 1, 32, CKF_DERIVE }, PR_FALSE },
574
    { CKM_XOR_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
575
    { CKM_EXTRACT_KEY_FROM_KEY, { 1, 32, CKF_DERIVE }, PR_FALSE },
576
    { CKM_DES3_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
577
    { CKM_DES3_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
578
    { CKM_AES_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
579
    { CKM_AES_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
580
    { CKM_CAMELLIA_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
581
    { CKM_CAMELLIA_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
582
#ifndef NSS_DISABLE_DEPRECATED_SEED
583
    { CKM_SEED_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
584
    { CKM_SEED_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
585
#endif
586
    /* ---------------------- SSL Key Derivations ------------------------- */
587
    { CKM_SSL3_PRE_MASTER_KEY_GEN, { 48, 48, CKF_GENERATE }, PR_FALSE },
588
    { CKM_SSL3_MASTER_KEY_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
589
    { CKM_SSL3_MASTER_KEY_DERIVE_DH, { 8, 128, CKF_DERIVE }, PR_FALSE },
590
    { CKM_SSL3_KEY_AND_MAC_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
591
    { CKM_SSL3_MD5_MAC, { 0, 16, CKF_DERIVE }, PR_FALSE },
592
    { CKM_SSL3_SHA1_MAC, { 0, 20, CKF_DERIVE }, PR_FALSE },
593
    { CKM_MD5_KEY_DERIVATION, { 0, 16, CKF_DERIVE }, PR_FALSE },
594
    { CKM_MD2_KEY_DERIVATION, { 0, 16, CKF_DERIVE }, PR_FALSE },
595
    { CKM_SHA1_KEY_DERIVATION, { 0, 20, CKF_DERIVE }, PR_FALSE },
596
    { CKM_SHA224_KEY_DERIVATION, { 0, 28, CKF_DERIVE }, PR_FALSE },
597
    { CKM_SHA256_KEY_DERIVATION, { 0, 32, CKF_DERIVE }, PR_FALSE },
598
    { CKM_SHA384_KEY_DERIVATION, { 0, 48, CKF_DERIVE }, PR_FALSE },
599
    { CKM_SHA512_KEY_DERIVATION, { 0, 64, CKF_DERIVE }, PR_FALSE },
600
    { CKM_TLS_MASTER_KEY_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
601
    { CKM_TLS12_MASTER_KEY_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
602
    { CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256,
603
      { 48, 48, CKF_DERIVE },
604
      PR_FALSE },
605
    { CKM_TLS_MASTER_KEY_DERIVE_DH, { 8, 128, CKF_DERIVE }, PR_FALSE },
606
    { CKM_TLS12_MASTER_KEY_DERIVE_DH, { 8, 128, CKF_DERIVE }, PR_FALSE },
607
    { CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE, { 48, 128, CKF_DERIVE }, PR_FALSE },
608
    { CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE_DH, { 48, 128, CKF_DERIVE }, PR_FALSE },
609
    { CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256,
610
      { 8, 128, CKF_DERIVE },
611
      PR_FALSE },
612
    { CKM_TLS_KEY_AND_MAC_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
613
    { CKM_TLS12_KEY_AND_MAC_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
614
    { CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256,
615
      { 48, 48, CKF_DERIVE },
616
      PR_FALSE },
617
    { CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE,
618
      { 48, 128, CKF_DERIVE },
619
      PR_FALSE },
620
    { CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH,
621
      { 48, 128, CKF_DERIVE },
622
      PR_FALSE },
623
    /* ---------------------- PBE Key Derivations  ------------------------ */
624
    { CKM_PBE_MD2_DES_CBC, { 8, 8, CKF_DERIVE }, PR_TRUE },
625
    { CKM_PBE_MD5_DES_CBC, { 8, 8, CKF_DERIVE }, PR_TRUE },
626
    /* ------------------ NSS PBE Key Derivations  ------------------- */
627
    { CKM_NSS_PBE_SHA1_DES_CBC, { 8, 8, CKF_GENERATE }, PR_TRUE },
628
    { CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC, { 24, 24, CKF_GENERATE }, PR_TRUE },
629
    { CKM_PBE_SHA1_DES3_EDE_CBC, { 24, 24, CKF_GENERATE }, PR_TRUE },
630
    { CKM_PBE_SHA1_DES2_EDE_CBC, { 24, 24, CKF_GENERATE }, PR_TRUE },
631
    { CKM_PBE_SHA1_RC2_40_CBC, { 40, 40, CKF_GENERATE }, PR_TRUE },
632
    { CKM_PBE_SHA1_RC2_128_CBC, { 128, 128, CKF_GENERATE }, PR_TRUE },
633
    { CKM_PBE_SHA1_RC4_40, { 40, 40, CKF_GENERATE }, PR_TRUE },
634
    { CKM_PBE_SHA1_RC4_128, { 128, 128, CKF_GENERATE }, PR_TRUE },
635
    { CKM_PBA_SHA1_WITH_SHA1_HMAC, { 20, 20, CKF_GENERATE }, PR_TRUE },
636
    { CKM_PKCS5_PBKD2, { 1, 256, CKF_GENERATE }, PR_TRUE },
637
    { CKM_NSS_PBE_SHA1_HMAC_KEY_GEN, { 20, 20, CKF_GENERATE }, PR_TRUE },
638
    { CKM_NSS_PBE_MD5_HMAC_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE },
639
    { CKM_NSS_PBE_MD2_HMAC_KEY_GEN, { 16, 16, CKF_GENERATE }, PR_TRUE },
640
    { CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN, { 28, 28, CKF_GENERATE }, PR_TRUE },
641
    { CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN, { 32, 32, CKF_GENERATE }, PR_TRUE },
642
    { CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN, { 48, 48, CKF_GENERATE }, PR_TRUE },
643
    { CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN, { 64, 64, CKF_GENERATE }, PR_TRUE },
644
    /* ------------------ NIST 800-108 Key Derivations  ------------------- */
645
    { CKM_SP800_108_COUNTER_KDF, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
646
    { CKM_SP800_108_FEEDBACK_KDF, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
647
    { CKM_SP800_108_DOUBLE_PIPELINE_KDF, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
648
    { CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
649
    { CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
650
    { CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA, { 0, CK_MAX, CKF_DERIVE }, PR_TRUE },
651
    /* ------------------ AES Key Wrap (also encrypt)  ------------------- */
652
    { CKM_NSS_AES_KEY_WRAP, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
653
    { CKM_NSS_AES_KEY_WRAP_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
654
    { CKM_AES_KEY_WRAP, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
655
    { CKM_AES_KEY_WRAP_PAD, { 16, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
656
    { CKM_AES_KEY_WRAP_KWP, { 1, 32, CKF_EN_DE_WR_UN }, PR_TRUE },
657
    /* --------------------------- J-PAKE -------------------------------- */
658
    { CKM_NSS_JPAKE_ROUND1_SHA1, { 0, 0, CKF_GENERATE }, PR_TRUE },
659
    { CKM_NSS_JPAKE_ROUND1_SHA256, { 0, 0, CKF_GENERATE }, PR_TRUE },
660
    { CKM_NSS_JPAKE_ROUND1_SHA384, { 0, 0, CKF_GENERATE }, PR_TRUE },
661
    { CKM_NSS_JPAKE_ROUND1_SHA512, { 0, 0, CKF_GENERATE }, PR_TRUE },
662
    { CKM_NSS_JPAKE_ROUND2_SHA1, { 0, 0, CKF_DERIVE }, PR_TRUE },
663
    { CKM_NSS_JPAKE_ROUND2_SHA256, { 0, 0, CKF_DERIVE }, PR_TRUE },
664
    { CKM_NSS_JPAKE_ROUND2_SHA384, { 0, 0, CKF_DERIVE }, PR_TRUE },
665
    { CKM_NSS_JPAKE_ROUND2_SHA512, { 0, 0, CKF_DERIVE }, PR_TRUE },
666
    { CKM_NSS_JPAKE_FINAL_SHA1, { 0, 0, CKF_DERIVE }, PR_TRUE },
667
    { CKM_NSS_JPAKE_FINAL_SHA256, { 0, 0, CKF_DERIVE }, PR_TRUE },
668
    { CKM_NSS_JPAKE_FINAL_SHA384, { 0, 0, CKF_DERIVE }, PR_TRUE },
669
    { CKM_NSS_JPAKE_FINAL_SHA512, { 0, 0, CKF_DERIVE }, PR_TRUE },
670
    /* -------------------- Constant Time TLS MACs ----------------------- */
671
    { CKM_NSS_HMAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE },
672
    { CKM_NSS_SSL3_MAC_CONSTANT_TIME, { 0, 0, CKF_DIGEST }, PR_TRUE },
673
    /* -------------------- IPSEC ----------------------- */
674
    { CKM_IKE2_PRF_PLUS_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE },
675
    { CKM_IKE_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE },
676
    { CKM_IKE1_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE },
677
    { CKM_IKE1_EXTENDED_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE },
678
    { CKM_NSS_IKE_PRF_PLUS_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE },
679
    { CKM_NSS_IKE_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE },
680
    { CKM_NSS_IKE1_PRF_DERIVE, { 8, 64, CKF_DERIVE }, PR_TRUE },
681
    { CKM_NSS_IKE1_APP_B_PRF_DERIVE, { 8, 255 * 64, CKF_DERIVE }, PR_TRUE },
682
/* -------------------- Kyber Operations ----------------------- */
683
#ifndef NSS_DISABLE_KYBER
684
    { CKM_NSS_KYBER_KEY_PAIR_GEN, { 0, 0, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
685
    { CKM_NSS_KYBER, { 0, 0, CKF_KEM }, PR_TRUE },
686
#endif
687
    { CKM_NSS_ML_KEM_KEY_PAIR_GEN, { 0, 0, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
688
    { CKM_NSS_ML_KEM, { 0, 0, CKF_KEM }, PR_TRUE },
689
    { CKM_ML_KEM_KEY_PAIR_GEN, { 0, 0, CKF_GENERATE_KEY_PAIR }, PR_TRUE },
690
    { CKM_ML_KEM, { 0, 0, CKF_KEM }, PR_TRUE },
691
/* don't advertize ML_DSA support until we have it working in freebl */
692
#ifdef NSS_ENABLE_ML_DSA
693
    { CKM_ML_DSA_KEY_PAIR_GEN, { ML_DSA_44_PUBLICKEY_LEN, ML_DSA_87_PUBLICKEY_LEN, CKF_GENERATE }, PR_TRUE },
694
    { CKM_ML_DSA, { ML_DSA_44_PUBLICKEY_LEN, ML_DSA_87_PUBLICKEY_LEN, CKF_SN_VR }, PR_TRUE },
695
#endif
696
};
697
static const CK_ULONG mechanismCount = sizeof(mechanisms) / sizeof(mechanisms[0]);
698
699
/* sigh global so fipstokn can read it */
700
PRBool nsc_init = PR_FALSE;
701
702
#if defined(CHECK_FORK_PTHREAD) || defined(CHECK_FORK_MIXED)
703
704
#include <pthread.h>
705
706
static void
707
ForkedChild(void)
708
{
709
    if (nsc_init || nsf_init) {
710
        forked = PR_TRUE;
711
    }
712
}
713
714
#endif
715
716
#define SFTKFreeWrap(ctxtype, mmm) \
717
    void SFTKFree_##mmm(void *vp)  \
718
236k
    {                              \
719
236k
        ctxtype *p = vp;           \
720
236k
        mmm(p);                    \
721
236k
    }
SFTKFree_nsslowkey_DestroyPublicKey
Line
Count
Source
718
140k
    {                              \
719
140k
        ctxtype *p = vp;           \
720
140k
        mmm(p);                    \
721
140k
    }
SFTKFree_nsslowkey_DestroyPrivateKey
Line
Count
Source
718
95.7k
    {                              \
719
95.7k
        ctxtype *p = vp;           \
720
95.7k
        mmm(p);                    \
721
95.7k
    }
722
723
SFTKFreeWrap(NSSLOWKEYPublicKey, nsslowkey_DestroyPublicKey);
724
SFTKFreeWrap(NSSLOWKEYPrivateKey, nsslowkey_DestroyPrivateKey);
725
726
static char *
727
sftk_setStringName(const char *inString, char *buffer, int buffer_length, PRBool nullTerminate)
728
96
{
729
96
    int full_length, string_length;
730
731
96
    full_length = nullTerminate ? buffer_length - 1 : buffer_length;
732
96
    string_length = PORT_Strlen(inString);
733
    /*
734
     *  shorten the string, respecting utf8 encoding
735
     *  to do so, we work backward from the end
736
     *  bytes looking from the end are either:
737
     *    - ascii [0x00,0x7f]
738
     *    - the [2-n]th byte of a multibyte sequence
739
     *        [0x3F,0xBF], i.e, most significant 2 bits are '10'
740
     *    - the first byte of a multibyte sequence [0xC0,0xFD],
741
     *        i.e, most significant 2 bits are '11'
742
     *
743
     *    When the string is too long, we lop off any trailing '10' bytes,
744
     *  if any. When these are all eliminated we lop off
745
     *  one additional byte. Thus if we lopped any '10'
746
     *  we'll be lopping a '11' byte (the first byte of the multibyte sequence),
747
     *  otherwise we're lopping off an ascii character.
748
     *
749
     *    To test for '10' bytes, we first AND it with
750
     *  11000000 (0xc0) so that we get 10000000 (0x80) if and only if
751
     *  the byte starts with 10. We test for equality.
752
     */
753
96
    while (string_length > full_length) {
754
        /* need to shorten */
755
0
        while (string_length > 0 &&
756
0
               ((inString[string_length - 1] & (char)0xc0) == (char)0x80)) {
757
            /* lop off '10' byte */
758
0
            string_length--;
759
0
        }
760
        /*
761
         * test string_length in case bad data is received
762
         * and string consisted of all '10' bytes,
763
         * avoiding any infinite loop
764
         */
765
0
        if (string_length) {
766
            /* remove either '11' byte or an asci byte */
767
0
            string_length--;
768
0
        }
769
0
    }
770
96
    PORT_Memset(buffer, ' ', full_length);
771
96
    if (nullTerminate) {
772
96
        buffer[full_length] = 0;
773
96
    }
774
96
    PORT_Memcpy(buffer, inString, string_length);
775
96
    return buffer;
776
96
}
777
/*
778
 * Configuration utils
779
 */
780
static CK_RV
781
sftk_configure(const char *man, const char *libdes)
782
16
{
783
784
    /* make sure the internationalization was done correctly... */
785
16
    if (man) {
786
0
        manufacturerID = sftk_setStringName(man, manufacturerID_space,
787
0
                                            sizeof(manufacturerID_space), PR_TRUE);
788
0
    }
789
16
    if (libdes) {
790
0
        libraryDescription = sftk_setStringName(libdes,
791
0
                                                libraryDescription_space, sizeof(libraryDescription_space),
792
0
                                                PR_TRUE);
793
0
    }
794
795
16
    return CKR_OK;
796
16
}
797
798
/*
799
 * ******************** Password Utilities *******************************
800
 */
801
802
/*
803
 * see if the key DB password is enabled
804
 */
805
static PRBool
806
sftk_hasNullPassword(SFTKSlot *slot, SFTKDBHandle *keydb)
807
0
{
808
0
    PRBool pwenabled;
809
810
0
    pwenabled = PR_FALSE;
811
0
    if (sftkdb_HasPasswordSet(keydb) == SECSuccess) {
812
0
        PRBool tokenRemoved = PR_FALSE;
813
0
        SECStatus rv = sftkdb_CheckPasswordNull(keydb, &tokenRemoved);
814
0
        if (tokenRemoved) {
815
0
            sftk_CloseAllSessions(slot, PR_FALSE);
816
0
        }
817
0
        return (rv == SECSuccess);
818
0
    }
819
820
0
    return pwenabled;
821
0
}
822
823
/*
824
 * ******************** Object Creation Utilities ***************************
825
 */
826
827
/* Make sure a given attribute exists. If it doesn't, initialize it to
828
 * value and len
829
 */
830
CK_RV
831
sftk_defaultAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
832
                      const void *value, unsigned int len)
833
22.8M
{
834
22.8M
    if (!sftk_hasAttribute(object, type)) {
835
16.8M
        return sftk_AddAttributeType(object, type, value, len);
836
16.8M
    }
837
5.98M
    return CKR_OK;
838
22.8M
}
839
840
/*
841
 * check the consistancy and initialize a Data Object
842
 */
843
static CK_RV
844
sftk_handleDataObject(SFTKSession *session, SFTKObject *object)
845
155k
{
846
155k
    CK_RV crv;
847
848
    /* first reject private and token data objects */
849
155k
    if (sftk_isTrue(object, CKA_PRIVATE) || sftk_isTrue(object, CKA_TOKEN)) {
850
0
        return CKR_ATTRIBUTE_VALUE_INVALID;
851
0
    }
852
853
    /* now just verify the required date fields */
854
155k
    crv = sftk_defaultAttribute(object, CKA_APPLICATION, NULL, 0);
855
155k
    if (crv != CKR_OK)
856
0
        return crv;
857
155k
    crv = sftk_defaultAttribute(object, CKA_VALUE, NULL, 0);
858
155k
    if (crv != CKR_OK)
859
0
        return crv;
860
861
155k
    return CKR_OK;
862
155k
}
863
864
/*
865
 * check the consistancy and initialize a Certificate Object
866
 */
867
static CK_RV
868
sftk_handleCertObject(SFTKSession *session, SFTKObject *object)
869
0
{
870
0
    CK_CERTIFICATE_TYPE type;
871
0
    SFTKAttribute *attribute;
872
0
    CK_RV crv;
873
874
    /* certificates must have a type */
875
0
    if (!sftk_hasAttribute(object, CKA_CERTIFICATE_TYPE)) {
876
0
        return CKR_TEMPLATE_INCOMPLETE;
877
0
    }
878
879
    /* we can't store any certs private */
880
0
    if (sftk_isTrue(object, CKA_PRIVATE)) {
881
0
        return CKR_ATTRIBUTE_VALUE_INVALID;
882
0
    }
883
884
    /* We only support X.509 Certs for now */
885
0
    attribute = sftk_FindAttribute(object, CKA_CERTIFICATE_TYPE);
886
0
    if (attribute == NULL)
887
0
        return CKR_TEMPLATE_INCOMPLETE;
888
0
    type = *(CK_CERTIFICATE_TYPE *)attribute->attrib.pValue;
889
0
    sftk_FreeAttribute(attribute);
890
891
0
    if (type != CKC_X_509) {
892
0
        return CKR_ATTRIBUTE_VALUE_INVALID;
893
0
    }
894
895
    /* X.509 Certificate */
896
897
    /* make sure we have a cert */
898
0
    if (!sftk_hasAttribute(object, CKA_VALUE)) {
899
0
        return CKR_TEMPLATE_INCOMPLETE;
900
0
    }
901
902
    /* in PKCS #11, Subject is a required field */
903
0
    if (!sftk_hasAttribute(object, CKA_SUBJECT)) {
904
0
        return CKR_TEMPLATE_INCOMPLETE;
905
0
    }
906
907
    /* in PKCS #11, Issuer is a required field */
908
0
    if (!sftk_hasAttribute(object, CKA_ISSUER)) {
909
0
        return CKR_TEMPLATE_INCOMPLETE;
910
0
    }
911
912
    /* in PKCS #11, Serial is a required field */
913
0
    if (!sftk_hasAttribute(object, CKA_SERIAL_NUMBER)) {
914
0
        return CKR_TEMPLATE_INCOMPLETE;
915
0
    }
916
917
    /* add it to the object */
918
0
    object->objectInfo = NULL;
919
0
    object->infoFree = (SFTKFree)NULL;
920
921
    /* now just verify the required date fields */
922
0
    crv = sftk_defaultAttribute(object, CKA_ID, NULL, 0);
923
0
    if (crv != CKR_OK) {
924
0
        return crv;
925
0
    }
926
927
0
    if (sftk_isTrue(object, CKA_TOKEN)) {
928
0
        SFTKSlot *slot = session->slot;
929
0
        SFTKDBHandle *certHandle = sftk_getCertDB(slot);
930
931
0
        if (certHandle == NULL) {
932
0
            return CKR_TOKEN_WRITE_PROTECTED;
933
0
        }
934
935
0
        crv = sftkdb_write(certHandle, object, &object->handle);
936
0
        sftk_freeDB(certHandle);
937
0
        return crv;
938
0
    }
939
940
0
    return CKR_OK;
941
0
}
942
943
/*
944
 * check the consistancy and initialize a Trust Object
945
 */
946
static CK_RV
947
sftk_handleNSSTrustObject(SFTKSession *session, SFTKObject *object)
948
0
{
949
    /* we can't store any certs private */
950
0
    if (sftk_isTrue(object, CKA_PRIVATE)) {
951
0
        return CKR_ATTRIBUTE_VALUE_INVALID;
952
0
    }
953
954
    /* certificates must have a type */
955
0
    if (!sftk_hasAttribute(object, CKA_ISSUER)) {
956
0
        return CKR_TEMPLATE_INCOMPLETE;
957
0
    }
958
0
    if (!sftk_hasAttribute(object, CKA_SERIAL_NUMBER)) {
959
0
        return CKR_TEMPLATE_INCOMPLETE;
960
0
    }
961
0
    if (!sftk_hasAttribute(object, CKA_NSS_CERT_SHA1_HASH)) {
962
0
        return CKR_TEMPLATE_INCOMPLETE;
963
0
    }
964
0
    if (!sftk_hasAttribute(object, CKA_NSS_CERT_MD5_HASH)) {
965
0
        return CKR_TEMPLATE_INCOMPLETE;
966
0
    }
967
968
0
    if (sftk_isTrue(object, CKA_TOKEN)) {
969
0
        SFTKSlot *slot = session->slot;
970
0
        SFTKDBHandle *certHandle = sftk_getCertDB(slot);
971
0
        CK_RV crv;
972
973
0
        if (certHandle == NULL) {
974
0
            return CKR_TOKEN_WRITE_PROTECTED;
975
0
        }
976
977
0
        crv = sftkdb_write(certHandle, object, &object->handle);
978
0
        sftk_freeDB(certHandle);
979
0
        return crv;
980
0
    }
981
982
0
    return CKR_OK;
983
0
}
984
985
/*
986
 * check the consistancy and initialize a Trust Object
987
 */
988
static CK_RV
989
sftk_handleTrustObject(SFTKSession *session, SFTKObject *object)
990
0
{
991
    /* we can't store any certs private */
992
0
    if (sftk_isTrue(object, CKA_PRIVATE)) {
993
0
        return CKR_ATTRIBUTE_VALUE_INVALID;
994
0
    }
995
996
    /* certificates must have a type */
997
0
    if (!sftk_hasAttribute(object, CKA_ISSUER)) {
998
0
        return CKR_TEMPLATE_INCOMPLETE;
999
0
    }
1000
0
    if (!sftk_hasAttribute(object, CKA_SERIAL_NUMBER)) {
1001
0
        return CKR_TEMPLATE_INCOMPLETE;
1002
0
    }
1003
0
    if (!sftk_hasAttribute(object, CKA_HASH_OF_CERTIFICATE)) {
1004
0
        return CKR_TEMPLATE_INCOMPLETE;
1005
0
    }
1006
0
    if (!sftk_hasAttribute(object, CKA_NAME_HASH_ALGORITHM)) {
1007
0
        return CKR_TEMPLATE_INCOMPLETE;
1008
0
    }
1009
1010
0
    if (sftk_isTrue(object, CKA_TOKEN)) {
1011
0
        SFTKSlot *slot = session->slot;
1012
0
        SFTKDBHandle *certHandle = sftk_getCertDB(slot);
1013
0
        CK_RV crv;
1014
1015
0
        if (certHandle == NULL) {
1016
0
            return CKR_TOKEN_WRITE_PROTECTED;
1017
0
        }
1018
1019
0
        crv = sftkdb_write(certHandle, object, &object->handle);
1020
0
        sftk_freeDB(certHandle);
1021
0
        return crv;
1022
0
    }
1023
1024
0
    return CKR_OK;
1025
0
}
1026
1027
/*
1028
 * check the consistancy and initialize a Trust Object
1029
 */
1030
static CK_RV
1031
sftk_handleSMimeObject(SFTKSession *session, SFTKObject *object)
1032
0
{
1033
1034
    /* we can't store any certs private */
1035
0
    if (sftk_isTrue(object, CKA_PRIVATE)) {
1036
0
        return CKR_ATTRIBUTE_VALUE_INVALID;
1037
0
    }
1038
1039
    /* certificates must have a type */
1040
0
    if (!sftk_hasAttribute(object, CKA_SUBJECT)) {
1041
0
        return CKR_TEMPLATE_INCOMPLETE;
1042
0
    }
1043
0
    if (!sftk_hasAttribute(object, CKA_NSS_EMAIL)) {
1044
0
        return CKR_TEMPLATE_INCOMPLETE;
1045
0
    }
1046
1047
0
    if (sftk_isTrue(object, CKA_TOKEN)) {
1048
0
        SFTKSlot *slot = session->slot;
1049
0
        SFTKDBHandle *certHandle;
1050
0
        CK_RV crv;
1051
1052
0
        PORT_Assert(slot);
1053
0
        if (slot == NULL) {
1054
0
            return CKR_SESSION_HANDLE_INVALID;
1055
0
        }
1056
1057
0
        certHandle = sftk_getCertDB(slot);
1058
0
        if (certHandle == NULL) {
1059
0
            return CKR_TOKEN_WRITE_PROTECTED;
1060
0
        }
1061
1062
0
        crv = sftkdb_write(certHandle, object, &object->handle);
1063
0
        sftk_freeDB(certHandle);
1064
0
        return crv;
1065
0
    }
1066
1067
0
    return CKR_OK;
1068
0
}
1069
1070
/*
1071
 * check the consistancy and initialize a Trust Object
1072
 */
1073
static CK_RV
1074
sftk_handleCrlObject(SFTKSession *session, SFTKObject *object)
1075
0
{
1076
1077
    /* we can't store any certs private */
1078
0
    if (sftk_isTrue(object, CKA_PRIVATE)) {
1079
0
        return CKR_ATTRIBUTE_VALUE_INVALID;
1080
0
    }
1081
1082
    /* certificates must have a type */
1083
0
    if (!sftk_hasAttribute(object, CKA_SUBJECT)) {
1084
0
        return CKR_TEMPLATE_INCOMPLETE;
1085
0
    }
1086
0
    if (!sftk_hasAttribute(object, CKA_VALUE)) {
1087
0
        return CKR_TEMPLATE_INCOMPLETE;
1088
0
    }
1089
1090
0
    if (sftk_isTrue(object, CKA_TOKEN)) {
1091
0
        SFTKSlot *slot = session->slot;
1092
0
        SFTKDBHandle *certHandle = sftk_getCertDB(slot);
1093
0
        CK_RV crv;
1094
1095
0
        if (certHandle == NULL) {
1096
0
            return CKR_TOKEN_WRITE_PROTECTED;
1097
0
        }
1098
1099
0
        crv = sftkdb_write(certHandle, object, &object->handle);
1100
0
        sftk_freeDB(certHandle);
1101
0
        return crv;
1102
0
    }
1103
1104
0
    return CKR_OK;
1105
0
}
1106
1107
/*
1108
 * check the consistancy and initialize a Public Key Object
1109
 */
1110
static CK_RV
1111
sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object,
1112
                           CK_KEY_TYPE key_type)
1113
142k
{
1114
142k
    CK_BBOOL encrypt = CK_FALSE;
1115
142k
    CK_BBOOL recover = CK_FALSE;
1116
142k
    CK_BBOOL wrap = CK_FALSE;
1117
142k
    CK_BBOOL derive = CK_FALSE;
1118
142k
    CK_BBOOL verify = CK_FALSE;
1119
142k
    CK_BBOOL encapsulate = CK_FALSE;
1120
142k
    CK_ULONG paramSet = 0;
1121
142k
    CK_RV crv;
1122
1123
142k
    switch (key_type) {
1124
39.8k
        case CKK_RSA:
1125
39.8k
            crv = sftk_ConstrainAttribute(object, CKA_MODULUS,
1126
39.8k
                                          RSA_MIN_MODULUS_BITS, 0, 0);
1127
39.8k
            if (crv != CKR_OK) {
1128
0
                return crv;
1129
0
            }
1130
39.8k
            crv = sftk_ConstrainAttribute(object, CKA_PUBLIC_EXPONENT, 2, 0, 0);
1131
39.8k
            if (crv != CKR_OK) {
1132
39
                return crv;
1133
39
            }
1134
39.7k
            encrypt = CK_TRUE;
1135
39.7k
            recover = CK_TRUE;
1136
39.7k
            wrap = CK_TRUE;
1137
39.7k
            verify = CK_TRUE;
1138
39.7k
            break;
1139
4.05k
        case CKK_DSA:
1140
4.05k
            crv = sftk_ConstrainAttribute(object, CKA_SUBPRIME,
1141
4.05k
                                          DSA_MIN_Q_BITS, DSA_MAX_Q_BITS, 0);
1142
4.05k
            if (crv != CKR_OK) {
1143
6
                return crv;
1144
6
            }
1145
4.05k
            crv = sftk_ConstrainAttribute(object, CKA_PRIME,
1146
4.05k
                                          DSA_MIN_P_BITS, DSA_MAX_P_BITS, 64);
1147
4.05k
            if (crv != CKR_OK) {
1148
32
                return crv;
1149
32
            }
1150
4.02k
            crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DSA_MAX_P_BITS, 0);
1151
4.02k
            if (crv != CKR_OK) {
1152
0
                return crv;
1153
0
            }
1154
4.02k
            crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DSA_MAX_P_BITS, 0);
1155
4.02k
            if (crv != CKR_OK) {
1156
0
                return crv;
1157
0
            }
1158
4.02k
            verify = CK_TRUE;
1159
4.02k
            break;
1160
6.84k
        case CKK_DH:
1161
6.84k
            crv = sftk_ConstrainAttribute(object, CKA_PRIME,
1162
6.84k
                                          DH_MIN_P_BITS, DH_MAX_P_BITS, 0);
1163
6.84k
            if (crv != CKR_OK) {
1164
0
                return crv;
1165
0
            }
1166
6.84k
            crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DH_MAX_P_BITS, 0);
1167
6.84k
            if (crv != CKR_OK) {
1168
3
                return crv;
1169
3
            }
1170
6.84k
            crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DH_MAX_P_BITS, 0);
1171
6.84k
            if (crv != CKR_OK) {
1172
402
                return crv;
1173
402
            }
1174
6.44k
            derive = CK_TRUE;
1175
6.44k
            break;
1176
0
        case CKK_EC_MONTGOMERY:
1177
0
        case CKK_EC_EDWARDS:
1178
76.9k
        case CKK_EC:
1179
76.9k
            if (!sftk_hasAttribute(object, CKA_EC_PARAMS)) {
1180
0
                return CKR_TEMPLATE_INCOMPLETE;
1181
0
            }
1182
76.9k
            if (!sftk_hasAttribute(object, CKA_EC_POINT)) {
1183
0
                return CKR_TEMPLATE_INCOMPLETE;
1184
0
            }
1185
            /* for ECDSA and EDDSA. Change if the structure of any of them is modified. */
1186
76.9k
            derive = (key_type == CKK_EC_EDWARDS) ? CK_FALSE : CK_TRUE;    /* CK_TRUE for ECDH */
1187
76.9k
            verify = (key_type == CKK_EC_MONTGOMERY) ? CK_FALSE : CK_TRUE; /* for ECDSA and EDDSA */
1188
76.9k
            break;
1189
0
#ifndef NSS_DISABLE_KYBER
1190
0
        case CKK_NSS_KYBER:
1191
0
#endif
1192
13.6k
        case CKK_NSS_ML_KEM:
1193
14.3k
        case CKK_ML_KEM:
1194
14.3k
            if (!sftk_hasAttribute(object, CKA_PARAMETER_SET)) {
1195
0
                if (!sftk_hasAttribute(object, CKA_NSS_PARAMETER_SET)) {
1196
0
                    return CKR_TEMPLATE_INCOMPLETE;
1197
0
                }
1198
0
            }
1199
14.3k
            encapsulate = CK_TRUE;
1200
14.3k
            break;
1201
0
        case CKK_ML_DSA:
1202
0
            if (!sftk_hasAttribute(object, CKA_PARAMETER_SET)) {
1203
0
                return CKR_TEMPLATE_INCOMPLETE;
1204
0
            }
1205
0
            crv = sftk_GetULongAttribute(object, CKA_PARAMETER_SET,
1206
0
                                         &paramSet);
1207
0
            if (crv != CKR_OK) {
1208
0
                return crv;
1209
0
            }
1210
0
            if (sftk_MLDSAGetSigLen(paramSet) == 0) {
1211
0
                return CKR_ATTRIBUTE_VALUE_INVALID;
1212
0
            }
1213
0
            verify = CK_TRUE;
1214
0
            break;
1215
0
        default:
1216
0
            return CKR_ATTRIBUTE_VALUE_INVALID;
1217
142k
    }
1218
1219
    /* make sure the required fields exist */
1220
141k
    crv = sftk_defaultAttribute(object, CKA_SUBJECT, NULL, 0);
1221
141k
    if (crv != CKR_OK)
1222
0
        return crv;
1223
141k
    crv = sftk_defaultAttribute(object, CKA_ENCRYPT, &encrypt, sizeof(CK_BBOOL));
1224
141k
    if (crv != CKR_OK)
1225
0
        return crv;
1226
141k
    crv = sftk_defaultAttribute(object, CKA_VERIFY, &verify, sizeof(CK_BBOOL));
1227
141k
    if (crv != CKR_OK)
1228
0
        return crv;
1229
141k
    crv = sftk_defaultAttribute(object, CKA_VERIFY_RECOVER,
1230
141k
                                &recover, sizeof(CK_BBOOL));
1231
141k
    if (crv != CKR_OK)
1232
0
        return crv;
1233
141k
    crv = sftk_defaultAttribute(object, CKA_WRAP, &wrap, sizeof(CK_BBOOL));
1234
141k
    if (crv != CKR_OK)
1235
0
        return crv;
1236
141k
    crv = sftk_defaultAttribute(object, CKA_DERIVE, &derive, sizeof(CK_BBOOL));
1237
141k
    if (crv != CKR_OK)
1238
0
        return crv;
1239
141k
    crv = sftk_defaultAttribute(object, CKA_ENCAPSULATE, &encapsulate,
1240
141k
                                sizeof(CK_BBOOL));
1241
141k
    if (crv != CKR_OK)
1242
0
        return crv;
1243
141k
    object->objectInfo = sftk_GetPubKey(object, key_type, &crv);
1244
141k
    if (object->objectInfo == NULL) {
1245
832
        return crv;
1246
832
    }
1247
140k
    object->infoFree = SFTKFree_nsslowkey_DestroyPublicKey;
1248
1249
    /* Check that an imported EC key is valid */
1250
140k
    if (key_type == CKK_EC || key_type == CKK_EC_EDWARDS || key_type == CKK_EC_MONTGOMERY) {
1251
76.1k
        NSSLOWKEYPublicKey *pubKey = (NSSLOWKEYPublicKey *)object->objectInfo;
1252
76.1k
        SECStatus rv = EC_ValidatePublicKey(&pubKey->u.ec.ecParams,
1253
76.1k
                                            &pubKey->u.ec.publicValue);
1254
1255
76.1k
        if (rv != SECSuccess) {
1256
316
            return CKR_TEMPLATE_INCONSISTENT;
1257
316
        }
1258
76.1k
    }
1259
1260
140k
    if (sftk_isTrue(object, CKA_TOKEN)) {
1261
0
        SFTKSlot *slot = session->slot;
1262
0
        SFTKDBHandle *certHandle = sftk_getCertDB(slot);
1263
1264
0
        if (certHandle == NULL) {
1265
0
            return CKR_TOKEN_WRITE_PROTECTED;
1266
0
        }
1267
1268
0
        crv = sftkdb_write(certHandle, object, &object->handle);
1269
0
        sftk_freeDB(certHandle);
1270
0
        return crv;
1271
0
    }
1272
1273
140k
    return CKR_OK;
1274
140k
}
1275
1276
static NSSLOWKEYPrivateKey *
1277
sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key, CK_RV *rvp);
1278
1279
static SECStatus
1280
sftk_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded);
1281
1282
/*
1283
 * check the consistancy and initialize a Private Key Object
1284
 */
1285
static CK_RV
1286
sftk_handlePrivateKeyObject(SFTKSession *session, SFTKObject *object, CK_KEY_TYPE key_type)
1287
95.7k
{
1288
95.7k
    CK_BBOOL cktrue = CK_TRUE;
1289
95.7k
    CK_BBOOL encrypt = CK_FALSE;
1290
95.7k
    CK_BBOOL sign = CK_FALSE;
1291
95.7k
    CK_BBOOL recover = CK_FALSE;
1292
95.7k
    CK_BBOOL wrap = CK_FALSE;
1293
95.7k
    CK_BBOOL derive = CK_FALSE;
1294
95.7k
    CK_BBOOL decapsulate = CK_FALSE;
1295
95.7k
    CK_BBOOL ckfalse = CK_FALSE;
1296
95.7k
    CK_ULONG paramSet = 0;
1297
95.7k
    PRBool createObjectInfo = PR_TRUE;
1298
95.7k
    PRBool fillPrivateKey = PR_FALSE;
1299
95.7k
    int missing_rsa_mod_component = 0;
1300
95.7k
    int missing_rsa_exp_component = 0;
1301
95.7k
    int missing_rsa_crt_component = 0;
1302
1303
95.7k
    SECItem mod;
1304
95.7k
    CK_RV crv;
1305
95.7k
    SECStatus rv;
1306
1307
95.7k
    switch (key_type) {
1308
24
        case CKK_RSA:
1309
24
            if (!sftk_hasAttribute(object, CKA_MODULUS)) {
1310
0
                missing_rsa_mod_component++;
1311
0
            }
1312
24
            if (!sftk_hasAttribute(object, CKA_PUBLIC_EXPONENT)) {
1313
0
                missing_rsa_exp_component++;
1314
0
            }
1315
24
            if (!sftk_hasAttribute(object, CKA_PRIVATE_EXPONENT)) {
1316
0
                missing_rsa_exp_component++;
1317
0
            }
1318
24
            if (!sftk_hasAttribute(object, CKA_PRIME_1)) {
1319
0
                missing_rsa_mod_component++;
1320
0
            }
1321
24
            if (!sftk_hasAttribute(object, CKA_PRIME_2)) {
1322
0
                missing_rsa_mod_component++;
1323
0
            }
1324
24
            if (!sftk_hasAttribute(object, CKA_EXPONENT_1)) {
1325
0
                missing_rsa_crt_component++;
1326
0
            }
1327
24
            if (!sftk_hasAttribute(object, CKA_EXPONENT_2)) {
1328
0
                missing_rsa_crt_component++;
1329
0
            }
1330
24
            if (!sftk_hasAttribute(object, CKA_COEFFICIENT)) {
1331
0
                missing_rsa_crt_component++;
1332
0
            }
1333
24
            if (missing_rsa_mod_component || missing_rsa_exp_component ||
1334
24
                missing_rsa_crt_component) {
1335
                /* we are missing a component, see if we have enough to rebuild
1336
                 * the rest */
1337
0
                int have_exp = 2 - missing_rsa_exp_component;
1338
0
                int have_component = 5 -
1339
0
                                     (missing_rsa_exp_component + missing_rsa_mod_component);
1340
1341
0
                if ((have_exp == 0) || (have_component < 3)) {
1342
                    /* nope, not enough to reconstruct the private key */
1343
0
                    return CKR_TEMPLATE_INCOMPLETE;
1344
0
                }
1345
0
                fillPrivateKey = PR_TRUE;
1346
0
            }
1347
            /*verify the parameters for consistency*/
1348
24
            rv = sftk_verifyRSAPrivateKey(object, fillPrivateKey);
1349
24
            if (rv != SECSuccess) {
1350
0
                return CKR_TEMPLATE_INCOMPLETE;
1351
0
            }
1352
1353
            /* make sure Netscape DB attribute is set correctly */
1354
24
            crv = sftk_Attribute2SSecItem(NULL, &mod, object, CKA_MODULUS);
1355
24
            if (crv != CKR_OK)
1356
0
                return crv;
1357
24
            crv = sftk_forceAttribute(object, CKA_NSS_DB,
1358
24
                                      sftk_item_expand(&mod));
1359
24
            if (mod.data)
1360
24
                SECITEM_ZfreeItem(&mod, PR_FALSE);
1361
24
            if (crv != CKR_OK)
1362
0
                return crv;
1363
1364
24
            sign = CK_TRUE;
1365
24
            wrap = CK_TRUE;
1366
24
            encrypt = CK_TRUE;
1367
24
            break;
1368
0
        case CKK_DSA:
1369
0
            if (!sftk_hasAttribute(object, CKA_SUBPRIME)) {
1370
0
                return CKR_TEMPLATE_INCOMPLETE;
1371
0
            }
1372
0
            if (!sftk_hasAttribute(object, CKA_PRIME)) {
1373
0
                return CKR_TEMPLATE_INCOMPLETE;
1374
0
            }
1375
0
            if (!sftk_hasAttribute(object, CKA_BASE)) {
1376
0
                return CKR_TEMPLATE_INCOMPLETE;
1377
0
            }
1378
0
            if (!sftk_hasAttribute(object, CKA_VALUE)) {
1379
0
                return CKR_TEMPLATE_INCOMPLETE;
1380
0
            }
1381
0
            sign = CK_TRUE;
1382
0
            break;
1383
6.83k
        case CKK_DH:
1384
6.83k
            if (!sftk_hasAttribute(object, CKA_PRIME)) {
1385
0
                return CKR_TEMPLATE_INCOMPLETE;
1386
0
            }
1387
6.83k
            if (!sftk_hasAttribute(object, CKA_BASE)) {
1388
0
                return CKR_TEMPLATE_INCOMPLETE;
1389
0
            }
1390
6.83k
            if (!sftk_hasAttribute(object, CKA_VALUE)) {
1391
0
                return CKR_TEMPLATE_INCOMPLETE;
1392
0
            }
1393
            /* allow subprime to be set after the fact */
1394
6.83k
            crv = sftk_defaultAttribute(object, CKA_SUBPRIME, NULL, 0);
1395
6.83k
            if (crv != CKR_OK) {
1396
0
                return crv;
1397
0
            }
1398
6.83k
            derive = CK_TRUE;
1399
6.83k
            break;
1400
75.1k
        case CKK_EC:
1401
75.1k
        case CKK_EC_EDWARDS:
1402
75.1k
        case CKK_EC_MONTGOMERY:
1403
75.1k
            if (!sftk_hasAttribute(object, CKA_EC_PARAMS)) {
1404
0
                return CKR_TEMPLATE_INCOMPLETE;
1405
0
            }
1406
75.1k
            if (!sftk_hasAttribute(object, CKA_VALUE)) {
1407
0
                return CKR_TEMPLATE_INCOMPLETE;
1408
0
            }
1409
            /* for ECDSA and EDDSA. Change if the structure of any of them is modified. */
1410
75.1k
            derive = (key_type == CKK_EC_EDWARDS) ? CK_FALSE : CK_TRUE;  /* CK_TRUE for ECDH */
1411
75.1k
            sign = (key_type == CKK_EC_MONTGOMERY) ? CK_FALSE : CK_TRUE; /* for ECDSA and EDDSA */
1412
75.1k
            break;
1413
0
        case CKK_NSS_JPAKE_ROUND1:
1414
0
            if (!sftk_hasAttribute(object, CKA_PRIME) ||
1415
0
                !sftk_hasAttribute(object, CKA_SUBPRIME) ||
1416
0
                !sftk_hasAttribute(object, CKA_BASE)) {
1417
0
                return CKR_TEMPLATE_INCOMPLETE;
1418
0
            }
1419
        /* fall through */
1420
0
        case CKK_NSS_JPAKE_ROUND2:
1421
            /* CKA_NSS_JPAKE_SIGNERID and CKA_NSS_JPAKE_PEERID are checked in
1422
               the J-PAKE code. */
1423
0
            derive = CK_TRUE;
1424
0
            createObjectInfo = PR_FALSE;
1425
0
            break;
1426
0
#ifndef NSS_DISABLE_KYBER
1427
0
        case CKK_NSS_KYBER:
1428
0
#endif
1429
13.6k
        case CKK_NSS_ML_KEM:
1430
13.6k
        case CKK_ML_KEM:
1431
13.6k
            if (!sftk_hasAttribute(object, CKA_KEY_TYPE)) {
1432
0
                return CKR_TEMPLATE_INCOMPLETE;
1433
0
            }
1434
13.6k
            if (!sftk_hasAttribute(object, CKA_VALUE) &&
1435
0
                !sftk_hasAttribute(object, CKA_SEED)) {
1436
0
                return CKR_TEMPLATE_INCOMPLETE;
1437
0
            }
1438
13.6k
            crv = sftk_GetULongAttribute(object, CKA_PARAMETER_SET,
1439
13.6k
                                         &paramSet);
1440
13.6k
            if (crv != CKR_OK) {
1441
0
                crv = sftk_GetULongAttribute(object, CKA_NSS_PARAMETER_SET,
1442
0
                                             &paramSet);
1443
0
                if (crv != CKR_OK) {
1444
0
                    return crv;
1445
0
                }
1446
0
            }
1447
1448
13.6k
            KyberParams kyberParams = sftk_kyber_PK11ParamToInternal(paramSet);
1449
13.6k
            if (kyberParams == params_kyber_invalid) {
1450
0
                return CKR_ATTRIBUTE_VALUE_INVALID;
1451
0
            }
1452
            /*
1453
             * if we have a seedm deal with making sure CKA_SEED and
1454
             * CKA_VALUE are consistant. We skip this step if the CKA_SEED and
1455
             * CKA_VALUE were generated together by us. */
1456
13.6k
            if (sftk_hasAttribute(object, CKA_SEED)) {
1457
13.6k
                PRBool seedOK = sftk_hasAttribute(object, CKA_NSS_SEED_OK);
1458
13.6k
                SFTKAttribute *seedAttribute = sftk_FindAttribute(object,
1459
13.6k
                                                                  CKA_SEED);
1460
13.6k
                PORT_Assert(seedAttribute);
1461
13.6k
                crv = CKR_OK;
1462
13.6k
                if (seedAttribute->attrib.ulValueLen != 0) {
1463
13.6k
                    SFTKAttribute *valueAttribute =
1464
13.6k
                        sftk_FindAttribute(object, CKA_VALUE);
1465
13.6k
                    CK_ULONG valueLen = valueAttribute ? valueAttribute->attrib.ulValueLen : 0;
1466
13.6k
                    if (!seedOK || valueLen == 0) {
1467
0
                        SECItem privKey = { siBuffer, NULL, 0 };
1468
0
                        SECItem pubKey = { siBuffer, NULL, 0 };
1469
0
                        SECItem seed = { siBuffer, NULL, 0 };
1470
1471
0
                        seed.data = seedAttribute->attrib.pValue;
1472
0
                        seed.len = (int)seedAttribute->attrib.ulValueLen;
1473
1474
0
                        if (!sftk_kyber_AllocPrivKeyItem(kyberParams, &privKey)) {
1475
0
                            crv = CKR_HOST_MEMORY;
1476
0
                            goto kyber_loser;
1477
0
                        }
1478
0
                        if (!sftk_kyber_AllocPubKeyItem(kyberParams, &pubKey)) {
1479
0
                            crv = CKR_HOST_MEMORY;
1480
0
                            goto kyber_loser;
1481
0
                        }
1482
0
                        rv = Kyber_NewKey(kyberParams, &seed, &privKey, &pubKey);
1483
0
                        if (rv != SECSuccess) {
1484
0
                            crv = CKR_ATTRIBUTE_VALUE_INVALID;
1485
0
                        } else if (valueLen == 0) {
1486
0
                            crv = sftk_forceAttribute(object, CKA_VALUE,
1487
0
                                                      privKey.data,
1488
0
                                                      privKey.len);
1489
0
                        } else {
1490
                            /* we have the value, so we must verify it */
1491
0
                            PORT_Assert(!seedOK);
1492
0
                            if ((privKey.len != valueLen) ||
1493
0
                                (PORT_Memcmp(valueAttribute->attrib.pValue,
1494
0
                                             privKey.data, valueLen) != 0)) {
1495
0
                                crv = CKR_ATTRIBUTE_VALUE_INVALID;
1496
0
                            }
1497
0
                        }
1498
0
                    kyber_loser:
1499
0
                        SECITEM_ZfreeItem(&privKey, PR_FALSE);
1500
0
                        SECITEM_ZfreeItem(&pubKey, PR_FALSE);
1501
                        /* seed is cleared when we free seedAttribute */
1502
0
                    }
1503
13.6k
                    if (valueAttribute)
1504
13.6k
                        sftk_FreeAttribute(valueAttribute);
1505
13.6k
                }
1506
13.6k
                sftk_FreeAttribute(seedAttribute);
1507
13.6k
                if (crv != CKR_OK) {
1508
0
                    return crv;
1509
0
                }
1510
13.6k
            }
1511
13.6k
            sftk_DeleteAttributeType(object, CKA_NSS_SEED_OK);
1512
            /* if we got this far, we should have a CKA_VALUE, either by
1513
             * one given to us, or by it being generated above */
1514
13.6k
            if (!sftk_hasAttribute(object, CKA_VALUE)) {
1515
0
                return CKR_TEMPLATE_INCOMPLETE;
1516
0
            }
1517
13.6k
            decapsulate = CK_TRUE;
1518
13.6k
            break;
1519
0
        case CKK_ML_DSA:
1520
0
            if (!sftk_hasAttribute(object, CKA_KEY_TYPE)) {
1521
0
                return CKR_TEMPLATE_INCOMPLETE;
1522
0
            }
1523
            /* make sure we have a CKA_PARAMETER_SET */
1524
0
            if (!sftk_hasAttribute(object, CKA_PARAMETER_SET)) {
1525
0
                return CKR_TEMPLATE_INCOMPLETE;
1526
0
            }
1527
            /* make sure it's one we understand */
1528
0
            crv = sftk_GetULongAttribute(object, CKA_PARAMETER_SET,
1529
0
                                         &paramSet);
1530
0
            if (crv != CKR_OK) {
1531
0
                return crv;
1532
0
            }
1533
0
            if (sftk_MLDSAGetSigLen(paramSet) == 0) {
1534
0
                return CKR_ATTRIBUTE_VALUE_INVALID;
1535
0
            }
1536
            /*
1537
             * if we have a seed deal with making sure seed and
1538
             * CKA_VALUE . We skip this step if the SEED and VALUE
1539
             * was generated together by us. */
1540
0
            if (sftk_hasAttribute(object, CKA_SEED)) {
1541
0
                PRBool seedOK = sftk_hasAttribute(object, CKA_NSS_SEED_OK);
1542
0
                SFTKAttribute *seedAttribute = sftk_FindAttribute(object,
1543
0
                                                                  CKA_SEED);
1544
0
                PORT_Assert(seedAttribute);
1545
0
                crv = CKR_OK;
1546
0
                if (seedAttribute->attrib.ulValueLen != 0) {
1547
0
                    SFTKAttribute *valueAttribute =
1548
0
                        sftk_FindAttribute(object, CKA_VALUE);
1549
0
                    CK_ULONG valueLen = valueAttribute ? valueAttribute->attrib.ulValueLen : 0;
1550
0
                    if (!seedOK || valueLen == 0) {
1551
0
                        MLDSAPrivateKey privKey;
1552
0
                        MLDSAPublicKey pubKey;
1553
0
                        SECItem seedItem;
1554
1555
0
                        seedItem.data = seedAttribute->attrib.pValue;
1556
0
                        seedItem.len = seedAttribute->attrib.ulValueLen;
1557
0
                        rv = MLDSA_NewKey(paramSet, &seedItem, &privKey,
1558
0
                                          &pubKey);
1559
0
                        if (rv != SECSuccess) {
1560
0
                            crv = CKR_ATTRIBUTE_VALUE_INVALID;
1561
0
                        } else if (valueLen == 0) {
1562
0
                            crv = sftk_forceAttribute(object, CKA_VALUE,
1563
0
                                                      privKey.keyVal,
1564
0
                                                      privKey.keyValLen);
1565
0
                        } else {
1566
                            /* we have the value, so we must need to
1567
                             * verify it */
1568
0
                            PORT_Assert(!seedOK);
1569
0
                            if ((privKey.keyValLen != valueLen) ||
1570
0
                                (PORT_Memcmp(valueAttribute->attrib.pValue,
1571
0
                                             privKey.keyVal, valueLen) != 0)) {
1572
0
                                crv = CKR_ATTRIBUTE_VALUE_INVALID;
1573
0
                            }
1574
0
                        }
1575
0
                        PORT_SafeZero(&privKey, sizeof(privKey));
1576
0
                        PORT_SafeZero(&pubKey, sizeof(pubKey));
1577
0
                    }
1578
0
                    if (valueAttribute)
1579
0
                        sftk_FreeAttribute(valueAttribute);
1580
0
                }
1581
0
                sftk_FreeAttribute(seedAttribute);
1582
0
                if (crv != CKR_OK) {
1583
0
                    return crv;
1584
0
                }
1585
0
            }
1586
0
            sftk_DeleteAttributeType(object, CKA_NSS_SEED_OK);
1587
            /* if we got this far, we should have a CKA_VALUE, either but
1588
             * one given to us, or by it being generated above */
1589
0
            if (!sftk_hasAttribute(object, CKA_VALUE)) {
1590
0
                return CKR_TEMPLATE_INCOMPLETE;
1591
0
            }
1592
0
            sign = CK_TRUE;
1593
0
            break;
1594
1595
0
        default:
1596
0
            return CKR_ATTRIBUTE_VALUE_INVALID;
1597
95.7k
    }
1598
95.7k
    crv = sftk_defaultAttribute(object, CKA_SUBJECT, NULL, 0);
1599
95.7k
    if (crv != CKR_OK)
1600
0
        return crv;
1601
95.7k
    crv = sftk_defaultAttribute(object, CKA_SENSITIVE, &cktrue, sizeof(CK_BBOOL));
1602
95.7k
    if (crv != CKR_OK)
1603
0
        return crv;
1604
95.7k
    crv = sftk_defaultAttribute(object, CKA_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL));
1605
95.7k
    if (crv != CKR_OK)
1606
0
        return crv;
1607
95.7k
    crv = sftk_defaultAttribute(object, CKA_DECRYPT, &encrypt, sizeof(CK_BBOOL));
1608
95.7k
    if (crv != CKR_OK)
1609
0
        return crv;
1610
95.7k
    crv = sftk_defaultAttribute(object, CKA_SIGN, &sign, sizeof(CK_BBOOL));
1611
95.7k
    if (crv != CKR_OK)
1612
0
        return crv;
1613
95.7k
    crv = sftk_defaultAttribute(object, CKA_SIGN_RECOVER, &recover,
1614
95.7k
                                sizeof(CK_BBOOL));
1615
95.7k
    if (crv != CKR_OK)
1616
0
        return crv;
1617
95.7k
    crv = sftk_defaultAttribute(object, CKA_UNWRAP, &wrap, sizeof(CK_BBOOL));
1618
95.7k
    if (crv != CKR_OK)
1619
0
        return crv;
1620
95.7k
    crv = sftk_defaultAttribute(object, CKA_DERIVE, &derive, sizeof(CK_BBOOL));
1621
95.7k
    if (crv != CKR_OK)
1622
0
        return crv;
1623
95.7k
    crv = sftk_defaultAttribute(object, CKA_DECAPSULATE, &decapsulate,
1624
95.7k
                                sizeof(CK_BBOOL));
1625
95.7k
    if (crv != CKR_OK)
1626
0
        return crv;
1627
    /* the next two bits get modified only in the key gen and token cases */
1628
95.7k
    crv = sftk_forceAttribute(object, CKA_ALWAYS_SENSITIVE,
1629
95.7k
                              &ckfalse, sizeof(CK_BBOOL));
1630
95.7k
    if (crv != CKR_OK)
1631
0
        return crv;
1632
95.7k
    crv = sftk_forceAttribute(object, CKA_NEVER_EXTRACTABLE,
1633
95.7k
                              &ckfalse, sizeof(CK_BBOOL));
1634
95.7k
    if (crv != CKR_OK)
1635
0
        return crv;
1636
1637
    /* should we check the non-token RSA private keys? */
1638
1639
95.7k
    if (sftk_isTrue(object, CKA_TOKEN)) {
1640
0
        SFTKSlot *slot = session->slot;
1641
0
        SFTKDBHandle *keyHandle = sftk_getKeyDB(slot);
1642
1643
0
        if (keyHandle == NULL) {
1644
0
            return CKR_TOKEN_WRITE_PROTECTED;
1645
0
        }
1646
1647
0
        crv = sftkdb_write(keyHandle, object, &object->handle);
1648
0
        sftk_freeDB(keyHandle);
1649
0
        return crv;
1650
95.7k
    } else if (createObjectInfo) {
1651
95.7k
        object->objectInfo = sftk_mkPrivKey(object, key_type, &crv);
1652
95.7k
        if (object->objectInfo == NULL)
1653
0
            return crv;
1654
95.7k
        object->infoFree = SFTKFree_nsslowkey_DestroyPrivateKey;
1655
95.7k
    }
1656
95.7k
    return CKR_OK;
1657
95.7k
}
1658
1659
/* forward declare the DES formating function for handleSecretKey */
1660
void sftk_FormatDESKey(unsigned char *key, int length);
1661
1662
/* Validate secret key data, and set defaults */
1663
static CK_RV
1664
validateSecretKey(SFTKSession *session, SFTKObject *object,
1665
                  CK_KEY_TYPE key_type, PRBool isFIPS)
1666
1.07M
{
1667
1.07M
    CK_RV crv;
1668
1.07M
    CK_BBOOL cktrue = CK_TRUE;
1669
1.07M
    CK_BBOOL ckfalse = CK_FALSE;
1670
1.07M
    SFTKAttribute *attribute = NULL;
1671
1.07M
    unsigned long requiredLen;
1672
1673
1.07M
    crv = sftk_defaultAttribute(object, CKA_SENSITIVE,
1674
1.07M
                                isFIPS ? &cktrue : &ckfalse, sizeof(CK_BBOOL));
1675
1.07M
    if (crv != CKR_OK)
1676
0
        return crv;
1677
1.07M
    crv = sftk_defaultAttribute(object, CKA_EXTRACTABLE,
1678
1.07M
                                &cktrue, sizeof(CK_BBOOL));
1679
1.07M
    if (crv != CKR_OK)
1680
0
        return crv;
1681
1.07M
    crv = sftk_defaultAttribute(object, CKA_ENCRYPT, &cktrue, sizeof(CK_BBOOL));
1682
1.07M
    if (crv != CKR_OK)
1683
0
        return crv;
1684
1.07M
    crv = sftk_defaultAttribute(object, CKA_DECRYPT, &cktrue, sizeof(CK_BBOOL));
1685
1.07M
    if (crv != CKR_OK)
1686
0
        return crv;
1687
1.07M
    crv = sftk_defaultAttribute(object, CKA_SIGN, &ckfalse, sizeof(CK_BBOOL));
1688
1.07M
    if (crv != CKR_OK)
1689
0
        return crv;
1690
1.07M
    crv = sftk_defaultAttribute(object, CKA_VERIFY, &ckfalse, sizeof(CK_BBOOL));
1691
1.07M
    if (crv != CKR_OK)
1692
0
        return crv;
1693
1.07M
    crv = sftk_defaultAttribute(object, CKA_WRAP, &cktrue, sizeof(CK_BBOOL));
1694
1.07M
    if (crv != CKR_OK)
1695
0
        return crv;
1696
1.07M
    crv = sftk_defaultAttribute(object, CKA_UNWRAP, &cktrue, sizeof(CK_BBOOL));
1697
1.07M
    if (crv != CKR_OK)
1698
0
        return crv;
1699
1700
1.07M
    if (!sftk_hasAttribute(object, CKA_VALUE)) {
1701
0
        return CKR_TEMPLATE_INCOMPLETE;
1702
0
    }
1703
    /* the next two bits get modified only in the key gen and token cases */
1704
1.07M
    crv = sftk_forceAttribute(object, CKA_ALWAYS_SENSITIVE,
1705
1.07M
                              &ckfalse, sizeof(CK_BBOOL));
1706
1.07M
    if (crv != CKR_OK)
1707
0
        return crv;
1708
1.07M
    crv = sftk_forceAttribute(object, CKA_NEVER_EXTRACTABLE,
1709
1.07M
                              &ckfalse, sizeof(CK_BBOOL));
1710
1.07M
    if (crv != CKR_OK)
1711
0
        return crv;
1712
1713
    /* some types of keys have a value length */
1714
1.07M
    crv = CKR_OK;
1715
1.07M
    switch (key_type) {
1716
        /* force CKA_VALUE_LEN to be set */
1717
629k
        case CKK_GENERIC_SECRET:
1718
629k
        case CKK_RC2:
1719
635k
        case CKK_RC4:
1720
#if NSS_SOFTOKEN_DOES_RC5
1721
        case CKK_RC5:
1722
#endif
1723
#ifdef NSS_SOFTOKEN_DOES_CAST
1724
        case CKK_CAST:
1725
        case CKK_CAST3:
1726
        case CKK_CAST5:
1727
#endif
1728
#if NSS_SOFTOKEN_DOES_IDEA
1729
        case CKK_IDEA:
1730
#endif
1731
635k
            attribute = sftk_FindAttribute(object, CKA_VALUE);
1732
            /* shouldn't happen */
1733
635k
            if (attribute == NULL)
1734
0
                return CKR_TEMPLATE_INCOMPLETE;
1735
635k
            crv = sftk_forceAttribute(object, CKA_VALUE_LEN,
1736
635k
                                      &attribute->attrib.ulValueLen, sizeof(CK_ULONG));
1737
635k
            sftk_FreeAttribute(attribute);
1738
635k
            break;
1739
        /* force the value to have the correct parity */
1740
12.0k
        case CKK_DES:
1741
12.0k
        case CKK_DES2:
1742
34.8k
        case CKK_DES3:
1743
34.8k
        case CKK_CDMF:
1744
34.8k
            attribute = sftk_FindAttribute(object, CKA_VALUE);
1745
            /* shouldn't happen */
1746
34.8k
            if (attribute == NULL)
1747
0
                return CKR_TEMPLATE_INCOMPLETE;
1748
34.8k
            requiredLen = sftk_MapKeySize(key_type);
1749
34.8k
            if (attribute->attrib.ulValueLen != requiredLen) {
1750
23
                sftk_FreeAttribute(attribute);
1751
23
                return CKR_KEY_SIZE_RANGE;
1752
23
            }
1753
            /* sftk_FindAttribute returns a private copy, so set the parity
1754
             * bits on it and then write the value back to the object. */
1755
34.8k
            sftk_FormatDESKey((unsigned char *)attribute->attrib.pValue,
1756
34.8k
                              attribute->attrib.ulValueLen);
1757
34.8k
            crv = sftk_forceAttribute(object, CKA_VALUE,
1758
34.8k
                                      attribute->attrib.pValue,
1759
34.8k
                                      attribute->attrib.ulValueLen);
1760
34.8k
            sftk_FreeAttribute(attribute);
1761
34.8k
            if (crv != CKR_OK)
1762
0
                return crv;
1763
34.8k
            break;
1764
235k
        case CKK_AES:
1765
235k
            attribute = sftk_FindAttribute(object, CKA_VALUE);
1766
            /* shouldn't happen */
1767
235k
            if (attribute == NULL)
1768
0
                return CKR_TEMPLATE_INCOMPLETE;
1769
235k
            if (attribute->attrib.ulValueLen != 16 &&
1770
192k
                attribute->attrib.ulValueLen != 24 &&
1771
191k
                attribute->attrib.ulValueLen != 32) {
1772
466
                sftk_FreeAttribute(attribute);
1773
466
                return CKR_KEY_SIZE_RANGE;
1774
466
            }
1775
234k
            crv = sftk_forceAttribute(object, CKA_VALUE_LEN,
1776
234k
                                      &attribute->attrib.ulValueLen, sizeof(CK_ULONG));
1777
234k
            sftk_FreeAttribute(attribute);
1778
234k
            break;
1779
169k
        default:
1780
169k
            break;
1781
1.07M
    }
1782
1783
1.07M
    return crv;
1784
1.07M
}
1785
1786
/*
1787
 * check the consistancy and initialize a Secret Key Object
1788
 */
1789
static CK_RV
1790
sftk_handleSecretKeyObject(SFTKSession *session, SFTKObject *object,
1791
                           CK_KEY_TYPE key_type, PRBool isFIPS)
1792
1.07M
{
1793
1.07M
    CK_RV crv;
1794
1795
    /* First validate and set defaults */
1796
1.07M
    crv = validateSecretKey(session, object, key_type, isFIPS);
1797
1.07M
    if (crv != CKR_OK)
1798
489
        goto loser;
1799
1800
    /* If the object is a TOKEN object, store in the database */
1801
1.07M
    if (sftk_isTrue(object, CKA_TOKEN)) {
1802
0
        SFTKSlot *slot = session->slot;
1803
0
        SFTKDBHandle *keyHandle = sftk_getKeyDB(slot);
1804
1805
0
        if (keyHandle == NULL) {
1806
0
            return CKR_TOKEN_WRITE_PROTECTED;
1807
0
        }
1808
1809
0
        crv = sftkdb_write(keyHandle, object, &object->handle);
1810
0
        sftk_freeDB(keyHandle);
1811
0
        return crv;
1812
0
    }
1813
1814
1.07M
loser:
1815
1816
1.07M
    return crv;
1817
1.07M
}
1818
1819
/*
1820
 * check the consistancy and initialize a Key Object
1821
 */
1822
static CK_RV
1823
sftk_handleKeyObject(SFTKSession *session, SFTKObject *object)
1824
1.31M
{
1825
1.31M
    SFTKAttribute *attribute;
1826
1.31M
    CK_KEY_TYPE key_type;
1827
1.31M
    CK_BBOOL ckfalse = CK_FALSE;
1828
1.31M
    CK_RV crv;
1829
1830
    /* verify the required fields */
1831
1.31M
    if (!sftk_hasAttribute(object, CKA_KEY_TYPE)) {
1832
0
        return CKR_TEMPLATE_INCOMPLETE;
1833
0
    }
1834
1835
    /* now verify the common fields */
1836
1.31M
    crv = sftk_defaultAttribute(object, CKA_ID, NULL, 0);
1837
1.31M
    if (crv != CKR_OK)
1838
0
        return crv;
1839
1.31M
    crv = sftk_defaultAttribute(object, CKA_START_DATE, NULL, 0);
1840
1.31M
    if (crv != CKR_OK)
1841
0
        return crv;
1842
1.31M
    crv = sftk_defaultAttribute(object, CKA_END_DATE, NULL, 0);
1843
1.31M
    if (crv != CKR_OK)
1844
0
        return crv;
1845
    /* CKA_DERIVE is common to all keys, but it's default value is
1846
     * key dependent */
1847
1.31M
    crv = sftk_defaultAttribute(object, CKA_LOCAL, &ckfalse, sizeof(CK_BBOOL));
1848
1.31M
    if (crv != CKR_OK)
1849
0
        return crv;
1850
1851
    /* get the key type */
1852
1.31M
    attribute = sftk_FindAttribute(object, CKA_KEY_TYPE);
1853
1.31M
    if (!attribute) {
1854
0
        return CKR_ATTRIBUTE_VALUE_INVALID;
1855
0
    }
1856
1.31M
    key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
1857
1.31M
    sftk_FreeAttribute(attribute);
1858
1859
1.31M
    switch (object->objclass) {
1860
142k
        case CKO_PUBLIC_KEY:
1861
142k
            return sftk_handlePublicKeyObject(session, object, key_type);
1862
95.7k
        case CKO_PRIVATE_KEY:
1863
95.7k
            return sftk_handlePrivateKeyObject(session, object, key_type);
1864
1.07M
        case CKO_SECRET_KEY:
1865
            /* make sure the required fields exist */
1866
1.07M
            return sftk_handleSecretKeyObject(session, object, key_type,
1867
1.07M
                                              (PRBool)(sftk_isFIPS(session->slot->slotID)));
1868
0
        default:
1869
0
            break;
1870
1.31M
    }
1871
0
    return CKR_ATTRIBUTE_VALUE_INVALID;
1872
1.31M
}
1873
1874
/*
1875
 * check the consistancy and Verify a DSA Parameter Object
1876
 */
1877
static CK_RV
1878
sftk_handleDSAParameterObject(SFTKSession *session, SFTKObject *object)
1879
0
{
1880
0
    SFTKAttribute *primeAttr = NULL;
1881
0
    SFTKAttribute *subPrimeAttr = NULL;
1882
0
    SFTKAttribute *baseAttr = NULL;
1883
0
    SFTKAttribute *seedAttr = NULL;
1884
0
    SFTKAttribute *hAttr = NULL;
1885
0
    SFTKAttribute *attribute;
1886
0
    CK_RV crv = CKR_TEMPLATE_INCOMPLETE;
1887
0
    PQGParams params;
1888
0
    PQGVerify vfy, *verify = NULL;
1889
0
    SECStatus result, rv;
1890
    /* This bool keeps track of whether or not we need verify parameters.
1891
     * If a P, Q and G or supplied, we dont' need verify parameters, as we
1892
     * have PQ and G.
1893
     *   - If G is not supplied, the presumption is that we want to
1894
     * verify P and Q only.
1895
     *   - If counter is supplied, it is presumed we want to verify PQ because
1896
     * the counter is only used in verification.
1897
     *   - If H is supplied, is is presumed we want to verify G because H is
1898
     * only used to verify G.
1899
     *   - Any verification step must have the SEED (counter or H could be
1900
     * missing depending on exactly what we want to verify). If SEED is supplied,
1901
     * the code just goes ahead and runs verify (other errors are parameter
1902
     * errors are detected by the PQG_VerifyParams function). If SEED is not
1903
     * supplied, but we determined that we are trying to verify (because needVfy
1904
     * is set, go ahead and return CKR_TEMPLATE_INCOMPLETE.
1905
     */
1906
0
    PRBool needVfy = PR_FALSE;
1907
1908
0
    primeAttr = sftk_FindAttribute(object, CKA_PRIME);
1909
0
    if (primeAttr == NULL)
1910
0
        goto loser;
1911
0
    params.prime.data = primeAttr->attrib.pValue;
1912
0
    params.prime.len = primeAttr->attrib.ulValueLen;
1913
1914
0
    subPrimeAttr = sftk_FindAttribute(object, CKA_SUBPRIME);
1915
0
    if (subPrimeAttr == NULL)
1916
0
        goto loser;
1917
0
    params.subPrime.data = subPrimeAttr->attrib.pValue;
1918
0
    params.subPrime.len = subPrimeAttr->attrib.ulValueLen;
1919
1920
0
    baseAttr = sftk_FindAttribute(object, CKA_BASE);
1921
0
    if (baseAttr != NULL) {
1922
0
        params.base.data = baseAttr->attrib.pValue;
1923
0
        params.base.len = baseAttr->attrib.ulValueLen;
1924
0
    } else {
1925
0
        params.base.data = NULL;
1926
0
        params.base.len = 0;
1927
0
        needVfy = PR_TRUE; /* presumably only including PQ so we can verify
1928
                            * them. */
1929
0
    }
1930
1931
0
    attribute = sftk_FindAttribute(object, CKA_NSS_PQG_COUNTER);
1932
0
    if (attribute != NULL) {
1933
0
        vfy.counter = *(CK_ULONG *)attribute->attrib.pValue;
1934
0
        sftk_FreeAttribute(attribute);
1935
0
        needVfy = PR_TRUE; /* included a count so we can verify PQ */
1936
0
    } else {
1937
0
        vfy.counter = -1;
1938
0
    }
1939
1940
0
    hAttr = sftk_FindAttribute(object, CKA_NSS_PQG_H);
1941
0
    if (hAttr != NULL) {
1942
0
        vfy.h.data = hAttr->attrib.pValue;
1943
0
        vfy.h.len = hAttr->attrib.ulValueLen;
1944
0
        needVfy = PR_TRUE; /* included H so we can verify G */
1945
0
    } else {
1946
0
        vfy.h.data = NULL;
1947
0
        vfy.h.len = 0;
1948
0
    }
1949
0
    seedAttr = sftk_FindAttribute(object, CKA_NSS_PQG_SEED);
1950
0
    if (seedAttr != NULL) {
1951
0
        vfy.seed.data = seedAttr->attrib.pValue;
1952
0
        vfy.seed.len = seedAttr->attrib.ulValueLen;
1953
1954
0
        verify = &vfy;
1955
0
    } else if (needVfy) {
1956
0
        goto loser; /* Verify always needs seed, if we need verify and not seed
1957
                     * then fail */
1958
0
    }
1959
1960
0
    crv = CKR_FUNCTION_FAILED;
1961
0
    rv = PQG_VerifyParams(&params, verify, &result);
1962
0
    if (rv == SECSuccess) {
1963
0
        crv = (result == SECSuccess) ? CKR_OK : CKR_ATTRIBUTE_VALUE_INVALID;
1964
0
    }
1965
1966
0
loser:
1967
0
    if (hAttr)
1968
0
        sftk_FreeAttribute(hAttr);
1969
0
    if (seedAttr)
1970
0
        sftk_FreeAttribute(seedAttr);
1971
0
    if (baseAttr)
1972
0
        sftk_FreeAttribute(baseAttr);
1973
0
    if (subPrimeAttr)
1974
0
        sftk_FreeAttribute(subPrimeAttr);
1975
0
    if (primeAttr)
1976
0
        sftk_FreeAttribute(primeAttr);
1977
1978
0
    return crv;
1979
0
}
1980
1981
/*
1982
 * check the consistancy and initialize a Key Parameter Object
1983
 */
1984
static CK_RV
1985
sftk_handleKeyParameterObject(SFTKSession *session, SFTKObject *object)
1986
0
{
1987
0
    SFTKAttribute *attribute;
1988
0
    CK_KEY_TYPE key_type;
1989
0
    CK_BBOOL ckfalse = CK_FALSE;
1990
0
    CK_RV crv;
1991
1992
    /* verify the required fields */
1993
0
    if (!sftk_hasAttribute(object, CKA_KEY_TYPE)) {
1994
0
        return CKR_TEMPLATE_INCOMPLETE;
1995
0
    }
1996
1997
    /* now verify the common fields */
1998
0
    crv = sftk_defaultAttribute(object, CKA_LOCAL, &ckfalse, sizeof(CK_BBOOL));
1999
0
    if (crv != CKR_OK)
2000
0
        return crv;
2001
2002
    /* get the key type */
2003
0
    attribute = sftk_FindAttribute(object, CKA_KEY_TYPE);
2004
0
    if (!attribute) {
2005
0
        return CKR_ATTRIBUTE_VALUE_INVALID;
2006
0
    }
2007
0
    key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
2008
0
    sftk_FreeAttribute(attribute);
2009
2010
0
    switch (key_type) {
2011
0
        case CKK_DSA:
2012
0
            return sftk_handleDSAParameterObject(session, object);
2013
2014
0
        default:
2015
0
            break;
2016
0
    }
2017
0
    return CKR_KEY_TYPE_INCONSISTENT;
2018
0
}
2019
2020
/*
2021
 * Handle Object does all the object consistancy checks, automatic attribute
2022
 * generation, attribute defaulting, etc. If handleObject succeeds, the object
2023
 * will be assigned an object handle, and the object installed in the session
2024
 * or stored in the DB.
2025
 */
2026
CK_RV
2027
sftk_handleObject(SFTKObject *object, SFTKSession *session)
2028
1.46M
{
2029
1.46M
    SFTKSlot *slot = session->slot;
2030
1.46M
    SFTKAttribute *attribute;
2031
1.46M
    CK_BBOOL ckfalse = CK_FALSE;
2032
1.46M
    CK_BBOOL cktrue = CK_TRUE;
2033
1.46M
    PRBool isLoggedIn, needLogin;
2034
1.46M
    CK_RV crv;
2035
2036
    /* make sure all the base object types are defined. If not set the
2037
     * defaults */
2038
1.46M
    crv = sftk_defaultAttribute(object, CKA_TOKEN, &ckfalse, sizeof(CK_BBOOL));
2039
1.46M
    if (crv != CKR_OK)
2040
0
        return crv;
2041
1.46M
    crv = sftk_defaultAttribute(object, CKA_PRIVATE, &ckfalse, sizeof(CK_BBOOL));
2042
1.46M
    if (crv != CKR_OK)
2043
0
        return crv;
2044
1.46M
    crv = sftk_defaultAttribute(object, CKA_LABEL, NULL, 0);
2045
1.46M
    if (crv != CKR_OK)
2046
0
        return crv;
2047
1.46M
    crv = sftk_defaultAttribute(object, CKA_MODIFIABLE, &cktrue, sizeof(CK_BBOOL));
2048
1.46M
    if (crv != CKR_OK)
2049
0
        return crv;
2050
2051
1.46M
    PR_Lock(slot->slotLock);
2052
1.46M
    isLoggedIn = slot->isLoggedIn;
2053
1.46M
    needLogin = slot->needLogin;
2054
1.46M
    PR_Unlock(slot->slotLock);
2055
2056
    /* don't create a private object if we aren't logged in */
2057
1.46M
    if (!isLoggedIn && needLogin && sftk_isTrue(object, CKA_PRIVATE)) {
2058
0
        return CKR_USER_NOT_LOGGED_IN;
2059
0
    }
2060
2061
1.46M
    if (((session->info.flags & CKF_RW_SESSION) == 0) &&
2062
1.46M
        (sftk_isTrue(object, CKA_TOKEN))) {
2063
0
        return CKR_SESSION_READ_ONLY;
2064
0
    }
2065
2066
    /* Assign a unique SESSION object handle to every new object,
2067
     * whether it is a session object or a token object.
2068
     * At this point, all new objects are structured as session objects.
2069
     * Objects with the CKA_TOKEN attribute true will be turned into
2070
     * token objects and will have a token object handle assigned to
2071
     * them by the handler for each object class, invoked below.
2072
     *
2073
     * It may be helpful to note/remember that
2074
     * sftk_narrowToXxxObject uses the object's handle and type field,
2075
     * but sftk_isTrue(...,CKA_TOKEN) examines the CKA_TOKEN attribute.
2076
     */
2077
1.46M
    object->handle = sftk_getNextHandle(slot);
2078
2079
    /* get the object class */
2080
1.46M
    attribute = sftk_FindAttribute(object, CKA_CLASS);
2081
1.46M
    if (attribute == NULL) {
2082
0
        return CKR_TEMPLATE_INCOMPLETE;
2083
0
    }
2084
1.46M
    object->objclass = *(CK_OBJECT_CLASS *)attribute->attrib.pValue;
2085
1.46M
    sftk_FreeAttribute(attribute);
2086
2087
    /* Now handle the specific object class.
2088
     * At this point, all objects are session objects, and the session
2089
     * number must be passed to the object class handlers.
2090
     */
2091
1.46M
    switch (object->objclass) {
2092
155k
        case CKO_DATA:
2093
155k
            crv = sftk_handleDataObject(session, object);
2094
155k
            break;
2095
0
        case CKO_CERTIFICATE:
2096
0
            crv = sftk_handleCertObject(session, object);
2097
0
            break;
2098
0
        case CKO_NSS_TRUST:
2099
0
            crv = sftk_handleNSSTrustObject(session, object);
2100
0
            break;
2101
0
        case CKO_TRUST:
2102
0
            crv = sftk_handleTrustObject(session, object);
2103
0
            break;
2104
0
        case CKO_NSS_CRL:
2105
0
            crv = sftk_handleCrlObject(session, object);
2106
0
            break;
2107
0
        case CKO_NSS_SMIME:
2108
0
            crv = sftk_handleSMimeObject(session, object);
2109
0
            break;
2110
95.7k
        case CKO_PRIVATE_KEY:
2111
237k
        case CKO_PUBLIC_KEY:
2112
1.31M
        case CKO_SECRET_KEY:
2113
1.31M
            crv = sftk_handleKeyObject(session, object);
2114
1.31M
            break;
2115
0
        case CKO_DOMAIN_PARAMETERS:
2116
0
            crv = sftk_handleKeyParameterObject(session, object);
2117
0
            break;
2118
0
        default:
2119
0
            crv = CKR_ATTRIBUTE_VALUE_INVALID;
2120
0
            break;
2121
1.46M
    }
2122
2123
    /* can't fail from here on out unless the pk_handlXXX functions have
2124
     * failed the request */
2125
1.46M
    if (crv != CKR_OK) {
2126
2.11k
        return crv;
2127
2.11k
    }
2128
2129
    /* Now link the object into the slot and session structures.
2130
     * If the object has a true CKA_TOKEN attribute, the above object
2131
     * class handlers will have set the sign bit in the object handle,
2132
     * causing the following test to be true. We still need to set the
2133
     * object type.
2134
     */
2135
1.46M
    if (sftk_isToken(object->handle)) {
2136
0
        object->type = SFTK_TOKEN_OBJECT_TYPE;
2137
0
        return sftk_convertSessionToToken(object);
2138
0
    }
2139
2140
1.46M
    object->type = SFTK_SESSION_OBJECT_TYPE;
2141
1.46M
    object->slot = slot;
2142
1.46M
    sftk_AddObject(session, object);
2143
1.46M
    return CKR_OK;
2144
1.46M
}
2145
2146
/*
2147
 * ******************** Public Key Utilities ***************************
2148
 */
2149
/* Generate a low public key structure from an object */
2150
NSSLOWKEYPublicKey *
2151
sftk_GetPubKey(SFTKObject *object, CK_KEY_TYPE key_type,
2152
               CK_RV *crvp)
2153
185k
{
2154
185k
    NSSLOWKEYPublicKey *pubKey;
2155
185k
    PLArenaPool *arena;
2156
185k
    CK_ULONG paramSet;
2157
185k
    CK_RV crv;
2158
2159
185k
    if (object->objclass != CKO_PUBLIC_KEY) {
2160
0
        *crvp = CKR_KEY_TYPE_INCONSISTENT;
2161
0
        return NULL;
2162
0
    }
2163
2164
185k
    if (sftk_isToken(object->handle)) {
2165
        /* ferret out the token object handle */
2166
0
    }
2167
2168
    /* If we already have a key, use it */
2169
185k
    if (object->objectInfo) {
2170
44.2k
        *crvp = CKR_OK;
2171
44.2k
        return (NSSLOWKEYPublicKey *)object->objectInfo;
2172
44.2k
    }
2173
2174
    /* allocate the structure */
2175
141k
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2176
141k
    if (arena == NULL) {
2177
0
        *crvp = CKR_HOST_MEMORY;
2178
0
        return NULL;
2179
0
    }
2180
2181
141k
    pubKey = (NSSLOWKEYPublicKey *)
2182
141k
        PORT_ArenaAlloc(arena, sizeof(NSSLOWKEYPublicKey));
2183
141k
    if (pubKey == NULL) {
2184
0
        PORT_FreeArena(arena, PR_FALSE);
2185
0
        *crvp = CKR_HOST_MEMORY;
2186
0
        return NULL;
2187
0
    }
2188
2189
    /* fill in the structure */
2190
141k
    pubKey->arena = arena;
2191
141k
    switch (key_type) {
2192
39.7k
        case CKK_RSA:
2193
39.7k
            pubKey->keyType = NSSLOWKEYRSAKey;
2194
            /* if we claim the object is FIPS, then make sure it's verified
2195
             * before we do an OAEP operation */
2196
39.7k
            pubKey->u.rsa.needVerify = sftk_hasFIPS(object);
2197
39.7k
            crv = sftk_Attribute2SSecItem(arena, &pubKey->u.rsa.modulus,
2198
39.7k
                                          object, CKA_MODULUS);
2199
39.7k
            if (crv != CKR_OK)
2200
0
                break;
2201
39.7k
            crv = sftk_Attribute2SSecItem(arena, &pubKey->u.rsa.publicExponent,
2202
39.7k
                                          object, CKA_PUBLIC_EXPONENT);
2203
39.7k
            break;
2204
4.02k
        case CKK_DSA:
2205
4.02k
            pubKey->keyType = NSSLOWKEYDSAKey;
2206
4.02k
            crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dsa.params.prime,
2207
4.02k
                                          object, CKA_PRIME);
2208
4.02k
            if (crv != CKR_OK)
2209
0
                break;
2210
4.02k
            crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dsa.params.subPrime,
2211
4.02k
                                          object, CKA_SUBPRIME);
2212
4.02k
            if (crv != CKR_OK)
2213
0
                break;
2214
4.02k
            crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dsa.params.base,
2215
4.02k
                                          object, CKA_BASE);
2216
4.02k
            if (crv != CKR_OK)
2217
0
                break;
2218
4.02k
            crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dsa.publicValue,
2219
4.02k
                                          object, CKA_VALUE);
2220
4.02k
            break;
2221
6.44k
        case CKK_DH:
2222
6.44k
            pubKey->keyType = NSSLOWKEYDHKey;
2223
6.44k
            crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dh.prime,
2224
6.44k
                                          object, CKA_PRIME);
2225
6.44k
            if (crv != CKR_OK)
2226
0
                break;
2227
6.44k
            crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dh.base,
2228
6.44k
                                          object, CKA_BASE);
2229
6.44k
            if (crv != CKR_OK)
2230
0
                break;
2231
6.44k
            crv = sftk_Attribute2SSecItem(arena, &pubKey->u.dh.publicValue,
2232
6.44k
                                          object, CKA_VALUE);
2233
6.44k
            break;
2234
0
        case CKK_EC_EDWARDS:
2235
0
        case CKK_EC_MONTGOMERY:
2236
76.9k
        case CKK_EC:
2237
76.9k
            pubKey->keyType = NSSLOWKEYECKey;
2238
76.9k
            crv = sftk_Attribute2SSecItem(arena,
2239
76.9k
                                          &pubKey->u.ec.ecParams.DEREncoding,
2240
76.9k
                                          object, CKA_EC_PARAMS);
2241
76.9k
            if (crv != CKR_OK)
2242
0
                break;
2243
2244
            /* Fill out the rest of the ecParams structure
2245
             * based on the encoded params
2246
             */
2247
76.9k
            if (EC_FillParams(arena, &pubKey->u.ec.ecParams.DEREncoding,
2248
76.9k
                              &pubKey->u.ec.ecParams) != SECSuccess) {
2249
555
                crv = CKR_DOMAIN_PARAMS_INVALID;
2250
555
                break;
2251
555
            }
2252
2253
76.4k
            crv = sftk_Attribute2SSecItem(arena, &pubKey->u.ec.publicValue,
2254
76.4k
                                          object, CKA_EC_POINT);
2255
76.4k
            if (crv == CKR_OK) {
2256
76.4k
                unsigned int keyLen = EC_GetPointSize(&pubKey->u.ec.ecParams);
2257
                /* special note: We can't just use the first byte to distinguish
2258
                 * between EC_POINT_FORM_UNCOMPRESSED and SEC_ASN1_OCTET_STRING.
2259
                 * Both are 0x04. */
2260
2261
                /* Handle the non-DER encoded case.
2262
                 * Some curves are always pressumed to be non-DER.
2263
                 */
2264
2265
                /* is the public key in uncompressed form? */
2266
76.4k
                if (pubKey->u.ec.ecParams.type != ec_params_named ||
2267
57.5k
                    (pubKey->u.ec.publicValue.len == keyLen &&
2268
18.8k
                     pubKey->u.ec.publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED)) {
2269
18.8k
                    break; /* key was not DER encoded, no need to unwrap */
2270
18.8k
                }
2271
2272
                /* handle the encoded case */
2273
57.5k
                if (pubKey->u.ec.publicValue.data[0] == SEC_ASN1_OCTET_STRING) {
2274
57.5k
                    SECItem publicValue;
2275
57.5k
                    SECStatus rv;
2276
2277
57.5k
                    rv = SEC_QuickDERDecodeItem(arena, &publicValue,
2278
57.5k
                                                SEC_ASN1_GET(SEC_OctetStringTemplate),
2279
57.5k
                                                &pubKey->u.ec.publicValue);
2280
                    /* nope, didn't decode correctly */
2281
57.5k
                    if (rv != SECSuccess) {
2282
0
                        crv = CKR_ATTRIBUTE_VALUE_INVALID;
2283
0
                        break;
2284
0
                    }
2285
2286
57.5k
                    if (publicValue.len == keyLen && publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED) {
2287
                        /* Received uncompressed point */
2288
57.2k
                        pubKey->u.ec.publicValue = publicValue;
2289
57.2k
                        break;
2290
57.2k
                    }
2291
2292
                    /* Trying to decompress */
2293
277
                    SECItem publicDecompressed = { siBuffer, NULL, 0 };
2294
277
                    (void)SECITEM_AllocItem(arena, &publicDecompressed, keyLen);
2295
277
                    if (EC_DecompressPublicKey(&publicValue, &pubKey->u.ec.ecParams, &publicDecompressed) == SECFailure) {
2296
277
                        crv = CKR_ATTRIBUTE_VALUE_INVALID;
2297
277
                        break;
2298
277
                    }
2299
2300
                    /* replace our previous public key with the decoded decompressed key */
2301
0
                    pubKey->u.ec.publicValue = publicDecompressed;
2302
2303
0
                    SECItem publicDecompressedEncoded = { siBuffer, NULL, 0 };
2304
0
                    (void)SEC_ASN1EncodeItem(arena, &publicDecompressedEncoded, &publicDecompressed,
2305
0
                                             SEC_ASN1_GET(SEC_OctetStringTemplate));
2306
0
                    if (CKR_OK != sftk_forceAttribute(object, CKA_EC_POINT, sftk_item_expand(&publicDecompressedEncoded))) {
2307
0
                        crv = CKR_ATTRIBUTE_VALUE_INVALID;
2308
0
                        break;
2309
0
                    }
2310
2311
0
                    break;
2312
0
                }
2313
0
                crv = CKR_ATTRIBUTE_VALUE_INVALID;
2314
0
            }
2315
0
            break;
2316
0
#ifndef NSS_DISABLE_KYBER
2317
0
        case CKK_NSS_KYBER:
2318
0
#endif
2319
13.6k
        case CKK_NSS_ML_KEM:
2320
14.3k
        case CKK_ML_KEM:
2321
14.3k
            pubKey->keyType = NSSLOWKEYMLKEMKey;
2322
14.3k
            crv = sftk_GetULongAttribute(object, CKA_PARAMETER_SET,
2323
14.3k
                                         &paramSet);
2324
14.3k
            if (crv != CKR_OK) {
2325
0
                crv = sftk_GetULongAttribute(object, CKA_NSS_PARAMETER_SET,
2326
0
                                             &paramSet);
2327
0
                if (crv != CKR_OK) {
2328
0
                    break;
2329
0
                }
2330
0
            }
2331
14.3k
            pubKey->u.mlkem.mlkemParams = sftk_kyber_PK11ParamToInternal(paramSet);
2332
14.3k
            if (pubKey->u.mlkem.mlkemParams == params_kyber_invalid) {
2333
0
                crv = CKR_PARAMETER_SET_NOT_SUPPORTED;
2334
0
                break;
2335
0
            }
2336
2337
14.3k
            crv = sftk_Attribute2SSecItem(arena, &pubKey->u.mlkem.key,
2338
14.3k
                                          object, CKA_VALUE);
2339
14.3k
            break;
2340
0
        case CKK_ML_DSA:
2341
0
            pubKey->keyType = NSSLOWKEYMLDSAKey;
2342
0
            crv = sftk_ReadAttribute(object, CKA_VALUE,
2343
0
                                     pubKey->u.mldsa.keyVal,
2344
0
                                     sizeof(pubKey->u.mldsa.keyVal),
2345
0
                                     &pubKey->u.mldsa.keyValLen);
2346
0
            if (crv != CKR_OK) {
2347
0
                break;
2348
0
            }
2349
0
            crv = sftk_GetULongAttribute(object, CKA_PARAMETER_SET,
2350
0
                                         &pubKey->u.mldsa.paramSet);
2351
2352
0
            break;
2353
0
        default:
2354
0
            crv = CKR_KEY_TYPE_INCONSISTENT;
2355
0
            break;
2356
141k
    }
2357
141k
    *crvp = crv;
2358
141k
    if (crv != CKR_OK) {
2359
832
        PORT_FreeArena(arena, PR_TRUE);
2360
832
        return NULL;
2361
832
    }
2362
2363
140k
    object->objectInfo = pubKey;
2364
140k
    object->infoFree = SFTKFree_nsslowkey_DestroyPublicKey;
2365
140k
    return pubKey;
2366
141k
}
2367
2368
/* make a private key from a verified object */
2369
static NSSLOWKEYPrivateKey *
2370
sftk_mkPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp)
2371
95.7k
{
2372
95.7k
    NSSLOWKEYPrivateKey *privKey;
2373
95.7k
    SFTKItemTemplate itemTemplate[SFTK_MAX_ITEM_TEMPLATE];
2374
95.7k
    int itemTemplateCount = 0;
2375
95.7k
    PLArenaPool *arena;
2376
95.7k
    CK_RV crv = CKR_OK;
2377
95.7k
    SECStatus rv;
2378
95.7k
    CK_ULONG paramSet;
2379
2380
95.7k
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2381
95.7k
    if (arena == NULL) {
2382
0
        *crvp = CKR_HOST_MEMORY;
2383
0
        return NULL;
2384
0
    }
2385
2386
95.7k
    privKey = (NSSLOWKEYPrivateKey *)
2387
95.7k
        PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPrivateKey));
2388
95.7k
    if (privKey == NULL) {
2389
0
        PORT_FreeArena(arena, PR_FALSE);
2390
0
        *crvp = CKR_HOST_MEMORY;
2391
0
        return NULL;
2392
0
    }
2393
2394
    /* in future this would be a switch on key_type */
2395
95.7k
    privKey->arena = arena;
2396
95.7k
    switch (key_type) {
2397
24
        case CKK_RSA:
2398
24
            privKey->keyType = NSSLOWKEYRSAKey;
2399
2400
24
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2401
24
                                   &privKey->u.rsa.modulus, CKA_MODULUS);
2402
24
            itemTemplateCount++;
2403
24
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2404
24
                                   &privKey->u.rsa.publicExponent, CKA_PUBLIC_EXPONENT);
2405
24
            itemTemplateCount++;
2406
24
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2407
24
                                   &privKey->u.rsa.privateExponent, CKA_PRIVATE_EXPONENT);
2408
24
            itemTemplateCount++;
2409
24
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2410
24
                                   &privKey->u.rsa.prime1, CKA_PRIME_1);
2411
24
            itemTemplateCount++;
2412
24
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2413
24
                                   &privKey->u.rsa.prime2, CKA_PRIME_2);
2414
24
            itemTemplateCount++;
2415
24
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2416
24
                                   &privKey->u.rsa.exponent1, CKA_EXPONENT_1);
2417
24
            itemTemplateCount++;
2418
24
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2419
24
                                   &privKey->u.rsa.exponent2, CKA_EXPONENT_2);
2420
24
            itemTemplateCount++;
2421
24
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2422
24
                                   &privKey->u.rsa.coefficient, CKA_COEFFICIENT);
2423
24
            itemTemplateCount++;
2424
24
            rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,
2425
24
                                 NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
2426
24
            if (rv != SECSuccess)
2427
0
                crv = CKR_HOST_MEMORY;
2428
24
            break;
2429
2430
0
        case CKK_DSA:
2431
0
            privKey->keyType = NSSLOWKEYDSAKey;
2432
0
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2433
0
                                   &privKey->u.dsa.params.prime, CKA_PRIME);
2434
0
            itemTemplateCount++;
2435
0
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2436
0
                                   &privKey->u.dsa.params.subPrime, CKA_SUBPRIME);
2437
0
            itemTemplateCount++;
2438
0
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2439
0
                                   &privKey->u.dsa.params.base, CKA_BASE);
2440
0
            itemTemplateCount++;
2441
0
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2442
0
                                   &privKey->u.dsa.privateValue, CKA_VALUE);
2443
0
            itemTemplateCount++;
2444
            /* privKey was zero'd so public value is already set to NULL, 0
2445
             * if we don't set it explicitly */
2446
0
            break;
2447
2448
6.83k
        case CKK_DH:
2449
6.83k
            privKey->keyType = NSSLOWKEYDHKey;
2450
6.83k
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2451
6.83k
                                   &privKey->u.dh.prime, CKA_PRIME);
2452
6.83k
            itemTemplateCount++;
2453
6.83k
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2454
6.83k
                                   &privKey->u.dh.base, CKA_BASE);
2455
6.83k
            itemTemplateCount++;
2456
6.83k
            SFTK_SET_ITEM_TEMPLATE(itemTemplate, itemTemplateCount,
2457
6.83k
                                   &privKey->u.dh.privateValue, CKA_VALUE);
2458
6.83k
            itemTemplateCount++;
2459
            /* privKey was zero'd so public value is already set to NULL, 0
2460
             * if we don't set it explicitly */
2461
6.83k
            break;
2462
0
        case CKK_EC_EDWARDS:
2463
0
        case CKK_EC_MONTGOMERY:
2464
75.1k
        case CKK_EC:
2465
75.1k
            privKey->keyType = NSSLOWKEYECKey;
2466
75.1k
            crv = sftk_Attribute2SSecItem(arena,
2467
75.1k
                                          &privKey->u.ec.ecParams.DEREncoding,
2468
75.1k
                                          object, CKA_EC_PARAMS);
2469
75.1k
            if (crv != CKR_OK)
2470
0
                break;
2471
2472
            /* Fill out the rest of the ecParams structure
2473
             * based on the encoded params
2474
             */
2475
75.1k
            if (EC_FillParams(arena, &privKey->u.ec.ecParams.DEREncoding,
2476
75.1k
                              &privKey->u.ec.ecParams) != SECSuccess) {
2477
0
                crv = CKR_DOMAIN_PARAMS_INVALID;
2478
0
                break;
2479
0
            }
2480
75.1k
            crv = sftk_Attribute2SSecItem(arena, &privKey->u.ec.privateValue,
2481
75.1k
                                          object, CKA_VALUE);
2482
75.1k
            if (crv != CKR_OK)
2483
0
                break;
2484
2485
75.1k
            if (sftk_hasAttribute(object, CKA_NSS_DB)) {
2486
75.1k
                crv = sftk_Attribute2SSecItem(arena, &privKey->u.ec.publicValue,
2487
75.1k
                                              object, CKA_NSS_DB);
2488
75.1k
                if (crv != CKR_OK) {
2489
0
                    break;
2490
0
                }
2491
                /* privKey was zero'd so public value is already set to NULL, 0
2492
                 * if we don't set it explicitly */
2493
75.1k
            } else if (key_type == CKK_EC) {
2494
                /* as no public key was provided during the import, we need to derive it here.
2495
                 See: PK11_ImportAndReturnPrivateKey*/
2496
0
                if (SECITEM_AllocItem(arena, &privKey->u.ec.publicValue,
2497
0
                                      EC_GetPointSize(&privKey->u.ec.ecParams)) == NULL) {
2498
0
                    crv = CKR_HOST_MEMORY;
2499
0
                    break;
2500
0
                }
2501
0
                PORT_Memset(privKey->u.ec.publicValue.data, 0, privKey->u.ec.publicValue.len);
2502
0
                rv = EC_DerivePublicKey(&privKey->u.ec.privateValue, &privKey->u.ec.ecParams, &privKey->u.ec.publicValue);
2503
0
                if (rv != SECSuccess) {
2504
0
                    crv = CKR_ATTRIBUTE_VALUE_INVALID;
2505
0
                    break;
2506
0
                }
2507
0
                sftk_forceAttribute(object, CKA_NSS_DB, privKey->u.ec.publicValue.data, privKey->u.ec.publicValue.len);
2508
0
            }
2509
2510
75.1k
            rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version,
2511
75.1k
                                 NSSLOWKEY_EC_PRIVATE_KEY_VERSION);
2512
75.1k
            if (rv != SECSuccess) {
2513
0
                crv = CKR_HOST_MEMORY;
2514
/* The following ifdef is needed for Linux arm distros and
2515
 * Android as gcc 4.6 has a bug when targeting arm (but not
2516
 * thumb). The bug has been fixed in gcc 4.7.
2517
 * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56561
2518
 */
2519
#if defined(__arm__) && !defined(__thumb__) && defined(__GNUC__)
2520
                *crvp = CKR_HOST_MEMORY;
2521
                break;
2522
#endif
2523
0
            }
2524
75.1k
            break;
2525
2526
0
#ifndef NSS_DISABLE_KYBER
2527
0
        case CKK_NSS_KYBER:
2528
0
#endif
2529
13.6k
        case CKK_NSS_ML_KEM:
2530
13.6k
        case CKK_ML_KEM:
2531
13.6k
            privKey->keyType = NSSLOWKEYMLKEMKey;
2532
13.6k
            crv = sftk_GetULongAttribute(object, CKA_PARAMETER_SET,
2533
13.6k
                                         &paramSet);
2534
13.6k
            if (crv != CKR_OK) {
2535
0
                crv = sftk_GetULongAttribute(object, CKA_NSS_PARAMETER_SET,
2536
0
                                             &paramSet);
2537
0
                if (crv != CKR_OK) {
2538
0
                    break;
2539
0
                }
2540
0
            }
2541
13.6k
            privKey->u.mlkem.mlkemParams = sftk_kyber_PK11ParamToInternal(paramSet);
2542
13.6k
            if (privKey->u.mlkem.mlkemParams == params_kyber_invalid) {
2543
0
                crv = CKR_PARAMETER_SET_NOT_SUPPORTED;
2544
0
                break;
2545
0
            }
2546
2547
13.6k
            crv = sftk_Attribute2SSecItem(arena, &privKey->u.mlkem.key,
2548
13.6k
                                          object, CKA_VALUE);
2549
13.6k
            if (crv != CKR_OK) {
2550
0
                break;
2551
0
            }
2552
13.6k
            crv = sftk_Attribute2SSecItem(arena, &privKey->u.mlkem.seed,
2553
13.6k
                                          object, CKA_SEED);
2554
13.6k
            if (crv != CKR_OK) {
2555
                /* we don't need the seed to function, if we don't have
2556
                 * it, just don't include it */
2557
0
                privKey->u.mlkem.seed.data = NULL;
2558
0
                privKey->u.mlkem.seed.len = 0;
2559
0
                crv = CKR_OK;
2560
0
            }
2561
13.6k
            break;
2562
2563
0
        case CKK_ML_DSA:
2564
0
            privKey->keyType = NSSLOWKEYMLDSAKey;
2565
0
            crv = sftk_ReadAttribute(object, CKA_VALUE,
2566
0
                                     privKey->u.mldsa.keyVal,
2567
0
                                     sizeof(privKey->u.mldsa.keyVal),
2568
0
                                     &privKey->u.mldsa.keyValLen);
2569
0
            if (crv != CKR_OK) {
2570
0
                break;
2571
0
            }
2572
0
            crv = sftk_ReadAttribute(object, CKA_SEED,
2573
0
                                     privKey->u.mldsa.seed,
2574
0
                                     sizeof(privKey->u.mldsa.seed),
2575
0
                                     &privKey->u.mldsa.seedLen);
2576
0
            if (crv != CKR_OK) {
2577
                /* no seed value, just set it to zero. The seed
2578
                 * has been lost or discarded for this key */
2579
0
                privKey->u.mldsa.seedLen = 0;
2580
0
            }
2581
0
            crv = sftk_GetULongAttribute(object, CKA_PARAMETER_SET,
2582
0
                                         &privKey->u.mldsa.paramSet);
2583
2584
0
            break;
2585
2586
0
        default:
2587
0
            crv = CKR_KEY_TYPE_INCONSISTENT;
2588
0
            break;
2589
95.7k
    }
2590
95.7k
    if (crv == CKR_OK && itemTemplateCount != 0) {
2591
6.85k
        PORT_Assert(itemTemplateCount > 0);
2592
6.85k
        PORT_Assert(itemTemplateCount <= SFTK_MAX_ITEM_TEMPLATE);
2593
6.85k
        crv = sftk_MultipleAttribute2SecItem(arena, object, itemTemplate,
2594
6.85k
                                             itemTemplateCount);
2595
6.85k
    }
2596
95.7k
    *crvp = crv;
2597
95.7k
    if (crv != CKR_OK) {
2598
0
        PORT_FreeArena(arena, PR_TRUE);
2599
0
        return NULL;
2600
0
    }
2601
95.7k
    return privKey;
2602
95.7k
}
2603
2604
/*
2605
 * If a partial RSA private key is present, fill in the rest if necessary,
2606
 * and then verify the parameters are well-formed
2607
 */
2608
static SECStatus
2609
sftk_verifyRSAPrivateKey(SFTKObject *object, PRBool fillIfNeeded)
2610
24
{
2611
24
    RSAPrivateKey tmpKey = { 0 };
2612
24
    SFTKAttribute *modulus = NULL;
2613
24
    SFTKAttribute *prime1 = NULL;
2614
24
    SFTKAttribute *prime2 = NULL;
2615
24
    SFTKAttribute *privateExponent = NULL;
2616
24
    SFTKAttribute *publicExponent = NULL;
2617
24
    SFTKAttribute *exponent1 = NULL;
2618
24
    SFTKAttribute *exponent2 = NULL;
2619
24
    SFTKAttribute *coefficient = NULL;
2620
24
    SECStatus rv;
2621
24
    CK_RV crv;
2622
2623
    /* first fill in the components that we have. Populate only uses
2624
     * the non-crt components, so only fill those in  */
2625
24
    tmpKey.arena = NULL;
2626
24
    modulus = sftk_FindAttribute(object, CKA_MODULUS);
2627
24
    if (modulus) {
2628
24
        tmpKey.modulus.data = modulus->attrib.pValue;
2629
24
        tmpKey.modulus.len = modulus->attrib.ulValueLen;
2630
24
    }
2631
24
    prime1 = sftk_FindAttribute(object, CKA_PRIME_1);
2632
24
    if (prime1) {
2633
24
        tmpKey.prime1.data = prime1->attrib.pValue;
2634
24
        tmpKey.prime1.len = prime1->attrib.ulValueLen;
2635
24
    }
2636
24
    prime2 = sftk_FindAttribute(object, CKA_PRIME_2);
2637
24
    if (prime2) {
2638
24
        tmpKey.prime2.data = prime2->attrib.pValue;
2639
24
        tmpKey.prime2.len = prime2->attrib.ulValueLen;
2640
24
    }
2641
24
    privateExponent = sftk_FindAttribute(object, CKA_PRIVATE_EXPONENT);
2642
24
    if (privateExponent) {
2643
24
        tmpKey.privateExponent.data = privateExponent->attrib.pValue;
2644
24
        tmpKey.privateExponent.len = privateExponent->attrib.ulValueLen;
2645
24
    }
2646
24
    publicExponent = sftk_FindAttribute(object, CKA_PUBLIC_EXPONENT);
2647
24
    if (publicExponent) {
2648
24
        tmpKey.publicExponent.data = publicExponent->attrib.pValue;
2649
24
        tmpKey.publicExponent.len = publicExponent->attrib.ulValueLen;
2650
24
    }
2651
24
    exponent1 = sftk_FindAttribute(object, CKA_EXPONENT_1);
2652
24
    if (exponent1) {
2653
24
        tmpKey.exponent1.data = exponent1->attrib.pValue;
2654
24
        tmpKey.exponent1.len = exponent1->attrib.ulValueLen;
2655
24
    }
2656
24
    exponent2 = sftk_FindAttribute(object, CKA_EXPONENT_2);
2657
24
    if (exponent2) {
2658
24
        tmpKey.exponent2.data = exponent2->attrib.pValue;
2659
24
        tmpKey.exponent2.len = exponent2->attrib.ulValueLen;
2660
24
    }
2661
24
    coefficient = sftk_FindAttribute(object, CKA_COEFFICIENT);
2662
24
    if (coefficient) {
2663
24
        tmpKey.coefficient.data = coefficient->attrib.pValue;
2664
24
        tmpKey.coefficient.len = coefficient->attrib.ulValueLen;
2665
24
    }
2666
2667
24
    if (fillIfNeeded) {
2668
        /*
2669
         * populate requires one exponent plus 2 other components to work.
2670
         * we expected our caller to check that first. If that didn't happen,
2671
         * populate will simply return an error here.
2672
         */
2673
0
        rv = RSA_PopulatePrivateKey(&tmpKey);
2674
0
        if (rv != SECSuccess) {
2675
0
            goto loser;
2676
0
        }
2677
0
    }
2678
24
    rv = RSA_PrivateKeyCheck(&tmpKey);
2679
24
    if (rv != SECSuccess) {
2680
0
        goto loser;
2681
0
    }
2682
    /* now that we have a fully populated key, set all our attribute values */
2683
24
    rv = SECFailure;
2684
24
    if (!modulus || modulus->attrib.pValue != tmpKey.modulus.data) {
2685
0
        crv = sftk_forceAttribute(object, CKA_MODULUS,
2686
0
                                  sftk_item_expand(&tmpKey.modulus));
2687
0
        if (crv != CKR_OK)
2688
0
            goto loser;
2689
0
    }
2690
24
    if (!publicExponent ||
2691
24
        publicExponent->attrib.pValue != tmpKey.publicExponent.data) {
2692
0
        crv = sftk_forceAttribute(object, CKA_PUBLIC_EXPONENT,
2693
0
                                  sftk_item_expand(&tmpKey.publicExponent));
2694
0
        if (crv != CKR_OK)
2695
0
            goto loser;
2696
0
    }
2697
24
    if (!privateExponent ||
2698
24
        privateExponent->attrib.pValue != tmpKey.privateExponent.data) {
2699
0
        crv = sftk_forceAttribute(object, CKA_PRIVATE_EXPONENT,
2700
0
                                  sftk_item_expand(&tmpKey.privateExponent));
2701
0
        if (crv != CKR_OK)
2702
0
            goto loser;
2703
0
    }
2704
24
    if (!prime1 || prime1->attrib.pValue != tmpKey.prime1.data) {
2705
0
        crv = sftk_forceAttribute(object, CKA_PRIME_1,
2706
0
                                  sftk_item_expand(&tmpKey.prime1));
2707
0
        if (crv != CKR_OK)
2708
0
            goto loser;
2709
0
    }
2710
24
    if (!prime2 || prime2->attrib.pValue != tmpKey.prime2.data) {
2711
0
        crv = sftk_forceAttribute(object, CKA_PRIME_2,
2712
0
                                  sftk_item_expand(&tmpKey.prime2));
2713
0
        if (crv != CKR_OK)
2714
0
            goto loser;
2715
0
    }
2716
24
    if (!exponent1 || exponent1->attrib.pValue != tmpKey.exponent1.data) {
2717
0
        crv = sftk_forceAttribute(object, CKA_EXPONENT_1,
2718
0
                                  sftk_item_expand(&tmpKey.exponent1));
2719
0
        if (crv != CKR_OK)
2720
0
            goto loser;
2721
0
    }
2722
24
    if (!exponent2 || exponent2->attrib.pValue != tmpKey.exponent2.data) {
2723
0
        crv = sftk_forceAttribute(object, CKA_EXPONENT_2,
2724
0
                                  sftk_item_expand(&tmpKey.exponent2));
2725
0
        if (crv != CKR_OK)
2726
0
            goto loser;
2727
0
    }
2728
24
    if (!coefficient || coefficient->attrib.pValue != tmpKey.coefficient.data) {
2729
0
        crv = sftk_forceAttribute(object, CKA_COEFFICIENT,
2730
0
                                  sftk_item_expand(&tmpKey.coefficient));
2731
0
        if (crv != CKR_OK)
2732
0
            goto loser;
2733
0
    }
2734
24
    rv = SECSuccess;
2735
2736
/* we're done (one way or the other), clean up all our stuff */
2737
24
loser:
2738
24
    if (tmpKey.arena) {
2739
0
        PORT_FreeArena(tmpKey.arena, PR_TRUE);
2740
0
    }
2741
24
    if (modulus) {
2742
24
        sftk_FreeAttribute(modulus);
2743
24
    }
2744
24
    if (prime1) {
2745
24
        sftk_FreeAttribute(prime1);
2746
24
    }
2747
24
    if (prime2) {
2748
24
        sftk_FreeAttribute(prime2);
2749
24
    }
2750
24
    if (privateExponent) {
2751
24
        sftk_FreeAttribute(privateExponent);
2752
24
    }
2753
24
    if (publicExponent) {
2754
24
        sftk_FreeAttribute(publicExponent);
2755
24
    }
2756
24
    if (exponent1) {
2757
24
        sftk_FreeAttribute(exponent1);
2758
24
    }
2759
24
    if (exponent2) {
2760
24
        sftk_FreeAttribute(exponent2);
2761
24
    }
2762
24
    if (coefficient) {
2763
24
        sftk_FreeAttribute(coefficient);
2764
24
    }
2765
24
    return rv;
2766
24
}
2767
2768
/* Generate a low private key structure from an object */
2769
NSSLOWKEYPrivateKey *
2770
sftk_GetPrivKey(SFTKObject *object, CK_KEY_TYPE key_type, CK_RV *crvp)
2771
186k
{
2772
186k
    NSSLOWKEYPrivateKey *priv = NULL;
2773
2774
186k
    if (object->objclass != CKO_PRIVATE_KEY) {
2775
0
        *crvp = CKR_KEY_TYPE_INCONSISTENT;
2776
0
        return NULL;
2777
0
    }
2778
186k
    if (object->objectInfo) {
2779
186k
        *crvp = CKR_OK;
2780
186k
        return (NSSLOWKEYPrivateKey *)object->objectInfo;
2781
186k
    }
2782
2783
0
    priv = sftk_mkPrivKey(object, key_type, crvp);
2784
0
    object->objectInfo = priv;
2785
0
    object->infoFree = SFTKFree_nsslowkey_DestroyPrivateKey;
2786
0
    return priv;
2787
186k
}
2788
2789
/* populate a public key object from a lowpublic keys structure */
2790
CK_RV
2791
sftk_PutPubKey(SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType, NSSLOWKEYPublicKey *pubKey)
2792
0
{
2793
0
    CK_OBJECT_CLASS classType = CKO_PUBLIC_KEY;
2794
0
    CK_BBOOL cktrue = CK_TRUE;
2795
0
    CK_RV crv = CKR_OK;
2796
0
    CK_ULONG paramSet = CKP_INVALID_ID;
2797
0
    sftk_DeleteAttributeType(publicKey, CKA_CLASS);
2798
0
    sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE);
2799
0
    sftk_DeleteAttributeType(publicKey, CKA_VALUE);
2800
2801
0
    switch (keyType) {
2802
0
        case CKK_RSA:
2803
0
            sftk_DeleteAttributeType(publicKey, CKA_MODULUS);
2804
0
            sftk_DeleteAttributeType(publicKey, CKA_PUBLIC_EXPONENT);
2805
            /* format the keys */
2806
            /* fill in the RSA dependent paramenters in the public key */
2807
0
            crv = sftk_AddAttributeType(publicKey, CKA_MODULUS,
2808
0
                                        sftk_item_expand(&pubKey->u.rsa.modulus));
2809
0
            if (crv != CKR_OK) {
2810
0
                break;
2811
0
            }
2812
0
            crv = sftk_AddAttributeType(publicKey, CKA_PUBLIC_EXPONENT,
2813
0
                                        sftk_item_expand(&pubKey->u.rsa.publicExponent));
2814
0
            break;
2815
0
        case CKK_DSA:
2816
0
            sftk_DeleteAttributeType(publicKey, CKA_PRIME);
2817
0
            sftk_DeleteAttributeType(publicKey, CKA_SUBPRIME);
2818
0
            sftk_DeleteAttributeType(publicKey, CKA_BASE);
2819
0
            crv = sftk_AddAttributeType(publicKey, CKA_PRIME,
2820
0
                                        sftk_item_expand(&pubKey->u.dsa.params.prime));
2821
0
            if (crv != CKR_OK) {
2822
0
                break;
2823
0
            }
2824
0
            crv = sftk_AddAttributeType(publicKey, CKA_SUBPRIME,
2825
0
                                        sftk_item_expand(&pubKey->u.dsa.params.subPrime));
2826
0
            if (crv != CKR_OK) {
2827
0
                break;
2828
0
            }
2829
0
            crv = sftk_AddAttributeType(publicKey, CKA_BASE,
2830
0
                                        sftk_item_expand(&pubKey->u.dsa.params.base));
2831
0
            if (crv != CKR_OK) {
2832
0
                break;
2833
0
            }
2834
0
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
2835
0
                                        sftk_item_expand(&pubKey->u.dsa.publicValue));
2836
0
            break;
2837
0
        case CKK_NSS_ML_KEM:
2838
0
        case CKK_ML_KEM:
2839
0
            sftk_DeleteAttributeType(publicKey, CKA_VALUE);
2840
0
            sftk_DeleteAttributeType(publicKey, CKA_PARAMETER_SET);
2841
0
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
2842
0
                                        sftk_item_expand(&pubKey->u.mlkem.key));
2843
0
            if (crv != CKR_OK) {
2844
0
                break;
2845
0
            }
2846
0
            paramSet = sftk_kyber_InternalToPK11Param(pubKey->u.mlkem.mlkemParams);
2847
0
            if (paramSet == CKP_INVALID_ID) {
2848
0
                crv = CKR_PUBLIC_KEY_INVALID;
2849
0
                break;
2850
0
            }
2851
0
            crv = sftk_AddAttributeType(publicKey, CKA_PARAMETER_SET,
2852
0
                                        (unsigned char *)&paramSet,
2853
0
                                        sizeof(paramSet));
2854
0
            break;
2855
0
        case CKK_ML_DSA:
2856
0
            sftk_DeleteAttributeType(publicKey, CKA_VALUE);
2857
0
            sftk_DeleteAttributeType(publicKey, CKA_PARAMETER_SET);
2858
0
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
2859
0
                                        pubKey->u.mldsa.keyVal,
2860
0
                                        pubKey->u.mldsa.keyValLen);
2861
0
            if (crv != CKR_OK) {
2862
0
                break;
2863
0
            }
2864
0
            crv = sftk_AddAttributeType(publicKey, CKA_PARAMETER_SET,
2865
0
                                        (unsigned char *)&pubKey->u.mldsa.paramSet,
2866
0
                                        sizeof(pubKey->u.mldsa.paramSet));
2867
0
            break;
2868
0
        case CKK_DH:
2869
0
            sftk_DeleteAttributeType(publicKey, CKA_PRIME);
2870
0
            sftk_DeleteAttributeType(publicKey, CKA_BASE);
2871
0
            crv = sftk_AddAttributeType(publicKey, CKA_PRIME,
2872
0
                                        sftk_item_expand(&pubKey->u.dh.prime));
2873
0
            if (crv != CKR_OK) {
2874
0
                break;
2875
0
            }
2876
0
            crv = sftk_AddAttributeType(publicKey, CKA_BASE,
2877
0
                                        sftk_item_expand(&pubKey->u.dh.base));
2878
0
            if (crv != CKR_OK) {
2879
0
                break;
2880
0
            }
2881
0
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
2882
0
                                        sftk_item_expand(&pubKey->u.dh.publicValue));
2883
0
            break;
2884
0
        case CKK_EC:
2885
0
        case CKK_EC_MONTGOMERY:
2886
0
        case CKK_EC_EDWARDS:
2887
0
            sftk_DeleteAttributeType(publicKey, CKA_EC_PARAMS);
2888
0
            sftk_DeleteAttributeType(publicKey, CKA_EC_POINT);
2889
0
            crv = sftk_AddAttributeType(publicKey, CKA_EC_PARAMS,
2890
0
                                        sftk_item_expand(&pubKey->u.ec.ecParams.DEREncoding));
2891
0
            if (crv != CKR_OK) {
2892
0
                break;
2893
0
            }
2894
0
            crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
2895
0
                                        sftk_item_expand(&pubKey->u.ec.publicValue));
2896
0
            break;
2897
0
        default:
2898
0
            return CKR_KEY_TYPE_INCONSISTENT;
2899
0
    }
2900
0
    if (crv != CKR_OK) {
2901
0
        return crv;
2902
0
    }
2903
0
    crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &classType,
2904
0
                                sizeof(CK_OBJECT_CLASS));
2905
0
    if (crv != CKR_OK) {
2906
0
        return crv;
2907
0
    }
2908
0
    crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &keyType,
2909
0
                                sizeof(CK_KEY_TYPE));
2910
0
    if (crv != CKR_OK) {
2911
0
        return crv;
2912
0
    }
2913
    /* now handle the operator attributes */
2914
0
    if (sftk_isTrue(privateKey, CKA_DECRYPT)) {
2915
0
        crv = sftk_forceAttribute(publicKey, CKA_ENCRYPT, &cktrue, sizeof(CK_BBOOL));
2916
0
        if (crv != CKR_OK) {
2917
0
            return crv;
2918
0
        }
2919
0
    }
2920
0
    if (sftk_isTrue(privateKey, CKA_SIGN)) {
2921
0
        crv = sftk_forceAttribute(publicKey, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
2922
0
        if (crv != CKR_OK) {
2923
0
            return crv;
2924
0
        }
2925
0
    }
2926
0
    if (sftk_isTrue(privateKey, CKA_SIGN_RECOVER)) {
2927
0
        crv = sftk_forceAttribute(publicKey, CKA_VERIFY_RECOVER, &cktrue, sizeof(CK_BBOOL));
2928
0
        if (crv != CKR_OK) {
2929
0
            return crv;
2930
0
        }
2931
0
    }
2932
0
    if (sftk_isTrue(privateKey, CKA_DECAPSULATE)) {
2933
0
        crv = sftk_forceAttribute(publicKey, CKA_ENCAPSULATE, &cktrue, sizeof(CK_BBOOL));
2934
0
        if (crv != CKR_OK) {
2935
0
            return crv;
2936
0
        }
2937
0
    }
2938
0
    if (sftk_isTrue(privateKey, CKA_DERIVE)) {
2939
0
        crv = sftk_forceAttribute(publicKey, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
2940
0
        if (crv != CKR_OK) {
2941
0
            return crv;
2942
0
        }
2943
0
    }
2944
0
    return crv;
2945
0
}
2946
2947
/*
2948
 **************************** Symetric Key utils ************************
2949
 */
2950
/*
2951
 * set the DES key with parity bits correctly
2952
 */
2953
void
2954
sftk_FormatDESKey(unsigned char *key, int length)
2955
34.8k
{
2956
34.8k
    int i;
2957
2958
    /* format the des key */
2959
678k
    for (i = 0; i < length; i++) {
2960
643k
        key[i] = parityTable[key[i] >> 1];
2961
643k
    }
2962
34.8k
}
2963
2964
/*
2965
 * check a des key (des2 or des3 subkey) for weak keys.
2966
 */
2967
PRBool
2968
sftk_CheckDESKey(unsigned char *key)
2969
0
{
2970
0
    int i;
2971
2972
    /* format the des key with parity  */
2973
0
    sftk_FormatDESKey(key, 8);
2974
2975
0
    for (i = 0; i < sftk_desWeakTableSize; i++) {
2976
0
        if (PORT_Memcmp(key, sftk_desWeakTable[i], 8) == 0) {
2977
0
            return PR_TRUE;
2978
0
        }
2979
0
    }
2980
0
    return PR_FALSE;
2981
0
}
2982
2983
/*
2984
 * check if a des or triple des key is weak.
2985
 */
2986
PRBool
2987
sftk_IsWeakKey(unsigned char *key, CK_KEY_TYPE key_type)
2988
83
{
2989
2990
83
    switch (key_type) {
2991
0
        case CKK_DES:
2992
0
            return sftk_CheckDESKey(key);
2993
0
        case CKM_DES2_KEY_GEN:
2994
0
            if (sftk_CheckDESKey(key))
2995
0
                return PR_TRUE;
2996
0
            return sftk_CheckDESKey(&key[8]);
2997
0
        case CKM_DES3_KEY_GEN:
2998
0
            if (sftk_CheckDESKey(key))
2999
0
                return PR_TRUE;
3000
0
            if (sftk_CheckDESKey(&key[8]))
3001
0
                return PR_TRUE;
3002
0
            return sftk_CheckDESKey(&key[16]);
3003
83
        default:
3004
83
            break;
3005
83
    }
3006
83
    return PR_FALSE;
3007
83
}
3008
3009
/**********************************************************************
3010
 *
3011
 *     Start of PKCS 11 functions
3012
 *
3013
 **********************************************************************/
3014
3015
/* return the function list */
3016
CK_RV
3017
NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList)
3018
0
{
3019
0
    *pFunctionList = (CK_FUNCTION_LIST_PTR)&sftk_funcList_v2;
3020
0
    return CKR_OK;
3021
0
}
3022
3023
/* return the function list */
3024
CK_RV
3025
C_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList)
3026
0
{
3027
0
#ifdef NSS_FIPS_DISABLED
3028
0
    return NSC_GetFunctionList(pFunctionList);
3029
#else
3030
    if (NSS_GetSystemFIPSEnabled()) {
3031
        return FC_GetFunctionList(pFunctionList);
3032
    } else {
3033
        return NSC_GetFunctionList(pFunctionList);
3034
    }
3035
#endif
3036
0
}
3037
3038
CK_RV
3039
NSC_GetInterfaceList(CK_INTERFACE_PTR interfaces, CK_ULONG_PTR pulCount)
3040
0
{
3041
0
    CK_ULONG count = *pulCount;
3042
0
    *pulCount = NSS_INTERFACE_COUNT;
3043
0
    if (interfaces == NULL) {
3044
0
        return CKR_OK;
3045
0
    }
3046
0
    if (count < NSS_INTERFACE_COUNT) {
3047
0
        return CKR_BUFFER_TOO_SMALL;
3048
0
    }
3049
0
    PORT_Memcpy(interfaces, nss_interfaces, sizeof(nss_interfaces));
3050
0
    return CKR_OK;
3051
0
}
3052
3053
CK_RV
3054
C_GetInterfaceList(CK_INTERFACE_PTR interfaces, CK_ULONG_PTR pulCount)
3055
0
{
3056
0
#ifdef NSS_FIPS_DISABLED
3057
0
    return NSC_GetInterfaceList(interfaces, pulCount);
3058
#else
3059
    if (NSS_GetSystemFIPSEnabled()) {
3060
        return FC_GetInterfaceList(interfaces, pulCount);
3061
    } else {
3062
        return NSC_GetInterfaceList(interfaces, pulCount);
3063
    }
3064
#endif
3065
0
}
3066
3067
/*
3068
 * Get the requested interface, use the nss_interfaces array so we can
3069
 * easily add new interfaces as they occur.
3070
 */
3071
CK_RV
3072
NSC_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, CK_VERSION_PTR pVersion,
3073
                 CK_INTERFACE_PTR_PTR ppInterface, CK_FLAGS flags)
3074
32
{
3075
32
    int i;
3076
96
    for (i = 0; i < NSS_INTERFACE_COUNT; i++) {
3077
96
        CK_INTERFACE_PTR interface = &nss_interfaces[i];
3078
96
        if (pInterfaceName && PORT_Strcmp((char *)pInterfaceName, (char *)interface->pInterfaceName) != 0) {
3079
64
            continue;
3080
64
        }
3081
32
        if (pVersion && PORT_Memcmp(pVersion, (CK_VERSION *)interface->pFunctionList, sizeof(CK_VERSION)) != 0) {
3082
0
            continue;
3083
0
        }
3084
32
        if (flags & ((interface->flags & flags) != flags)) {
3085
0
            continue;
3086
0
        }
3087
32
        *ppInterface = interface;
3088
32
        return CKR_OK;
3089
32
    }
3090
0
    return CKR_ARGUMENTS_BAD;
3091
32
}
3092
3093
CK_RV
3094
C_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, CK_VERSION_PTR pVersion,
3095
               CK_INTERFACE_PTR_PTR ppInterface, CK_FLAGS flags)
3096
0
{
3097
0
#ifdef NSS_FIPS_DISABLED
3098
0
    return NSC_GetInterface(pInterfaceName, pVersion, ppInterface, flags);
3099
#else
3100
    if (NSS_GetSystemFIPSEnabled()) {
3101
        return FC_GetInterface(pInterfaceName, pVersion, ppInterface, flags);
3102
    } else {
3103
        return NSC_GetInterface(pInterfaceName, pVersion, ppInterface, flags);
3104
    }
3105
#endif
3106
0
}
3107
3108
static PLHashNumber
3109
sftk_HashNumber(const void *key)
3110
40.4M
{
3111
40.4M
    return (PLHashNumber)((char *)key - (char *)NULL);
3112
40.4M
}
3113
3114
/*
3115
 * eventually I'd like to expunge all occurances of XXX_SLOT_ID and
3116
 * just go with the info in the slot. This is one place, however,
3117
 * where it might be a little difficult.
3118
 */
3119
const char *
3120
sftk_getDefTokName(CK_SLOT_ID slotID)
3121
32
{
3122
32
    static char buf[33];
3123
3124
32
    switch (slotID) {
3125
16
        case NETSCAPE_SLOT_ID:
3126
16
            return "NSS Generic Crypto Services     ";
3127
16
        case PRIVATE_KEY_SLOT_ID:
3128
16
            return "NSS Certificate DB              ";
3129
0
        case FIPS_SLOT_ID:
3130
0
            return "NSS FIPS 140-2 Certificate DB   ";
3131
0
        default:
3132
0
            break;
3133
32
    }
3134
0
    snprintf(buf, sizeof(buf), "NSS Application Token %08x  ", (unsigned int)slotID);
3135
0
    return buf;
3136
32
}
3137
3138
const char *
3139
sftk_getDefSlotName(CK_SLOT_ID slotID)
3140
32
{
3141
32
    static char buf[65];
3142
3143
32
    switch (slotID) {
3144
16
        case NETSCAPE_SLOT_ID:
3145
16
            return "NSS Internal Cryptographic Services                             ";
3146
16
        case PRIVATE_KEY_SLOT_ID:
3147
16
            return "NSS User Private Key and Certificate Services                   ";
3148
0
        case FIPS_SLOT_ID:
3149
0
            return "NSS FIPS 140-2 User Private Key Services                        ";
3150
0
        default:
3151
0
            break;
3152
32
    }
3153
0
    snprintf(buf, sizeof(buf),
3154
0
             "NSS Application Slot %08x                                   ",
3155
0
             (unsigned int)slotID);
3156
0
    return buf;
3157
32
}
3158
3159
static CK_ULONG nscSlotCount[2] = { 0, 0 };
3160
static CK_SLOT_ID_PTR nscSlotList[2] = { NULL, NULL };
3161
static CK_ULONG nscSlotListSize[2] = { 0, 0 };
3162
static PLHashTable *nscSlotHashTable[2] = { NULL, NULL };
3163
3164
static unsigned int
3165
sftk_GetModuleIndex(CK_SLOT_ID slotID)
3166
40.4M
{
3167
40.4M
    if (sftk_isFIPS(slotID)) {
3168
0
        return NSC_FIPS_MODULE;
3169
0
    }
3170
40.4M
    return NSC_NON_FIPS_MODULE;
3171
40.4M
}
3172
3173
/* look up a slot structure from the ID (used to be a macro when we only
3174
 * had two slots) */
3175
/* if all is true, return the slot even if it has been 'unloaded' */
3176
/* if all is false, only return the slots which are present */
3177
SFTKSlot *
3178
sftk_SlotFromID(CK_SLOT_ID slotID, PRBool all)
3179
40.4M
{
3180
40.4M
    SFTKSlot *slot;
3181
40.4M
    unsigned int index = sftk_GetModuleIndex(slotID);
3182
3183
40.4M
    if (nscSlotHashTable[index] == NULL)
3184
0
        return NULL;
3185
40.4M
    slot = (SFTKSlot *)PL_HashTableLookupConst(nscSlotHashTable[index],
3186
40.4M
                                               (void *)(uintptr_t)slotID);
3187
    /* cleared slots shouldn't 'show up' */
3188
40.4M
    if (slot && !all && !slot->present)
3189
0
        slot = NULL;
3190
40.4M
    return slot;
3191
40.4M
}
3192
3193
CK_SLOT_ID
3194
sftk_SlotIDFromSessionHandle(CK_SESSION_HANDLE handle)
3195
36.8M
{
3196
36.8M
    CK_ULONG slotIDIndex = (handle >> 24) & 0x7f;
3197
36.8M
    CK_ULONG moduleIndex = (handle >> 31) & 1;
3198
3199
36.8M
    if (slotIDIndex >= nscSlotCount[moduleIndex]) {
3200
0
        return (CK_SLOT_ID)-1;
3201
0
    }
3202
36.8M
    return nscSlotList[moduleIndex][slotIDIndex];
3203
36.8M
}
3204
3205
SFTKSlot *
3206
sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle)
3207
36.8M
{
3208
36.8M
    return sftk_SlotFromID(sftk_SlotIDFromSessionHandle(handle), PR_FALSE);
3209
36.8M
}
3210
3211
static CK_RV
3212
sftk_RegisterSlot(SFTKSlot *slot, unsigned int moduleIndex)
3213
32
{
3214
32
    PLHashEntry *entry;
3215
32
    unsigned int index;
3216
3217
32
    index = sftk_GetModuleIndex(slot->slotID);
3218
3219
    /* make sure the slotID for this module is valid */
3220
32
    if (moduleIndex != index) {
3221
0
        return CKR_SLOT_ID_INVALID;
3222
0
    }
3223
3224
32
    if (nscSlotList[index] == NULL) {
3225
16
        nscSlotListSize[index] = NSC_SLOT_LIST_BLOCK_SIZE;
3226
16
        nscSlotList[index] = (CK_SLOT_ID *)
3227
16
            PORT_ZAlloc(nscSlotListSize[index] * sizeof(CK_SLOT_ID));
3228
16
        if (nscSlotList[index] == NULL) {
3229
0
            return CKR_HOST_MEMORY;
3230
0
        }
3231
16
    }
3232
32
    if (nscSlotCount[index] >= nscSlotListSize[index]) {
3233
0
        CK_SLOT_ID *oldNscSlotList = nscSlotList[index];
3234
0
        CK_ULONG oldNscSlotListSize = nscSlotListSize[index];
3235
0
        nscSlotListSize[index] += NSC_SLOT_LIST_BLOCK_SIZE;
3236
0
        nscSlotList[index] = (CK_SLOT_ID *)PORT_Realloc(oldNscSlotList,
3237
0
                                                        nscSlotListSize[index] * sizeof(CK_SLOT_ID));
3238
0
        if (nscSlotList[index] == NULL) {
3239
            /* evidently coverity doesn't know realloc does not
3240
             * free var if it fails ! */
3241
            /* coverity [use_after_free : FALSE] */
3242
0
            nscSlotList[index] = oldNscSlotList;
3243
0
            nscSlotListSize[index] = oldNscSlotListSize;
3244
0
            return CKR_HOST_MEMORY;
3245
0
        }
3246
0
    }
3247
3248
32
    if (nscSlotHashTable[index] == NULL) {
3249
16
        nscSlotHashTable[index] = PL_NewHashTable(64, sftk_HashNumber,
3250
16
                                                  PL_CompareValues, PL_CompareValues, NULL, 0);
3251
16
        if (nscSlotHashTable[index] == NULL) {
3252
0
            return CKR_HOST_MEMORY;
3253
0
        }
3254
16
    }
3255
3256
32
    entry = PL_HashTableAdd(nscSlotHashTable[index], (void *)(uintptr_t)slot->slotID, slot);
3257
32
    if (entry == NULL) {
3258
0
        return CKR_HOST_MEMORY;
3259
0
    }
3260
32
    slot->index = (nscSlotCount[index] & 0x7f) | ((index << 7) & 0x80);
3261
32
    nscSlotList[index][nscSlotCount[index]++] = slot->slotID;
3262
3263
32
    return CKR_OK;
3264
32
}
3265
3266
/*
3267
 * ths function has all the common initialization that happens whenever we
3268
 * create a new slot or repurpose an old slot (only valid for slotID's 4
3269
 * and greater).
3270
 *
3271
 * things that are not reinitialized are:
3272
 *   slotID (can't change)
3273
 *   slotDescription (can't change once defined)
3274
 *   the locks and hash tables (difficult to change in running code, and
3275
 *     unnecessary. hash tables and list are cleared on shutdown, but they
3276
 *     are cleared in a 'friendly' way).
3277
 *   session and object ID counters -- so any old sessions and objects in the
3278
 *     application will get properly notified that the world has changed.
3279
 *
3280
 * things that are reinitialized:
3281
 *   database (otherwise what would the point be;).
3282
 *   state variables related to databases.
3283
 *   session count stat info.
3284
 *   tokenDescription.
3285
 *
3286
 * NOTE: slotID's 4 and greater show up as removable devices.
3287
 *
3288
 */
3289
CK_RV
3290
SFTK_SlotReInit(SFTKSlot *slot, char *configdir, char *updatedir,
3291
                char *updateID, sftk_token_parameters *params,
3292
                unsigned int moduleIndex)
3293
32
{
3294
32
    PRBool needLogin = !params->noKeyDB;
3295
32
    CK_RV crv;
3296
3297
32
    slot->hasTokens = PR_FALSE;
3298
32
    slot->sessionIDConflict = 0;
3299
32
    slot->sessionCount = 0;
3300
32
    slot->rwSessionCount = 0;
3301
32
    slot->needLogin = PR_FALSE;
3302
32
    slot->isLoggedIn = PR_FALSE;
3303
32
    slot->ssoLoggedIn = PR_FALSE;
3304
32
    slot->DB_loaded = PR_FALSE;
3305
32
    slot->certDB = NULL;
3306
32
    slot->keyDB = NULL;
3307
32
    slot->minimumPinLen = 0;
3308
32
    slot->readOnly = params->readOnly;
3309
32
    sftk_setStringName(params->tokdes ? params->tokdes : sftk_getDefTokName(slot->slotID), slot->tokDescription,
3310
32
                       sizeof(slot->tokDescription), PR_TRUE);
3311
32
    sftk_setStringName(params->updtokdes ? params->updtokdes : " ",
3312
32
                       slot->updateTokDescription,
3313
32
                       sizeof(slot->updateTokDescription), PR_TRUE);
3314
3315
32
    if ((!params->noCertDB) || (!params->noKeyDB)) {
3316
0
        SFTKDBHandle *certHandle = NULL;
3317
0
        SFTKDBHandle *keyHandle = NULL;
3318
0
        crv = sftk_DBInit(params->configdir ? params->configdir : configdir,
3319
0
                          params->certPrefix, params->keyPrefix,
3320
0
                          params->updatedir ? params->updatedir : updatedir,
3321
0
                          params->updCertPrefix, params->updKeyPrefix,
3322
0
                          params->updateID ? params->updateID : updateID,
3323
0
                          params->readOnly, params->noCertDB, params->noKeyDB,
3324
0
                          params->forceOpen,
3325
0
                          moduleIndex == NSC_FIPS_MODULE,
3326
0
                          &certHandle, &keyHandle);
3327
0
        if (crv != CKR_OK) {
3328
0
            goto loser;
3329
0
        }
3330
3331
0
        slot->certDB = certHandle;
3332
0
        slot->keyDB = keyHandle;
3333
0
    }
3334
32
    if (needLogin) {
3335
        /* if the data base is initialized with a null password,remember that */
3336
0
        slot->needLogin =
3337
0
            (PRBool)!sftk_hasNullPassword(slot, slot->keyDB);
3338
0
        if ((params->minPW >= 0) && (params->minPW <= SFTK_MAX_PIN)) {
3339
0
            slot->minimumPinLen = params->minPW;
3340
0
        }
3341
0
        if ((slot->minimumPinLen == 0) && (params->pwRequired)) {
3342
0
            slot->minimumPinLen = 1;
3343
0
        }
3344
        /* Make sure the pin len is set to the Minimum allowed value for fips
3345
         * when in FIPS mode. NOTE: we don't set it if the database has not
3346
         * been initialized yet so that we can init into level1 mode if needed
3347
         */
3348
0
        if ((sftkdb_HasPasswordSet(slot->keyDB) == SECSuccess) &&
3349
0
            (moduleIndex == NSC_FIPS_MODULE) &&
3350
0
            (slot->minimumPinLen < FIPS_MIN_PIN)) {
3351
0
            slot->minimumPinLen = FIPS_MIN_PIN;
3352
0
        }
3353
0
    }
3354
3355
32
    slot->present = PR_TRUE;
3356
32
    return CKR_OK;
3357
3358
0
loser:
3359
0
    SFTK_ShutdownSlot(slot);
3360
0
    return crv;
3361
32
}
3362
3363
/*
3364
 * initialize one of the slot structures. figure out which by the ID
3365
 */
3366
CK_RV
3367
SFTK_SlotInit(char *configdir, char *updatedir, char *updateID,
3368
              sftk_token_parameters *params, unsigned int moduleIndex)
3369
32
{
3370
32
    unsigned int i;
3371
32
    CK_SLOT_ID slotID = params->slotID;
3372
32
    SFTKSlot *slot;
3373
32
    CK_RV crv = CKR_HOST_MEMORY;
3374
3375
    /*
3376
     * first we initialize everything that is 'permanent' with this slot.
3377
     * that is everything we aren't going to shutdown if we close this slot
3378
     * and open it up again with different databases */
3379
3380
32
    slot = PORT_ZNew(SFTKSlot);
3381
3382
32
    if (slot == NULL) {
3383
0
        return CKR_HOST_MEMORY;
3384
0
    }
3385
3386
32
    slot->optimizeSpace = params->optimizeSpace;
3387
32
    if (slot->optimizeSpace) {
3388
32
        slot->sessObjHashSize = SPACE_SESSION_OBJECT_HASH_SIZE;
3389
32
        slot->sessHashSize = SPACE_SESSION_HASH_SIZE;
3390
32
        slot->numSessionLocks = 1;
3391
32
    } else {
3392
0
        slot->sessObjHashSize = TIME_SESSION_OBJECT_HASH_SIZE;
3393
0
        slot->sessHashSize = TIME_SESSION_HASH_SIZE;
3394
0
        slot->numSessionLocks = slot->sessHashSize / BUCKETS_PER_SESSION_LOCK;
3395
0
    }
3396
32
    slot->sessionLockMask = slot->numSessionLocks - 1;
3397
3398
32
    slot->slotLock = PR_NewLock();
3399
32
    if (slot->slotLock == NULL)
3400
0
        goto mem_loser;
3401
32
    slot->sessionLock = PORT_ZNewArray(PRLock *, slot->numSessionLocks);
3402
32
    if (slot->sessionLock == NULL)
3403
0
        goto mem_loser;
3404
64
    for (i = 0; i < slot->numSessionLocks; i++) {
3405
32
        slot->sessionLock[i] = PR_NewLock();
3406
32
        if (slot->sessionLock[i] == NULL)
3407
0
            goto mem_loser;
3408
32
    }
3409
32
    slot->objectLock = PR_NewLock();
3410
32
    if (slot->objectLock == NULL)
3411
0
        goto mem_loser;
3412
32
    slot->pwCheckLock = PR_NewLock();
3413
32
    if (slot->pwCheckLock == NULL)
3414
0
        goto mem_loser;
3415
32
    slot->head = PORT_ZNewArray(SFTKSession *, slot->sessHashSize);
3416
32
    if (slot->head == NULL)
3417
0
        goto mem_loser;
3418
32
    slot->sessObjHashTable = PORT_ZNewArray(SFTKObject *, slot->sessObjHashSize);
3419
32
    if (slot->sessObjHashTable == NULL)
3420
0
        goto mem_loser;
3421
32
    slot->tokObjHashTable = PL_NewHashTable(64, sftk_HashNumber, PL_CompareValues,
3422
32
                                            SECITEM_HashCompare, NULL, 0);
3423
32
    if (slot->tokObjHashTable == NULL)
3424
0
        goto mem_loser;
3425
3426
32
    slot->sessionIDCount = 0;
3427
32
    slot->sessionObjectHandleCount = NSC_MIN_SESSION_OBJECT_HANDLE;
3428
32
    slot->slotID = slotID;
3429
32
    sftk_setStringName(params->slotdes ? params->slotdes : sftk_getDefSlotName(slotID), slot->slotDescription,
3430
32
                       sizeof(slot->slotDescription), PR_TRUE);
3431
32
    crv = sftk_InitSession(&slot->moduleObjects, slot, slotID, NULL, NULL,
3432
32
                           CKF_SERIAL_SESSION);
3433
32
    if (crv != CKR_OK) {
3434
0
        goto loser;
3435
0
    }
3436
3437
    /* call the reinit code to set everything that changes between token
3438
     * init calls */
3439
32
    crv = SFTK_SlotReInit(slot, configdir, updatedir, updateID,
3440
32
                          params, moduleIndex);
3441
32
    if (crv != CKR_OK) {
3442
0
        goto loser;
3443
0
    }
3444
32
    if (sftk_isFIPS(slotID)) {
3445
0
        crv = sftk_CreateValidationObjects(slot);
3446
0
        if (crv != CKR_OK) {
3447
0
            goto loser;
3448
0
        }
3449
0
    }
3450
32
    crv = sftk_RegisterSlot(slot, moduleIndex);
3451
32
    if (crv != CKR_OK) {
3452
0
        goto loser;
3453
0
    }
3454
32
    return CKR_OK;
3455
3456
0
mem_loser:
3457
0
    crv = CKR_HOST_MEMORY;
3458
0
loser:
3459
0
    SFTK_DestroySlotData(slot);
3460
0
    return crv;
3461
0
}
3462
3463
#ifdef DEBUG
3464
/*
3465
 * Count session objects that are still live in a slot and belong to an
3466
 * application session. The module's own objects (the FIPS validation
3467
 * indicators hung off slot->moduleObjects) are excluded because softoken owns
3468
 * them and tears them down separately in SFTK_DestroySlotData.
3469
 *
3470
 * When all of a slot's sessions are torn down (logout case below) a
3471
 * well-behaved application has already destroyed every object it created, so
3472
 * this count should be zero. A leftover object means the application created a
3473
 * session object and relied on session/slot teardown to reap it instead of
3474
 * destroying it -- harmless at exit, but an unbounded leak while the process
3475
 * runs, since these accumulate on NSS's long-lived internal session.
3476
 */
3477
static unsigned int
3478
sftk_countLiveSessionObjects(SFTKSlot *slot)
3479
0
{
3480
0
    unsigned int i;
3481
0
    unsigned int count = 0;
3482
3483
0
    PR_Lock(slot->objectLock);
3484
0
    for (i = 0; i < slot->sessObjHashSize; i++) {
3485
0
        SFTKObject *object;
3486
0
        for (object = slot->sessObjHashTable[i]; object;
3487
0
             object = object->next) {
3488
0
            SFTKSessionObject *so = sftk_narrowToSessionObject(object);
3489
0
            if (so && so->session != &slot->moduleObjects) {
3490
0
                count++;
3491
0
            }
3492
0
        }
3493
0
    }
3494
0
    PR_Unlock(slot->objectLock);
3495
0
    return count;
3496
0
}
3497
#endif /* DEBUG */
3498
3499
CK_RV
3500
sftk_CloseAllSessions(SFTKSlot *slot, PRBool logout)
3501
84
{
3502
84
    SFTKSession *session;
3503
84
    unsigned int i;
3504
84
    SFTKDBHandle *handle;
3505
3506
84
#ifdef DEBUG
3507
    /* When NSS_STRICT_SHUTDOWN is set, assert that the application has
3508
     * destroyed all of its session objects before every session on the slot is
3509
     * torn down (which happens via NSC_CloseAllSessions at slot teardown /
3510
     * C_Finalize, and via SFTK_ShutdownSlot). The fork child inherits the
3511
     * parent's objects and cannot clean them up, so skip the check there. */
3512
84
    if (logout && !parentForkedAfterC_Initialize &&
3513
84
        PR_GetEnvSecure("NSS_STRICT_SHUTDOWN")) {
3514
0
        unsigned int live = sftk_countLiveSessionObjects(slot);
3515
0
        if (live != 0) {
3516
0
            PR_fprintf(PR_STDERR,
3517
0
                       "NSS_STRICT_SHUTDOWN: slot %lu still has %u live "
3518
0
                       "session object(s) when closing all sessions\n",
3519
0
                       (unsigned long)slot->slotID, live);
3520
0
        }
3521
0
        PORT_Assert(live == 0);
3522
0
    }
3523
84
#endif
3524
3525
    /* first log out the card */
3526
    /* special case - if we are in a middle of upgrade, we want to close the
3527
     * sessions to fake a token removal to tell the upper level code we have
3528
     * switched from one database to another, but we don't want to
3529
     * explicity logout in case we can continue the upgrade with the
3530
     * existing password if possible.
3531
     */
3532
84
    if (logout) {
3533
84
        handle = sftk_getKeyDB(slot);
3534
84
        SKIP_AFTER_FORK(PR_Lock(slot->slotLock));
3535
84
        slot->isLoggedIn = PR_FALSE;
3536
84
        if (slot->needLogin && handle) {
3537
0
            sftkdb_ClearPassword(handle);
3538
0
        }
3539
84
        SKIP_AFTER_FORK(PR_Unlock(slot->slotLock));
3540
84
        if (handle) {
3541
0
            sftk_freeDB(handle);
3542
0
        }
3543
84
    }
3544
3545
    /* now close all the current sessions */
3546
    /* NOTE: If you try to open new sessions before NSC_CloseAllSessions
3547
     * completes, some of those new sessions may or may not be closed by
3548
     * NSC_CloseAllSessions... but any session running when this code starts
3549
     * will guarrenteed be close, and no session will be partially closed */
3550
2.77k
    for (i = 0; i < slot->sessHashSize; i++) {
3551
2.68k
        PRLock *lock = SFTK_HEAD_BUCKET_LOCK(slot, i);
3552
2.71k
        do {
3553
2.71k
            SKIP_AFTER_FORK(PR_Lock(lock));
3554
2.71k
            session = slot->head[i];
3555
            /* hand deque */
3556
            /* this duplicates function of NSC_close session functions, but
3557
             * because we know that we are freeing all the sessions, we can
3558
             * do more efficient processing */
3559
2.71k
            if (session) {
3560
30
                slot->head[i] = session->next;
3561
30
                if (session->next)
3562
0
                    session->next->prev = NULL;
3563
30
                session->next = session->prev = NULL;
3564
30
                SKIP_AFTER_FORK(PR_Unlock(lock));
3565
30
                SKIP_AFTER_FORK(PR_Lock(slot->slotLock));
3566
30
                --slot->sessionCount;
3567
30
                if (session->info.flags & CKF_RW_SESSION) {
3568
0
                    --slot->rwSessionCount;
3569
0
                }
3570
30
                SKIP_AFTER_FORK(PR_Unlock(slot->slotLock));
3571
2.68k
            } else {
3572
2.68k
                SKIP_AFTER_FORK(PR_Unlock(lock));
3573
2.68k
            }
3574
2.71k
            if (session) {
3575
30
                sftk_FreeSession(session);
3576
30
            }
3577
2.71k
        } while (session != NULL);
3578
2.68k
    }
3579
84
    return CKR_OK;
3580
84
}
3581
3582
/*
3583
 * shut down the databases.
3584
 * we get the slot lock (which also protects slot->certDB and slot->keyDB)
3585
 * and clear the values so the new users will not find the databases.
3586
 * once things are clear, we can release our references to the databases.
3587
 * The databases will close when the last reference is released.
3588
 *
3589
 * We use reference counts so that we don't crash if someone shuts down
3590
 * a token that another thread is actively using.
3591
 */
3592
static void
3593
sftk_DBShutdown(SFTKSlot *slot)
3594
28
{
3595
28
    SFTKDBHandle *certHandle;
3596
28
    SFTKDBHandle *keyHandle;
3597
28
    SKIP_AFTER_FORK(PR_Lock(slot->slotLock));
3598
28
    certHandle = slot->certDB;
3599
28
    slot->certDB = NULL;
3600
28
    keyHandle = slot->keyDB;
3601
28
    slot->keyDB = NULL;
3602
28
    SKIP_AFTER_FORK(PR_Unlock(slot->slotLock));
3603
28
    if (certHandle) {
3604
0
        sftk_freeDB(certHandle);
3605
0
    }
3606
28
    if (keyHandle) {
3607
0
        sftk_freeDB(keyHandle);
3608
0
    }
3609
28
}
3610
3611
CK_RV
3612
SFTK_ShutdownSlot(SFTKSlot *slot)
3613
28
{
3614
    /* make sure no new PK11 calls work except C_GetSlotInfo */
3615
28
    slot->present = PR_FALSE;
3616
3617
    /* close all outstanding sessions
3618
     * the sessHashSize variable guarentees we have all the session
3619
     * mechanism set up */
3620
28
    if (slot->head) {
3621
28
        sftk_CloseAllSessions(slot, PR_TRUE);
3622
28
    }
3623
3624
    /* clear all objects.. session objects are cleared as a result of
3625
     * closing all the sessions. We just need to clear the token object
3626
     * cache. slot->tokObjHashTable guarentees we have the token
3627
     * infrastructure set up. */
3628
28
    if (slot->tokObjHashTable) {
3629
28
        SFTK_ClearTokenKeyHashTable(slot);
3630
28
    }
3631
3632
    /* clear the slot description for the next guy */
3633
28
    PORT_Memset(slot->tokDescription, 0, sizeof(slot->tokDescription));
3634
3635
    /* now shut down the databases. */
3636
28
    sftk_DBShutdown(slot);
3637
28
    return CKR_OK;
3638
28
}
3639
3640
/*
3641
 * initialize one of the slot structures. figure out which by the ID
3642
 */
3643
CK_RV
3644
SFTK_DestroySlotData(SFTKSlot *slot)
3645
28
{
3646
28
    unsigned int i;
3647
3648
28
    SFTK_ShutdownSlot(slot);
3649
3650
28
    sftk_ClearSession(&slot->moduleObjects);
3651
3652
28
    if (slot->tokObjHashTable) {
3653
28
        PL_HashTableDestroy(slot->tokObjHashTable);
3654
28
        slot->tokObjHashTable = NULL;
3655
28
    }
3656
3657
28
    if (slot->sessObjHashTable) {
3658
28
        PORT_Free(slot->sessObjHashTable);
3659
28
        slot->sessObjHashTable = NULL;
3660
28
    }
3661
28
    slot->sessObjHashSize = 0;
3662
3663
28
    if (slot->head) {
3664
28
        PORT_Free(slot->head);
3665
28
        slot->head = NULL;
3666
28
    }
3667
28
    slot->sessHashSize = 0;
3668
3669
    /* OK everything has been disassembled, now we can finally get rid
3670
     * of the locks */
3671
28
    SKIP_AFTER_FORK(PR_DestroyLock(slot->slotLock));
3672
28
    slot->slotLock = NULL;
3673
28
    if (slot->sessionLock) {
3674
56
        for (i = 0; i < slot->numSessionLocks; i++) {
3675
28
            if (slot->sessionLock[i]) {
3676
28
                SKIP_AFTER_FORK(PR_DestroyLock(slot->sessionLock[i]));
3677
28
                slot->sessionLock[i] = NULL;
3678
28
            }
3679
28
        }
3680
28
        PORT_Free(slot->sessionLock);
3681
28
        slot->sessionLock = NULL;
3682
28
    }
3683
28
    if (slot->objectLock) {
3684
28
        SKIP_AFTER_FORK(PR_DestroyLock(slot->objectLock));
3685
28
        slot->objectLock = NULL;
3686
28
    }
3687
28
    if (slot->pwCheckLock) {
3688
28
        SKIP_AFTER_FORK(PR_DestroyLock(slot->pwCheckLock));
3689
28
        slot->pwCheckLock = NULL;
3690
28
    }
3691
28
    PORT_Free(slot);
3692
28
    return CKR_OK;
3693
28
}
3694
3695
/*
3696
 * handle the SECMOD.db
3697
 */
3698
char **
3699
NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args)
3700
32
{
3701
32
#ifdef NSS_DISABLE_DBM
3702
32
    return NSSUTIL_DoModuleDBFunction(function, parameters, args);
3703
#else
3704
    char *secmod = NULL;
3705
    char *appName = NULL;
3706
    char *filename = NULL;
3707
    NSSDBType dbType = NSS_DB_TYPE_NONE;
3708
    PRBool rw;
3709
    static char *success = "Success";
3710
    char **rvstr = NULL;
3711
3712
    rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args);
3713
    if (rvstr != NULL) {
3714
        return rvstr;
3715
    }
3716
3717
    if (PORT_GetError() != SEC_ERROR_LEGACY_DATABASE) {
3718
        return NULL;
3719
    }
3720
3721
    /* The legacy database uses the old dbm, which is only linked with the
3722
     * legacy DB handler, which is only callable from softoken */
3723
3724
    secmod = _NSSUTIL_GetSecmodName(parameters, &dbType, &appName,
3725
                                    &filename, &rw);
3726
3727
    switch (function) {
3728
        case SECMOD_MODULE_DB_FUNCTION_FIND:
3729
            if (secmod == NULL) {
3730
                PORT_SetError(SEC_ERROR_INVALID_ARGS);
3731
                goto loser;
3732
            }
3733
            if (rw && (dbType != NSS_DB_TYPE_LEGACY) &&
3734
                (dbType != NSS_DB_TYPE_MULTIACCESS)) {
3735
                /* if we get here, we are trying to update the local database */
3736
                /* force data from the legacy DB */
3737
                char *oldSecmod = NULL;
3738
                char *oldAppName = NULL;
3739
                char *oldFilename = NULL;
3740
                PRBool oldrw;
3741
                char **strings = NULL;
3742
                int i;
3743
3744
                dbType = NSS_DB_TYPE_LEGACY;
3745
                oldSecmod = _NSSUTIL_GetSecmodName(parameters, &dbType, &oldAppName,
3746
                                                   &oldFilename, &oldrw);
3747
                strings = sftkdbCall_ReadSecmodDB(appName, oldFilename, oldSecmod,
3748
                                                  (char *)parameters, oldrw);
3749
                if (strings) {
3750
                    /* write out the strings */
3751
                    for (i = 0; strings[i]; i++) {
3752
                        NSSUTIL_DoModuleDBFunction(SECMOD_MODULE_DB_FUNCTION_ADD,
3753
                                                   parameters, strings[i]);
3754
                    }
3755
                    sftkdbCall_ReleaseSecmodDBData(oldAppName, oldFilename, oldSecmod,
3756
                                                   (char **)strings, oldrw);
3757
                } else {
3758
                    /* write out a dummy record */
3759
                    NSSUTIL_DoModuleDBFunction(SECMOD_MODULE_DB_FUNCTION_ADD,
3760
                                               parameters, " ");
3761
                }
3762
                if (oldSecmod) {
3763
                    PR_smprintf_free(oldSecmod);
3764
                }
3765
                if (oldAppName) {
3766
                    PORT_Free(oldAppName);
3767
                }
3768
                if (oldFilename) {
3769
                    PORT_Free(oldFilename);
3770
                }
3771
                rvstr = NSSUTIL_DoModuleDBFunction(function, parameters, args);
3772
                break;
3773
            }
3774
            rvstr = sftkdbCall_ReadSecmodDB(appName, filename, secmod,
3775
                                            (char *)parameters, rw);
3776
            break;
3777
        case SECMOD_MODULE_DB_FUNCTION_ADD:
3778
            if (secmod == NULL) {
3779
                PORT_SetError(SEC_ERROR_INVALID_ARGS);
3780
                goto loser;
3781
            }
3782
            rvstr = (sftkdbCall_AddSecmodDB(appName, filename, secmod,
3783
                                            (char *)args, rw) == SECSuccess)
3784
                        ? &success
3785
                        : NULL;
3786
            break;
3787
        case SECMOD_MODULE_DB_FUNCTION_DEL:
3788
            if (secmod == NULL) {
3789
                PORT_SetError(SEC_ERROR_INVALID_ARGS);
3790
                goto loser;
3791
            }
3792
            rvstr = (sftkdbCall_DeleteSecmodDB(appName, filename, secmod,
3793
                                               (char *)args, rw) == SECSuccess)
3794
                        ? &success
3795
                        : NULL;
3796
            break;
3797
        case SECMOD_MODULE_DB_FUNCTION_RELEASE:
3798
            rvstr = (sftkdbCall_ReleaseSecmodDBData(appName, filename, secmod,
3799
                                                    (char **)args, rw) == SECSuccess)
3800
                        ? &success
3801
                        : NULL;
3802
            break;
3803
    }
3804
3805
loser:
3806
    if (secmod)
3807
        PR_smprintf_free(secmod);
3808
    if (appName)
3809
        PORT_Free(appName);
3810
    if (filename)
3811
        PORT_Free(filename);
3812
    return rvstr;
3813
#endif /* NSS_DISABLE_DBM */
3814
32
}
3815
3816
static void
3817
nscFreeAllSlots(unsigned int moduleIndex)
3818
14
{
3819
    /* free all the slots */
3820
14
    SFTKSlot *slot = NULL;
3821
14
    CK_SLOT_ID slotID;
3822
14
    int i;
3823
3824
14
    if (nscSlotList[moduleIndex]) {
3825
14
        CK_ULONG tmpSlotCount = nscSlotCount[moduleIndex];
3826
14
        CK_SLOT_ID_PTR tmpSlotList = nscSlotList[moduleIndex];
3827
14
        PLHashTable *tmpSlotHashTable = nscSlotHashTable[moduleIndex];
3828
3829
        /* first close all the session */
3830
42
        for (i = 0; i < (int)tmpSlotCount; i++) {
3831
28
            slotID = tmpSlotList[i];
3832
28
            (void)NSC_CloseAllSessions(slotID);
3833
28
        }
3834
3835
        /* now clear out the statics */
3836
14
        nscSlotList[moduleIndex] = NULL;
3837
14
        nscSlotCount[moduleIndex] = 0;
3838
14
        nscSlotHashTable[moduleIndex] = NULL;
3839
14
        nscSlotListSize[moduleIndex] = 0;
3840
3841
42
        for (i = 0; i < (int)tmpSlotCount; i++) {
3842
28
            slotID = tmpSlotList[i];
3843
28
            slot = (SFTKSlot *)
3844
28
                PL_HashTableLookup(tmpSlotHashTable, (void *)(uintptr_t)slotID);
3845
28
            PORT_Assert(slot);
3846
28
            if (!slot)
3847
0
                continue;
3848
28
            SFTK_DestroySlotData(slot);
3849
28
            PL_HashTableRemove(tmpSlotHashTable, (void *)(uintptr_t)slotID);
3850
28
        }
3851
14
        PORT_Free(tmpSlotList);
3852
14
        PL_HashTableDestroy(tmpSlotHashTable);
3853
14
    }
3854
14
}
3855
3856
static void
3857
sftk_closePeer(PRBool isFIPS)
3858
0
{
3859
0
    CK_SLOT_ID slotID = isFIPS ? PRIVATE_KEY_SLOT_ID : FIPS_SLOT_ID;
3860
0
    SFTKSlot *slot;
3861
0
    unsigned int moduleIndex = isFIPS ? NSC_NON_FIPS_MODULE : NSC_FIPS_MODULE;
3862
0
    PLHashTable *tmpSlotHashTable = nscSlotHashTable[moduleIndex];
3863
3864
0
    slot = (SFTKSlot *)PL_HashTableLookup(tmpSlotHashTable, (void *)(uintptr_t)slotID);
3865
0
    if (slot == NULL) {
3866
0
        return;
3867
0
    }
3868
0
    sftk_DBShutdown(slot);
3869
0
    return;
3870
0
}
3871
3872
extern void sftk_PBELockInit(void);
3873
extern void sftk_PBELockShutdown(void);
3874
3875
/* Parse the library parameters from the first occurance in the following src.:
3876
 * 1. C_INITIALIZED_ARGS - lib params are included in LibraryParameters field
3877
 * 2. NSS_LIB_PARAMS - env. var. containing the lib. params.
3878
 * 3. NSS_LIB_PARAMS_FILE - env. var. pointion to a file with lib. params.
3879
 * 4. /etc/nss/params.config - default lib. param. file location [Linux only]
3880
 * 5. LIB_PARAM_DEFAULT - string ensureing the pressence at all times
3881
 *    "configdir='' certPrefix='' keyPrefix='' secmod='' flags=noCertDB,noModDB"
3882
 */
3883
static CK_RV
3884
sftk_getParameters(CK_C_INITIALIZE_ARGS *init_args, PRBool isFIPS,
3885
                   sftk_parameters *paramStrings)
3886
16
{
3887
16
    CK_RV crv;
3888
16
    char *libParams;
3889
16
    const char *filename;
3890
16
    PRFileDesc *file_dc;
3891
16
    PRBool free_mem = PR_FALSE;
3892
3893
16
    if (!init_args || !init_args->LibraryParameters) {
3894
        /* Library parameters were not provided via C_Initialize_args*/
3895
3896
        /* Enviromental value has precedence to configuration filename */
3897
0
        libParams = PR_GetEnvSecure("NSS_LIB_PARAMS");
3898
3899
0
        if (!libParams) {
3900
            /* Load from config filename or use default */
3901
0
            filename = PR_GetEnvSecure("NSS_LIB_PARAMS_FILE");
3902
0
#ifdef XP_UNIX
3903
            /* Use default configuration file for Linux only */
3904
0
            if (!filename)
3905
0
                filename = LIB_PARAM_DEFAULT_FILE_LOCATION;
3906
0
#endif
3907
0
            if (filename) {
3908
0
                file_dc = PR_OpenFile(filename, PR_RDONLY, 444);
3909
0
                if (file_dc) {
3910
                    /* file opened */
3911
0
                    PRInt32 len = PR_Available(file_dc);
3912
0
                    libParams = PORT_NewArray(char, len + 1);
3913
0
                    if (libParams) {
3914
                        /* memory allocated */
3915
0
                        if (PR_Read(file_dc, libParams, len) == -1) {
3916
0
                            PORT_Free(libParams);
3917
0
                            libParams = NULL;
3918
0
                        } else {
3919
0
                            free_mem = PR_TRUE;
3920
0
                            libParams[len] = '\0';
3921
0
                        }
3922
0
                    }
3923
3924
0
                    PR_Close(file_dc);
3925
0
                }
3926
0
            }
3927
0
        }
3928
3929
0
        if (libParams == NULL)
3930
0
            libParams = LIB_PARAM_DEFAULT;
3931
3932
16
    } else {
3933
        /* Use parameters provided with C_Initialize_args */
3934
16
        libParams = (char *)init_args->LibraryParameters;
3935
16
    }
3936
3937
16
    crv = sftk_parseParameters(libParams, paramStrings, isFIPS);
3938
16
    if (crv != CKR_OK) {
3939
0
        crv = CKR_ARGUMENTS_BAD;
3940
0
        goto loser;
3941
0
    }
3942
3943
16
    crv = CKR_OK;
3944
16
loser:
3945
16
    if (free_mem)
3946
0
        PORT_Free(libParams);
3947
3948
16
    return crv;
3949
16
}
3950
3951
/* NSC_Initialize initializes the Cryptoki library. */
3952
CK_RV
3953
nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
3954
16
{
3955
16
    CK_RV crv = CKR_OK;
3956
16
    SECStatus rv;
3957
16
    CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *)pReserved;
3958
16
    PRBool destroy_freelist_on_error = PR_TRUE;
3959
16
    int i;
3960
16
    unsigned int moduleIndex = isFIPS ? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE;
3961
3962
16
    if (isFIPS) {
3963
0
        loginWaitTime = PR_SecondsToInterval(1);
3964
0
    }
3965
3966
16
    ENABLE_FORK_CHECK();
3967
3968
16
    sftk_PBELockInit();
3969
3970
16
    rv = SECOID_Init();
3971
16
    if (rv != SECSuccess) {
3972
0
        crv = CKR_DEVICE_ERROR;
3973
0
        return crv;
3974
0
    }
3975
3976
16
    rv = BL_Init(); /* initialize freebl engine */
3977
16
    if (rv != SECSuccess) {
3978
0
        crv = CKR_DEVICE_ERROR;
3979
0
        return crv;
3980
0
    }
3981
3982
16
    rv = RNG_RNGInit(); /* initialize random number generator */
3983
16
    if (rv != SECSuccess) {
3984
0
        crv = CKR_DEVICE_ERROR;
3985
0
        return crv;
3986
0
    }
3987
3988
    /* NOTE:
3989
     * we should be getting out mutexes from this list, not statically binding
3990
     * them from NSPR. This should happen before we allow the internal to split
3991
     * off from the rest on NSS.
3992
     */
3993
3994
    /* initialize the key and cert db's */
3995
16
    if (init_args && (!(init_args->flags & CKF_OS_LOCKING_OK))) {
3996
0
        if (init_args->CreateMutex && init_args->DestroyMutex &&
3997
0
            init_args->LockMutex && init_args->UnlockMutex) {
3998
            /* softoken always uses NSPR (ie. OS locking), and doesn't know how
3999
             * to use the lock functions provided by the application.
4000
             */
4001
0
            crv = CKR_CANT_LOCK;
4002
0
            return crv;
4003
0
        }
4004
0
        if (init_args->CreateMutex || init_args->DestroyMutex ||
4005
0
            init_args->LockMutex || init_args->UnlockMutex) {
4006
            /* only some of the lock functions were provided by the
4007
             * application. This is invalid per PKCS#11 spec.
4008
             */
4009
0
            crv = CKR_ARGUMENTS_BAD;
4010
0
            return crv;
4011
0
        }
4012
0
    }
4013
4014
16
    sftk_parameters paramStrings;
4015
4016
    /* load and parse the library parameters */
4017
16
    crv = sftk_getParameters(init_args, isFIPS, &paramStrings);
4018
16
    if (crv != CKR_OK) {
4019
0
        goto loser;
4020
0
    }
4021
4022
16
    crv = sftk_configure(paramStrings.man, paramStrings.libdes);
4023
16
    if (crv != CKR_OK) {
4024
0
        goto loser;
4025
0
    }
4026
4027
    /* if we have a peer already open, have him close his DB's so we
4028
     * don't clobber each other. */
4029
16
    if ((isFIPS && nsc_init) || (!isFIPS && nsf_init)) {
4030
0
        sftk_closePeer(isFIPS);
4031
0
        if (sftk_audit_enabled) {
4032
0
            if (isFIPS && nsc_init) {
4033
0
                sftk_LogAuditMessage(NSS_AUDIT_INFO, NSS_AUDIT_FIPS_STATE,
4034
0
                                     "enabled FIPS mode");
4035
0
            } else {
4036
0
                sftk_LogAuditMessage(NSS_AUDIT_INFO, NSS_AUDIT_FIPS_STATE,
4037
0
                                     "disabled FIPS mode");
4038
0
            }
4039
0
        }
4040
        /* if we have a peer open, we don't want to destroy the freelist
4041
         * from under the peer if we fail, the free list will be
4042
         * destroyed in that case when the C_Finalize is called for
4043
         * the peer */
4044
0
        destroy_freelist_on_error = PR_FALSE;
4045
0
    }
4046
    /* allow us to create objects in SFTK_SlotInit */
4047
16
    sftk_InitFreeLists();
4048
4049
48
    for (i = 0; i < paramStrings.token_count; i++) {
4050
32
        crv = SFTK_SlotInit(paramStrings.configdir,
4051
32
                            paramStrings.updatedir, paramStrings.updateID,
4052
32
                            &paramStrings.tokens[i], moduleIndex);
4053
32
        if (crv != CKR_OK) {
4054
0
            nscFreeAllSlots(moduleIndex);
4055
0
            break;
4056
0
        }
4057
32
    }
4058
4059
16
loser:
4060
4061
16
    sftk_freeParams(&paramStrings);
4062
4063
16
    if (destroy_freelist_on_error && (CKR_OK != crv)) {
4064
        /* idempotent. If the list are already freed, this is a noop */
4065
0
        sftk_CleanupFreeLists();
4066
0
    }
4067
4068
#ifndef NO_FORK_CHECK
4069
    if (CKR_OK == crv) {
4070
#if defined(CHECK_FORK_MIXED)
4071
        /* Before Solaris 10, fork handlers are not unregistered at dlclose()
4072
         * time. So, we only use pthread_atfork on Solaris 10 and later. For
4073
         * earlier versions, we use PID checks.
4074
         */
4075
        char buf[200];
4076
        int major = 0, minor = 0;
4077
4078
        long rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
4079
        if (rv > 0 && rv < sizeof(buf)) {
4080
            if (2 == sscanf(buf, "%d.%d", &major, &minor)) {
4081
                /* Are we on Solaris 10 or greater ? */
4082
                if (major > 5 || (5 == major && minor >= 10)) {
4083
                    /* we are safe to use pthread_atfork */
4084
                    usePthread_atfork = PR_TRUE;
4085
                }
4086
            }
4087
        }
4088
        if (usePthread_atfork) {
4089
            pthread_atfork(NULL, NULL, ForkedChild);
4090
        } else {
4091
            myPid = getpid();
4092
        }
4093
4094
#elif defined(CHECK_FORK_PTHREAD)
4095
        pthread_atfork(NULL, NULL, ForkedChild);
4096
#elif defined(CHECK_FORK_GETPID)
4097
        myPid = getpid();
4098
#else
4099
#error Incorrect fork check method.
4100
#endif
4101
    }
4102
#endif
4103
16
    return crv;
4104
16
}
4105
4106
CK_RV
4107
NSC_Initialize(CK_VOID_PTR pReserved)
4108
16
{
4109
16
    CK_RV crv;
4110
4111
16
    sftk_ForkReset(pReserved, &crv);
4112
4113
16
    if (nsc_init) {
4114
0
        return CKR_CRYPTOKI_ALREADY_INITIALIZED;
4115
0
    }
4116
16
    crv = nsc_CommonInitialize(pReserved, PR_FALSE);
4117
16
    nsc_init = (PRBool)(crv == CKR_OK);
4118
16
    return crv;
4119
16
}
4120
4121
/* NSC_Finalize indicates that an application is done with the
4122
 * Cryptoki library.*/
4123
CK_RV
4124
nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS)
4125
14
{
4126
    /* propagate the fork status to freebl and util */
4127
14
    BL_SetForkState(parentForkedAfterC_Initialize);
4128
14
    UTIL_SetForkState(parentForkedAfterC_Initialize);
4129
4130
14
    nscFreeAllSlots(isFIPS ? NSC_FIPS_MODULE : NSC_NON_FIPS_MODULE);
4131
4132
    /* don't muck with the globals if our peer is still initialized */
4133
14
    if (isFIPS && nsc_init) {
4134
0
        return CKR_OK;
4135
0
    }
4136
14
    if (!isFIPS && nsf_init) {
4137
0
        return CKR_OK;
4138
0
    }
4139
4140
14
    sftk_CleanupFreeLists();
4141
14
    sftkdb_Shutdown();
4142
4143
    /* This function does not discard all our previously aquired entropy. */
4144
14
    RNG_RNGShutdown();
4145
4146
    /* tell freeBL to clean up after itself */
4147
14
    BL_Cleanup();
4148
4149
    /* reset fork status in freebl. We must do this before BL_Unload so that
4150
     * this call doesn't force freebl to be reloaded. */
4151
14
    BL_SetForkState(PR_FALSE);
4152
4153
#ifndef NSS_STATIC_SOFTOKEN
4154
    /* unload freeBL shared library from memory. This may only decrement the
4155
     * OS refcount if it's been loaded multiple times, eg. by libssl */
4156
    BL_Unload();
4157
#endif
4158
4159
    /* clean up the default OID table */
4160
14
    SECOID_Shutdown();
4161
4162
14
    sftk_PBELockShutdown();
4163
4164
    /* reset fork status in util */
4165
14
    UTIL_SetForkState(PR_FALSE);
4166
4167
14
    nsc_init = PR_FALSE;
4168
4169
#ifndef NO_FORK_CHECK
4170
#ifdef CHECK_FORK_MIXED
4171
    if (!usePthread_atfork) {
4172
        myPid = 0; /* allow CHECK_FORK in the next softoken initialization to
4173
                    * succeed */
4174
    } else {
4175
        forked = PR_FALSE; /* allow reinitialization */
4176
    }
4177
#elif defined(CHECK_FORK_GETPID)
4178
    myPid = 0; /* allow reinitialization */
4179
#elif defined(CHECK_FORK_PTHREAD)
4180
    forked = PR_FALSE; /* allow reinitialization */
4181
#endif
4182
#endif
4183
14
    return CKR_OK;
4184
14
}
4185
4186
/* Hard-reset the entire softoken PKCS#11 module if the parent process forked
4187
 * while it was initialized. */
4188
PRBool
4189
sftk_ForkReset(CK_VOID_PTR pReserved, CK_RV *crv)
4190
30
{
4191
#ifndef NO_FORK_CHECK
4192
    if (PARENT_FORKED()) {
4193
        parentForkedAfterC_Initialize = PR_TRUE;
4194
        if (nsc_init) {
4195
            /* finalize non-FIPS token */
4196
            *crv = nsc_CommonFinalize(pReserved, PR_FALSE);
4197
            PORT_Assert(CKR_OK == *crv);
4198
            nsc_init = (PRBool) !(*crv == CKR_OK);
4199
        }
4200
        if (nsf_init) {
4201
            /* finalize FIPS token */
4202
            *crv = nsc_CommonFinalize(pReserved, PR_TRUE);
4203
            PORT_Assert(CKR_OK == *crv);
4204
            nsf_init = (PRBool) !(*crv == CKR_OK);
4205
        }
4206
        parentForkedAfterC_Initialize = PR_FALSE;
4207
        return PR_TRUE;
4208
    }
4209
#endif
4210
30
    return PR_FALSE;
4211
30
}
4212
4213
/* NSC_Finalize indicates that an application is done with the
4214
 * Cryptoki library.*/
4215
CK_RV
4216
NSC_Finalize(CK_VOID_PTR pReserved)
4217
14
{
4218
14
    CK_RV crv;
4219
4220
    /* reset entire PKCS#11 module upon fork */
4221
14
    if (sftk_ForkReset(pReserved, &crv)) {
4222
0
        return crv;
4223
0
    }
4224
4225
14
    if (!nsc_init) {
4226
0
        return CKR_OK;
4227
0
    }
4228
4229
14
    crv = nsc_CommonFinalize(pReserved, PR_FALSE);
4230
4231
14
    nsc_init = (PRBool) !(crv == CKR_OK);
4232
4233
14
    return crv;
4234
14
}
4235
4236
extern const char __nss_softokn_version[];
4237
4238
/* NSC_GetInfo returns general information about Cryptoki. */
4239
CK_RV
4240
NSC_GetInfo(CK_INFO_PTR pInfo)
4241
16
{
4242
16
#define NSS_VERSION_VARIABLE __nss_softokn_version
4243
16
#include "verref.h"
4244
4245
16
    CHECK_FORK();
4246
4247
16
    pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
4248
16
    pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
4249
16
    PORT_Memcpy(pInfo->manufacturerID, manufacturerID, 32);
4250
16
    pInfo->libraryVersion.major = SOFTOKEN_VMAJOR;
4251
16
    pInfo->libraryVersion.minor = SOFTOKEN_VMINOR;
4252
16
    PORT_Memcpy(pInfo->libraryDescription, libraryDescription, 32);
4253
16
    pInfo->flags = 0;
4254
16
    return CKR_OK;
4255
16
}
4256
4257
/* NSC_GetInfo returns general information about Cryptoki. */
4258
CK_RV
4259
NSC_GetInfoV2(CK_INFO_PTR pInfo)
4260
0
{
4261
0
    CHECK_FORK();
4262
4263
0
    pInfo->cryptokiVersion.major = 2;
4264
0
    pInfo->cryptokiVersion.minor = 40;
4265
0
    PORT_Memcpy(pInfo->manufacturerID, manufacturerID, 32);
4266
0
    pInfo->libraryVersion.major = SOFTOKEN_VMAJOR;
4267
0
    pInfo->libraryVersion.minor = SOFTOKEN_VMINOR;
4268
0
    PORT_Memcpy(pInfo->libraryDescription, libraryDescription, 32);
4269
0
    pInfo->flags = 0;
4270
0
    return CKR_OK;
4271
0
}
4272
4273
/* NSC_GetSlotList obtains a list of slots in the system. */
4274
CK_RV
4275
nsc_CommonGetSlotList(CK_BBOOL tokenPresent,
4276
                      CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount,
4277
                      unsigned int moduleIndex)
4278
32
{
4279
32
    *pulCount = nscSlotCount[moduleIndex];
4280
32
    if (pSlotList != NULL) {
4281
16
        PORT_Memcpy(pSlotList, nscSlotList[moduleIndex],
4282
16
                    nscSlotCount[moduleIndex] * sizeof(CK_SLOT_ID));
4283
16
    }
4284
32
    return CKR_OK;
4285
32
}
4286
4287
/* NSC_GetSlotList obtains a list of slots in the system. */
4288
CK_RV
4289
NSC_GetSlotList(CK_BBOOL tokenPresent,
4290
                CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
4291
32
{
4292
32
    CHECK_FORK();
4293
32
    return nsc_CommonGetSlotList(tokenPresent, pSlotList, pulCount,
4294
32
                                 NSC_NON_FIPS_MODULE);
4295
32
}
4296
4297
/* NSC_GetSlotInfo obtains information about a particular slot in the system. */
4298
CK_RV
4299
NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
4300
32
{
4301
32
    SFTKSlot *slot = sftk_SlotFromID(slotID, PR_TRUE);
4302
4303
32
    CHECK_FORK();
4304
4305
32
    if (slot == NULL)
4306
0
        return CKR_SLOT_ID_INVALID;
4307
4308
32
    PORT_Memcpy(pInfo->manufacturerID, manufacturerID,
4309
32
                sizeof(pInfo->manufacturerID));
4310
32
    PORT_Memcpy(pInfo->slotDescription, slot->slotDescription,
4311
32
                sizeof(pInfo->slotDescription));
4312
32
    pInfo->flags = (slot->present) ? CKF_TOKEN_PRESENT : 0;
4313
4314
    /* all user defined slots are defined as removable */
4315
32
    if (slotID >= SFTK_MIN_USER_SLOT_ID) {
4316
0
        pInfo->flags |= CKF_REMOVABLE_DEVICE;
4317
32
    } else {
4318
        /* In the case where we are doing a merge update, we need
4319
         * the DB slot to be removable so the token name can change
4320
         * appropriately. */
4321
32
        SFTKDBHandle *handle = sftk_getKeyDB(slot);
4322
32
        if (handle) {
4323
0
            if (sftkdb_InUpdateMerge(handle)) {
4324
0
                pInfo->flags |= CKF_REMOVABLE_DEVICE;
4325
0
            }
4326
0
            sftk_freeDB(handle);
4327
0
        }
4328
32
    }
4329
4330
    /* If there is no key database, this is for example the case when NSS was
4331
     * initialized with NSS_NoDbInit(), then there won't be any point in
4332
     * requesting a PIN. Set the CKF_USER_PIN_INITIALIZED bit so that
4333
     * PK11_NeedUserInit() doesn't indicate that a PIN is needed.
4334
     */
4335
32
    if (slot->keyDB == NULL) {
4336
32
        pInfo->flags |= CKF_USER_PIN_INITIALIZED;
4337
32
    }
4338
4339
    /* ok we really should read it out of the keydb file. */
4340
    /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */
4341
32
    pInfo->hardwareVersion.major = SOFTOKEN_VMAJOR;
4342
32
    pInfo->hardwareVersion.minor = SOFTOKEN_VMINOR;
4343
32
    pInfo->firmwareVersion.major = SOFTOKEN_VPATCH;
4344
32
    pInfo->firmwareVersion.minor = SOFTOKEN_VBUILD;
4345
32
    return CKR_OK;
4346
32
}
4347
4348
/*
4349
 * check the current state of the 'needLogin' flag in case the database has
4350
 * been changed underneath us.
4351
 */
4352
static PRBool
4353
sftk_checkNeedLogin(SFTKSlot *slot, SFTKDBHandle *keyHandle)
4354
0
{
4355
0
    PRBool needLogin;
4356
0
    if (sftkdb_PWCached(keyHandle) == SECSuccess) {
4357
0
        PR_Lock(slot->slotLock);
4358
0
        needLogin = slot->needLogin;
4359
0
        PR_Unlock(slot->slotLock);
4360
0
    } else {
4361
0
        needLogin = (PRBool)!sftk_hasNullPassword(slot, keyHandle);
4362
0
        PR_Lock(slot->slotLock);
4363
0
        slot->needLogin = needLogin;
4364
0
        PR_Unlock(slot->slotLock);
4365
0
    }
4366
0
    return needLogin;
4367
0
}
4368
4369
static PRBool
4370
sftk_isBlank(const char *s, int len)
4371
0
{
4372
0
    int i;
4373
0
    for (i = 0; i < len; i++) {
4374
0
        if (s[i] != ' ') {
4375
0
            return PR_FALSE;
4376
0
        }
4377
0
    }
4378
0
    return PR_TRUE;
4379
0
}
4380
4381
/* NSC_GetTokenInfo obtains information about a particular token in
4382
 * the system. */
4383
CK_RV
4384
NSC_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
4385
32
{
4386
32
    SFTKSlot *slot;
4387
32
    SFTKDBHandle *handle;
4388
4389
32
    CHECK_FORK();
4390
4391
32
    if (!nsc_init && !nsf_init)
4392
0
        return CKR_CRYPTOKI_NOT_INITIALIZED;
4393
32
    slot = sftk_SlotFromID(slotID, PR_FALSE);
4394
32
    if (slot == NULL)
4395
0
        return CKR_SLOT_ID_INVALID;
4396
4397
32
    PORT_Memcpy(pInfo->manufacturerID, manufacturerID, 32);
4398
32
    PORT_Memcpy(pInfo->model, "NSS 3           ", 16);
4399
32
    PORT_Memcpy(pInfo->serialNumber, "0000000000000000", 16);
4400
32
    PORT_Memcpy(pInfo->utcTime, "0000000000000000", 16);
4401
32
    pInfo->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
4402
32
    pInfo->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE;
4403
32
    PR_Lock(slot->slotLock); /* Protect sessionCount / rwSessioncount */
4404
32
    pInfo->ulSessionCount = slot->sessionCount;
4405
32
    pInfo->ulRwSessionCount = slot->rwSessionCount;
4406
32
    PR_Unlock(slot->slotLock); /* Unlock before sftk_getKeyDB */
4407
32
    pInfo->firmwareVersion.major = 0;
4408
32
    pInfo->firmwareVersion.minor = 0;
4409
32
    PORT_Memcpy(pInfo->label, slot->tokDescription, sizeof(pInfo->label));
4410
32
    handle = sftk_getKeyDB(slot);
4411
32
    pInfo->flags = CKF_RNG | CKF_DUAL_CRYPTO_OPERATIONS;
4412
32
    if (handle == NULL) {
4413
32
        pInfo->flags |= CKF_WRITE_PROTECTED;
4414
32
        pInfo->ulMaxPinLen = 0;
4415
32
        pInfo->ulMinPinLen = 0;
4416
32
        pInfo->ulTotalPublicMemory = 0;
4417
32
        pInfo->ulFreePublicMemory = 0;
4418
32
        pInfo->ulTotalPrivateMemory = 0;
4419
32
        pInfo->ulFreePrivateMemory = 0;
4420
32
        pInfo->hardwareVersion.major = 4;
4421
32
        pInfo->hardwareVersion.minor = 0;
4422
32
    } else {
4423
        /*
4424
         * we have three possible states which we may be in:
4425
         *   (1) No DB password has been initialized. This also means we
4426
         *   have no keys in the key db.
4427
         *   (2) Password initialized to NULL. This means we have keys, but
4428
         *   the user has chosen not use a password.
4429
         *   (3) Finally we have an initialized password whicn is not NULL, and
4430
         *   we will need to prompt for it.
4431
         */
4432
0
        if (sftkdb_HasPasswordSet(handle) == SECFailure) {
4433
0
            pInfo->flags |= CKF_LOGIN_REQUIRED;
4434
0
        } else if (!sftk_checkNeedLogin(slot, handle)) {
4435
0
            pInfo->flags |= CKF_USER_PIN_INITIALIZED;
4436
0
        } else {
4437
0
            pInfo->flags |= CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED;
4438
            /*
4439
             * if we are doing a merge style update, and we need to get the password
4440
             * of our source database (the database we are updating from), make sure we
4441
             * return a token name that will match the database we are prompting for.
4442
             */
4443
0
            if (sftkdb_NeedUpdateDBPassword(handle)) {
4444
                /* if we have an update tok description, use it. otherwise
4445
                 * use the updateID for this database */
4446
0
                if (!sftk_isBlank(slot->updateTokDescription,
4447
0
                                  sizeof(pInfo->label))) {
4448
0
                    PORT_Memcpy(pInfo->label, slot->updateTokDescription,
4449
0
                                sizeof(pInfo->label));
4450
0
                } else {
4451
                    /* build from updateID */
4452
0
                    const char *updateID = sftkdb_GetUpdateID(handle);
4453
0
                    if (updateID) {
4454
0
                        sftk_setStringName(updateID, (char *)pInfo->label,
4455
0
                                           sizeof(pInfo->label), PR_FALSE);
4456
0
                    }
4457
0
                }
4458
0
            }
4459
0
        }
4460
0
        pInfo->ulMaxPinLen = SFTK_MAX_PIN;
4461
0
        pInfo->ulMinPinLen = (CK_ULONG)slot->minimumPinLen;
4462
0
        pInfo->ulTotalPublicMemory = 1;
4463
0
        pInfo->ulFreePublicMemory = 1;
4464
0
        pInfo->ulTotalPrivateMemory = 1;
4465
0
        pInfo->ulFreePrivateMemory = 1;
4466
#ifdef SHDB_FIXME
4467
        pInfo->hardwareVersion.major = CERT_DB_FILE_VERSION;
4468
        pInfo->hardwareVersion.minor = handle->version;
4469
#else
4470
0
        pInfo->hardwareVersion.major = 0;
4471
0
        pInfo->hardwareVersion.minor = 0;
4472
0
#endif
4473
0
        sftk_freeDB(handle);
4474
0
    }
4475
    /*
4476
     * CKF_LOGIN_REQUIRED CKF_USER_PIN_INITIALIZED  how CKF_TOKEN_INITIALIZED
4477
     *                                              should be set
4478
     *         0                   0                           1
4479
     *         1                   0                           0
4480
     *         0                   1                           1
4481
     *         1                   1                           1
4482
     */
4483
32
    if (!(pInfo->flags & CKF_LOGIN_REQUIRED) ||
4484
32
        (pInfo->flags & CKF_USER_PIN_INITIALIZED)) {
4485
32
        pInfo->flags |= CKF_TOKEN_INITIALIZED;
4486
32
    }
4487
32
    return CKR_OK;
4488
32
}
4489
4490
/* NSC_GetMechanismList obtains a list of mechanism types
4491
 * supported by a token. */
4492
CK_RV
4493
NSC_GetMechanismList(CK_SLOT_ID slotID,
4494
                     CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount)
4495
64
{
4496
64
    CK_ULONG i;
4497
4498
64
    CHECK_FORK();
4499
4500
64
    switch (slotID) {
4501
        /* default: */
4502
32
        case NETSCAPE_SLOT_ID:
4503
32
            *pulCount = mechanismCount;
4504
32
            if (pMechanismList != NULL) {
4505
3.82k
                for (i = 0; i < mechanismCount; i++) {
4506
3.80k
                    pMechanismList[i] = mechanisms[i].type;
4507
3.80k
                }
4508
16
            }
4509
32
            break;
4510
32
        default:
4511
32
            *pulCount = 0;
4512
7.64k
            for (i = 0; i < mechanismCount; i++) {
4513
7.61k
                if (mechanisms[i].privkey) {
4514
5.85k
                    (*pulCount)++;
4515
5.85k
                    if (pMechanismList != NULL) {
4516
2.92k
                        *pMechanismList++ = mechanisms[i].type;
4517
2.92k
                    }
4518
5.85k
                }
4519
7.61k
            }
4520
32
            break;
4521
64
    }
4522
64
    return CKR_OK;
4523
64
}
4524
4525
/* NSC_GetMechanismInfo obtains information about a particular mechanism
4526
 * possibly supported by a token. */
4527
CK_RV
4528
NSC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
4529
                     CK_MECHANISM_INFO_PTR pInfo)
4530
278k
{
4531
278k
    PRBool isPrivateKey;
4532
278k
    CK_ULONG i;
4533
4534
278k
    CHECK_FORK();
4535
4536
278k
    switch (slotID) {
4537
249k
        case NETSCAPE_SLOT_ID:
4538
249k
            isPrivateKey = PR_FALSE;
4539
249k
            break;
4540
28.7k
        default:
4541
28.7k
            isPrivateKey = PR_TRUE;
4542
28.7k
            break;
4543
278k
    }
4544
17.6M
    for (i = 0; i < mechanismCount; i++) {
4545
17.6M
        if (type == mechanisms[i].type) {
4546
278k
            if (isPrivateKey && !mechanisms[i].privkey) {
4547
0
                return CKR_MECHANISM_INVALID;
4548
0
            }
4549
278k
            PORT_Memcpy(pInfo, &mechanisms[i].info, sizeof(CK_MECHANISM_INFO));
4550
278k
            return CKR_OK;
4551
278k
        }
4552
17.6M
    }
4553
0
    return CKR_MECHANISM_INVALID;
4554
278k
}
4555
4556
/*
4557
 * If we are using the V2 interface, strip out the message flags
4558
 */
4559
0
#define SFTK_MESSAGE_FLAGS (CKF_MESSAGE_ENCRYPT | CKF_MESSAGE_DECRYPT | CKF_MESSAGE_SIGN | CKF_MESSAGE_VERIFY)
4560
CK_RV
4561
NSC_GetMechanismInfoV2(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
4562
                       CK_MECHANISM_INFO_PTR pInfo)
4563
0
{
4564
0
    CK_RV crv;
4565
0
    crv = NSC_GetMechanismInfo(slotID, type, pInfo);
4566
0
    if (crv == CKR_OK) {
4567
0
        pInfo->flags = pInfo->flags & ~SFTK_MESSAGE_FLAGS;
4568
0
    }
4569
0
    return crv;
4570
0
}
4571
4572
CK_RV
4573
sftk_MechAllowsOperation(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE op)
4574
515k
{
4575
515k
    CK_ULONG i;
4576
515k
    CK_FLAGS flags = sftk_AttributeToFlags(op);
4577
4578
515k
    if (flags == 0) {
4579
0
        return CKR_ARGUMENTS_BAD;
4580
0
    }
4581
30.1M
    for (i = 0; i < mechanismCount; i++) {
4582
30.1M
        if (type == mechanisms[i].type) {
4583
515k
            return (flags & mechanisms[i].info.flags) ? CKR_OK
4584
515k
                                                      : CKR_MECHANISM_INVALID;
4585
515k
        }
4586
30.1M
    }
4587
655
    return CKR_MECHANISM_INVALID;
4588
515k
}
4589
4590
/* NSC_InitToken initializes a token. */
4591
CK_RV
4592
NSC_InitToken(CK_SLOT_ID slotID, CK_CHAR_PTR pPin,
4593
              CK_ULONG ulPinLen, CK_CHAR_PTR pLabel)
4594
0
{
4595
0
    SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
4596
0
    SFTKDBHandle *handle;
4597
0
    SECStatus rv;
4598
0
    unsigned int i;
4599
0
    SFTKObject *object;
4600
4601
0
    CHECK_FORK();
4602
4603
0
    if (slot == NULL)
4604
0
        return CKR_SLOT_ID_INVALID;
4605
4606
    /* don't initialize the database if we aren't talking to a token
4607
     * that uses the key database.
4608
     */
4609
0
    if (slotID == NETSCAPE_SLOT_ID) {
4610
0
        return CKR_TOKEN_WRITE_PROTECTED;
4611
0
    }
4612
4613
    /* first, delete all our loaded key and cert objects from our
4614
     * internal list. */
4615
0
    PR_Lock(slot->objectLock);
4616
0
    for (i = 0; i < slot->sessObjHashSize; i++) {
4617
0
        do {
4618
0
            object = slot->sessObjHashTable[i];
4619
            /* hand deque */
4620
            /* this duplicates function of NSC_close session functions, but
4621
             * because we know that we are freeing all the sessions, we can
4622
             * do more efficient processing */
4623
0
            if (object) {
4624
0
                slot->sessObjHashTable[i] = object->next;
4625
4626
0
                if (object->next)
4627
0
                    object->next->prev = NULL;
4628
0
                object->next = object->prev = NULL;
4629
0
            }
4630
0
            if (object)
4631
0
                sftk_FreeObject(object);
4632
0
        } while (object != NULL);
4633
0
    }
4634
0
    slot->DB_loaded = PR_FALSE;
4635
0
    PR_Unlock(slot->objectLock);
4636
4637
    /* then clear out the key database */
4638
0
    handle = sftk_getKeyDB(slot);
4639
0
    if (handle == NULL) {
4640
0
        return CKR_TOKEN_WRITE_PROTECTED;
4641
0
    }
4642
4643
0
    rv = sftkdb_ResetKeyDB(handle);
4644
    /* clear the password */
4645
0
    sftkdb_ClearPassword(handle);
4646
    /* update slot->needLogin (should be true now since no password is set) */
4647
0
    sftk_checkNeedLogin(slot, handle);
4648
0
    sftk_freeDB(handle);
4649
0
    if (rv != SECSuccess) {
4650
0
        return CKR_DEVICE_ERROR;
4651
0
    }
4652
4653
0
    return CKR_OK;
4654
0
}
4655
4656
/* NSC_InitPIN initializes the normal user's PIN. */
4657
CK_RV
4658
NSC_InitPIN(CK_SESSION_HANDLE hSession,
4659
            CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
4660
0
{
4661
0
    SFTKSession *sp = NULL;
4662
0
    SFTKSlot *slot;
4663
0
    SFTKDBHandle *handle = NULL;
4664
0
    char newPinStr[SFTK_MAX_PIN + 1];
4665
0
    SECStatus rv;
4666
0
    CK_RV crv = CKR_SESSION_HANDLE_INVALID;
4667
0
    PRBool tokenRemoved = PR_FALSE;
4668
4669
0
    CHECK_FORK();
4670
4671
0
    sp = sftk_SessionFromHandle(hSession);
4672
0
    if (sp == NULL) {
4673
0
        goto loser;
4674
0
    }
4675
4676
0
    slot = sftk_SlotFromSession(sp);
4677
0
    if (slot == NULL) {
4678
0
        goto loser;
4679
0
    }
4680
4681
0
    handle = sftk_getKeyDB(slot);
4682
0
    if (handle == NULL) {
4683
0
        crv = CKR_PIN_LEN_RANGE;
4684
0
        goto loser;
4685
0
    }
4686
4687
0
    if (sp->info.state != CKS_RW_SO_FUNCTIONS) {
4688
0
        crv = CKR_USER_NOT_LOGGED_IN;
4689
0
        goto loser;
4690
0
    }
4691
4692
0
    sftk_FreeSession(sp);
4693
0
    sp = NULL;
4694
4695
    /* make sure the pins aren't too long */
4696
0
    if (ulPinLen > SFTK_MAX_PIN) {
4697
0
        crv = CKR_PIN_LEN_RANGE;
4698
0
        goto loser;
4699
0
    }
4700
0
    if (ulPinLen < (CK_ULONG)slot->minimumPinLen) {
4701
0
        crv = CKR_PIN_LEN_RANGE;
4702
0
        goto loser;
4703
0
    }
4704
4705
0
    if (sftkdb_HasPasswordSet(handle) != SECFailure) {
4706
0
        crv = CKR_DEVICE_ERROR;
4707
0
        goto loser;
4708
0
    }
4709
4710
    /* convert to null terminated string */
4711
0
    PORT_Memcpy(newPinStr, pPin, ulPinLen);
4712
0
    newPinStr[ulPinLen] = 0;
4713
4714
    /* build the hashed pins which we pass around */
4715
4716
    /* change the data base */
4717
0
    rv = sftkdb_ChangePassword(handle, NULL, newPinStr, &tokenRemoved);
4718
0
    if (tokenRemoved) {
4719
0
        sftk_CloseAllSessions(slot, PR_FALSE);
4720
0
    }
4721
0
    PORT_Memset(newPinStr, 0, ulPinLen);
4722
0
    sftk_freeDB(handle);
4723
0
    handle = NULL;
4724
4725
    /* Now update our local copy of the pin */
4726
0
    if (rv == SECSuccess) {
4727
0
        if (ulPinLen == 0) {
4728
0
            PR_Lock(slot->slotLock);
4729
0
            slot->needLogin = PR_FALSE;
4730
0
            PR_Unlock(slot->slotLock);
4731
0
        }
4732
        /* database has been initialized, now force min password in FIPS
4733
         * mode. NOTE: if we are in level1, we may not have a password, but
4734
         * forcing it now will prevent an insufficient password from being set.
4735
         */
4736
0
        if ((sftk_GetModuleIndex(slot->slotID) == NSC_FIPS_MODULE) &&
4737
0
            (slot->minimumPinLen < FIPS_MIN_PIN)) {
4738
0
            slot->minimumPinLen = FIPS_MIN_PIN;
4739
0
        }
4740
0
        return CKR_OK;
4741
0
    }
4742
0
    crv = CKR_PIN_INCORRECT;
4743
4744
0
loser:
4745
0
    if (sp) {
4746
0
        sftk_FreeSession(sp);
4747
0
    }
4748
0
    if (handle) {
4749
0
        sftk_freeDB(handle);
4750
0
    }
4751
0
    return crv;
4752
0
}
4753
4754
/* NSC_SetPIN modifies the PIN of user that is currently logged in. */
4755
/* NOTE: This is only valid for the PRIVATE_KEY_SLOT */
4756
CK_RV
4757
NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
4758
           CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen)
4759
0
{
4760
0
    SFTKSession *sp = NULL;
4761
0
    SFTKSlot *slot;
4762
0
    SFTKDBHandle *handle = NULL;
4763
0
    char newPinStr[SFTK_MAX_PIN + 1], oldPinStr[SFTK_MAX_PIN + 1];
4764
0
    SECStatus rv;
4765
0
    CK_RV crv = CKR_SESSION_HANDLE_INVALID;
4766
0
    PRBool needLogin;
4767
0
    PRBool tokenRemoved = PR_FALSE;
4768
4769
0
    CHECK_FORK();
4770
4771
0
    sp = sftk_SessionFromHandle(hSession);
4772
0
    if (sp == NULL) {
4773
0
        goto loser;
4774
0
    }
4775
4776
0
    slot = sftk_SlotFromSession(sp);
4777
0
    if (!slot) {
4778
0
        goto loser;
4779
0
    }
4780
4781
0
    handle = sftk_getKeyDB(slot);
4782
0
    if (handle == NULL) {
4783
0
        sftk_FreeSession(sp);
4784
0
        return CKR_PIN_LEN_RANGE; /* XXX FIXME wrong return value */
4785
0
    }
4786
4787
0
    PR_Lock(slot->slotLock);
4788
0
    needLogin = slot->needLogin;
4789
0
    PR_Unlock(slot->slotLock);
4790
0
    if (needLogin && sp->info.state != CKS_RW_USER_FUNCTIONS) {
4791
0
        crv = CKR_USER_NOT_LOGGED_IN;
4792
0
        goto loser;
4793
0
    }
4794
4795
0
    sftk_FreeSession(sp);
4796
0
    sp = NULL;
4797
4798
    /* make sure the pins aren't too long */
4799
0
    if ((ulNewLen > SFTK_MAX_PIN) || (ulOldLen > SFTK_MAX_PIN)) {
4800
0
        crv = CKR_PIN_LEN_RANGE;
4801
0
        goto loser;
4802
0
    }
4803
    /* check the length of new pin, unless both old and new passwords
4804
     * are empty */
4805
0
    if ((ulNewLen != 0 || ulOldLen != 0) &&
4806
0
        ulNewLen < (CK_ULONG)slot->minimumPinLen) {
4807
0
        crv = CKR_PIN_LEN_RANGE;
4808
0
        goto loser;
4809
0
    }
4810
4811
    /* convert to null terminated string */
4812
0
    PORT_Memcpy(newPinStr, pNewPin, ulNewLen);
4813
0
    newPinStr[ulNewLen] = 0;
4814
0
    PORT_Memcpy(oldPinStr, pOldPin, ulOldLen);
4815
0
    oldPinStr[ulOldLen] = 0;
4816
4817
    /* change the data base password */
4818
0
    PR_Lock(slot->pwCheckLock);
4819
0
    rv = sftkdb_ChangePassword(handle, oldPinStr, newPinStr, &tokenRemoved);
4820
0
    PORT_Memset(newPinStr, 0, ulNewLen);
4821
0
    PORT_Memset(oldPinStr, 0, ulOldLen);
4822
0
    if (tokenRemoved) {
4823
0
        sftk_CloseAllSessions(slot, PR_FALSE);
4824
0
    }
4825
0
    if ((rv != SECSuccess) && (sftk_isFIPS(slot->slotID))) {
4826
0
        PR_Sleep(loginWaitTime);
4827
0
    }
4828
0
    PR_Unlock(slot->pwCheckLock);
4829
4830
    /* Now update our local copy of the pin */
4831
0
    if (rv == SECSuccess) {
4832
0
        PR_Lock(slot->slotLock);
4833
0
        slot->needLogin = (PRBool)(ulNewLen != 0);
4834
0
        slot->isLoggedIn = (PRBool)(sftkdb_PWCached(handle) == SECSuccess);
4835
0
        PR_Unlock(slot->slotLock);
4836
        /* Reset login flags. */
4837
0
        if (ulNewLen == 0) {
4838
0
            PR_Lock(slot->slotLock);
4839
0
            slot->isLoggedIn = PR_FALSE;
4840
0
            slot->ssoLoggedIn = PR_FALSE;
4841
0
            PR_Unlock(slot->slotLock);
4842
4843
0
            tokenRemoved = PR_FALSE;
4844
0
            rv = sftkdb_CheckPasswordNull(handle, &tokenRemoved);
4845
0
            if (tokenRemoved) {
4846
0
                sftk_CloseAllSessions(slot, PR_FALSE);
4847
0
            }
4848
0
        }
4849
0
        sftk_update_all_states(slot);
4850
0
        sftk_freeDB(handle);
4851
0
        return CKR_OK;
4852
0
    }
4853
0
    crv = CKR_PIN_INCORRECT;
4854
0
loser:
4855
0
    if (sp) {
4856
0
        sftk_FreeSession(sp);
4857
0
    }
4858
0
    if (handle) {
4859
0
        sftk_freeDB(handle);
4860
0
    }
4861
0
    return crv;
4862
0
}
4863
4864
/* NSC_OpenSession opens a session between an application and a token. */
4865
CK_RV
4866
NSC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags,
4867
                CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession)
4868
1.77M
{
4869
1.77M
    SFTKSlot *slot;
4870
1.77M
    CK_SESSION_HANDLE sessionID;
4871
1.77M
    SFTKSession *session;
4872
1.77M
    SFTKSession *sameID;
4873
4874
1.77M
    CHECK_FORK();
4875
4876
1.77M
    slot = sftk_SlotFromID(slotID, PR_FALSE);
4877
1.77M
    if (slot == NULL)
4878
0
        return CKR_SLOT_ID_INVALID;
4879
4880
    /* new session (we only have serial sessions) */
4881
1.77M
    session = sftk_NewSession(slotID, Notify, pApplication,
4882
1.77M
                              flags | CKF_SERIAL_SESSION);
4883
1.77M
    if (session == NULL)
4884
0
        return CKR_HOST_MEMORY;
4885
4886
1.77M
    if (slot->readOnly && (flags & CKF_RW_SESSION)) {
4887
        /* NETSCAPE_SLOT_ID is Read ONLY */
4888
0
        session->info.flags &= ~CKF_RW_SESSION;
4889
0
    }
4890
1.77M
    PR_Lock(slot->slotLock);
4891
1.77M
    ++slot->sessionCount;
4892
1.77M
    if (session->info.flags & CKF_RW_SESSION) {
4893
0
        ++slot->rwSessionCount;
4894
0
    }
4895
1.77M
    PR_Unlock(slot->slotLock);
4896
4897
1.77M
    do {
4898
1.77M
        PRLock *lock;
4899
1.77M
        do {
4900
1.77M
            sessionID = (PR_ATOMIC_INCREMENT(&slot->sessionIDCount) & 0xffffff) | (slot->index << 24);
4901
1.77M
        } while (sessionID == CK_INVALID_HANDLE);
4902
1.77M
        lock = SFTK_SESSION_LOCK(slot, sessionID);
4903
1.77M
        PR_Lock(lock);
4904
1.77M
        sftkqueue_find(sameID, sessionID, slot->head, slot->sessHashSize);
4905
1.77M
        if (sameID == NULL) {
4906
1.77M
            session->handle = sessionID;
4907
1.77M
            sftk_update_state(slot, session);
4908
1.77M
            sftkqueue_add(session, sessionID, slot->head, slot->sessHashSize);
4909
1.77M
        } else {
4910
0
            slot->sessionIDConflict++; /* for debugging */
4911
0
        }
4912
1.77M
        PR_Unlock(lock);
4913
1.77M
    } while (sameID != NULL);
4914
4915
1.77M
    *phSession = sessionID;
4916
1.77M
    return CKR_OK;
4917
1.77M
}
4918
4919
/* NSC_CloseSession closes a session between an application and a token. */
4920
CK_RV
4921
NSC_CloseSession(CK_SESSION_HANDLE hSession)
4922
1.77M
{
4923
1.77M
    SFTKSlot *slot;
4924
1.77M
    SFTKSession *session;
4925
1.77M
    PRBool sessionFound;
4926
1.77M
    PRLock *lock;
4927
4928
1.77M
    CHECK_FORK();
4929
4930
1.77M
    session = sftk_SessionFromHandle(hSession);
4931
1.77M
    if (session == NULL)
4932
0
        return CKR_SESSION_HANDLE_INVALID;
4933
1.77M
    slot = sftk_SlotFromSession(session);
4934
1.77M
    sessionFound = PR_FALSE;
4935
4936
    /* lock */
4937
1.77M
    lock = SFTK_SESSION_LOCK(slot, hSession);
4938
1.77M
    PR_Lock(lock);
4939
1.77M
    if (sftkqueue_is_queued(session, hSession, slot->head, slot->sessHashSize)) {
4940
1.77M
        sessionFound = PR_TRUE;
4941
1.77M
        sftkqueue_delete(session, hSession, slot->head, slot->sessHashSize);
4942
        /* Drop the bucket's reference. We still hold the reference taken
4943
         * by sftk_SessionFromHandle, so refCount cannot reach 0 here. */
4944
1.77M
        PORT_Assert(session->refCount > 1);
4945
1.77M
        session->refCount--;
4946
1.77M
    }
4947
1.77M
    PR_Unlock(lock);
4948
4949
1.77M
    if (sessionFound) {
4950
1.77M
        SFTKDBHandle *handle;
4951
1.77M
        handle = sftk_getKeyDB(slot);
4952
1.77M
        PR_Lock(slot->slotLock);
4953
1.77M
        if (--slot->sessionCount == 0) {
4954
0
            slot->isLoggedIn = PR_FALSE;
4955
0
            if (slot->needLogin && handle) {
4956
0
                sftkdb_ClearPassword(handle);
4957
0
            }
4958
0
        }
4959
1.77M
        if (session->info.flags & CKF_RW_SESSION) {
4960
0
            --slot->rwSessionCount;
4961
0
        }
4962
1.77M
        PR_Unlock(slot->slotLock);
4963
1.77M
        if (handle) {
4964
0
            sftk_freeDB(handle);
4965
0
        }
4966
1.77M
    }
4967
4968
    /* Drop the lookup reference. Whichever caller drives refCount to 0
4969
     * destroys the session. */
4970
1.77M
    sftk_FreeSession(session);
4971
1.77M
    return CKR_OK;
4972
1.77M
}
4973
4974
/* NSC_CloseAllSessions closes all sessions with a token. */
4975
CK_RV
4976
NSC_CloseAllSessions(CK_SLOT_ID slotID)
4977
56
{
4978
56
    SFTKSlot *slot;
4979
4980
#ifndef NO_FORK_CHECK
4981
    /* skip fork check if we are being called from C_Initialize or C_Finalize */
4982
    if (!parentForkedAfterC_Initialize) {
4983
        CHECK_FORK();
4984
    }
4985
#endif
4986
4987
56
    slot = sftk_SlotFromID(slotID, PR_FALSE);
4988
56
    if (slot == NULL)
4989
0
        return CKR_SLOT_ID_INVALID;
4990
4991
56
    return sftk_CloseAllSessions(slot, PR_TRUE);
4992
56
}
4993
4994
/* NSC_GetSessionInfo obtains information about the session. */
4995
CK_RV
4996
NSC_GetSessionInfo(CK_SESSION_HANDLE hSession,
4997
                   CK_SESSION_INFO_PTR pInfo)
4998
0
{
4999
0
    SFTKSession *session;
5000
5001
0
    CHECK_FORK();
5002
5003
0
    session = sftk_SessionFromHandle(hSession);
5004
0
    if (session == NULL)
5005
0
        return CKR_SESSION_HANDLE_INVALID;
5006
5007
0
    PORT_Memcpy(pInfo, &session->info, sizeof(CK_SESSION_INFO));
5008
0
    sftk_FreeSession(session);
5009
0
    return CKR_OK;
5010
0
}
5011
5012
/* NSC_Login logs a user into a token. */
5013
CK_RV
5014
NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
5015
          CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
5016
0
{
5017
0
    SFTKSlot *slot;
5018
0
    SFTKSession *session;
5019
0
    SFTKDBHandle *handle;
5020
0
    CK_FLAGS sessionFlags;
5021
0
    SECStatus rv;
5022
0
    CK_RV crv;
5023
0
    char pinStr[SFTK_MAX_PIN + 1];
5024
0
    PRBool tokenRemoved = PR_FALSE;
5025
0
    PRBool isLoggedIn;
5026
0
    PRBool needLogin;
5027
5028
0
    CHECK_FORK();
5029
5030
    /* get the slot */
5031
0
    slot = sftk_SlotFromSessionHandle(hSession);
5032
0
    if (slot == NULL) {
5033
0
        return CKR_SESSION_HANDLE_INVALID;
5034
0
    }
5035
5036
    /* make sure the session is valid */
5037
0
    session = sftk_SessionFromHandle(hSession);
5038
0
    if (session == NULL) {
5039
0
        return CKR_SESSION_HANDLE_INVALID;
5040
0
    }
5041
0
    sessionFlags = session->info.flags;
5042
0
    sftk_FreeSession(session);
5043
0
    session = NULL;
5044
5045
    /* can't log into the Netscape Slot */
5046
0
    if (slot->slotID == NETSCAPE_SLOT_ID) {
5047
0
        return CKR_USER_TYPE_INVALID;
5048
0
    }
5049
5050
0
    PR_Lock(slot->slotLock);
5051
0
    isLoggedIn = slot->isLoggedIn;
5052
0
    needLogin = slot->needLogin;
5053
0
    PR_Unlock(slot->slotLock);
5054
5055
0
    if (isLoggedIn)
5056
0
        return CKR_USER_ALREADY_LOGGED_IN;
5057
0
    if (!needLogin) {
5058
0
        return ulPinLen ? CKR_PIN_INCORRECT : CKR_OK;
5059
0
    }
5060
5061
0
    PR_Lock(slot->slotLock);
5062
0
    slot->ssoLoggedIn = PR_FALSE;
5063
0
    PR_Unlock(slot->slotLock);
5064
5065
0
    if (ulPinLen > SFTK_MAX_PIN)
5066
0
        return CKR_PIN_LEN_RANGE;
5067
5068
    /* convert to null terminated string */
5069
0
    if (ulPinLen) {
5070
0
        PORT_Memcpy(pinStr, pPin, ulPinLen);
5071
0
    }
5072
0
    pinStr[ulPinLen] = 0;
5073
5074
0
    handle = sftk_getKeyDB(slot);
5075
0
    if (handle == NULL) {
5076
0
        PORT_Memset(pinStr, 0, ulPinLen);
5077
0
        return CKR_USER_TYPE_INVALID;
5078
0
    }
5079
5080
    /*
5081
     * Deal with bootstrap. We allow the SSO to login in with a NULL
5082
     * password if and only if we haven't initialized the KEY DB yet.
5083
     * We only allow this on a RW session.
5084
     */
5085
0
    rv = sftkdb_HasPasswordSet(handle);
5086
0
    if (rv == SECFailure) {
5087
        /* allow SSO's to log in only if there is not password on the
5088
         * key database */
5089
0
        if (((userType == CKU_SO) && (sessionFlags & CKF_RW_SESSION))
5090
            /* fips always needs to authenticate, even if there isn't a db */
5091
0
            || (sftk_isFIPS(slot->slotID))) {
5092
            /* should this be a fixed password? */
5093
0
            if (ulPinLen == 0) {
5094
0
                sftkdb_ClearPassword(handle);
5095
0
                PR_Lock(slot->slotLock);
5096
0
                slot->isLoggedIn = PR_TRUE;
5097
0
                slot->ssoLoggedIn = (PRBool)(userType == CKU_SO);
5098
0
                PR_Unlock(slot->slotLock);
5099
0
                sftk_update_all_states(slot);
5100
0
                crv = CKR_OK;
5101
0
                goto done;
5102
0
            }
5103
0
            crv = CKR_PIN_INCORRECT;
5104
0
            goto done;
5105
0
        }
5106
0
        crv = CKR_USER_TYPE_INVALID;
5107
0
        goto done;
5108
0
    }
5109
5110
    /* don't allow the SSO to log in if the user is already initialized */
5111
0
    if (userType != CKU_USER) {
5112
0
        crv = CKR_USER_TYPE_INVALID;
5113
0
        goto done;
5114
0
    }
5115
5116
    /* build the hashed pins which we pass around */
5117
0
    PR_Lock(slot->pwCheckLock);
5118
0
    rv = sftkdb_CheckPassword(handle, pinStr, &tokenRemoved);
5119
0
    if (tokenRemoved) {
5120
0
        sftk_CloseAllSessions(slot, PR_FALSE);
5121
0
    }
5122
0
    if ((rv != SECSuccess) && (sftk_isFIPS(slot->slotID))) {
5123
0
        PR_Sleep(loginWaitTime);
5124
0
    }
5125
0
    PR_Unlock(slot->pwCheckLock);
5126
0
    if (rv == SECSuccess) {
5127
0
        PR_Lock(slot->slotLock);
5128
        /* make sure the login state matches the underlying
5129
         * database state */
5130
0
        slot->isLoggedIn = sftkdb_PWCached(handle) == SECSuccess ? PR_TRUE : PR_FALSE;
5131
0
        PR_Unlock(slot->slotLock);
5132
5133
0
        sftk_freeDB(handle);
5134
0
        handle = NULL;
5135
5136
        /* update all sessions */
5137
0
        sftk_update_all_states(slot);
5138
0
        return CKR_OK;
5139
0
    }
5140
5141
0
    crv = CKR_PIN_INCORRECT;
5142
0
done:
5143
0
    PORT_Memset(pinStr, 0, ulPinLen);
5144
0
    if (handle) {
5145
0
        sftk_freeDB(handle);
5146
0
    }
5147
0
    return crv;
5148
0
}
5149
5150
CK_RV
5151
NSC_LoginUser(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
5152
              CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pUsername,
5153
              CK_ULONG ulUsernameLen)
5154
0
{
5155
    /* softoken currently does not support additional users */
5156
0
    return CKR_OPERATION_NOT_INITIALIZED;
5157
0
}
5158
5159
/* NSC_Logout logs a user out from a token. */
5160
CK_RV
5161
NSC_Logout(CK_SESSION_HANDLE hSession)
5162
0
{
5163
0
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
5164
0
    SFTKSession *session;
5165
0
    SFTKDBHandle *handle;
5166
5167
0
    CHECK_FORK();
5168
5169
0
    if (slot == NULL) {
5170
0
        return CKR_SESSION_HANDLE_INVALID;
5171
0
    }
5172
0
    session = sftk_SessionFromHandle(hSession);
5173
0
    if (session == NULL)
5174
0
        return CKR_SESSION_HANDLE_INVALID;
5175
0
    sftk_FreeSession(session);
5176
0
    session = NULL;
5177
5178
0
    PR_Lock(slot->slotLock);
5179
0
    PRBool isLoggedIn = slot->isLoggedIn;
5180
0
    PR_Unlock(slot->slotLock);
5181
0
    if (!isLoggedIn) {
5182
0
        return CKR_USER_NOT_LOGGED_IN;
5183
0
    }
5184
5185
0
    handle = sftk_getKeyDB(slot);
5186
0
    PR_Lock(slot->slotLock);
5187
0
    slot->isLoggedIn = PR_FALSE;
5188
0
    slot->ssoLoggedIn = PR_FALSE;
5189
0
    if (slot->needLogin && handle) {
5190
0
        sftkdb_ClearPassword(handle);
5191
0
    }
5192
0
    PR_Unlock(slot->slotLock);
5193
0
    if (handle) {
5194
0
        sftk_freeDB(handle);
5195
0
    }
5196
5197
0
    sftk_update_all_states(slot);
5198
0
    return CKR_OK;
5199
0
}
5200
5201
/*
5202
 * Create or remove a new slot on the fly.
5203
 * When creating a slot, "slot" is the slot that the request came from. The
5204
 * resulting slot will live in the same module as "slot".
5205
 * When removing a slot, "slot" is the slot to be removed.
5206
 * "object" is the creation object that specifies the module spec for the slot
5207
 * to add or remove.
5208
 */
5209
static CK_RV
5210
sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class,
5211
                   SFTKObject *object)
5212
0
{
5213
0
    PRBool isValidUserSlot = PR_FALSE;
5214
0
    PRBool isValidFIPSUserSlot = PR_FALSE;
5215
0
    PRBool isValidSlot = PR_FALSE;
5216
0
    PRBool isFIPS = PR_FALSE;
5217
0
    unsigned int moduleIndex = NSC_NON_FIPS_MODULE;
5218
0
    SFTKAttribute *attribute;
5219
0
    sftk_parameters paramStrings;
5220
0
    CK_SLOT_ID slotID = 0;
5221
0
    SFTKSlot *newSlot = NULL;
5222
0
    CK_RV crv = CKR_OK;
5223
5224
0
    if (class != CKO_NSS_DELSLOT && class != CKO_NSS_NEWSLOT) {
5225
0
        return CKR_ATTRIBUTE_VALUE_INVALID;
5226
0
    }
5227
0
    if (class == CKO_NSS_NEWSLOT && slot->slotID == FIPS_SLOT_ID) {
5228
0
        isFIPS = PR_TRUE;
5229
0
    }
5230
0
    attribute = sftk_FindAttribute(object, CKA_NSS_MODULE_SPEC);
5231
0
    if (attribute == NULL) {
5232
0
        return CKR_TEMPLATE_INCOMPLETE;
5233
0
    }
5234
    /* sftk_parseParameters scans attribute->attrib.pValue as a C string;
5235
     * reject if it isn't NUL-terminated within ulValueLen. */
5236
0
    if (attribute->attrib.ulValueLen == 0 ||
5237
0
        memchr(attribute->attrib.pValue, '\0',
5238
0
               attribute->attrib.ulValueLen) == NULL) {
5239
0
        crv = CKR_ATTRIBUTE_VALUE_INVALID;
5240
0
        goto loser;
5241
0
    }
5242
0
    crv = sftk_parseParameters((char *)attribute->attrib.pValue,
5243
0
                               &paramStrings, isFIPS);
5244
0
    if (crv != CKR_OK) {
5245
0
        goto loser;
5246
0
    }
5247
5248
    /* enforce only one at a time */
5249
0
    if (paramStrings.token_count != 1) {
5250
0
        crv = CKR_ATTRIBUTE_VALUE_INVALID;
5251
0
        goto loser;
5252
0
    }
5253
5254
0
    slotID = paramStrings.tokens[0].slotID;
5255
5256
    /* stay within the valid ID space */
5257
0
    isValidUserSlot = (slotID >= SFTK_MIN_USER_SLOT_ID &&
5258
0
                       slotID <= SFTK_MAX_USER_SLOT_ID);
5259
0
    isValidFIPSUserSlot = (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID &&
5260
0
                           slotID <= SFTK_MAX_FIPS_USER_SLOT_ID);
5261
5262
0
    if (class == CKO_NSS_DELSLOT) {
5263
0
        if (slot->slotID == slotID) {
5264
0
            isValidSlot = isValidUserSlot || isValidFIPSUserSlot;
5265
0
        }
5266
0
    } else {
5267
        /* only the crypto or FIPS slots can create new slot objects */
5268
0
        if (slot->slotID == NETSCAPE_SLOT_ID) {
5269
0
            isValidSlot = isValidUserSlot;
5270
0
            moduleIndex = NSC_NON_FIPS_MODULE;
5271
0
        } else if (slot->slotID == FIPS_SLOT_ID) {
5272
0
            isValidSlot = isValidFIPSUserSlot;
5273
0
            moduleIndex = NSC_FIPS_MODULE;
5274
0
        }
5275
0
    }
5276
5277
0
    if (!isValidSlot) {
5278
0
        crv = CKR_ATTRIBUTE_VALUE_INVALID;
5279
0
        goto loser;
5280
0
    }
5281
5282
    /* unload any existing slot at this id */
5283
0
    newSlot = sftk_SlotFromID(slotID, PR_TRUE);
5284
0
    if (newSlot && newSlot->present) {
5285
0
        crv = SFTK_ShutdownSlot(newSlot);
5286
0
        if (crv != CKR_OK) {
5287
0
            goto loser;
5288
0
        }
5289
0
    }
5290
5291
    /* if we were just planning on deleting the slot, then do so now */
5292
0
    if (class == CKO_NSS_DELSLOT) {
5293
        /* sort of a unconventional use of this error code, be we are
5294
         * overusing CKR_ATTRIBUTE_VALUE_INVALID, and it does apply */
5295
0
        crv = newSlot ? CKR_OK : CKR_SLOT_ID_INVALID;
5296
0
        goto loser; /* really exit */
5297
0
    }
5298
5299
0
    if (newSlot) {
5300
0
        crv = SFTK_SlotReInit(newSlot, paramStrings.configdir,
5301
0
                              paramStrings.updatedir, paramStrings.updateID,
5302
0
                              &paramStrings.tokens[0], moduleIndex);
5303
0
    } else {
5304
0
        crv = SFTK_SlotInit(paramStrings.configdir,
5305
0
                            paramStrings.updatedir, paramStrings.updateID,
5306
0
                            &paramStrings.tokens[0], moduleIndex);
5307
0
    }
5308
5309
0
loser:
5310
0
    sftk_freeParams(&paramStrings);
5311
0
    sftk_FreeAttribute(attribute);
5312
5313
0
    return crv;
5314
0
}
5315
5316
/* NSC_CreateObject creates a new object. */
5317
CK_RV
5318
NSC_CreateObject(CK_SESSION_HANDLE hSession,
5319
                 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
5320
                 CK_OBJECT_HANDLE_PTR phObject)
5321
76.8k
{
5322
76.8k
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
5323
76.8k
    SFTKSession *session;
5324
76.8k
    SFTKObject *object;
5325
    /* make sure class isn't randomly CKO_NSS_NEWSLOT or
5326
     * CKO_NETSCPE_DELSLOT. */
5327
76.8k
    CK_OBJECT_CLASS class = CKO_VENDOR_DEFINED;
5328
76.8k
    CK_RV crv;
5329
76.8k
    int i;
5330
5331
76.8k
    CHECK_FORK();
5332
5333
76.8k
    *phObject = CK_INVALID_HANDLE;
5334
5335
76.8k
    if (slot == NULL) {
5336
0
        return CKR_SESSION_HANDLE_INVALID;
5337
0
    }
5338
    /*
5339
     * now lets create an object to hang the attributes off of
5340
     */
5341
76.8k
    object = sftk_NewObject(slot); /* fill in the handle later */
5342
76.8k
    if (object == NULL) {
5343
0
        return CKR_HOST_MEMORY;
5344
0
    }
5345
5346
    /*
5347
     * sftk_NewObject will set object->validation_value to
5348
     * SFTK_VALIDATION_FIPS_FLAG if the slot is FIPS.
5349
     * We don't need to worry about that here, as FC_CreateObject will always
5350
     * disallow the import of secret and private keys, regardless of isFIPS
5351
     * approval status. Therefore, at this point we know that the key is a
5352
     * public key, which is acceptable to be imported in plaintext.
5353
     */
5354
5355
    /*
5356
     * load the template values into the object
5357
     */
5358
525k
    for (i = 0; i < (int)ulCount; i++) {
5359
448k
        crv = sftk_AddAttributeType(object, sftk_attr_expand(&pTemplate[i]));
5360
448k
        if (crv != CKR_OK) {
5361
0
            sftk_FreeObject(object);
5362
0
            return crv;
5363
0
        }
5364
448k
        if ((pTemplate[i].type == CKA_CLASS) && pTemplate[i].pValue) {
5365
76.8k
            class = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
5366
76.8k
        }
5367
448k
    }
5368
5369
    /* get the session */
5370
76.8k
    session = sftk_SessionFromHandle(hSession);
5371
76.8k
    if (session == NULL) {
5372
0
        sftk_FreeObject(object);
5373
0
        return CKR_SESSION_HANDLE_INVALID;
5374
0
    }
5375
5376
    /*
5377
     * handle pseudo objects (CKO_NEWSLOT)
5378
     */
5379
76.8k
    if ((class == CKO_NSS_NEWSLOT) || (class == CKO_NSS_DELSLOT)) {
5380
0
        crv = sftk_CreateNewSlot(slot, class, object);
5381
0
        goto done;
5382
0
    }
5383
5384
    /*
5385
     * handle the base object stuff
5386
     */
5387
76.8k
    crv = sftk_handleObject(object, session);
5388
76.8k
    *phObject = object->handle;
5389
76.8k
done:
5390
76.8k
    sftk_FreeSession(session);
5391
76.8k
    sftk_FreeObject(object);
5392
5393
76.8k
    return crv;
5394
76.8k
}
5395
5396
/* NSC_CopyObject copies an object, creating a new object for the copy. */
5397
CK_RV
5398
NSC_CopyObject(CK_SESSION_HANDLE hSession,
5399
               CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
5400
               CK_OBJECT_HANDLE_PTR phNewObject)
5401
24
{
5402
24
    SFTKObject *destObject, *srcObject;
5403
24
    SFTKSession *session;
5404
24
    CK_RV crv = CKR_OK;
5405
24
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
5406
24
    int i;
5407
5408
24
    CHECK_FORK();
5409
5410
24
    if (slot == NULL) {
5411
0
        return CKR_SESSION_HANDLE_INVALID;
5412
0
    }
5413
    /* Get srcObject so we can find the class */
5414
24
    session = sftk_SessionFromHandle(hSession);
5415
24
    if (session == NULL) {
5416
0
        return CKR_SESSION_HANDLE_INVALID;
5417
0
    }
5418
24
    srcObject = sftk_ObjectFromHandle(hObject, session);
5419
24
    if (srcObject == NULL) {
5420
0
        sftk_FreeSession(session);
5421
0
        return CKR_OBJECT_HANDLE_INVALID;
5422
0
    }
5423
    /*
5424
     * create an object to hang the attributes off of
5425
     */
5426
24
    destObject = sftk_NewObject(slot); /* fill in the handle later */
5427
24
    if (destObject == NULL) {
5428
0
        sftk_FreeSession(session);
5429
0
        sftk_FreeObject(srcObject);
5430
0
        return CKR_HOST_MEMORY;
5431
0
    }
5432
5433
    /*
5434
     * load the template values into the object
5435
     */
5436
40
    for (i = 0; i < (int)ulCount; i++) {
5437
16
        if (sftk_modifyType(pTemplate[i].type, srcObject->objclass) == SFTK_NEVER) {
5438
0
            crv = CKR_ATTRIBUTE_READ_ONLY;
5439
0
            break;
5440
0
        }
5441
16
        crv = sftk_AddAttributeType(destObject, sftk_attr_expand(&pTemplate[i]));
5442
16
        if (crv != CKR_OK) {
5443
0
            break;
5444
0
        }
5445
16
    }
5446
24
    if (crv != CKR_OK) {
5447
0
        sftk_FreeSession(session);
5448
0
        sftk_FreeObject(srcObject);
5449
0
        sftk_FreeObject(destObject);
5450
0
        return crv;
5451
0
    }
5452
5453
    /* sensitive can only be changed to CK_TRUE */
5454
24
    if (sftk_hasAttribute(destObject, CKA_SENSITIVE)) {
5455
0
        if (!sftk_isTrue(destObject, CKA_SENSITIVE)) {
5456
0
            sftk_FreeSession(session);
5457
0
            sftk_FreeObject(srcObject);
5458
0
            sftk_FreeObject(destObject);
5459
0
            return CKR_ATTRIBUTE_READ_ONLY;
5460
0
        }
5461
0
    }
5462
5463
    /*
5464
     * now copy the old attributes from the new attributes
5465
     */
5466
    /* don't create a token object if we aren't in a rw session */
5467
    /* we need to hold the lock to copy a consistant version of
5468
     * the object. */
5469
24
    crv = sftk_CopyObject(destObject, srcObject);
5470
5471
24
    destObject->objclass = srcObject->objclass;
5472
24
    sftk_FreeObject(srcObject);
5473
24
    if (crv != CKR_OK) {
5474
0
        sftk_FreeObject(destObject);
5475
0
        sftk_FreeSession(session);
5476
0
        return crv;
5477
0
    }
5478
5479
24
    crv = sftk_handleObject(destObject, session);
5480
24
    *phNewObject = destObject->handle;
5481
24
    sftk_FreeSession(session);
5482
24
    sftk_FreeObject(destObject);
5483
5484
24
    return crv;
5485
24
}
5486
5487
/* NSC_GetObjectSize gets the size of an object in bytes. */
5488
CK_RV
5489
NSC_GetObjectSize(CK_SESSION_HANDLE hSession,
5490
                  CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize)
5491
0
{
5492
0
    CHECK_FORK();
5493
5494
0
    *pulSize = 0;
5495
0
    return CKR_OK;
5496
0
}
5497
5498
static CK_RV
5499
nsc_GetTokenAttributeValue(SFTKSession *session, CK_OBJECT_HANDLE hObject,
5500
                           CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
5501
0
{
5502
0
    SFTKSlot *slot = sftk_SlotFromSession(session);
5503
0
    SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, hObject);
5504
0
    SFTKDBHandle *keydb = NULL;
5505
0
    CK_RV crv;
5506
5507
0
    if (dbHandle == NULL) {
5508
0
        return CKR_OBJECT_HANDLE_INVALID;
5509
0
    }
5510
5511
0
    crv = sftkdb_GetAttributeValue(dbHandle, hObject, pTemplate, ulCount);
5512
5513
    /* make sure we don't export any sensitive information */
5514
0
    keydb = sftk_getKeyDB(slot);
5515
0
    if (dbHandle == keydb) {
5516
0
        CK_ULONG i;
5517
0
        for (i = 0; i < ulCount; i++) {
5518
0
            if (sftk_isSensitive(pTemplate[i].type, CKO_PRIVATE_KEY)) {
5519
0
                crv = CKR_ATTRIBUTE_SENSITIVE;
5520
0
                if (pTemplate[i].pValue && (pTemplate[i].ulValueLen != -1)) {
5521
0
                    PORT_Memset(pTemplate[i].pValue, 0,
5522
0
                                pTemplate[i].ulValueLen);
5523
0
                }
5524
0
                pTemplate[i].ulValueLen = -1;
5525
0
            }
5526
0
        }
5527
0
    }
5528
5529
0
    sftk_freeDB(dbHandle);
5530
0
    if (keydb) {
5531
0
        sftk_freeDB(keydb);
5532
0
    }
5533
0
    return crv;
5534
0
}
5535
5536
PRBool
5537
sftk_template_hasAttribute(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *pTemplate,
5538
                           CK_ULONG ulCount)
5539
0
{
5540
0
    for (int i = 0; i < ulCount; i++) {
5541
0
        if (pTemplate[i].type == type) {
5542
0
            return PR_TRUE;
5543
0
        }
5544
0
    }
5545
0
    return PR_FALSE;
5546
0
}
5547
5548
/* NSC_GetAttributeValue obtains the value of one or more object attributes. */
5549
CK_RV
5550
NSC_GetAttributeValue(CK_SESSION_HANDLE hSession,
5551
                      CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
5552
1.29M
{
5553
1.29M
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
5554
1.29M
    SFTKSession *session;
5555
1.29M
    SFTKObject *object;
5556
1.29M
    SFTKAttribute *attribute;
5557
1.29M
    PRBool sensitive, isLoggedIn, needLogin;
5558
1.29M
    CK_RV crv;
5559
1.29M
    int i;
5560
5561
1.29M
    CHECK_FORK();
5562
5563
1.29M
    if (slot == NULL) {
5564
0
        return CKR_SESSION_HANDLE_INVALID;
5565
0
    }
5566
    /*
5567
     * make sure we're allowed
5568
     */
5569
1.29M
    session = sftk_SessionFromHandle(hSession);
5570
1.29M
    if (session == NULL) {
5571
0
        return CKR_SESSION_HANDLE_INVALID;
5572
0
    }
5573
5574
    /* short circuit everything for token objects */
5575
1.29M
    if (sftk_isToken(hObject) &&
5576
        /* we we have a CKA_OBJECT_VALIDATION_FLAG, don't do the
5577
         * short circuit. the SDB code doesn't know how to process
5578
         * this attribute */
5579
0
        !sftk_template_hasAttribute(CKA_OBJECT_VALIDATION_FLAGS, pTemplate,
5580
0
                                    ulCount)) {
5581
0
        crv = nsc_GetTokenAttributeValue(session, hObject, pTemplate, ulCount);
5582
0
        sftk_FreeSession(session);
5583
0
        return crv;
5584
0
    }
5585
5586
    /* handle the session object */
5587
1.29M
    object = sftk_ObjectFromHandle(hObject, session);
5588
1.29M
    sftk_FreeSession(session);
5589
1.29M
    if (object == NULL) {
5590
0
        return CKR_OBJECT_HANDLE_INVALID;
5591
0
    }
5592
5593
1.29M
    PR_Lock(slot->slotLock);
5594
1.29M
    isLoggedIn = slot->isLoggedIn;
5595
1.29M
    needLogin = slot->needLogin;
5596
1.29M
    PR_Unlock(slot->slotLock);
5597
5598
    /* don't read a private object if we aren't logged in */
5599
1.29M
    if (!isLoggedIn && needLogin && sftk_isTrue(object, CKA_PRIVATE)) {
5600
0
        sftk_FreeObject(object);
5601
0
        return CKR_USER_NOT_LOGGED_IN;
5602
0
    }
5603
5604
1.29M
    crv = CKR_OK;
5605
1.29M
    sensitive = sftk_isTrue(object, CKA_SENSITIVE);
5606
3.16M
    for (i = 0; i < (int)ulCount; i++) {
5607
        /* Make sure that this attribute is retrievable */
5608
1.87M
        if (sensitive && sftk_isSensitive(pTemplate[i].type, object->objclass)) {
5609
0
            crv = CKR_ATTRIBUTE_SENSITIVE;
5610
0
            pTemplate[i].ulValueLen = -1;
5611
0
            continue;
5612
0
        }
5613
1.87M
        attribute = sftk_FindAttribute(object, pTemplate[i].type);
5614
1.87M
        if (attribute == NULL) {
5615
16
            crv = CKR_ATTRIBUTE_TYPE_INVALID;
5616
16
            pTemplate[i].ulValueLen = -1;
5617
16
            continue;
5618
16
        }
5619
1.87M
        if (pTemplate[i].pValue != NULL) {
5620
1.34M
            PORT_Memcpy(pTemplate[i].pValue, attribute->attrib.pValue,
5621
1.34M
                        attribute->attrib.ulValueLen);
5622
1.34M
        }
5623
1.87M
        pTemplate[i].ulValueLen = attribute->attrib.ulValueLen;
5624
1.87M
        sftk_FreeAttribute(attribute);
5625
1.87M
    }
5626
5627
1.29M
    sftk_FreeObject(object);
5628
1.29M
    return crv;
5629
1.29M
}
5630
5631
/* NSC_SetAttributeValue modifies the value of one or more object attributes */
5632
CK_RV
5633
NSC_SetAttributeValue(CK_SESSION_HANDLE hSession,
5634
                      CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
5635
95.2k
{
5636
95.2k
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
5637
95.2k
    SFTKSession *session;
5638
95.2k
    SFTKAttribute *attribute;
5639
95.2k
    SFTKObject *object;
5640
95.2k
    PRBool isToken, isLoggedIn, needLogin;
5641
95.2k
    CK_RV crv = CKR_OK;
5642
95.2k
    CK_BBOOL legal;
5643
95.2k
    int i;
5644
5645
95.2k
    CHECK_FORK();
5646
5647
95.2k
    if (slot == NULL) {
5648
0
        return CKR_SESSION_HANDLE_INVALID;
5649
0
    }
5650
    /*
5651
     * make sure we're allowed
5652
     */
5653
95.2k
    session = sftk_SessionFromHandle(hSession);
5654
95.2k
    if (session == NULL) {
5655
0
        return CKR_SESSION_HANDLE_INVALID;
5656
0
    }
5657
5658
95.2k
    object = sftk_ObjectFromHandle(hObject, session);
5659
95.2k
    if (object == NULL) {
5660
0
        sftk_FreeSession(session);
5661
0
        return CKR_OBJECT_HANDLE_INVALID;
5662
0
    }
5663
5664
95.2k
    PR_Lock(slot->slotLock);
5665
95.2k
    isLoggedIn = slot->isLoggedIn;
5666
95.2k
    needLogin = slot->needLogin;
5667
95.2k
    PR_Unlock(slot->slotLock);
5668
5669
    /* don't modify a private object if we aren't logged in */
5670
95.2k
    if (!isLoggedIn && needLogin && sftk_isTrue(object, CKA_PRIVATE)) {
5671
0
        sftk_FreeSession(session);
5672
0
        sftk_FreeObject(object);
5673
0
        return CKR_USER_NOT_LOGGED_IN;
5674
0
    }
5675
5676
    /* don't modify a token object if we aren't in a rw session */
5677
95.2k
    isToken = sftk_isTrue(object, CKA_TOKEN);
5678
95.2k
    if (((session->info.flags & CKF_RW_SESSION) == 0) && isToken) {
5679
0
        sftk_FreeSession(session);
5680
0
        sftk_FreeObject(object);
5681
0
        return CKR_SESSION_READ_ONLY;
5682
0
    }
5683
95.2k
    sftk_FreeSession(session);
5684
5685
    /* only change modifiable objects */
5686
95.2k
    if (!sftk_isTrue(object, CKA_MODIFIABLE)) {
5687
0
        sftk_FreeObject(object);
5688
0
        return CKR_ATTRIBUTE_READ_ONLY;
5689
0
    }
5690
5691
190k
    for (i = 0; i < (int)ulCount; i++) {
5692
        /* Make sure that this attribute is changeable */
5693
95.2k
        switch (sftk_modifyType(pTemplate[i].type, object->objclass)) {
5694
0
            case SFTK_NEVER:
5695
0
            case SFTK_ONCOPY:
5696
0
            default:
5697
0
                crv = CKR_ATTRIBUTE_READ_ONLY;
5698
0
                break;
5699
5700
0
            case SFTK_SENSITIVE:
5701
0
                legal = (pTemplate[i].type == CKA_EXTRACTABLE) ? CK_FALSE : CK_TRUE;
5702
0
                if ((*(CK_BBOOL *)pTemplate[i].pValue) != legal) {
5703
0
                    crv = CKR_ATTRIBUTE_READ_ONLY;
5704
0
                }
5705
0
                break;
5706
95.2k
            case SFTK_ALWAYS:
5707
95.2k
                break;
5708
95.2k
        }
5709
95.2k
        if (crv != CKR_OK)
5710
0
            break;
5711
5712
        /* find the old attribute */
5713
95.2k
        attribute = sftk_FindAttribute(object, pTemplate[i].type);
5714
95.2k
        if (attribute == NULL) {
5715
0
            crv = CKR_ATTRIBUTE_TYPE_INVALID;
5716
0
            break;
5717
0
        }
5718
95.2k
        sftk_FreeAttribute(attribute);
5719
95.2k
        crv = sftk_forceAttribute(object, sftk_attr_expand(&pTemplate[i]));
5720
95.2k
        if (crv != CKR_OK)
5721
0
            break;
5722
95.2k
    }
5723
5724
95.2k
    sftk_FreeObject(object);
5725
95.2k
    return crv;
5726
95.2k
}
5727
5728
static CK_RV
5729
sftk_expandSearchList(SFTKSearchResults *search, int count)
5730
0
{
5731
0
    search->array_size += count;
5732
0
    search->handles = (CK_OBJECT_HANDLE *)PORT_Realloc(search->handles,
5733
0
                                                       sizeof(CK_OBJECT_HANDLE) * search->array_size);
5734
0
    return search->handles ? CKR_OK : CKR_HOST_MEMORY;
5735
0
}
5736
5737
static CK_RV
5738
sftk_searchDatabase(SFTKDBHandle *handle, SFTKSearchResults *search,
5739
                    const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
5740
1.36M
{
5741
1.36M
    CK_RV crv;
5742
1.36M
    int objectListSize = search->array_size - search->size;
5743
1.36M
    CK_OBJECT_HANDLE *array = &search->handles[search->size];
5744
1.36M
    SDBFind *find = NULL;
5745
1.36M
    CK_ULONG count;
5746
5747
1.36M
    crv = sftkdb_FindObjectsInit(handle, pTemplate, ulCount, &find);
5748
1.36M
    if (crv != CKR_OK)
5749
0
        return crv;
5750
1.36M
    do {
5751
1.36M
        crv = sftkdb_FindObjects(handle, find, array, objectListSize, &count);
5752
1.36M
        if ((crv != CKR_OK) || (count == 0))
5753
1.36M
            break;
5754
0
        search->size += count;
5755
0
        objectListSize -= count;
5756
0
        if (objectListSize > 0)
5757
0
            break;
5758
0
        crv = sftk_expandSearchList(search, NSC_SEARCH_BLOCK_SIZE);
5759
0
        objectListSize = NSC_SEARCH_BLOCK_SIZE;
5760
0
        array = &search->handles[search->size];
5761
0
    } while (crv == CKR_OK);
5762
1.36M
    sftkdb_FindObjectsFinal(handle, find);
5763
5764
1.36M
    return crv;
5765
1.36M
}
5766
5767
/* softoken used to search the SMimeEntries automatically instead of
5768
 * doing this in pk11wrap. This code should really be up in
5769
 * pk11wrap so that it will work with other tokens other than softoken.
5770
 */
5771
CK_RV
5772
sftk_emailhack(SFTKSlot *slot, SFTKDBHandle *handle,
5773
               SFTKSearchResults *search, CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
5774
1.36M
{
5775
1.36M
    PRBool isCert = PR_FALSE;
5776
1.36M
    int emailIndex = -1;
5777
1.36M
    unsigned int i;
5778
1.36M
    SFTKSearchResults smime_search;
5779
1.36M
    CK_ATTRIBUTE smime_template[2];
5780
1.36M
    CK_OBJECT_CLASS smime_class = CKO_NSS_SMIME;
5781
1.36M
    SFTKAttribute *attribute = NULL;
5782
1.36M
    SFTKObject *object = NULL;
5783
1.36M
    CK_RV crv = CKR_OK;
5784
5785
1.36M
    smime_search.handles = NULL; /* paranoia, some one is bound to add a goto
5786
                                  * loser before this gets initialized */
5787
5788
    /* see if we are looking for email certs */
5789
3.91M
    for (i = 0; i < ulCount; i++) {
5790
3.51M
        if (pTemplate[i].type == CKA_CLASS) {
5791
1.36M
            if ((pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS) ||
5792
1.36M
                 (*(CK_OBJECT_CLASS *)pTemplate[i].pValue) != CKO_CERTIFICATE)) {
5793
                /* not a cert, skip out */
5794
958k
                break;
5795
958k
            }
5796
405k
            isCert = PR_TRUE;
5797
2.14M
        } else if (pTemplate[i].type == CKA_NSS_EMAIL) {
5798
0
            emailIndex = i;
5799
0
        }
5800
2.55M
        if (isCert && (emailIndex != -1))
5801
0
            break;
5802
2.55M
    }
5803
5804
1.36M
    if (!isCert || (emailIndex == -1)) {
5805
1.36M
        return CKR_OK;
5806
1.36M
    }
5807
5808
    /* we are doing a cert and email search, find the SMimeEntry */
5809
0
    smime_template[0].type = CKA_CLASS;
5810
0
    smime_template[0].pValue = &smime_class;
5811
0
    smime_template[0].ulValueLen = sizeof(smime_class);
5812
0
    smime_template[1] = pTemplate[emailIndex];
5813
5814
0
    smime_search.handles = (CK_OBJECT_HANDLE *)
5815
0
        PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * NSC_SEARCH_BLOCK_SIZE);
5816
0
    if (smime_search.handles == NULL) {
5817
0
        crv = CKR_HOST_MEMORY;
5818
0
        goto loser;
5819
0
    }
5820
0
    smime_search.index = 0;
5821
0
    smime_search.size = 0;
5822
0
    smime_search.array_size = NSC_SEARCH_BLOCK_SIZE;
5823
5824
0
    crv = sftk_searchDatabase(handle, &smime_search, smime_template, 2);
5825
0
    if (crv != CKR_OK || smime_search.size == 0) {
5826
0
        goto loser;
5827
0
    }
5828
5829
    /* get the SMime subject */
5830
0
    object = sftk_NewTokenObject(slot, NULL, smime_search.handles[0]);
5831
0
    if (object == NULL) {
5832
0
        crv = CKR_HOST_MEMORY; /* is there any other reason for this failure? */
5833
0
        goto loser;
5834
0
    }
5835
0
    attribute = sftk_FindAttribute(object, CKA_SUBJECT);
5836
0
    if (attribute == NULL) {
5837
0
        crv = CKR_ATTRIBUTE_TYPE_INVALID;
5838
0
        goto loser;
5839
0
    }
5840
5841
    /* now find the certs with that subject */
5842
0
    pTemplate[emailIndex] = attribute->attrib;
5843
    /* now add the appropriate certs to the search list */
5844
0
    crv = sftk_searchDatabase(handle, search, pTemplate, ulCount);
5845
0
    pTemplate[emailIndex] = smime_template[1]; /* restore the user's template*/
5846
5847
0
loser:
5848
0
    if (attribute) {
5849
0
        sftk_FreeAttribute(attribute);
5850
0
    }
5851
0
    if (object) {
5852
0
        sftk_FreeObject(object);
5853
0
    }
5854
0
    if (smime_search.handles) {
5855
0
        PORT_Free(smime_search.handles);
5856
0
    }
5857
5858
0
    return crv;
5859
0
}
5860
5861
static void
5862
sftk_pruneSearch(CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount,
5863
                 PRBool *searchCertDB, PRBool *searchKeyDB)
5864
1.36M
{
5865
1.36M
    CK_ULONG i;
5866
5867
1.36M
    *searchCertDB = PR_TRUE;
5868
1.36M
    *searchKeyDB = PR_TRUE;
5869
2.72M
    for (i = 0; i < ulCount; i++) {
5870
2.72M
        if (pTemplate[i].type == CKA_CLASS && pTemplate[i].pValue != NULL) {
5871
1.36M
            CK_OBJECT_CLASS class = *((CK_OBJECT_CLASS *)pTemplate[i].pValue);
5872
1.36M
            if (class == CKO_PRIVATE_KEY || class == CKO_SECRET_KEY) {
5873
0
                *searchCertDB = PR_FALSE;
5874
1.36M
            } else {
5875
1.36M
                *searchKeyDB = PR_FALSE;
5876
1.36M
            }
5877
1.36M
            break;
5878
1.36M
        }
5879
2.72M
    }
5880
1.36M
}
5881
5882
static CK_RV
5883
sftk_searchTokenList(SFTKSlot *slot, SFTKSearchResults *search,
5884
                     CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount,
5885
                     PRBool isLoggedIn)
5886
1.36M
{
5887
1.36M
    CK_RV crv = CKR_OK;
5888
1.36M
    CK_RV crv2;
5889
1.36M
    PRBool searchCertDB;
5890
1.36M
    PRBool searchKeyDB;
5891
5892
1.36M
    sftk_pruneSearch(pTemplate, ulCount, &searchCertDB, &searchKeyDB);
5893
5894
1.36M
    if (searchCertDB) {
5895
1.36M
        SFTKDBHandle *certHandle = sftk_getCertDB(slot);
5896
1.36M
        crv = sftk_searchDatabase(certHandle, search, pTemplate, ulCount);
5897
1.36M
        crv2 = sftk_emailhack(slot, certHandle, search, pTemplate, ulCount);
5898
1.36M
        if (crv == CKR_OK)
5899
1.36M
            crv = crv2;
5900
1.36M
        sftk_freeDB(certHandle);
5901
1.36M
    }
5902
5903
1.36M
    if (crv == CKR_OK && isLoggedIn && searchKeyDB) {
5904
0
        SFTKDBHandle *keyHandle = sftk_getKeyDB(slot);
5905
0
        crv = sftk_searchDatabase(keyHandle, search, pTemplate, ulCount);
5906
0
        sftk_freeDB(keyHandle);
5907
0
    }
5908
1.36M
    return crv;
5909
1.36M
}
5910
5911
/* Atomically install a search, returning whatever was previously installed
5912
 * (which the caller must free). Without the lock, two concurrent
5913
 * FindObjectsInit calls each read NULL, then one's later assignment
5914
 * overwrites the other's, leaking the loser. The lock also protects the
5915
 * "take" side, so a concurrent FindObjects/FindObjectsFinal can't observe
5916
 * a torn replacement. */
5917
static SFTKSearchResults *
5918
sftk_SwapSearch(SFTKSession *session, SFTKSearchResults *new_search)
5919
4.09M
{
5920
4.09M
    SFTKSlot *slot = sftk_SlotFromSession(session);
5921
4.09M
    PRLock *lock = SFTK_SESSION_LOCK(slot, session->handle);
5922
4.09M
    SFTKSearchResults *prev;
5923
4.09M
    PR_Lock(lock);
5924
4.09M
    prev = session->search;
5925
4.09M
    session->search = new_search;
5926
4.09M
    PR_Unlock(lock);
5927
4.09M
    return prev;
5928
4.09M
}
5929
5930
/* Try to reinstall a search after a partial consume. If a concurrent
5931
 * FindObjectsInit replaced the search while we worked, our search is
5932
 * stale; signal the caller to free it. */
5933
static PRBool
5934
sftk_RestoreSearch(SFTKSession *session, SFTKSearchResults *search)
5935
0
{
5936
0
    SFTKSlot *slot = sftk_SlotFromSession(session);
5937
0
    PRLock *lock = SFTK_SESSION_LOCK(slot, session->handle);
5938
0
    PRBool restored;
5939
0
    PR_Lock(lock);
5940
0
    if (session->search == NULL) {
5941
0
        session->search = search;
5942
0
        restored = PR_TRUE;
5943
0
    } else {
5944
0
        restored = PR_FALSE;
5945
0
    }
5946
0
    PR_Unlock(lock);
5947
0
    return restored;
5948
0
}
5949
5950
/* NSC_FindObjectsInit initializes a search for token and session objects
5951
 * that match a template. */
5952
CK_RV
5953
NSC_FindObjectsInit(CK_SESSION_HANDLE hSession,
5954
                    CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
5955
1.36M
{
5956
1.36M
    SFTKSearchResults *search = NULL, *freeSearch = NULL;
5957
1.36M
    SFTKSession *session = NULL;
5958
1.36M
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
5959
1.36M
    CK_RV crv = CKR_OK;
5960
1.36M
    PRBool isLoggedIn;
5961
5962
1.36M
    CHECK_FORK();
5963
5964
1.36M
    if (slot == NULL) {
5965
0
        return CKR_SESSION_HANDLE_INVALID;
5966
0
    }
5967
1.36M
    session = sftk_SessionFromHandle(hSession);
5968
1.36M
    if (session == NULL) {
5969
0
        crv = CKR_SESSION_HANDLE_INVALID;
5970
0
        goto loser;
5971
0
    }
5972
5973
1.36M
    search = (SFTKSearchResults *)PORT_Alloc(sizeof(SFTKSearchResults));
5974
1.36M
    if (search == NULL) {
5975
0
        crv = CKR_HOST_MEMORY;
5976
0
        goto loser;
5977
0
    }
5978
1.36M
    search->handles = (CK_OBJECT_HANDLE *)
5979
1.36M
        PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * NSC_SEARCH_BLOCK_SIZE);
5980
1.36M
    if (search->handles == NULL) {
5981
0
        crv = CKR_HOST_MEMORY;
5982
0
        goto loser;
5983
0
    }
5984
1.36M
    search->index = 0;
5985
1.36M
    search->size = 0;
5986
1.36M
    search->array_size = NSC_SEARCH_BLOCK_SIZE;
5987
5988
1.36M
    PR_Lock(slot->slotLock);
5989
1.36M
    isLoggedIn = (PRBool)((!slot->needLogin) || slot->isLoggedIn);
5990
1.36M
    PR_Unlock(slot->slotLock);
5991
5992
1.36M
    PRBool validTokenAttribute = PR_FALSE;
5993
1.36M
    PRBool tokenAttributeValue = PR_FALSE;
5994
1.36M
    for (CK_ULONG i = 0; i < ulCount; i++) {
5995
1.36M
        CK_ATTRIBUTE_PTR attr = &pTemplate[i];
5996
1.36M
        if (attr->type == CKA_TOKEN && attr->pValue && attr->ulValueLen == sizeof(CK_BBOOL)) {
5997
1.36M
            if (*(CK_BBOOL *)attr->pValue == CK_TRUE) {
5998
1.36M
                validTokenAttribute = PR_TRUE;
5999
1.36M
                tokenAttributeValue = PR_TRUE;
6000
1.36M
            } else if (*(CK_BBOOL *)attr->pValue == CK_FALSE) {
6001
0
                validTokenAttribute = PR_TRUE;
6002
0
                tokenAttributeValue = PR_FALSE;
6003
0
            }
6004
1.36M
            break;
6005
1.36M
        }
6006
1.36M
    }
6007
6008
    // Search over the token object list if the template's CKA_TOKEN attribute is set to
6009
    // CK_TRUE or if it is not set.
6010
1.36M
    if (validTokenAttribute == PR_FALSE || tokenAttributeValue == PR_TRUE) {
6011
1.36M
        crv = sftk_searchTokenList(slot, search, pTemplate, ulCount, isLoggedIn);
6012
1.36M
        if (crv != CKR_OK) {
6013
0
            goto loser;
6014
0
        }
6015
1.36M
    }
6016
6017
    // Search over the session object list if the template's CKA_TOKEN attribute is set to
6018
    // CK_FALSE or if it is not set.
6019
1.36M
    if (validTokenAttribute == PR_FALSE || tokenAttributeValue == PR_FALSE) {
6020
122
        crv = sftk_searchObjectList(search, slot->sessObjHashTable,
6021
122
                                    slot->sessObjHashSize, slot->objectLock,
6022
122
                                    pTemplate, ulCount, isLoggedIn);
6023
122
        if (crv != CKR_OK) {
6024
0
            goto loser;
6025
0
        }
6026
122
    }
6027
6028
1.36M
    freeSearch = sftk_SwapSearch(session, search);
6029
1.36M
    if (freeSearch != NULL) {
6030
0
        sftk_FreeSearch(freeSearch);
6031
0
    }
6032
1.36M
    sftk_FreeSession(session);
6033
1.36M
    return CKR_OK;
6034
6035
0
loser:
6036
0
    if (search) {
6037
0
        sftk_FreeSearch(search);
6038
0
    }
6039
0
    if (session) {
6040
0
        sftk_FreeSession(session);
6041
0
    }
6042
0
    return crv;
6043
1.36M
}
6044
6045
/* NSC_FindObjects continues a search for token and session objects
6046
 * that match a template, obtaining additional object handles. */
6047
CK_RV
6048
NSC_FindObjects(CK_SESSION_HANDLE hSession,
6049
                CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount,
6050
                CK_ULONG_PTR pulObjectCount)
6051
1.36M
{
6052
1.36M
    SFTKSession *session;
6053
1.36M
    SFTKSearchResults *search;
6054
1.36M
    int transfer;
6055
1.36M
    int left;
6056
6057
1.36M
    CHECK_FORK();
6058
6059
1.36M
    *pulObjectCount = 0;
6060
1.36M
    session = sftk_SessionFromHandle(hSession);
6061
1.36M
    if (session == NULL)
6062
0
        return CKR_SESSION_HANDLE_INVALID;
6063
    /* Take ownership of the search for the duration of the iteration so
6064
     * a concurrent FindObjectsInit/FindObjectsFinal can't free it under
6065
     * us. If another thread takes it first, we behave as if the search
6066
     * had been exhausted: zero results, no error. */
6067
1.36M
    search = sftk_SwapSearch(session, NULL);
6068
1.36M
    if (search == NULL) {
6069
0
        sftk_FreeSession(session);
6070
0
        return CKR_OK;
6071
0
    }
6072
1.36M
    left = search->size - search->index;
6073
1.36M
    transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount;
6074
1.36M
    if (transfer > 0) {
6075
0
        PORT_Memcpy(phObject, &search->handles[search->index],
6076
0
                    transfer * sizeof(CK_OBJECT_HANDLE));
6077
1.36M
    } else {
6078
1.36M
        *phObject = CK_INVALID_HANDLE;
6079
1.36M
    }
6080
6081
1.36M
    search->index += transfer;
6082
1.36M
    if (search->index == search->size) {
6083
        /* fully consumed */
6084
1.36M
        sftk_FreeSearch(search);
6085
1.36M
    } else if (!sftk_RestoreSearch(session, search)) {
6086
        /* A concurrent FindObjectsInit installed a newer search while
6087
         * we were iterating; ours is now stale, drop it. */
6088
0
        sftk_FreeSearch(search);
6089
0
    }
6090
1.36M
    *pulObjectCount = transfer;
6091
1.36M
    sftk_FreeSession(session);
6092
1.36M
    return CKR_OK;
6093
1.36M
}
6094
6095
/* NSC_FindObjectsFinal finishes a search for token and session objects. */
6096
CK_RV
6097
NSC_FindObjectsFinal(CK_SESSION_HANDLE hSession)
6098
1.36M
{
6099
1.36M
    SFTKSession *session;
6100
1.36M
    SFTKSearchResults *search;
6101
6102
1.36M
    CHECK_FORK();
6103
6104
1.36M
    session = sftk_SessionFromHandle(hSession);
6105
1.36M
    if (session == NULL)
6106
0
        return CKR_SESSION_HANDLE_INVALID;
6107
1.36M
    search = sftk_SwapSearch(session, NULL);
6108
1.36M
    sftk_FreeSession(session);
6109
1.36M
    if (search != NULL) {
6110
0
        sftk_FreeSearch(search);
6111
0
    }
6112
1.36M
    return CKR_OK;
6113
1.36M
}
6114
6115
CK_RV
6116
NSC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot,
6117
                     CK_VOID_PTR pReserved)
6118
0
{
6119
0
    CHECK_FORK();
6120
6121
0
    return CKR_FUNCTION_NOT_SUPPORTED;
6122
0
}
6123
6124
CK_RV
6125
NSC_AsyncComplete(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pFunctionName,
6126
                  CK_ASYNC_DATA_PTR pResult)
6127
0
{
6128
0
    CHECK_FORK();
6129
6130
0
    return CKR_FUNCTION_NOT_SUPPORTED;
6131
0
}
6132
6133
CK_RV
6134
NSC_AsyncGetID(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pFunctionName,
6135
               CK_ULONG_PTR pulID)
6136
0
{
6137
0
    CHECK_FORK();
6138
6139
0
    return CKR_FUNCTION_NOT_SUPPORTED;
6140
0
}
6141
6142
CK_RV
6143
NSC_AsyncJoin(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pFunctionName,
6144
              CK_ULONG ulID, CK_BYTE_PTR pData, CK_ULONG ulData)
6145
0
{
6146
0
    CHECK_FORK();
6147
6148
0
    return CKR_FUNCTION_NOT_SUPPORTED;
6149
0
}
6150
6151
static CK_RV
6152
nsc_NSSGetFIPSStatus(CK_SESSION_HANDLE hSession,
6153
                     CK_OBJECT_HANDLE hObject,
6154
                     CK_ULONG ulOperationType,
6155
                     CK_ULONG *pulFIPSStatus)
6156
0
{
6157
0
    CK_ULONG sessionState = CKS_NSS_UNINITIALIZED;
6158
0
    CK_ULONG objectState = CKS_NSS_UNINITIALIZED;
6159
0
    PRBool needSession = PR_FALSE;
6160
0
    PRBool needObject = PR_FALSE;
6161
0
    SFTKSession *session;
6162
0
    SFTKObject *object;
6163
6164
0
    *pulFIPSStatus = CKS_NSS_FIPS_NOT_OK;
6165
6166
    /* first determine what we need to look up */
6167
0
    switch (ulOperationType) {
6168
0
        case CKT_NSS_SESSION_CHECK:
6169
0
        case CKT_NSS_SESSION_LAST_CHECK:
6170
0
            needSession = PR_TRUE;
6171
0
            needObject = PR_FALSE;
6172
0
            break;
6173
0
        case CKT_NSS_OBJECT_CHECK:
6174
0
            needSession = PR_FALSE;
6175
0
            needObject = PR_TRUE;
6176
0
            break;
6177
0
        case CKT_NSS_BOTH_CHECK:
6178
0
            needSession = PR_TRUE;
6179
0
            needObject = PR_TRUE;
6180
0
            break;
6181
0
        default:
6182
0
            return CKR_ARGUMENTS_BAD;
6183
0
    }
6184
6185
    /* we always need the session handle, the object handle is only
6186
     * meaningful if there is a session */
6187
0
    session = sftk_SessionFromHandle(hSession);
6188
0
    if (!session) {
6189
0
        return CKR_SESSION_HANDLE_INVALID;
6190
0
    }
6191
0
    if (needSession) {
6192
0
        if (CKT_NSS_SESSION_LAST_CHECK == ulOperationType) {
6193
0
            sessionState = session->lastOpWasFIPS ? CKS_NSS_FIPS_OK : CKS_NSS_FIPS_NOT_OK;
6194
0
        } else {
6195
0
            if (session->enc_context) {
6196
0
                sessionState = session->enc_context->isFIPS ? CKS_NSS_FIPS_OK : CKS_NSS_FIPS_NOT_OK;
6197
0
            }
6198
0
            if (sessionState != CKS_NSS_FIPS_NOT_OK && session->hash_context) {
6199
0
                sessionState = session->hash_context->isFIPS ? CKS_NSS_FIPS_OK : CKS_NSS_FIPS_NOT_OK;
6200
0
            }
6201
            /* sessionState is set to CKS_NSS_UNINITIALIZED if neither
6202
             * context exists */
6203
0
        }
6204
0
    }
6205
6206
0
    if (needObject) {
6207
0
        object = sftk_ObjectFromHandle(hObject, session);
6208
0
        if (!object) {
6209
0
            sftk_FreeSession(session);
6210
0
            return CKR_OBJECT_HANDLE_INVALID;
6211
0
        }
6212
0
        objectState = sftk_hasFIPS(object) ? CKS_NSS_FIPS_OK : CKS_NSS_FIPS_NOT_OK;
6213
0
        sftk_FreeObject(object);
6214
0
    }
6215
6216
0
    sftk_FreeSession(session);
6217
6218
    /* If we didn't fetch the state, then it is uninitialized.
6219
     * The session state can also be uninitialized if there are no active
6220
     * crypto operations on the session. Turns out the rules for combining
6221
     * the states are the same whether or not the state was uninitialzed
6222
     * because we didn't fetch it or because there wasn't a state to fetch.
6223
     */
6224
6225
    /* if the object State is uninitialized, return the state of the session. */
6226
0
    if (objectState == CKS_NSS_UNINITIALIZED) {
6227
        /* if they are both uninitalized, return CKS_FIPS_NOT_OK */
6228
0
        if (sessionState == CKS_NSS_UNINITIALIZED) {
6229
            /* *pulFIPSStatus already set to CKS_FIPS_NOT_OK */
6230
0
            return CKR_OK;
6231
0
        }
6232
0
        *pulFIPSStatus = sessionState;
6233
0
        return CKR_OK;
6234
0
    }
6235
    /* objectState is initialized, if sessionState is uninitialized, we can
6236
     * just return objectState */
6237
0
    if (sessionState == CKS_NSS_UNINITIALIZED) {
6238
0
        *pulFIPSStatus = objectState;
6239
0
        return CKR_OK;
6240
0
    }
6241
6242
    /* they are are not equal, one must be CKS_FIPS_NOT_OK, so we return that
6243
     * value CKS_FIPS_NOT_OK */
6244
0
    if (objectState != sessionState) {
6245
        /* *pulFIPSStatus already set to CKS_FIPS_NOT_OK */
6246
0
        return CKR_OK;
6247
0
    }
6248
6249
    /* objectState and sessionState or the same, so we can return either */
6250
0
    *pulFIPSStatus = sessionState;
6251
0
    return CKR_OK;
6252
0
}
6253
6254
CK_RV
6255
NSC_GetSessionValidationFlags(CK_SESSION_HANDLE hSession,
6256
                              CK_SESSION_VALIDATION_FLAGS_TYPE type,
6257
                              CK_FLAGS_PTR pFlags)
6258
0
{
6259
0
    CK_RV crv;
6260
0
    CK_ULONG status = CKS_NSS_UNINITIALIZED;
6261
0
    CK_ULONG status1 = CKS_NSS_UNINITIALIZED;
6262
6263
0
    *pFlags = 0;
6264
6265
0
    crv = nsc_NSSGetFIPSStatus(hSession, CK_INVALID_HANDLE,
6266
0
                               CKT_NSS_SESSION_LAST_CHECK, &status);
6267
0
    if (crv != CKR_OK) {
6268
0
        return crv;
6269
0
    }
6270
0
    crv = nsc_NSSGetFIPSStatus(hSession, CK_INVALID_HANDLE,
6271
0
                               CKT_NSS_SESSION_CHECK, &status1);
6272
0
    if (crv != CKR_OK) {
6273
0
        return crv;
6274
0
    }
6275
    /* PCKS #11 only defines the last operation. For us this includes
6276
     * things in the CKT_NSS_SESSION_CHECK */
6277
0
    if ((status == CKS_NSS_FIPS_OK) || (status1 == CKS_NSS_FIPS_OK)) {
6278
0
        *pFlags = SFTK_VALIDATION_FIPS_FLAG;
6279
0
    }
6280
0
    return CKR_OK;
6281
0
}