Coverage Report

Created: 2026-07-07 06:15

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