Coverage Report

Created: 2025-04-22 06:15

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