Coverage Report

Created: 2024-02-25 06:31

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