Coverage Report

Created: 2024-11-21 07:03

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