Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/nss/lib/softoken/pkcs11c.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
21
#include <limits.h> /* for UINT_MAX and ULONG_MAX */
22
23
#include "lowkeyti.h"
24
#include "seccomon.h"
25
#include "secitem.h"
26
#include "secport.h"
27
#include "blapi.h"
28
#include "pkcs11.h"
29
#include "pkcs11i.h"
30
#include "pkcs1sig.h"
31
#include "lowkeyi.h"
32
#include "secder.h"
33
#include "secdig.h"
34
#include "lowpbe.h" /* We do PBE below */
35
#include "pkcs11t.h"
36
#include "secoid.h"
37
#include "cmac.h"
38
#include "alghmac.h"
39
#include "softoken.h"
40
#include "secasn1.h"
41
#include "secerr.h"
42
#include "kem.h"
43
#include "kyber.h"
44
45
#include "prprf.h"
46
#include "prenv.h"
47
48
#define __PASTE(x, y) x##y
49
115
#define BAD_PARAM_CAST(pMech, typeSize) (!pMech->pParameter || pMech->ulParameterLen < typeSize)
50
/*
51
 * we renamed all our internal functions, get the correct
52
 * definitions for them...
53
 */
54
#undef CK_PKCS11_FUNCTION_INFO
55
#undef CK_NEED_ARG_LIST
56
57
#define CK_PKCS11_3_0 1
58
59
#define CK_EXTERN extern
60
#define CK_PKCS11_FUNCTION_INFO(func) \
61
    CK_RV __PASTE(NS, func)
62
#define CK_NEED_ARG_LIST 1
63
64
#include "pkcs11f.h"
65
66
/* create a definition of SHA1 that's consistent
67
 * with the rest of the CKM_SHAxxx hashes*/
68
22
#define CKM_SHA1 CKM_SHA_1
69
14
#define CKM_SHA1_HMAC CKM_SHA_1_HMAC
70
0
#define CKM_SHA1_HMAC_GENERAL CKM_SHA_1_HMAC_GENERAL
71
72
typedef struct {
73
    PRUint8 client_version[2];
74
    PRUint8 random[46];
75
} SSL3RSAPreMasterSecret;
76
77
static void
78
sftk_Null(void *data, PRBool freeit)
79
0
{
80
0
    return;
81
0
}
82
83
#ifdef EC_DEBUG
84
#define SEC_PRINT(str1, str2, num, sitem)             \
85
    printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
86
           str1, str2, num, sitem->len);              \
87
    for (i = 0; i < sitem->len; i++) {                \
88
        printf("%02x:", sitem->data[i]);              \
89
    }                                                 \
90
    printf("\n")
91
#else
92
#undef EC_DEBUG
93
#define SEC_PRINT(a, b, c, d)
94
#endif
95
96
/* Wrappers to avoid undefined behavior calling functions through a pointer of incorrect type. */
97
#define SFTKHashWrap(ctxtype, mmm)                                                        \
98
    static void                                                                           \
99
        SFTKHash_##mmm##_Update(void *vctx, const unsigned char *input, unsigned int len) \
100
1.19k
    {                                                                                     \
101
1.19k
        ctxtype *ctx = vctx;                                                              \
102
1.19k
        mmm##_Update(ctx, input, len);                                                    \
103
1.19k
    }                                                                                     \
Unexecuted instantiation: pkcs11c.c:SFTKHash_MD2_Update
pkcs11c.c:SFTKHash_MD5_Update
Line
Count
Source
100
98
    {                                                                                     \
101
98
        ctxtype *ctx = vctx;                                                              \
102
98
        mmm##_Update(ctx, input, len);                                                    \
103
98
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA1_Update
Line
Count
Source
100
130
    {                                                                                     \
101
130
        ctxtype *ctx = vctx;                                                              \
102
130
        mmm##_Update(ctx, input, len);                                                    \
103
130
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA224_Update
Line
Count
Source
100
56
    {                                                                                     \
101
56
        ctxtype *ctx = vctx;                                                              \
102
56
        mmm##_Update(ctx, input, len);                                                    \
103
56
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA256_Update
Line
Count
Source
100
152
    {                                                                                     \
101
152
        ctxtype *ctx = vctx;                                                              \
102
152
        mmm##_Update(ctx, input, len);                                                    \
103
152
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA384_Update
Line
Count
Source
100
99
    {                                                                                     \
101
99
        ctxtype *ctx = vctx;                                                              \
102
99
        mmm##_Update(ctx, input, len);                                                    \
103
99
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA512_Update
Line
Count
Source
100
132
    {                                                                                     \
101
132
        ctxtype *ctx = vctx;                                                              \
102
132
        mmm##_Update(ctx, input, len);                                                    \
103
132
    }                                                                                     \
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_224_Update
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_256_Update
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_384_Update
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_512_Update
pkcs11c.c:SFTKHash_sftk_MAC_Update
Line
Count
Source
100
524
    {                                                                                     \
101
524
        ctxtype *ctx = vctx;                                                              \
102
524
        mmm##_Update(ctx, input, len);                                                    \
103
524
    }                                                                                     \
104
    static void                                                                           \
105
        SFTKHash_##mmm##_End(void *vctx, unsigned char *digest,                           \
106
                             unsigned int *len, unsigned int maxLen)                      \
107
133
    {                                                                                     \
108
133
        ctxtype *ctx = vctx;                                                              \
109
133
        mmm##_End(ctx, digest, len, maxLen);                                              \
110
133
    }                                                                                     \
Unexecuted instantiation: pkcs11c.c:SFTKHash_MD2_End
pkcs11c.c:SFTKHash_MD5_End
Line
Count
Source
107
9
    {                                                                                     \
108
9
        ctxtype *ctx = vctx;                                                              \
109
9
        mmm##_End(ctx, digest, len, maxLen);                                              \
110
9
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA1_End
Line
Count
Source
107
11
    {                                                                                     \
108
11
        ctxtype *ctx = vctx;                                                              \
109
11
        mmm##_End(ctx, digest, len, maxLen);                                              \
110
11
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA224_End
Line
Count
Source
107
5
    {                                                                                     \
108
5
        ctxtype *ctx = vctx;                                                              \
109
5
        mmm##_End(ctx, digest, len, maxLen);                                              \
110
5
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA256_End
Line
Count
Source
107
20
    {                                                                                     \
108
20
        ctxtype *ctx = vctx;                                                              \
109
20
        mmm##_End(ctx, digest, len, maxLen);                                              \
110
20
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA384_End
Line
Count
Source
107
9
    {                                                                                     \
108
9
        ctxtype *ctx = vctx;                                                              \
109
9
        mmm##_End(ctx, digest, len, maxLen);                                              \
110
9
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA512_End
Line
Count
Source
107
10
    {                                                                                     \
108
10
        ctxtype *ctx = vctx;                                                              \
109
10
        mmm##_End(ctx, digest, len, maxLen);                                              \
110
10
    }                                                                                     \
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_224_End
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_256_End
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_384_End
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_512_End
pkcs11c.c:SFTKHash_sftk_MAC_End
Line
Count
Source
107
69
    {                                                                                     \
108
69
        ctxtype *ctx = vctx;                                                              \
109
69
        mmm##_End(ctx, digest, len, maxLen);                                              \
110
69
    }                                                                                     \
111
    static void                                                                           \
112
        SFTKHash_##mmm##_DestroyContext(void *vctx, PRBool freeit)                        \
113
133
    {                                                                                     \
114
133
        ctxtype *ctx = vctx;                                                              \
115
133
        mmm##_DestroyContext(ctx, freeit);                                                \
116
133
    }
Unexecuted instantiation: pkcs11c.c:SFTKHash_MD2_DestroyContext
pkcs11c.c:SFTKHash_MD5_DestroyContext
Line
Count
Source
113
9
    {                                                                                     \
114
9
        ctxtype *ctx = vctx;                                                              \
115
9
        mmm##_DestroyContext(ctx, freeit);                                                \
116
9
    }
pkcs11c.c:SFTKHash_SHA1_DestroyContext
Line
Count
Source
113
11
    {                                                                                     \
114
11
        ctxtype *ctx = vctx;                                                              \
115
11
        mmm##_DestroyContext(ctx, freeit);                                                \
116
11
    }
pkcs11c.c:SFTKHash_SHA224_DestroyContext
Line
Count
Source
113
5
    {                                                                                     \
114
5
        ctxtype *ctx = vctx;                                                              \
115
5
        mmm##_DestroyContext(ctx, freeit);                                                \
116
5
    }
pkcs11c.c:SFTKHash_SHA256_DestroyContext
Line
Count
Source
113
20
    {                                                                                     \
114
20
        ctxtype *ctx = vctx;                                                              \
115
20
        mmm##_DestroyContext(ctx, freeit);                                                \
116
20
    }
pkcs11c.c:SFTKHash_SHA384_DestroyContext
Line
Count
Source
113
9
    {                                                                                     \
114
9
        ctxtype *ctx = vctx;                                                              \
115
9
        mmm##_DestroyContext(ctx, freeit);                                                \
116
9
    }
pkcs11c.c:SFTKHash_SHA512_DestroyContext
Line
Count
Source
113
10
    {                                                                                     \
114
10
        ctxtype *ctx = vctx;                                                              \
115
10
        mmm##_DestroyContext(ctx, freeit);                                                \
116
10
    }
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_224_DestroyContext
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_256_DestroyContext
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_384_DestroyContext
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_512_DestroyContext
pkcs11c.c:SFTKHash_sftk_MAC_DestroyContext
Line
Count
Source
113
69
    {                                                                                     \
114
69
        ctxtype *ctx = vctx;                                                              \
115
69
        mmm##_DestroyContext(ctx, freeit);                                                \
116
69
    }
117
118
SFTKHashWrap(MD2Context, MD2);
119
SFTKHashWrap(MD5Context, MD5);
120
SFTKHashWrap(SHA1Context, SHA1);
121
SFTKHashWrap(SHA224Context, SHA224);
122
SFTKHashWrap(SHA256Context, SHA256);
123
SFTKHashWrap(SHA384Context, SHA384);
124
SFTKHashWrap(SHA512Context, SHA512);
125
SFTKHashWrap(SHA3_224Context, SHA3_224);
126
SFTKHashWrap(SHA3_256Context, SHA3_256);
127
SFTKHashWrap(SHA3_384Context, SHA3_384);
128
SFTKHashWrap(SHA3_512Context, SHA3_512);
129
SFTKHashWrap(sftk_MACCtx, sftk_MAC);
130
131
static void
132
SFTKHash_SHA1_Begin(void *vctx)
133
0
{
134
0
    SHA1Context *ctx = vctx;
135
0
    SHA1_Begin(ctx);
136
0
}
137
138
static void
139
SFTKHash_MD5_Begin(void *vctx)
140
0
{
141
0
    MD5Context *ctx = vctx;
142
0
    MD5_Begin(ctx);
143
0
}
144
145
#define SFTKCipherWrap(ctxtype, mmm)                                         \
146
    static SECStatus                                                         \
147
        SFTKCipher_##mmm(void *vctx, unsigned char *output,                  \
148
                         unsigned int *outputLen, unsigned int maxOutputLen, \
149
                         const unsigned char *input, unsigned int inputLen)  \
150
18
    {                                                                        \
151
18
        ctxtype *ctx = vctx;                                                 \
152
18
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
153
18
                   input, inputLen);                                         \
154
18
    }
Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC2_Encrypt
Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC2_Decrypt
Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC4_Encrypt
Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC4_Decrypt
pkcs11c.c:SFTKCipher_DES_Encrypt
Line
Count
Source
150
1
    {                                                                        \
151
1
        ctxtype *ctx = vctx;                                                 \
152
1
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
153
1
                   input, inputLen);                                         \
154
1
    }
pkcs11c.c:SFTKCipher_DES_Decrypt
Line
Count
Source
150
3
    {                                                                        \
151
3
        ctxtype *ctx = vctx;                                                 \
152
3
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
153
3
                   input, inputLen);                                         \
154
3
    }
pkcs11c.c:SFTKCipher_SEED_Encrypt
Line
Count
Source
150
4
    {                                                                        \
151
4
        ctxtype *ctx = vctx;                                                 \
152
4
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
153
4
                   input, inputLen);                                         \
154
4
    }
pkcs11c.c:SFTKCipher_SEED_Decrypt
Line
Count
Source
150
3
    {                                                                        \
151
3
        ctxtype *ctx = vctx;                                                 \
152
3
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
153
3
                   input, inputLen);                                         \
154
3
    }
Unexecuted instantiation: pkcs11c.c:SFTKCipher_Camellia_Encrypt
Unexecuted instantiation: pkcs11c.c:SFTKCipher_Camellia_Decrypt
pkcs11c.c:SFTKCipher_AES_Encrypt
Line
Count
Source
150
2
    {                                                                        \
151
2
        ctxtype *ctx = vctx;                                                 \
152
2
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
153
2
                   input, inputLen);                                         \
154
2
    }
pkcs11c.c:SFTKCipher_AES_Decrypt
Line
Count
Source
150
5
    {                                                                        \
151
5
        ctxtype *ctx = vctx;                                                 \
152
5
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
153
5
                   input, inputLen);                                         \
154
5
    }
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_EncryptKWP
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_DecryptKWP
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_Encrypt
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_Decrypt
155
156
SFTKCipherWrap(AESKeyWrapContext, AESKeyWrap_EncryptKWP);
157
SFTKCipherWrap(AESKeyWrapContext, AESKeyWrap_DecryptKWP);
158
159
#define SFTKCipherWrap2(ctxtype, mmm)                                        \
160
    SFTKCipherWrap(ctxtype, mmm##_Encrypt);                                  \
161
    SFTKCipherWrap(ctxtype, mmm##_Decrypt);                                  \
162
    static void SFTKCipher_##mmm##_DestroyContext(void *vctx, PRBool freeit) \
163
17
    {                                                                        \
164
17
        ctxtype *ctx = vctx;                                                 \
165
17
        mmm##_DestroyContext(ctx, freeit);                                   \
166
17
    }
Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC2_DestroyContext
Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC4_DestroyContext
pkcs11c.c:SFTKCipher_DES_DestroyContext
Line
Count
Source
163
3
    {                                                                        \
164
3
        ctxtype *ctx = vctx;                                                 \
165
3
        mmm##_DestroyContext(ctx, freeit);                                   \
166
3
    }
pkcs11c.c:SFTKCipher_SEED_DestroyContext
Line
Count
Source
163
7
    {                                                                        \
164
7
        ctxtype *ctx = vctx;                                                 \
165
7
        mmm##_DestroyContext(ctx, freeit);                                   \
166
7
    }
Unexecuted instantiation: pkcs11c.c:SFTKCipher_Camellia_DestroyContext
pkcs11c.c:SFTKCipher_AES_DestroyContext
Line
Count
Source
163
7
    {                                                                        \
164
7
        ctxtype *ctx = vctx;                                                 \
165
7
        mmm##_DestroyContext(ctx, freeit);                                   \
166
7
    }
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_DestroyContext
167
168
SFTKCipherWrap2(RC2Context, RC2);
169
SFTKCipherWrap2(RC4Context, RC4);
170
SFTKCipherWrap2(DESContext, DES);
171
SFTKCipherWrap2(SEEDContext, SEED);
172
SFTKCipherWrap2(CamelliaContext, Camellia);
173
SFTKCipherWrap2(AESContext, AES);
174
SFTKCipherWrap2(AESKeyWrapContext, AESKeyWrap);
175
176
#if NSS_SOFTOKEN_DOES_RC5
177
SFTKCipherWrap2(RC5Context, RC5);
178
#endif
179
180
/*
181
 * free routines.... Free local type  allocated data, and convert
182
 * other free routines to the destroy signature.
183
 */
184
static void
185
sftk_FreePrivKey(void *vkey, PRBool freeit)
186
0
{
187
0
    NSSLOWKEYPrivateKey *key = vkey;
188
0
    nsslowkey_DestroyPrivateKey(key);
189
0
}
190
191
static void
192
sftk_Space(void *data, PRBool freeit)
193
69
{
194
69
    PORT_Free(data);
195
69
}
196
197
static void
198
sftk_ZSpace(void *data, PRBool freeit)
199
0
{
200
0
    size_t len = *(size_t *)data;
201
0
    PORT_ZFree(data, len);
202
0
}
203
204
/*
205
 * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
206
 * Deprecating a full des key to 40 bit key strenth.
207
 */
208
static CK_RV
209
sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey)
210
0
{
211
0
    unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae };
212
0
    unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 };
213
0
    unsigned char enc_src[8];
214
0
    unsigned char enc_dest[8];
215
0
    unsigned int leng, i;
216
0
    DESContext *descx;
217
0
    SECStatus rv;
218
0
    CK_RV crv = CKR_OK;
219
220
    /* zero the parity bits */
221
0
    for (i = 0; i < 8; i++) {
222
0
        enc_src[i] = cdmfkey[i] & 0xfe;
223
0
    }
224
225
    /* encrypt with key 1 */
226
0
    descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE);
227
0
    if (descx == NULL) {
228
0
        crv = CKR_HOST_MEMORY;
229
0
        goto done;
230
0
    }
231
0
    rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8);
232
0
    DES_DestroyContext(descx, PR_TRUE);
233
0
    if (rv != SECSuccess) {
234
0
        crv = sftk_MapCryptError(PORT_GetError());
235
0
        goto done;
236
0
    }
237
238
    /* xor source with des, zero the parity bits and deprecate the key*/
239
0
    for (i = 0; i < 8; i++) {
240
0
        if (i & 1) {
241
0
            enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe;
242
0
        } else {
243
0
            enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e;
244
0
        }
245
0
    }
246
247
    /* encrypt with key 2 */
248
0
    descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE);
249
0
    if (descx == NULL) {
250
0
        crv = CKR_HOST_MEMORY;
251
0
        goto done;
252
0
    }
253
0
    rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8);
254
0
    DES_DestroyContext(descx, PR_TRUE);
255
0
    if (rv != SECSuccess) {
256
0
        crv = sftk_MapCryptError(PORT_GetError());
257
0
        goto done;
258
0
    }
259
260
    /* set the corret parity on our new des key */
261
0
    sftk_FormatDESKey(deskey, 8);
262
0
done:
263
0
    PORT_Memset(enc_src, 0, sizeof enc_src);
264
0
    PORT_Memset(enc_dest, 0, sizeof enc_dest);
265
0
    return crv;
266
0
}
267
268
/* NSC_DestroyObject destroys an object. */
269
CK_RV
270
NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
271
326
{
272
326
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
273
326
    SFTKSession *session;
274
326
    SFTKObject *object;
275
326
    SFTKFreeStatus status;
276
277
326
    CHECK_FORK();
278
279
326
    if (slot == NULL) {
280
0
        return CKR_SESSION_HANDLE_INVALID;
281
0
    }
282
    /*
283
     * This whole block just makes sure we really can destroy the
284
     * requested object.
285
     */
286
326
    session = sftk_SessionFromHandle(hSession);
287
326
    if (session == NULL) {
288
0
        return CKR_SESSION_HANDLE_INVALID;
289
0
    }
290
291
326
    object = sftk_ObjectFromHandle(hObject, session);
292
326
    if (object == NULL) {
293
60
        sftk_FreeSession(session);
294
60
        return CKR_OBJECT_HANDLE_INVALID;
295
60
    }
296
297
    /* don't destroy a private object if we aren't logged in */
298
266
    if ((!slot->isLoggedIn) && (slot->needLogin) &&
299
266
        (sftk_isTrue(object, CKA_PRIVATE))) {
300
0
        sftk_FreeSession(session);
301
0
        sftk_FreeObject(object);
302
0
        return CKR_USER_NOT_LOGGED_IN;
303
0
    }
304
305
    /* don't destroy a token object if we aren't in a rw session */
306
307
266
    if (((session->info.flags & CKF_RW_SESSION) == 0) &&
308
266
        (sftk_isTrue(object, CKA_TOKEN))) {
309
0
        sftk_FreeSession(session);
310
0
        sftk_FreeObject(object);
311
0
        return CKR_SESSION_READ_ONLY;
312
0
    }
313
314
266
    sftk_DeleteObject(session, object);
315
316
266
    sftk_FreeSession(session);
317
318
    /*
319
     * get some indication if the object is destroyed. Note: this is not
320
     * 100%. Someone may have an object reference outstanding (though that
321
     * should not be the case by here. Also note that the object is "half"
322
     * destroyed. Our internal representation is destroyed, but it may still
323
     * be in the data base.
324
     */
325
266
    status = sftk_FreeObject(object);
326
327
266
    return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;
328
266
}
329
330
/*
331
 * Returns true if "params" contains a valid set of PSS parameters
332
 */
333
static PRBool
334
sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params)
335
0
{
336
0
    if (!params) {
337
0
        return PR_FALSE;
338
0
    }
339
0
    if (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL ||
340
0
        sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) {
341
0
        return PR_FALSE;
342
0
    }
343
0
    return PR_TRUE;
344
0
}
345
346
/*
347
 * Returns true if "params" contains a valid set of OAEP parameters
348
 */
349
static PRBool
350
sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS *params)
351
0
{
352
0
    if (!params) {
353
0
        return PR_FALSE;
354
0
    }
355
    /* The requirements of ulSourceLen/pSourceData come from PKCS #11, which
356
     * state:
357
     *   If the parameter is empty, pSourceData must be NULL and
358
     *   ulSourceDataLen must be zero.
359
     */
360
0
    if (params->source != CKZ_DATA_SPECIFIED ||
361
0
        (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) ||
362
0
        (sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) ||
363
0
        (params->ulSourceDataLen == 0 && params->pSourceData != NULL) ||
364
0
        (params->ulSourceDataLen != 0 && params->pSourceData == NULL)) {
365
0
        return PR_FALSE;
366
0
    }
367
0
    return PR_TRUE;
368
0
}
369
370
/*
371
 * return a context based on the SFTKContext type.
372
 */
373
SFTKSessionContext *
374
sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type)
375
1.55k
{
376
1.55k
    switch (type) {
377
27
        case SFTK_ENCRYPT:
378
74
        case SFTK_DECRYPT:
379
74
        case SFTK_MESSAGE_ENCRYPT:
380
74
        case SFTK_MESSAGE_DECRYPT:
381
74
            return session->enc_context;
382
795
        case SFTK_HASH:
383
795
            return session->hash_context;
384
689
        case SFTK_SIGN:
385
689
        case SFTK_SIGN_RECOVER:
386
689
        case SFTK_VERIFY:
387
689
        case SFTK_VERIFY_RECOVER:
388
689
        case SFTK_MESSAGE_SIGN:
389
689
        case SFTK_MESSAGE_VERIFY:
390
689
            return session->hash_context;
391
1.55k
    }
392
0
    return NULL;
393
1.55k
}
394
395
/*
396
 * change a context based on the SFTKContext type.
397
 */
398
void
399
sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
400
                      SFTKSessionContext *context)
401
306
{
402
306
    switch (type) {
403
11
        case SFTK_ENCRYPT:
404
40
        case SFTK_DECRYPT:
405
40
        case SFTK_MESSAGE_ENCRYPT:
406
40
        case SFTK_MESSAGE_DECRYPT:
407
40
            session->enc_context = context;
408
40
            break;
409
128
        case SFTK_HASH:
410
128
            session->hash_context = context;
411
128
            break;
412
138
        case SFTK_SIGN:
413
138
        case SFTK_SIGN_RECOVER:
414
138
        case SFTK_VERIFY:
415
138
        case SFTK_VERIFY_RECOVER:
416
138
        case SFTK_MESSAGE_SIGN:
417
138
        case SFTK_MESSAGE_VERIFY:
418
138
            session->hash_context = context;
419
138
            break;
420
306
    }
421
306
    return;
422
306
}
423
424
/*
425
 * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal,
426
 * and C_XXX function. The function takes a session handle, the context type,
427
 * and wether or not the session needs to be multipart. It returns the context,
428
 * and optionally returns the session pointer (if sessionPtr != NULL) if session
429
 * pointer is returned, the caller is responsible for freeing it.
430
 */
431
CK_RV
432
sftk_GetContext(CK_SESSION_HANDLE handle, SFTKSessionContext **contextPtr,
433
                SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr)
434
1.35k
{
435
1.35k
    SFTKSession *session;
436
1.35k
    SFTKSessionContext *context;
437
438
1.35k
    session = sftk_SessionFromHandle(handle);
439
1.35k
    if (session == NULL)
440
0
        return CKR_SESSION_HANDLE_INVALID;
441
1.35k
    context = sftk_ReturnContextByType(session, type);
442
    /* make sure the context is valid */
443
1.35k
    if ((context == NULL) || (context->type != type) || (needMulti && !(context->multi))) {
444
0
        sftk_FreeSession(session);
445
0
        return CKR_OPERATION_NOT_INITIALIZED;
446
0
    }
447
1.35k
    *contextPtr = context;
448
1.35k
    if (sessionPtr != NULL) {
449
674
        *sessionPtr = session;
450
676
    } else {
451
676
        sftk_FreeSession(session);
452
676
    }
453
1.35k
    return CKR_OK;
454
1.35k
}
455
456
/** Terminate operation (in the PKCS#11 spec sense).
457
 *  Intuitive name for FreeContext/SetNullContext pair.
458
 */
459
void
460
sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype,
461
                 SFTKSessionContext *context)
462
149
{
463
149
    session->lastOpWasFIPS = context->isFIPS;
464
149
    sftk_FreeContext(context);
465
149
    sftk_SetContextByType(session, ctype, NULL);
466
149
}
467
468
/*
469
 ************** Crypto Functions:     Encrypt ************************
470
 */
471
472
/*
473
 * All the NSC_InitXXX functions have a set of common checks and processing they
474
 * all need to do at the beginning. This is done here.
475
 */
476
CK_RV
477
sftk_InitGeneric(SFTKSession *session, CK_MECHANISM *pMechanism,
478
                 SFTKSessionContext **contextPtr,
479
                 SFTKContextType ctype, SFTKObject **keyPtr,
480
                 CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
481
                 CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation)
482
208
{
483
208
    SFTKObject *key = NULL;
484
208
    SFTKAttribute *att;
485
208
    SFTKSessionContext *context;
486
487
    /* We can only init if there is not current context active */
488
208
    if (sftk_ReturnContextByType(session, ctype) != NULL) {
489
0
        return CKR_OPERATION_ACTIVE;
490
0
    }
491
492
    /* find the key */
493
208
    if (keyPtr) {
494
144
        key = sftk_ObjectFromHandle(hKey, session);
495
144
        if (key == NULL) {
496
0
            return CKR_KEY_HANDLE_INVALID;
497
0
        }
498
499
        /* make sure it's a valid  key for this operation */
500
144
        if (((key->objclass != CKO_SECRET_KEY) &&
501
144
             (key->objclass != pubKeyType)) ||
502
144
            !sftk_isTrue(key, operation)) {
503
0
            sftk_FreeObject(key);
504
0
            return CKR_KEY_TYPE_INCONSISTENT;
505
0
        }
506
        /* get the key type */
507
144
        att = sftk_FindAttribute(key, CKA_KEY_TYPE);
508
144
        if (att == NULL) {
509
0
            sftk_FreeObject(key);
510
0
            return CKR_KEY_TYPE_INCONSISTENT;
511
0
        }
512
144
        PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE));
513
144
        if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) {
514
0
            sftk_FreeAttribute(att);
515
0
            sftk_FreeObject(key);
516
0
            return CKR_ATTRIBUTE_VALUE_INVALID;
517
0
        }
518
144
        PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE));
519
144
        sftk_FreeAttribute(att);
520
144
        *keyPtr = key;
521
144
    }
522
523
    /* allocate the context structure */
524
208
    context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext));
525
208
    if (context == NULL) {
526
0
        if (key)
527
0
            sftk_FreeObject(key);
528
0
        return CKR_HOST_MEMORY;
529
0
    }
530
208
    context->type = ctype;
531
208
    context->multi = PR_TRUE;
532
208
    context->rsa = PR_FALSE;
533
208
    context->cipherInfo = NULL;
534
208
    context->hashInfo = NULL;
535
208
    context->doPad = PR_FALSE;
536
208
    context->padDataLength = 0;
537
208
    context->key = key;
538
208
    context->blockSize = 0;
539
208
    context->maxLen = 0;
540
208
    context->isFIPS = sftk_operationIsFIPS(session->slot, pMechanism,
541
208
                                           operation, key);
542
208
    *contextPtr = context;
543
208
    return CKR_OK;
544
208
}
545
546
static int
547
sftk_aes_mode(CK_MECHANISM_TYPE mechanism)
548
18
{
549
18
    switch (mechanism) {
550
0
        case CKM_AES_CBC_PAD:
551
2
        case CKM_AES_CBC:
552
2
            return NSS_AES_CBC;
553
4
        case CKM_AES_ECB:
554
4
            return NSS_AES;
555
0
        case CKM_AES_CTS:
556
0
            return NSS_AES_CTS;
557
0
        case CKM_AES_CTR:
558
0
            return NSS_AES_CTR;
559
12
        case CKM_AES_GCM:
560
12
            return NSS_AES_GCM;
561
18
    }
562
0
    return -1;
563
18
}
564
565
static SECStatus
566
sftk_RSAEncryptRaw(void *ctx, unsigned char *output,
567
                   unsigned int *outputLen, unsigned int maxLen,
568
                   const unsigned char *input, unsigned int inputLen)
569
0
{
570
0
    NSSLOWKEYPublicKey *key = ctx;
571
0
    SECStatus rv = SECFailure;
572
573
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
574
0
    if (key->keyType != NSSLOWKEYRSAKey) {
575
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
576
0
        return SECFailure;
577
0
    }
578
579
0
    rv = RSA_EncryptRaw(&key->u.rsa, output, outputLen, maxLen, input,
580
0
                        inputLen);
581
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
582
0
        sftk_fatalError = PR_TRUE;
583
0
    }
584
585
0
    return rv;
586
0
}
587
588
static SECStatus
589
sftk_RSADecryptRaw(void *ctx, unsigned char *output,
590
                   unsigned int *outputLen, unsigned int maxLen,
591
                   const unsigned char *input, unsigned int inputLen)
592
0
{
593
0
    NSSLOWKEYPrivateKey *key = ctx;
594
0
    SECStatus rv = SECFailure;
595
596
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
597
0
    if (key->keyType != NSSLOWKEYRSAKey) {
598
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
599
0
        return SECFailure;
600
0
    }
601
602
0
    rv = RSA_DecryptRaw(&key->u.rsa, output, outputLen, maxLen, input,
603
0
                        inputLen);
604
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
605
0
        sftk_fatalError = PR_TRUE;
606
0
    }
607
608
0
    return rv;
609
0
}
610
611
static SECStatus
612
sftk_RSAEncrypt(void *ctx, unsigned char *output,
613
                unsigned int *outputLen, unsigned int maxLen,
614
                const unsigned char *input, unsigned int inputLen)
615
0
{
616
0
    NSSLOWKEYPublicKey *key = ctx;
617
0
    SECStatus rv = SECFailure;
618
619
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
620
0
    if (key->keyType != NSSLOWKEYRSAKey) {
621
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
622
0
        return SECFailure;
623
0
    }
624
625
0
    rv = RSA_EncryptBlock(&key->u.rsa, output, outputLen, maxLen, input,
626
0
                          inputLen);
627
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
628
0
        sftk_fatalError = PR_TRUE;
629
0
    }
630
631
0
    return rv;
632
0
}
633
634
static SECStatus
635
sftk_RSADecrypt(void *ctx, unsigned char *output,
636
                unsigned int *outputLen, unsigned int maxLen,
637
                const unsigned char *input, unsigned int inputLen)
638
0
{
639
0
    NSSLOWKEYPrivateKey *key = ctx;
640
0
    SECStatus rv = SECFailure;
641
642
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
643
0
    if (key->keyType != NSSLOWKEYRSAKey) {
644
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
645
0
        return SECFailure;
646
0
    }
647
648
0
    rv = RSA_DecryptBlock(&key->u.rsa, output, outputLen, maxLen, input,
649
0
                          inputLen);
650
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
651
0
        sftk_fatalError = PR_TRUE;
652
0
    }
653
654
0
    return rv;
655
0
}
656
657
static void
658
sftk_freeRSAOAEPInfo(void *ctx, PRBool freeit)
659
0
{
660
0
    SFTKOAEPInfo *info = ctx;
661
0
    PORT_ZFree(info->params.pSourceData, info->params.ulSourceDataLen);
662
0
    PORT_ZFree(info, sizeof(SFTKOAEPInfo));
663
0
}
664
665
static SECStatus
666
sftk_RSAEncryptOAEP(void *ctx, unsigned char *output,
667
                    unsigned int *outputLen, unsigned int maxLen,
668
                    const unsigned char *input, unsigned int inputLen)
669
0
{
670
0
    SFTKOAEPInfo *info = ctx;
671
0
    HASH_HashType hashAlg;
672
0
    HASH_HashType maskHashAlg;
673
674
0
    PORT_Assert(info->key.pub->keyType == NSSLOWKEYRSAKey);
675
0
    if (info->key.pub->keyType != NSSLOWKEYRSAKey) {
676
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
677
0
        return SECFailure;
678
0
    }
679
680
0
    hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg);
681
0
    maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf);
682
683
0
    return RSA_EncryptOAEP(&info->key.pub->u.rsa, hashAlg, maskHashAlg,
684
0
                           (const unsigned char *)info->params.pSourceData,
685
0
                           info->params.ulSourceDataLen, NULL, 0,
686
0
                           output, outputLen, maxLen, input, inputLen);
687
0
}
688
689
static SECStatus
690
sftk_RSADecryptOAEP(void *ctx, unsigned char *output,
691
                    unsigned int *outputLen, unsigned int maxLen,
692
                    const unsigned char *input, unsigned int inputLen)
693
0
{
694
0
    SFTKOAEPInfo *info = ctx;
695
0
    SECStatus rv = SECFailure;
696
0
    HASH_HashType hashAlg;
697
0
    HASH_HashType maskHashAlg;
698
699
0
    PORT_Assert(info->key.priv->keyType == NSSLOWKEYRSAKey);
700
0
    if (info->key.priv->keyType != NSSLOWKEYRSAKey) {
701
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
702
0
        return SECFailure;
703
0
    }
704
705
0
    hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg);
706
0
    maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf);
707
708
0
    rv = RSA_DecryptOAEP(&info->key.priv->u.rsa, hashAlg, maskHashAlg,
709
0
                         (const unsigned char *)info->params.pSourceData,
710
0
                         info->params.ulSourceDataLen,
711
0
                         output, outputLen, maxLen, input, inputLen);
712
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
713
0
        sftk_fatalError = PR_TRUE;
714
0
    }
715
0
    return rv;
716
0
}
717
718
static SFTKChaCha20Poly1305Info *
719
sftk_ChaCha20Poly1305_CreateContext(const unsigned char *key,
720
                                    unsigned int keyLen,
721
                                    const CK_NSS_AEAD_PARAMS *params)
722
14
{
723
14
    SFTKChaCha20Poly1305Info *ctx;
724
725
14
    if (params->ulNonceLen != sizeof(ctx->nonce)) {
726
6
        PORT_SetError(SEC_ERROR_INPUT_LEN);
727
6
        return NULL;
728
6
    }
729
730
8
    ctx = PORT_New(SFTKChaCha20Poly1305Info);
731
8
    if (ctx == NULL) {
732
0
        return NULL;
733
0
    }
734
735
8
    if (ChaCha20Poly1305_InitContext(&ctx->freeblCtx, key, keyLen,
736
8
                                     params->ulTagLen) != SECSuccess) {
737
1
        PORT_Free(ctx);
738
1
        return NULL;
739
1
    }
740
741
7
    PORT_Memcpy(ctx->nonce, params->pNonce, sizeof(ctx->nonce));
742
743
    /* AAD data and length must both be null, or both non-null. */
744
7
    PORT_Assert((params->pAAD == NULL) == (params->ulAADLen == 0));
745
746
7
    if (params->ulAADLen > sizeof(ctx->ad)) {
747
        /* Need to allocate an overflow buffer for the additional data. */
748
0
        ctx->adOverflow = (unsigned char *)PORT_Alloc(params->ulAADLen);
749
0
        if (!ctx->adOverflow) {
750
0
            PORT_Free(ctx);
751
0
            return NULL;
752
0
        }
753
0
        PORT_Memcpy(ctx->adOverflow, params->pAAD, params->ulAADLen);
754
7
    } else {
755
7
        ctx->adOverflow = NULL;
756
7
        if (params->pAAD) {
757
0
            PORT_Memcpy(ctx->ad, params->pAAD, params->ulAADLen);
758
0
        }
759
7
    }
760
7
    ctx->adLen = params->ulAADLen;
761
762
7
    return ctx;
763
7
}
764
765
static void
766
sftk_ChaCha20Poly1305_DestroyContext(void *vctx,
767
                                     PRBool freeit)
768
7
{
769
7
    SFTKChaCha20Poly1305Info *ctx = vctx;
770
7
    ChaCha20Poly1305_DestroyContext(&ctx->freeblCtx, PR_FALSE);
771
7
    if (ctx->adOverflow != NULL) {
772
0
        PORT_ZFree(ctx->adOverflow, ctx->adLen);
773
0
        ctx->adOverflow = NULL;
774
7
    } else {
775
7
        PORT_Memset(ctx->ad, 0, ctx->adLen);
776
7
    }
777
7
    ctx->adLen = 0;
778
7
    if (freeit) {
779
7
        PORT_Free(ctx);
780
7
    }
781
7
}
782
783
static SECStatus
784
sftk_ChaCha20Poly1305_Encrypt(void *vctx,
785
                              unsigned char *output, unsigned int *outputLen,
786
                              unsigned int maxOutputLen,
787
                              const unsigned char *input, unsigned int inputLen)
788
0
{
789
0
    const SFTKChaCha20Poly1305Info *ctx = vctx;
790
0
    const unsigned char *ad = ctx->adOverflow;
791
792
0
    if (ad == NULL) {
793
0
        ad = ctx->ad;
794
0
    }
795
796
0
    return ChaCha20Poly1305_Seal(&ctx->freeblCtx, output, outputLen,
797
0
                                 maxOutputLen, input, inputLen, ctx->nonce,
798
0
                                 sizeof(ctx->nonce), ad, ctx->adLen);
799
0
}
800
801
static SECStatus
802
sftk_ChaCha20Poly1305_Decrypt(void *vctx,
803
                              unsigned char *output, unsigned int *outputLen,
804
                              unsigned int maxOutputLen,
805
                              const unsigned char *input, unsigned int inputLen)
806
7
{
807
7
    const SFTKChaCha20Poly1305Info *ctx = vctx;
808
7
    const unsigned char *ad = ctx->adOverflow;
809
810
7
    if (ad == NULL) {
811
7
        ad = ctx->ad;
812
7
    }
813
814
7
    return ChaCha20Poly1305_Open(&ctx->freeblCtx, output, outputLen,
815
7
                                 maxOutputLen, input, inputLen, ctx->nonce,
816
7
                                 sizeof(ctx->nonce), ad, ctx->adLen);
817
7
}
818
819
static SECStatus
820
sftk_ChaCha20Ctr(void *vctx,
821
                 unsigned char *output, unsigned int *outputLen,
822
                 unsigned int maxOutputLen,
823
                 const unsigned char *input, unsigned int inputLen)
824
0
{
825
0
    if (maxOutputLen < inputLen) {
826
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
827
0
        return SECFailure;
828
0
    }
829
0
    SFTKChaCha20CtrInfo *ctx = vctx;
830
0
    ChaCha20_Xor(output, input, inputLen, ctx->key,
831
0
                 ctx->nonce, ctx->counter);
832
0
    *outputLen = inputLen;
833
0
    return SECSuccess;
834
0
}
835
836
static void
837
sftk_ChaCha20Ctr_DestroyContext(void *vctx,
838
                                PRBool freeit)
839
0
{
840
0
    SFTKChaCha20CtrInfo *ctx = vctx;
841
0
    memset(ctx, 0, sizeof(SFTKChaCha20CtrInfo));
842
0
    if (freeit) {
843
0
        PORT_Free(ctx);
844
0
    }
845
0
}
846
847
/** NSC_CryptInit initializes an encryption/Decryption operation.
848
 *
849
 * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey.
850
 * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block
851
 *  ciphers MAC'ing.
852
 */
853
CK_RV
854
sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
855
               CK_OBJECT_HANDLE hKey,
856
               CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage,
857
               SFTKContextType contextType, PRBool isEncrypt)
858
61
{
859
61
    SFTKSession *session;
860
61
    SFTKObject *key;
861
61
    SFTKSessionContext *context;
862
61
    SFTKAttribute *att;
863
61
#ifndef NSS_DISABLE_DEPRECATED_RC2
864
61
    CK_RC2_CBC_PARAMS *rc2_param;
865
61
    unsigned effectiveKeyLength;
866
61
#endif
867
#if NSS_SOFTOKEN_DOES_RC5
868
    CK_RC5_CBC_PARAMS *rc5_param;
869
    SECItem rc5Key;
870
#endif
871
61
    CK_NSS_GCM_PARAMS nss_gcm_param;
872
61
    void *aes_param;
873
61
    CK_NSS_AEAD_PARAMS nss_aead_params;
874
61
    CK_NSS_AEAD_PARAMS *nss_aead_params_ptr = NULL;
875
61
    CK_KEY_TYPE key_type;
876
61
    CK_RV crv = CKR_OK;
877
61
    unsigned char newdeskey[24];
878
61
    PRBool useNewKey = PR_FALSE;
879
61
    int t;
880
881
61
    if (!pMechanism) {
882
0
        return CKR_MECHANISM_PARAM_INVALID;
883
0
    }
884
885
61
    crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage);
886
61
    if (crv != CKR_OK)
887
12
        return crv;
888
889
49
    session = sftk_SessionFromHandle(hSession);
890
49
    if (session == NULL)
891
0
        return CKR_SESSION_HANDLE_INVALID;
892
893
49
    crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key,
894
49
                           hKey, &key_type,
895
49
                           isEncrypt ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY,
896
49
                           keyUsage);
897
898
49
    if (crv != CKR_OK) {
899
0
        sftk_FreeSession(session);
900
0
        return crv;
901
0
    }
902
903
49
    context->doPad = PR_FALSE;
904
49
    switch (pMechanism->mechanism) {
905
0
        case CKM_RSA_PKCS:
906
0
        case CKM_RSA_X_509:
907
0
            if (key_type != CKK_RSA) {
908
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
909
0
                break;
910
0
            }
911
0
            context->multi = PR_FALSE;
912
0
            context->rsa = PR_TRUE;
913
0
            if (isEncrypt) {
914
0
                NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
915
0
                if (pubKey == NULL) {
916
0
                    crv = CKR_KEY_HANDLE_INVALID;
917
0
                    break;
918
0
                }
919
0
                context->maxLen = nsslowkey_PublicModulusLen(pubKey);
920
0
                context->cipherInfo = (void *)pubKey;
921
0
                context->update = pMechanism->mechanism == CKM_RSA_X_509
922
0
                                      ? sftk_RSAEncryptRaw
923
0
                                      : sftk_RSAEncrypt;
924
0
            } else {
925
0
                NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key, CKK_RSA, &crv);
926
0
                if (privKey == NULL) {
927
0
                    crv = CKR_KEY_HANDLE_INVALID;
928
0
                    break;
929
0
                }
930
0
                context->maxLen = nsslowkey_PrivateModulusLen(privKey);
931
0
                context->cipherInfo = (void *)privKey;
932
0
                context->update = pMechanism->mechanism == CKM_RSA_X_509
933
0
                                      ? sftk_RSADecryptRaw
934
0
                                      : sftk_RSADecrypt;
935
0
            }
936
0
            context->destroy = sftk_Null;
937
0
            break;
938
0
        case CKM_RSA_PKCS_OAEP:
939
0
            if (key_type != CKK_RSA) {
940
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
941
0
                break;
942
0
            }
943
0
            if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) ||
944
0
                !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter)) {
945
0
                crv = CKR_MECHANISM_PARAM_INVALID;
946
0
                break;
947
0
            }
948
0
            context->multi = PR_FALSE;
949
0
            context->rsa = PR_TRUE;
950
0
            {
951
0
                SFTKOAEPInfo *info;
952
0
                CK_RSA_PKCS_OAEP_PARAMS *params =
953
0
                    (CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter;
954
                /* make a copy of the source data value for future
955
                 * use (once the user has reclaimed his data in pParameter)*/
956
0
                void *newSource = NULL;
957
0
                if (params->pSourceData) {
958
0
                    newSource = PORT_Alloc(params->ulSourceDataLen);
959
0
                    if (newSource == NULL) {
960
0
                        crv = CKR_HOST_MEMORY;
961
0
                        break;
962
0
                    }
963
0
                    PORT_Memcpy(newSource, params->pSourceData, params->ulSourceDataLen);
964
0
                }
965
0
                info = PORT_New(SFTKOAEPInfo);
966
0
                if (info == NULL) {
967
0
                    PORT_ZFree(newSource, params->ulSourceDataLen);
968
0
                    crv = CKR_HOST_MEMORY;
969
0
                    break;
970
0
                }
971
0
                info->params = *params;
972
0
                info->params.pSourceData = newSource;
973
0
                info->isEncrypt = isEncrypt;
974
975
                /* now setup encryption and decryption contexts */
976
0
                if (isEncrypt) {
977
0
                    info->key.pub = sftk_GetPubKey(key, CKK_RSA, &crv);
978
0
                    if (info->key.pub == NULL) {
979
0
                        sftk_freeRSAOAEPInfo(info, PR_TRUE);
980
0
                        crv = CKR_KEY_HANDLE_INVALID;
981
0
                        break;
982
0
                    }
983
0
                    context->update = sftk_RSAEncryptOAEP;
984
0
                    context->maxLen = nsslowkey_PublicModulusLen(info->key.pub);
985
0
                } else {
986
0
                    info->key.priv = sftk_GetPrivKey(key, CKK_RSA, &crv);
987
0
                    if (info->key.priv == NULL) {
988
0
                        sftk_freeRSAOAEPInfo(info, PR_TRUE);
989
0
                        crv = CKR_KEY_HANDLE_INVALID;
990
0
                        break;
991
0
                    }
992
0
                    context->update = sftk_RSADecryptOAEP;
993
0
                    context->maxLen = nsslowkey_PrivateModulusLen(info->key.priv);
994
0
                }
995
0
                context->cipherInfo = info;
996
0
            }
997
0
            context->destroy = sftk_freeRSAOAEPInfo;
998
0
            break;
999
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
1000
0
        case CKM_RC2_CBC_PAD:
1001
0
            context->doPad = PR_TRUE;
1002
        /* fall thru */
1003
0
        case CKM_RC2_ECB:
1004
0
        case CKM_RC2_CBC:
1005
0
            context->blockSize = 8;
1006
0
            if (key_type != CKK_RC2) {
1007
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1008
0
                break;
1009
0
            }
1010
0
            att = sftk_FindAttribute(key, CKA_VALUE);
1011
0
            if (att == NULL) {
1012
0
                crv = CKR_KEY_HANDLE_INVALID;
1013
0
                break;
1014
0
            }
1015
1016
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_CBC_PARAMS))) {
1017
0
                crv = CKR_MECHANISM_PARAM_INVALID;
1018
0
                break;
1019
0
            }
1020
0
            rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
1021
0
            effectiveKeyLength = (rc2_param->ulEffectiveBits + 7) / 8;
1022
0
            context->cipherInfo =
1023
0
                RC2_CreateContext((unsigned char *)att->attrib.pValue,
1024
0
                                  att->attrib.ulValueLen, rc2_param->iv,
1025
0
                                  pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : NSS_RC2_CBC, effectiveKeyLength);
1026
0
            sftk_FreeAttribute(att);
1027
0
            if (context->cipherInfo == NULL) {
1028
0
                crv = CKR_HOST_MEMORY;
1029
0
                break;
1030
0
            }
1031
0
            context->update = isEncrypt ? SFTKCipher_RC2_Encrypt : SFTKCipher_RC2_Decrypt;
1032
0
            context->destroy = SFTKCipher_RC2_DestroyContext;
1033
0
            break;
1034
0
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
1035
1036
#if NSS_SOFTOKEN_DOES_RC5
1037
        case CKM_RC5_CBC_PAD:
1038
            context->doPad = PR_TRUE;
1039
        /* fall thru */
1040
        case CKM_RC5_ECB:
1041
        case CKM_RC5_CBC:
1042
            if (key_type != CKK_RC5) {
1043
                crv = CKR_KEY_TYPE_INCONSISTENT;
1044
                break;
1045
            }
1046
            att = sftk_FindAttribute(key, CKA_VALUE);
1047
            if (att == NULL) {
1048
                crv = CKR_KEY_HANDLE_INVALID;
1049
                break;
1050
            }
1051
1052
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_CBC_PARAMS))) {
1053
                crv = CKR_MECHANISM_PARAM_INVALID;
1054
                break;
1055
            }
1056
            rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
1057
            context->blockSize = rc5_param->ulWordsize * 2;
1058
            rc5Key.data = (unsigned char *)att->attrib.pValue;
1059
            rc5Key.len = att->attrib.ulValueLen;
1060
            context->cipherInfo = RC5_CreateContext(&rc5Key, rc5_param->ulRounds,
1061
                                                    rc5_param->ulWordsize, rc5_param->pIv,
1062
                                                    pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);
1063
            sftk_FreeAttribute(att);
1064
            if (context->cipherInfo == NULL) {
1065
                crv = CKR_HOST_MEMORY;
1066
                break;
1067
            }
1068
            context->update = isEncrypt ? SFTKCipher_RC5_Encrypt : SFTKCipher_RC5_Decrypt;
1069
            context->destroy = SFTKCipher_RC5_DestroyContext;
1070
            break;
1071
#endif
1072
0
        case CKM_RC4:
1073
0
            if (key_type != CKK_RC4) {
1074
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1075
0
                break;
1076
0
            }
1077
0
            att = sftk_FindAttribute(key, CKA_VALUE);
1078
0
            if (att == NULL) {
1079
0
                crv = CKR_KEY_HANDLE_INVALID;
1080
0
                break;
1081
0
            }
1082
0
            context->cipherInfo =
1083
0
                RC4_CreateContext((unsigned char *)att->attrib.pValue,
1084
0
                                  att->attrib.ulValueLen);
1085
0
            sftk_FreeAttribute(att);
1086
0
            if (context->cipherInfo == NULL) {
1087
0
                crv = CKR_HOST_MEMORY; /* WRONG !!! */
1088
0
                break;
1089
0
            }
1090
0
            context->update = isEncrypt ? SFTKCipher_RC4_Encrypt : SFTKCipher_RC4_Decrypt;
1091
0
            context->destroy = SFTKCipher_RC4_DestroyContext;
1092
0
            break;
1093
0
        case CKM_CDMF_CBC_PAD:
1094
0
            context->doPad = PR_TRUE;
1095
        /* fall thru */
1096
0
        case CKM_CDMF_ECB:
1097
0
        case CKM_CDMF_CBC:
1098
0
            if (key_type != CKK_CDMF) {
1099
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1100
0
                break;
1101
0
            }
1102
0
            t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;
1103
0
            goto finish_des;
1104
2
        case CKM_DES_ECB:
1105
2
            if (key_type != CKK_DES) {
1106
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1107
0
                break;
1108
0
            }
1109
2
            t = NSS_DES;
1110
2
            goto finish_des;
1111
0
        case CKM_DES_CBC_PAD:
1112
0
            context->doPad = PR_TRUE;
1113
        /* fall thru */
1114
2
        case CKM_DES_CBC:
1115
2
            if (key_type != CKK_DES) {
1116
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1117
0
                break;
1118
0
            }
1119
2
            t = NSS_DES_CBC;
1120
2
            goto finish_des;
1121
0
        case CKM_DES3_ECB:
1122
0
            if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
1123
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1124
0
                break;
1125
0
            }
1126
0
            t = NSS_DES_EDE3;
1127
0
            goto finish_des;
1128
0
        case CKM_DES3_CBC_PAD:
1129
0
            context->doPad = PR_TRUE;
1130
        /* fall thru */
1131
0
        case CKM_DES3_CBC:
1132
0
            if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
1133
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1134
0
                break;
1135
0
            }
1136
0
            t = NSS_DES_EDE3_CBC;
1137
4
        finish_des:
1138
4
            if ((t != NSS_DES && t != NSS_DES_EDE3) && (pMechanism->pParameter == NULL ||
1139
2
                                                        pMechanism->ulParameterLen < 8)) {
1140
1
                crv = CKR_DOMAIN_PARAMS_INVALID;
1141
1
                break;
1142
1
            }
1143
3
            context->blockSize = 8;
1144
3
            att = sftk_FindAttribute(key, CKA_VALUE);
1145
3
            if (att == NULL) {
1146
0
                crv = CKR_KEY_HANDLE_INVALID;
1147
0
                break;
1148
0
            }
1149
3
            if (key_type == CKK_DES2 &&
1150
3
                (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) {
1151
                /* extend DES2 key to DES3 key. */
1152
0
                memcpy(newdeskey, att->attrib.pValue, 16);
1153
0
                memcpy(newdeskey + 16, newdeskey, 8);
1154
0
                useNewKey = PR_TRUE;
1155
3
            } else if (key_type == CKK_CDMF) {
1156
0
                crv = sftk_cdmf2des((unsigned char *)att->attrib.pValue, newdeskey);
1157
0
                if (crv != CKR_OK) {
1158
0
                    sftk_FreeAttribute(att);
1159
0
                    break;
1160
0
                }
1161
0
                useNewKey = PR_TRUE;
1162
0
            }
1163
3
            context->cipherInfo = DES_CreateContext(
1164
3
                useNewKey ? newdeskey : (unsigned char *)att->attrib.pValue,
1165
3
                (unsigned char *)pMechanism->pParameter, t, isEncrypt);
1166
3
            if (useNewKey)
1167
0
                memset(newdeskey, 0, sizeof newdeskey);
1168
3
            sftk_FreeAttribute(att);
1169
3
            if (context->cipherInfo == NULL) {
1170
0
                crv = CKR_HOST_MEMORY;
1171
0
                break;
1172
0
            }
1173
3
            context->update = isEncrypt ? SFTKCipher_DES_Encrypt : SFTKCipher_DES_Decrypt;
1174
3
            context->destroy = SFTKCipher_DES_DestroyContext;
1175
3
            break;
1176
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
1177
0
        case CKM_SEED_CBC_PAD:
1178
0
            context->doPad = PR_TRUE;
1179
        /* fall thru */
1180
4
        case CKM_SEED_CBC:
1181
4
            if (!pMechanism->pParameter ||
1182
4
                pMechanism->ulParameterLen != 16) {
1183
2
                crv = CKR_MECHANISM_PARAM_INVALID;
1184
2
                break;
1185
2
            }
1186
        /* fall thru */
1187
7
        case CKM_SEED_ECB:
1188
7
            context->blockSize = 16;
1189
7
            if (key_type != CKK_SEED) {
1190
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1191
0
                break;
1192
0
            }
1193
7
            att = sftk_FindAttribute(key, CKA_VALUE);
1194
7
            if (att == NULL) {
1195
0
                crv = CKR_KEY_HANDLE_INVALID;
1196
0
                break;
1197
0
            }
1198
7
            context->cipherInfo = SEED_CreateContext(
1199
7
                (unsigned char *)att->attrib.pValue,
1200
7
                (unsigned char *)pMechanism->pParameter,
1201
7
                pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC,
1202
7
                isEncrypt);
1203
7
            sftk_FreeAttribute(att);
1204
7
            if (context->cipherInfo == NULL) {
1205
0
                crv = CKR_HOST_MEMORY;
1206
0
                break;
1207
0
            }
1208
7
            context->update = isEncrypt ? SFTKCipher_SEED_Encrypt : SFTKCipher_SEED_Decrypt;
1209
7
            context->destroy = SFTKCipher_SEED_DestroyContext;
1210
7
            break;
1211
0
#endif /* NSS_DISABLE_DEPRECATED_SEED */
1212
0
        case CKM_CAMELLIA_CBC_PAD:
1213
0
            context->doPad = PR_TRUE;
1214
        /* fall thru */
1215
2
        case CKM_CAMELLIA_CBC:
1216
2
            if (!pMechanism->pParameter ||
1217
2
                pMechanism->ulParameterLen != 16) {
1218
2
                crv = CKR_MECHANISM_PARAM_INVALID;
1219
2
                break;
1220
2
            }
1221
        /* fall thru */
1222
1
        case CKM_CAMELLIA_ECB:
1223
1
            context->blockSize = 16;
1224
1
            if (key_type != CKK_CAMELLIA) {
1225
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1226
0
                break;
1227
0
            }
1228
1
            att = sftk_FindAttribute(key, CKA_VALUE);
1229
1
            if (att == NULL) {
1230
0
                crv = CKR_KEY_HANDLE_INVALID;
1231
0
                break;
1232
0
            }
1233
1
            context->cipherInfo = Camellia_CreateContext(
1234
1
                (unsigned char *)att->attrib.pValue,
1235
1
                (unsigned char *)pMechanism->pParameter,
1236
1
                pMechanism->mechanism ==
1237
1
                        CKM_CAMELLIA_ECB
1238
1
                    ? NSS_CAMELLIA
1239
1
                    : NSS_CAMELLIA_CBC,
1240
1
                isEncrypt, att->attrib.ulValueLen);
1241
1
            sftk_FreeAttribute(att);
1242
1
            if (context->cipherInfo == NULL) {
1243
1
                crv = CKR_HOST_MEMORY;
1244
1
                break;
1245
1
            }
1246
0
            context->update = isEncrypt ? SFTKCipher_Camellia_Encrypt : SFTKCipher_Camellia_Decrypt;
1247
0
            context->destroy = SFTKCipher_Camellia_DestroyContext;
1248
0
            break;
1249
1250
0
        case CKM_AES_CBC_PAD:
1251
0
            context->doPad = PR_TRUE;
1252
        /* fall thru */
1253
4
        case CKM_AES_ECB:
1254
7
        case CKM_AES_CBC:
1255
7
            context->blockSize = 16;
1256
7
        case CKM_AES_CTS:
1257
7
        case CKM_AES_CTR:
1258
19
        case CKM_AES_GCM:
1259
19
            aes_param = pMechanism->pParameter;
1260
            /*
1261
             *  Due to a mismatch between the documentation and the header
1262
             *  file, two different definitions for CK_GCM_PARAMS exist.
1263
             *  The header file is normative according to Oasis, but NSS used
1264
             *  the documentation. In PKCS #11 v3.0, this was reconciled in
1265
             *  favor of the header file definition. To maintain binary
1266
             *  compatibility, NSS now defines CK_GCM_PARAMS_V3 as the official
1267
             *  version v3 (V2.4 header file) and CK_NSS_GCM_PARAMS as the
1268
             *  legacy (V2.4 documentation, NSS version). CK_GCM_PARAMS
1269
             *  is defined as CK_GCM_PARAMS_V3 if NSS_PKCS11_2_0_COMPAT is not
1270
             *  defined and CK_NSS_GCM_PARAMS if it is. Internally
1271
             *  softoken continues to use the legacy version. The code below
1272
             *  automatically detects which parameter was passed in and
1273
             *  converts CK_GCM_PARAMS_V3 to the CK_NSS_GCM_PARAMS (legacy
1274
             *  version) on the fly. NSS proper will eventually start
1275
             *  using the CK_GCM_PARAMS_V3 version and fall back to the
1276
             *  CK_NSS_GCM_PARAMS if the CK_GCM_PARAMS_V3 version fails with
1277
             *  CKR_MECHANISM_PARAM_INVALID.
1278
             */
1279
19
            if (pMechanism->mechanism == CKM_AES_GCM) {
1280
12
                if (!aes_param) {
1281
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1282
0
                    break;
1283
0
                }
1284
12
                if (pMechanism->ulParameterLen == sizeof(CK_GCM_PARAMS_V3)) {
1285
                    /* convert the true V3 parameters into the old NSS parameters */
1286
0
                    CK_GCM_PARAMS_V3 *gcm_params = (CK_GCM_PARAMS_V3 *)aes_param;
1287
0
                    if (gcm_params->ulIvLen * 8 != gcm_params->ulIvBits) {
1288
                        /* only support byte aligned IV lengths */
1289
0
                        crv = CKR_MECHANISM_PARAM_INVALID;
1290
0
                        break;
1291
0
                    }
1292
0
                    aes_param = (void *)&nss_gcm_param;
1293
0
                    nss_gcm_param.pIv = gcm_params->pIv;
1294
0
                    nss_gcm_param.ulIvLen = gcm_params->ulIvLen;
1295
0
                    nss_gcm_param.pAAD = gcm_params->pAAD;
1296
0
                    nss_gcm_param.ulAADLen = gcm_params->ulAADLen;
1297
0
                    nss_gcm_param.ulTagBits = gcm_params->ulTagBits;
1298
12
                } else if (pMechanism->ulParameterLen != sizeof(CK_NSS_GCM_PARAMS)) {
1299
                    /* neither old nor new style params, must be invalid */
1300
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1301
0
                    break;
1302
0
                }
1303
12
            } else if ((pMechanism->mechanism == CKM_AES_CTR && BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CTR_PARAMS))) ||
1304
7
                       ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CTS) && BAD_PARAM_CAST(pMechanism, AES_BLOCK_SIZE))) {
1305
1
                crv = CKR_MECHANISM_PARAM_INVALID;
1306
1
                break;
1307
1
            }
1308
1309
18
            if (pMechanism->mechanism == CKM_AES_GCM) {
1310
12
                context->multi = PR_FALSE;
1311
12
            }
1312
18
            if (key_type != CKK_AES) {
1313
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1314
0
                break;
1315
0
            }
1316
18
            att = sftk_FindAttribute(key, CKA_VALUE);
1317
18
            if (att == NULL) {
1318
0
                crv = CKR_KEY_HANDLE_INVALID;
1319
0
                break;
1320
0
            }
1321
18
            context->cipherInfo = AES_CreateContext(
1322
18
                (unsigned char *)att->attrib.pValue,
1323
18
                (unsigned char *)aes_param,
1324
18
                sftk_aes_mode(pMechanism->mechanism),
1325
18
                isEncrypt, att->attrib.ulValueLen, 16);
1326
18
            sftk_FreeAttribute(att);
1327
18
            if (context->cipherInfo == NULL) {
1328
11
                crv = CKR_HOST_MEMORY;
1329
11
                break;
1330
11
            }
1331
7
            context->update = isEncrypt ? SFTKCipher_AES_Encrypt : SFTKCipher_AES_Decrypt;
1332
7
            context->destroy = SFTKCipher_AES_DestroyContext;
1333
7
            break;
1334
1335
14
        case CKM_NSS_CHACHA20_POLY1305:
1336
14
        case CKM_CHACHA20_POLY1305:
1337
14
            if (pMechanism->mechanism == CKM_NSS_CHACHA20_POLY1305) {
1338
14
                if (key_type != CKK_NSS_CHACHA20) {
1339
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
1340
0
                    break;
1341
0
                }
1342
14
                if ((pMechanism->pParameter == NULL) ||
1343
14
                    (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS))) {
1344
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1345
0
                    break;
1346
0
                }
1347
14
                nss_aead_params_ptr = (CK_NSS_AEAD_PARAMS *)pMechanism->pParameter;
1348
14
            } else {
1349
0
                CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR chacha_poly_params;
1350
0
                if (key_type != CKK_CHACHA20) {
1351
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
1352
0
                    break;
1353
0
                }
1354
0
                if ((pMechanism->pParameter == NULL) ||
1355
0
                    (pMechanism->ulParameterLen !=
1356
0
                     sizeof(CK_SALSA20_CHACHA20_POLY1305_PARAMS))) {
1357
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1358
0
                    break;
1359
0
                }
1360
0
                chacha_poly_params = (CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR)
1361
0
                                         pMechanism->pParameter;
1362
0
                nss_aead_params_ptr = &nss_aead_params;
1363
0
                nss_aead_params.pNonce = chacha_poly_params->pNonce;
1364
0
                nss_aead_params.ulNonceLen = chacha_poly_params->ulNonceLen;
1365
0
                nss_aead_params.pAAD = chacha_poly_params->pAAD;
1366
0
                nss_aead_params.ulAADLen = chacha_poly_params->ulAADLen;
1367
0
                nss_aead_params.ulTagLen = 16; /* Poly1305 is always 16 */
1368
0
            }
1369
1370
14
            context->multi = PR_FALSE;
1371
14
            att = sftk_FindAttribute(key, CKA_VALUE);
1372
14
            if (att == NULL) {
1373
0
                crv = CKR_KEY_HANDLE_INVALID;
1374
0
                break;
1375
0
            }
1376
14
            context->cipherInfo = sftk_ChaCha20Poly1305_CreateContext(
1377
14
                (unsigned char *)att->attrib.pValue, att->attrib.ulValueLen,
1378
14
                nss_aead_params_ptr);
1379
14
            sftk_FreeAttribute(att);
1380
14
            if (context->cipherInfo == NULL) {
1381
7
                crv = sftk_MapCryptError(PORT_GetError());
1382
7
                break;
1383
7
            }
1384
7
            context->update = isEncrypt ? sftk_ChaCha20Poly1305_Encrypt : sftk_ChaCha20Poly1305_Decrypt;
1385
7
            context->destroy = sftk_ChaCha20Poly1305_DestroyContext;
1386
7
            break;
1387
1388
0
        case CKM_NSS_CHACHA20_CTR: /* old NSS private version */
1389
0
        case CKM_CHACHA20:         /* PKCS #11 v3 version */
1390
0
        {
1391
0
            unsigned char *counter;
1392
0
            unsigned char *nonce;
1393
0
            unsigned long counter_len;
1394
0
            unsigned long nonce_len;
1395
0
            context->multi = PR_FALSE;
1396
0
            if (pMechanism->mechanism == CKM_NSS_CHACHA20_CTR) {
1397
0
                if (key_type != CKK_NSS_CHACHA20) {
1398
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
1399
0
                    break;
1400
0
                }
1401
0
                if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) {
1402
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1403
0
                    break;
1404
0
                }
1405
0
                counter_len = 4;
1406
0
                counter = pMechanism->pParameter;
1407
0
                nonce = counter + 4;
1408
0
                nonce_len = 12;
1409
0
            } else {
1410
0
                CK_CHACHA20_PARAMS_PTR chacha20_param_ptr;
1411
0
                if (key_type != CKK_CHACHA20) {
1412
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
1413
0
                    break;
1414
0
                }
1415
0
                if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != sizeof(CK_CHACHA20_PARAMS)) {
1416
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1417
0
                    break;
1418
0
                }
1419
0
                chacha20_param_ptr = (CK_CHACHA20_PARAMS_PTR)pMechanism->pParameter;
1420
0
                if ((chacha20_param_ptr->blockCounterBits != 32) &&
1421
0
                    (chacha20_param_ptr->blockCounterBits != 64)) {
1422
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1423
0
                    break;
1424
0
                }
1425
0
                counter_len = chacha20_param_ptr->blockCounterBits / PR_BITS_PER_BYTE;
1426
0
                counter = chacha20_param_ptr->pBlockCounter;
1427
0
                nonce = chacha20_param_ptr->pNonce;
1428
0
                nonce_len = chacha20_param_ptr->ulNonceBits / PR_BITS_PER_BYTE;
1429
0
            }
1430
1431
0
            att = sftk_FindAttribute(key, CKA_VALUE);
1432
0
            if (att == NULL) {
1433
0
                crv = CKR_KEY_HANDLE_INVALID;
1434
0
                break;
1435
0
            }
1436
0
            SFTKChaCha20CtrInfo *ctx = PORT_ZNew(SFTKChaCha20CtrInfo);
1437
0
            if (!ctx) {
1438
0
                sftk_FreeAttribute(att);
1439
0
                crv = CKR_HOST_MEMORY;
1440
0
                break;
1441
0
            }
1442
0
            if (att->attrib.ulValueLen != sizeof(ctx->key)) {
1443
0
                sftk_FreeAttribute(att);
1444
0
                PORT_Free(ctx);
1445
0
                crv = CKR_KEY_HANDLE_INVALID;
1446
0
                break;
1447
0
            }
1448
0
            memcpy(ctx->key, att->attrib.pValue, att->attrib.ulValueLen);
1449
0
            sftk_FreeAttribute(att);
1450
1451
            /* make sure we don't overflow our parameters */
1452
0
            if ((sizeof(ctx->counter) < counter_len) ||
1453
0
                (sizeof(ctx->nonce) < nonce_len)) {
1454
0
                PORT_Free(ctx);
1455
0
                crv = CKR_MECHANISM_PARAM_INVALID;
1456
0
                break;
1457
0
            }
1458
1459
            /* The counter is little endian. */
1460
0
            int i = 0;
1461
0
            for (; i < counter_len; ++i) {
1462
0
                ctx->counter |= (PRUint32)counter[i] << (i * 8);
1463
0
            }
1464
0
            memcpy(ctx->nonce, nonce, nonce_len);
1465
0
            context->cipherInfo = ctx;
1466
0
            context->update = sftk_ChaCha20Ctr;
1467
0
            context->destroy = sftk_ChaCha20Ctr_DestroyContext;
1468
0
            break;
1469
0
        }
1470
1471
0
        case CKM_NSS_AES_KEY_WRAP_PAD:
1472
0
        case CKM_AES_KEY_WRAP_PAD:
1473
0
            context->doPad = PR_TRUE;
1474
        /* fall thru */
1475
0
        case CKM_NSS_AES_KEY_WRAP:
1476
0
        case CKM_AES_KEY_WRAP:
1477
0
            context->blockSize = 8;
1478
0
        case CKM_AES_KEY_WRAP_KWP:
1479
0
            context->multi = PR_FALSE;
1480
0
            if (key_type != CKK_AES) {
1481
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1482
0
                break;
1483
0
            }
1484
0
            att = sftk_FindAttribute(key, CKA_VALUE);
1485
0
            if (att == NULL) {
1486
0
                crv = CKR_KEY_HANDLE_INVALID;
1487
0
                break;
1488
0
            }
1489
0
            context->cipherInfo = AESKeyWrap_CreateContext(
1490
0
                (unsigned char *)att->attrib.pValue,
1491
0
                (unsigned char *)pMechanism->pParameter,
1492
0
                isEncrypt, att->attrib.ulValueLen);
1493
0
            sftk_FreeAttribute(att);
1494
0
            if (context->cipherInfo == NULL) {
1495
0
                crv = CKR_HOST_MEMORY;
1496
0
                break;
1497
0
            }
1498
0
            if (pMechanism->mechanism == CKM_AES_KEY_WRAP_KWP) {
1499
0
                context->update = isEncrypt ? SFTKCipher_AESKeyWrap_EncryptKWP
1500
0
                                            : SFTKCipher_AESKeyWrap_DecryptKWP;
1501
0
            } else {
1502
0
                context->update = isEncrypt ? SFTKCipher_AESKeyWrap_Encrypt
1503
0
                                            : SFTKCipher_AESKeyWrap_Decrypt;
1504
0
            }
1505
0
            context->destroy = SFTKCipher_AESKeyWrap_DestroyContext;
1506
0
            break;
1507
1508
0
        default:
1509
0
            crv = CKR_MECHANISM_INVALID;
1510
0
            break;
1511
49
    }
1512
1513
49
    if (crv != CKR_OK) {
1514
25
        sftk_FreeContext(context);
1515
25
        sftk_FreeSession(session);
1516
25
        return crv;
1517
25
    }
1518
24
    sftk_SetContextByType(session, contextType, context);
1519
24
    sftk_FreeSession(session);
1520
24
    return CKR_OK;
1521
49
}
1522
1523
/* NSC_EncryptInit initializes an encryption operation. */
1524
CK_RV
1525
NSC_EncryptInit(CK_SESSION_HANDLE hSession,
1526
                CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1527
28
{
1528
28
    CHECK_FORK();
1529
28
    return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT,
1530
28
                          SFTK_ENCRYPT, PR_TRUE);
1531
28
}
1532
1533
/* NSC_EncryptUpdate continues a multiple-part encryption operation. */
1534
CK_RV
1535
NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,
1536
                  CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
1537
                  CK_ULONG_PTR pulEncryptedPartLen)
1538
3
{
1539
3
    SFTKSessionContext *context;
1540
3
    unsigned int outlen, i;
1541
3
    unsigned int padoutlen = 0;
1542
3
    unsigned int maxout = *pulEncryptedPartLen;
1543
3
    CK_RV crv;
1544
3
    SECStatus rv;
1545
1546
3
    CHECK_FORK();
1547
1548
    /* make sure we're legal */
1549
3
    crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, NULL);
1550
3
    if (crv != CKR_OK)
1551
0
        return crv;
1552
1553
3
    if (!pEncryptedPart) {
1554
0
        if (context->doPad) {
1555
0
            CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength;
1556
0
            CK_ULONG blocksToSend = totalDataAvailable / context->blockSize;
1557
1558
0
            *pulEncryptedPartLen = blocksToSend * context->blockSize;
1559
0
            return CKR_OK;
1560
0
        }
1561
0
        *pulEncryptedPartLen = ulPartLen;
1562
0
        return CKR_OK;
1563
0
    }
1564
1565
    /* do padding */
1566
3
    if (context->doPad) {
1567
        /* deal with previous buffered data */
1568
0
        if (context->padDataLength != 0) {
1569
            /* fill in the padded to a full block size */
1570
0
            for (i = context->padDataLength;
1571
0
                 (ulPartLen != 0) && i < context->blockSize; i++) {
1572
0
                context->padBuf[i] = *pPart++;
1573
0
                ulPartLen--;
1574
0
                context->padDataLength++;
1575
0
            }
1576
1577
            /* not enough data to encrypt yet? then return */
1578
0
            if (context->padDataLength != context->blockSize) {
1579
0
                *pulEncryptedPartLen = 0;
1580
0
                return CKR_OK;
1581
0
            }
1582
            /* encrypt the current padded data */
1583
0
            rv = (*context->update)(context->cipherInfo, pEncryptedPart,
1584
0
                                    &padoutlen, maxout, context->padBuf,
1585
0
                                    context->blockSize);
1586
0
            if (rv != SECSuccess) {
1587
0
                return sftk_MapCryptError(PORT_GetError());
1588
0
            }
1589
0
            pEncryptedPart += padoutlen;
1590
0
            maxout -= padoutlen;
1591
0
        }
1592
        /* save the residual */
1593
0
        context->padDataLength = ulPartLen % context->blockSize;
1594
0
        if (context->padDataLength) {
1595
0
            PORT_Memcpy(context->padBuf,
1596
0
                        &pPart[ulPartLen - context->padDataLength],
1597
0
                        context->padDataLength);
1598
0
            ulPartLen -= context->padDataLength;
1599
0
        }
1600
        /* if we've exhausted our new buffer, we're done */
1601
0
        if (ulPartLen == 0) {
1602
0
            *pulEncryptedPartLen = padoutlen;
1603
0
            return CKR_OK;
1604
0
        }
1605
0
    }
1606
1607
    /* do it: NOTE: this assumes buf size in is >= buf size out! */
1608
3
    rv = (*context->update)(context->cipherInfo, pEncryptedPart,
1609
3
                            &outlen, maxout, pPart, ulPartLen);
1610
3
    if (rv != SECSuccess) {
1611
3
        return sftk_MapCryptError(PORT_GetError());
1612
3
    }
1613
0
    *pulEncryptedPartLen = (CK_ULONG)(outlen + padoutlen);
1614
0
    return CKR_OK;
1615
3
}
1616
1617
/* NSC_EncryptFinal finishes a multiple-part encryption operation. */
1618
CK_RV
1619
NSC_EncryptFinal(CK_SESSION_HANDLE hSession,
1620
                 CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
1621
0
{
1622
0
    SFTKSession *session;
1623
0
    SFTKSessionContext *context;
1624
0
    unsigned int outlen, i;
1625
0
    unsigned int maxout = *pulLastEncryptedPartLen;
1626
0
    CK_RV crv;
1627
0
    SECStatus rv = SECSuccess;
1628
0
    PRBool contextFinished = PR_TRUE;
1629
1630
0
    CHECK_FORK();
1631
1632
    /* make sure we're legal */
1633
0
    crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, &session);
1634
0
    if (crv != CKR_OK)
1635
0
        return crv;
1636
1637
0
    *pulLastEncryptedPartLen = 0;
1638
0
    if (!pLastEncryptedPart) {
1639
        /* caller is checking the amount of remaining data */
1640
0
        if (context->blockSize > 0 && context->doPad) {
1641
0
            *pulLastEncryptedPartLen = context->blockSize;
1642
0
            contextFinished = PR_FALSE; /* still have padding to go */
1643
0
        }
1644
0
        goto finish;
1645
0
    }
1646
1647
    /* do padding */
1648
0
    if (context->doPad) {
1649
0
        unsigned char padbyte = (unsigned char)(context->blockSize - context->padDataLength);
1650
        /* fill out rest of pad buffer with pad magic*/
1651
0
        for (i = context->padDataLength; i < context->blockSize; i++) {
1652
0
            context->padBuf[i] = padbyte;
1653
0
        }
1654
0
        rv = (*context->update)(context->cipherInfo, pLastEncryptedPart,
1655
0
                                &outlen, maxout, context->padBuf, context->blockSize);
1656
0
        if (rv == SECSuccess)
1657
0
            *pulLastEncryptedPartLen = (CK_ULONG)outlen;
1658
0
    }
1659
1660
0
finish:
1661
0
    if (contextFinished)
1662
0
        sftk_TerminateOp(session, SFTK_ENCRYPT, context);
1663
0
    sftk_FreeSession(session);
1664
0
    return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
1665
0
}
1666
1667
/* NSC_Encrypt encrypts single-part data. */
1668
CK_RV
1669
NSC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
1670
            CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
1671
            CK_ULONG_PTR pulEncryptedDataLen)
1672
4
{
1673
4
    SFTKSession *session;
1674
4
    SFTKSessionContext *context;
1675
4
    unsigned int outlen;
1676
4
    unsigned int maxoutlen = *pulEncryptedDataLen;
1677
4
    CK_RV crv;
1678
4
    CK_RV crv2;
1679
4
    SECStatus rv = SECSuccess;
1680
4
    SECItem pText;
1681
1682
4
    pText.type = siBuffer;
1683
4
    pText.data = pData;
1684
4
    pText.len = ulDataLen;
1685
1686
4
    CHECK_FORK();
1687
1688
    /* make sure we're legal */
1689
4
    crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, &session);
1690
4
    if (crv != CKR_OK)
1691
0
        return crv;
1692
1693
4
    if (!pEncryptedData) {
1694
0
        outlen = context->rsa ? context->maxLen : ulDataLen + 2 * context->blockSize;
1695
0
        goto done;
1696
0
    }
1697
1698
4
    if (context->doPad) {
1699
0
        if (context->multi) {
1700
0
            CK_ULONG updateLen = maxoutlen;
1701
0
            CK_ULONG finalLen;
1702
            /* padding is fairly complicated, have the update and final
1703
             * code deal with it */
1704
0
            sftk_FreeSession(session);
1705
0
            crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData,
1706
0
                                    &updateLen);
1707
0
            if (crv != CKR_OK) {
1708
0
                updateLen = 0;
1709
0
            }
1710
0
            maxoutlen -= updateLen;
1711
0
            pEncryptedData += updateLen;
1712
0
            finalLen = maxoutlen;
1713
0
            crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen);
1714
0
            if (crv == CKR_OK && crv2 == CKR_OK) {
1715
0
                *pulEncryptedDataLen = updateLen + finalLen;
1716
0
            }
1717
0
            return crv == CKR_OK ? crv2 : crv;
1718
0
        }
1719
        /* doPad without multi means that padding must be done on the first
1720
        ** and only update.  There will be no final.
1721
        */
1722
0
        PORT_Assert(context->blockSize > 1);
1723
0
        if (context->blockSize > 1) {
1724
0
            CK_ULONG remainder = ulDataLen % context->blockSize;
1725
0
            CK_ULONG padding = context->blockSize - remainder;
1726
0
            pText.len += padding;
1727
0
            pText.data = PORT_ZAlloc(pText.len);
1728
0
            if (pText.data) {
1729
0
                memcpy(pText.data, pData, ulDataLen);
1730
0
                memset(pText.data + ulDataLen, padding, padding);
1731
0
            } else {
1732
0
                crv = CKR_HOST_MEMORY;
1733
0
                goto fail;
1734
0
            }
1735
0
        }
1736
0
    }
1737
1738
    /* do it: NOTE: this assumes buf size is big enough. */
1739
4
    rv = (*context->update)(context->cipherInfo, pEncryptedData,
1740
4
                            &outlen, maxoutlen, pText.data, pText.len);
1741
4
    crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
1742
4
    if (pText.data != pData)
1743
0
        PORT_ZFree(pText.data, pText.len);
1744
4
fail:
1745
4
    sftk_TerminateOp(session, SFTK_ENCRYPT, context);
1746
4
done:
1747
4
    sftk_FreeSession(session);
1748
4
    if (crv == CKR_OK) {
1749
0
        *pulEncryptedDataLen = (CK_ULONG)outlen;
1750
0
    }
1751
4
    return crv;
1752
4
}
1753
1754
/*
1755
 ************** Crypto Functions:     Decrypt ************************
1756
 */
1757
1758
/* NSC_DecryptInit initializes a decryption operation. */
1759
CK_RV
1760
NSC_DecryptInit(CK_SESSION_HANDLE hSession,
1761
                CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1762
33
{
1763
33
    CHECK_FORK();
1764
33
    return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT,
1765
33
                          SFTK_DECRYPT, PR_FALSE);
1766
33
}
1767
1768
/* NSC_DecryptUpdate continues a multiple-part decryption operation. */
1769
CK_RV
1770
NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
1771
                  CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
1772
                  CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
1773
6
{
1774
6
    SFTKSessionContext *context;
1775
6
    unsigned int padoutlen = 0;
1776
6
    unsigned int outlen;
1777
6
    unsigned int maxout = *pulPartLen;
1778
6
    CK_RV crv;
1779
6
    SECStatus rv;
1780
1781
6
    CHECK_FORK();
1782
1783
    /* make sure we're legal */
1784
6
    crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, NULL);
1785
6
    if (crv != CKR_OK)
1786
0
        return crv;
1787
1788
    /* this can only happen on an NSS programming error */
1789
6
    PORT_Assert((context->padDataLength == 0) || context->padDataLength == context->blockSize);
1790
1791
6
    if (context->doPad) {
1792
        /* Check the data length for block ciphers. If we are padding,
1793
         * then we must be using a block cipher. In the non-padding case
1794
         * the error will be returned by the underlying decryption
1795
         * function when we do the actual decrypt. We need to do the
1796
         * check here to avoid returning a negative length to the caller
1797
         * or reading before the beginning of the pEncryptedPart buffer.
1798
         */
1799
0
        if ((ulEncryptedPartLen == 0) ||
1800
0
            (ulEncryptedPartLen % context->blockSize) != 0) {
1801
0
            return CKR_ENCRYPTED_DATA_LEN_RANGE;
1802
0
        }
1803
0
    }
1804
1805
6
    if (!pPart) {
1806
0
        if (context->doPad) {
1807
0
            *pulPartLen =
1808
0
                ulEncryptedPartLen + context->padDataLength - context->blockSize;
1809
0
            return CKR_OK;
1810
0
        }
1811
        /* for stream ciphers there is are no constraints on ulEncryptedPartLen.
1812
         * for block ciphers, it must be a multiple of blockSize. The error is
1813
         * detected when this function is called again do decrypt the output.
1814
         */
1815
0
        *pulPartLen = ulEncryptedPartLen;
1816
0
        return CKR_OK;
1817
0
    }
1818
1819
6
    if (context->doPad) {
1820
        /* first decrypt our saved buffer */
1821
0
        if (context->padDataLength != 0) {
1822
0
            rv = (*context->update)(context->cipherInfo, pPart, &padoutlen,
1823
0
                                    maxout, context->padBuf, context->blockSize);
1824
0
            if (rv != SECSuccess)
1825
0
                return sftk_MapDecryptError(PORT_GetError());
1826
0
            pPart += padoutlen;
1827
0
            maxout -= padoutlen;
1828
0
        }
1829
        /* now save the final block for the next decrypt or the final */
1830
0
        PORT_Memcpy(context->padBuf, &pEncryptedPart[ulEncryptedPartLen - context->blockSize],
1831
0
                    context->blockSize);
1832
0
        context->padDataLength = context->blockSize;
1833
0
        ulEncryptedPartLen -= context->padDataLength;
1834
0
    }
1835
1836
    /* do it: NOTE: this assumes buf size in is >= buf size out! */
1837
6
    rv = (*context->update)(context->cipherInfo, pPart, &outlen,
1838
6
                            maxout, pEncryptedPart, ulEncryptedPartLen);
1839
6
    if (rv != SECSuccess) {
1840
5
        return sftk_MapDecryptError(PORT_GetError());
1841
5
    }
1842
1
    *pulPartLen = (CK_ULONG)(outlen + padoutlen);
1843
1
    return CKR_OK;
1844
6
}
1845
1846
/* NSC_DecryptFinal finishes a multiple-part decryption operation. */
1847
CK_RV
1848
NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
1849
                 CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen)
1850
0
{
1851
0
    SFTKSession *session;
1852
0
    SFTKSessionContext *context;
1853
0
    unsigned int outlen;
1854
0
    unsigned int maxout = *pulLastPartLen;
1855
0
    CK_RV crv;
1856
0
    SECStatus rv = SECSuccess;
1857
1858
0
    CHECK_FORK();
1859
1860
    /* make sure we're legal */
1861
0
    crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, &session);
1862
0
    if (crv != CKR_OK)
1863
0
        return crv;
1864
1865
0
    *pulLastPartLen = 0;
1866
0
    if (!pLastPart) {
1867
        /* caller is checking the amount of remaining data */
1868
0
        if (context->padDataLength > 0) {
1869
0
            *pulLastPartLen = context->padDataLength;
1870
0
        }
1871
0
        goto finish;
1872
0
    }
1873
1874
0
    if (context->doPad) {
1875
        /* decrypt our saved buffer */
1876
0
        if (context->padDataLength != 0) {
1877
            /* this assumes that pLastPart is big enough to hold the *whole*
1878
             * buffer!!! */
1879
0
            rv = (*context->update)(context->cipherInfo, pLastPart, &outlen,
1880
0
                                    maxout, context->padBuf, context->blockSize);
1881
0
            if (rv != SECSuccess) {
1882
0
                crv = sftk_MapDecryptError(PORT_GetError());
1883
0
            } else {
1884
0
                unsigned int padSize = 0;
1885
0
                crv = sftk_CheckCBCPadding(pLastPart, outlen,
1886
0
                                           context->blockSize, &padSize);
1887
                /* Update pulLastPartLen, in constant time, if crv is OK */
1888
0
                *pulLastPartLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulLastPartLen);
1889
0
            }
1890
0
        }
1891
0
    }
1892
1893
0
    sftk_TerminateOp(session, SFTK_DECRYPT, context);
1894
0
finish:
1895
0
    sftk_FreeSession(session);
1896
0
    return crv;
1897
0
}
1898
1899
/* NSC_Decrypt decrypts encrypted data in a single part. */
1900
CK_RV
1901
NSC_Decrypt(CK_SESSION_HANDLE hSession,
1902
            CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
1903
            CK_ULONG_PTR pulDataLen)
1904
12
{
1905
12
    SFTKSession *session;
1906
12
    SFTKSessionContext *context;
1907
12
    unsigned int outlen;
1908
12
    unsigned int maxoutlen = *pulDataLen;
1909
12
    CK_RV crv;
1910
12
    CK_RV crv2;
1911
12
    SECStatus rv = SECSuccess;
1912
1913
12
    CHECK_FORK();
1914
1915
    /* make sure we're legal */
1916
12
    crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_FALSE, &session);
1917
12
    if (crv != CKR_OK)
1918
0
        return crv;
1919
1920
12
    if (!pData) {
1921
0
        *pulDataLen = (CK_ULONG)(ulEncryptedDataLen + context->blockSize);
1922
0
        goto done;
1923
0
    }
1924
1925
12
    if (context->doPad && context->multi) {
1926
0
        CK_ULONG updateLen = maxoutlen;
1927
0
        CK_ULONG finalLen;
1928
        /* padding is fairly complicated, have the update and final
1929
         * code deal with it */
1930
0
        sftk_FreeSession(session);
1931
0
        crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
1932
0
                                pData, &updateLen);
1933
0
        if (crv == CKR_OK) {
1934
0
            maxoutlen -= updateLen;
1935
0
            pData += updateLen;
1936
0
        }
1937
0
        finalLen = maxoutlen;
1938
0
        crv2 = NSC_DecryptFinal(hSession, pData, &finalLen);
1939
0
        if (crv == CKR_OK) {
1940
0
            *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv2), updateLen + finalLen, *pulDataLen);
1941
0
            return crv2;
1942
0
        } else {
1943
0
            return crv;
1944
0
        }
1945
0
    }
1946
1947
12
    rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
1948
12
                            pEncryptedData, ulEncryptedDataLen);
1949
    /* XXX need to do MUCH better error mapping than this. */
1950
12
    crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
1951
12
    if (rv == SECSuccess) {
1952
1
        if (context->doPad) {
1953
0
            unsigned int padSize = 0;
1954
0
            crv = sftk_CheckCBCPadding(pData, outlen, context->blockSize,
1955
0
                                       &padSize);
1956
            /* Update pulDataLen, in constant time, if crv is OK */
1957
0
            *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulDataLen);
1958
1
        } else {
1959
1
            *pulDataLen = (CK_ULONG)outlen;
1960
1
        }
1961
1
    }
1962
12
    sftk_TerminateOp(session, SFTK_DECRYPT, context);
1963
12
done:
1964
12
    sftk_FreeSession(session);
1965
12
    return crv;
1966
12
}
1967
1968
/*
1969
 ************** Crypto Functions:     Digest (HASH)  ************************
1970
 */
1971
1972
/* NSC_DigestInit initializes a message-digesting operation. */
1973
CK_RV
1974
NSC_DigestInit(CK_SESSION_HANDLE hSession,
1975
               CK_MECHANISM_PTR pMechanism)
1976
64
{
1977
64
    SFTKSession *session;
1978
64
    SFTKSessionContext *context;
1979
64
    CK_RV crv = CKR_OK;
1980
1981
64
    CHECK_FORK();
1982
1983
64
    session = sftk_SessionFromHandle(hSession);
1984
64
    if (session == NULL)
1985
0
        return CKR_SESSION_HANDLE_INVALID;
1986
64
    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_HASH,
1987
64
                           NULL, 0, NULL, 0, CKA_DIGEST);
1988
64
    if (crv != CKR_OK) {
1989
0
        sftk_FreeSession(session);
1990
0
        return crv;
1991
0
    }
1992
1993
64
#define INIT_MECH(mmm)                                         \
1994
64
    case CKM_##mmm: {                                          \
1995
64
        mmm##Context *mmm##_ctx = mmm##_NewContext();          \
1996
64
        context->cipherInfo = (void *)mmm##_ctx;               \
1997
64
        context->cipherInfoLen = mmm##_FlattenSize(mmm##_ctx); \
1998
64
        context->currentMech = CKM_##mmm;                      \
1999
64
        context->hashUpdate = SFTKHash_##mmm##_Update;         \
2000
64
        context->end = SFTKHash_##mmm##_End;                   \
2001
64
        context->destroy = SFTKHash_##mmm##_DestroyContext;    \
2002
64
        context->maxLen = mmm##_LENGTH;                        \
2003
64
        if (mmm##_ctx)                                         \
2004
64
            mmm##_Begin(mmm##_ctx);                            \
2005
64
        else                                                   \
2006
64
            crv = CKR_HOST_MEMORY;                             \
2007
64
        break;                                                 \
2008
64
    }
2009
2010
64
    switch (pMechanism->mechanism) {
2011
0
        INIT_MECH(MD2)
2012
9
        INIT_MECH(MD5)
2013
11
        INIT_MECH(SHA1)
2014
5
        INIT_MECH(SHA224)
2015
20
        INIT_MECH(SHA256)
2016
9
        INIT_MECH(SHA384)
2017
10
        INIT_MECH(SHA512)
2018
0
        INIT_MECH(SHA3_224)
2019
0
        INIT_MECH(SHA3_256)
2020
0
        INIT_MECH(SHA3_384)
2021
0
        INIT_MECH(SHA3_512)
2022
2023
0
        default:
2024
0
            crv = CKR_MECHANISM_INVALID;
2025
0
            break;
2026
64
    }
2027
2028
64
    if (crv != CKR_OK) {
2029
0
        sftk_FreeContext(context);
2030
0
        sftk_FreeSession(session);
2031
0
        return crv;
2032
0
    }
2033
64
    sftk_SetContextByType(session, SFTK_HASH, context);
2034
64
    sftk_FreeSession(session);
2035
64
    return CKR_OK;
2036
64
}
2037
2038
/* NSC_Digest digests data in a single part. */
2039
CK_RV
2040
NSC_Digest(CK_SESSION_HANDLE hSession,
2041
           CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,
2042
           CK_ULONG_PTR pulDigestLen)
2043
0
{
2044
0
    SFTKSession *session;
2045
0
    SFTKSessionContext *context;
2046
0
    unsigned int digestLen;
2047
0
    unsigned int maxout = *pulDigestLen;
2048
0
    CK_RV crv;
2049
2050
0
    CHECK_FORK();
2051
2052
    /* make sure we're legal */
2053
0
    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_FALSE, &session);
2054
0
    if (crv != CKR_OK)
2055
0
        return crv;
2056
2057
0
    if (pDigest == NULL) {
2058
0
        *pulDigestLen = context->maxLen;
2059
0
        goto finish;
2060
0
    }
2061
2062
0
#if (ULONG_MAX > UINT_MAX)
2063
    /* The context->hashUpdate function takes an unsigned int for its data
2064
     * length argument, but NSC_Digest takes an unsigned long. */
2065
0
    while (ulDataLen > UINT_MAX) {
2066
0
        (*context->hashUpdate)(context->cipherInfo, pData, UINT_MAX);
2067
0
        pData += UINT_MAX;
2068
0
        ulDataLen -= UINT_MAX;
2069
0
    }
2070
0
#endif
2071
0
    (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen);
2072
2073
    /*  NOTE: this assumes buf size is bigenough for the algorithm */
2074
0
    (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
2075
0
    *pulDigestLen = digestLen;
2076
2077
0
    sftk_TerminateOp(session, SFTK_HASH, context);
2078
0
finish:
2079
0
    sftk_FreeSession(session);
2080
0
    return CKR_OK;
2081
0
}
2082
2083
/* NSC_DigestUpdate continues a multiple-part message-digesting operation. */
2084
CK_RV
2085
NSC_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
2086
                 CK_ULONG ulPartLen)
2087
667
{
2088
667
    SFTKSessionContext *context;
2089
667
    CK_RV crv;
2090
2091
667
    CHECK_FORK();
2092
2093
    /* make sure we're legal */
2094
667
    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, NULL);
2095
667
    if (crv != CKR_OK)
2096
0
        return crv;
2097
2098
667
#if (ULONG_MAX > UINT_MAX)
2099
    /* The context->hashUpdate function takes an unsigned int for its data
2100
     * length argument, but NSC_DigestUpdate takes an unsigned long. */
2101
667
    while (ulPartLen > UINT_MAX) {
2102
0
        (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX);
2103
0
        pPart += UINT_MAX;
2104
0
        ulPartLen -= UINT_MAX;
2105
0
    }
2106
667
#endif
2107
667
    (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen);
2108
2109
667
    return CKR_OK;
2110
667
}
2111
2112
/* NSC_DigestFinal finishes a multiple-part message-digesting operation. */
2113
CK_RV
2114
NSC_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
2115
                CK_ULONG_PTR pulDigestLen)
2116
64
{
2117
64
    SFTKSession *session;
2118
64
    SFTKSessionContext *context;
2119
64
    unsigned int maxout = *pulDigestLen;
2120
64
    unsigned int digestLen;
2121
64
    CK_RV crv;
2122
2123
64
    CHECK_FORK();
2124
2125
    /* make sure we're legal */
2126
64
    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
2127
64
    if (crv != CKR_OK)
2128
0
        return crv;
2129
2130
64
    if (pDigest != NULL) {
2131
64
        (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
2132
64
        *pulDigestLen = digestLen;
2133
64
        sftk_TerminateOp(session, SFTK_HASH, context);
2134
64
    } else {
2135
0
        *pulDigestLen = context->maxLen;
2136
0
    }
2137
2138
64
    sftk_FreeSession(session);
2139
64
    return CKR_OK;
2140
64
}
2141
2142
/*
2143
 * these helper functions are used by Generic Macing and Signing functions
2144
 * that use hashes as part of their operations.
2145
 */
2146
#define DOSUB(mmm)                                              \
2147
    static CK_RV                                                \
2148
        sftk_doSub##mmm(SFTKSessionContext *context)            \
2149
0
    {                                                           \
2150
0
        mmm##Context *mmm##_ctx = mmm##_NewContext();           \
2151
0
        context->hashInfo = (void *)mmm##_ctx;                  \
2152
0
        context->hashUpdate = SFTKHash_##mmm##_Update;          \
2153
0
        context->end = SFTKHash_##mmm##_End;                    \
2154
0
        context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \
2155
0
        if (!context->hashInfo) {                               \
2156
0
            return CKR_HOST_MEMORY;                             \
2157
0
        }                                                       \
2158
0
        mmm##_Begin(mmm##_ctx);                                 \
2159
0
        return CKR_OK;                                          \
2160
0
    }
Unexecuted instantiation: pkcs11c.c:sftk_doSubMD5
Unexecuted instantiation: pkcs11c.c:sftk_doSubMD2
Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA1
Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA224
Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA256
Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA384
Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA512
2161
2162
DOSUB(MD2)
2163
DOSUB(MD5)
2164
DOSUB(SHA1)
2165
DOSUB(SHA224)
2166
DOSUB(SHA256)
2167
DOSUB(SHA384)
2168
DOSUB(SHA512)
2169
2170
static SECStatus
2171
sftk_SignCopy(
2172
    void *copyLen,
2173
    unsigned char *out, unsigned int *outLength,
2174
    unsigned int maxLength,
2175
    const unsigned char *hashResult,
2176
    unsigned int hashResultLength)
2177
69
{
2178
69
    unsigned int toCopy = *(CK_ULONG *)copyLen;
2179
69
    if (toCopy > maxLength) {
2180
0
        toCopy = maxLength;
2181
0
    }
2182
69
    if (toCopy > hashResultLength) {
2183
0
        toCopy = hashResultLength;
2184
0
    }
2185
69
    memcpy(out, hashResult, toCopy);
2186
69
    if (outLength) {
2187
69
        *outLength = toCopy;
2188
69
    }
2189
69
    return SECSuccess;
2190
69
}
2191
2192
/* Verify is just a compare for HMAC */
2193
static SECStatus
2194
sftk_HMACCmp(void *copyLen, const unsigned char *sig, unsigned int sigLen,
2195
             const unsigned char *hash, unsigned int hashLen)
2196
0
{
2197
0
    if (NSS_SecureMemcmp(sig, hash, *(CK_ULONG *)copyLen) == 0) {
2198
0
        return SECSuccess;
2199
0
    }
2200
2201
0
    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
2202
0
    return SECFailure;
2203
0
}
2204
2205
/*
2206
 * common HMAC + CMAC initialization routine
2207
 */
2208
static CK_RV
2209
sftk_doMACInit(CK_MECHANISM_TYPE mech, SFTKSessionContext *session,
2210
               SFTKObject *key, CK_ULONG mac_size)
2211
69
{
2212
69
    CK_RV crv;
2213
69
    sftk_MACCtx *context;
2214
69
    CK_ULONG *intpointer;
2215
69
    PRBool isFIPS = sftk_isFIPS(key->slot->slotID);
2216
2217
    /* Set up the initial context. */
2218
69
    crv = sftk_MAC_Create(mech, key, &context);
2219
69
    if (crv != CKR_OK) {
2220
0
        return crv;
2221
0
    }
2222
2223
69
    session->hashInfo = context;
2224
69
    session->multi = PR_TRUE;
2225
2226
    /* Required by FIPS 198 Section 4. Delay this check until after the MAC
2227
     * has been initialized to steal the output size of the MAC. */
2228
69
    if (isFIPS && (mac_size < 4 || mac_size < context->mac_size / 2)) {
2229
0
        sftk_MAC_DestroyContext(context, PR_TRUE);
2230
0
        return CKR_BUFFER_TOO_SMALL;
2231
0
    }
2232
2233
    /* Configure our helper functions appropriately. Note that these casts
2234
     * ignore the return values. */
2235
69
    session->hashUpdate = SFTKHash_sftk_MAC_Update;
2236
69
    session->end = SFTKHash_sftk_MAC_End;
2237
69
    session->hashdestroy = SFTKHash_sftk_MAC_DestroyContext;
2238
2239
69
    intpointer = PORT_New(CK_ULONG);
2240
69
    if (intpointer == NULL) {
2241
0
        sftk_MAC_DestroyContext(context, PR_TRUE);
2242
0
        return CKR_HOST_MEMORY;
2243
0
    }
2244
69
    *intpointer = mac_size;
2245
69
    session->cipherInfo = intpointer;
2246
2247
    /* Since we're only "hashing", copy the result from session->end to the
2248
     * caller using sftk_SignCopy. */
2249
69
    session->update = sftk_SignCopy;
2250
69
    session->verify = sftk_HMACCmp;
2251
69
    session->destroy = sftk_Space;
2252
2253
69
    session->maxLen = context->mac_size;
2254
2255
69
    return CKR_OK;
2256
69
}
2257
2258
/*
2259
 *  SSL Macing support. SSL Macs are inited, then update with the base
2260
 * hashing algorithm, then finalized in sign and verify
2261
 */
2262
2263
/*
2264
 * FROM SSL:
2265
 * 60 bytes is 3 times the maximum length MAC size that is supported.
2266
 * We probably should have one copy of this table. We still need this table
2267
 * in ssl to 'sign' the handshake hashes.
2268
 */
2269
static unsigned char ssl_pad_1[60] = {
2270
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2271
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2272
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2273
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2274
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2275
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2276
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2277
    0x36, 0x36, 0x36, 0x36
2278
};
2279
static unsigned char ssl_pad_2[60] = {
2280
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2281
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2282
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2283
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2284
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2285
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2286
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2287
    0x5c, 0x5c, 0x5c, 0x5c
2288
};
2289
2290
static SECStatus
2291
sftk_SSLMACSign(void *ctx, unsigned char *sig, unsigned int *sigLen,
2292
                unsigned int maxLen, const unsigned char *hash, unsigned int hashLen)
2293
0
{
2294
0
    SFTKSSLMACInfo *info = ctx;
2295
0
    unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
2296
0
    unsigned int out;
2297
2298
0
    info->begin(info->hashContext);
2299
0
    info->update(info->hashContext, info->key, info->keySize);
2300
0
    info->update(info->hashContext, ssl_pad_2, info->padSize);
2301
0
    info->update(info->hashContext, hash, hashLen);
2302
0
    info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH);
2303
0
    PORT_Memcpy(sig, tmpBuf, info->macSize);
2304
0
    PORT_Memset(tmpBuf, 0, info->macSize);
2305
0
    *sigLen = info->macSize;
2306
0
    return SECSuccess;
2307
0
}
2308
2309
static SECStatus
2310
sftk_SSLMACVerify(void *ctx, const unsigned char *sig, unsigned int sigLen,
2311
                  const unsigned char *hash, unsigned int hashLen)
2312
0
{
2313
0
    SFTKSSLMACInfo *info = ctx;
2314
0
    unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
2315
0
    unsigned int out;
2316
0
    int cmp;
2317
2318
0
    info->begin(info->hashContext);
2319
0
    info->update(info->hashContext, info->key, info->keySize);
2320
0
    info->update(info->hashContext, ssl_pad_2, info->padSize);
2321
0
    info->update(info->hashContext, hash, hashLen);
2322
0
    info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH);
2323
0
    cmp = NSS_SecureMemcmp(sig, tmpBuf, info->macSize);
2324
0
    PORT_Memset(tmpBuf, 0, info->macSize);
2325
0
    return (cmp == 0) ? SECSuccess : SECFailure;
2326
0
}
2327
2328
/*
2329
 * common HMAC initalization routine
2330
 */
2331
static CK_RV
2332
sftk_doSSLMACInit(SFTKSessionContext *context, SECOidTag oid,
2333
                  SFTKObject *key, CK_ULONG mac_size)
2334
0
{
2335
0
    SFTKAttribute *keyval;
2336
0
    SFTKBegin begin;
2337
0
    int padSize;
2338
0
    SFTKSSLMACInfo *sslmacinfo;
2339
0
    CK_RV crv = CKR_MECHANISM_INVALID;
2340
2341
0
    if (oid == SEC_OID_SHA1) {
2342
0
        crv = sftk_doSubSHA1(context);
2343
0
        if (crv != CKR_OK)
2344
0
            return crv;
2345
0
        begin = SFTKHash_SHA1_Begin;
2346
0
        padSize = 40;
2347
0
    } else {
2348
0
        crv = sftk_doSubMD5(context);
2349
0
        if (crv != CKR_OK)
2350
0
            return crv;
2351
0
        begin = SFTKHash_MD5_Begin;
2352
0
        padSize = 48;
2353
0
    }
2354
0
    context->multi = PR_TRUE;
2355
2356
0
    keyval = sftk_FindAttribute(key, CKA_VALUE);
2357
0
    if (keyval == NULL)
2358
0
        return CKR_KEY_SIZE_RANGE;
2359
2360
0
    context->hashUpdate(context->hashInfo, keyval->attrib.pValue,
2361
0
                        keyval->attrib.ulValueLen);
2362
0
    context->hashUpdate(context->hashInfo, ssl_pad_1, padSize);
2363
0
    sslmacinfo = (SFTKSSLMACInfo *)PORT_Alloc(sizeof(SFTKSSLMACInfo));
2364
0
    if (sslmacinfo == NULL) {
2365
0
        sftk_FreeAttribute(keyval);
2366
0
        return CKR_HOST_MEMORY;
2367
0
    }
2368
0
    sslmacinfo->size = sizeof(SFTKSSLMACInfo);
2369
0
    sslmacinfo->macSize = mac_size;
2370
0
    sslmacinfo->hashContext = context->hashInfo;
2371
0
    PORT_Memcpy(sslmacinfo->key, keyval->attrib.pValue,
2372
0
                keyval->attrib.ulValueLen);
2373
0
    sslmacinfo->keySize = keyval->attrib.ulValueLen;
2374
0
    sslmacinfo->begin = begin;
2375
0
    sslmacinfo->end = context->end;
2376
0
    sslmacinfo->update = context->hashUpdate;
2377
0
    sslmacinfo->padSize = padSize;
2378
0
    sftk_FreeAttribute(keyval);
2379
0
    context->cipherInfo = (void *)sslmacinfo;
2380
0
    context->destroy = sftk_ZSpace;
2381
0
    context->update = sftk_SSLMACSign;
2382
0
    context->verify = sftk_SSLMACVerify;
2383
0
    context->maxLen = mac_size;
2384
0
    return CKR_OK;
2385
0
}
2386
2387
/*
2388
 ************** Crypto Functions:     Sign  ************************
2389
 */
2390
2391
/**
2392
 * Check if We're using CBCMacing and initialize the session context if we are.
2393
 *  @param contextType SFTK_SIGN or SFTK_VERIFY
2394
 *  @param keyUsage    check whether key allows this usage
2395
 */
2396
static CK_RV
2397
sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
2398
                CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage,
2399
                SFTKContextType contextType)
2400
2401
95
{
2402
95
    CK_MECHANISM cbc_mechanism;
2403
95
    CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE;
2404
95
#ifndef NSS_DISABLE_DEPRECATED_RC2
2405
95
    CK_RC2_CBC_PARAMS rc2_params;
2406
95
#endif
2407
#if NSS_SOFTOKEN_DOES_RC5
2408
    CK_RC5_CBC_PARAMS rc5_params;
2409
    CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
2410
#endif
2411
95
    unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
2412
95
    unsigned char k2[SFTK_MAX_BLOCK_SIZE];
2413
95
    unsigned char k3[SFTK_MAX_BLOCK_SIZE];
2414
95
    SFTKSessionContext *context;
2415
95
    CK_RV crv;
2416
95
    unsigned int blockSize;
2417
95
    PRBool isXCBC = PR_FALSE;
2418
2419
95
    if (!pMechanism) {
2420
0
        return CKR_MECHANISM_PARAM_INVALID;
2421
0
    }
2422
2423
95
    switch (pMechanism->mechanism) {
2424
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
2425
0
        case CKM_RC2_MAC_GENERAL:
2426
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_MAC_GENERAL_PARAMS))) {
2427
0
                return CKR_MECHANISM_PARAM_INVALID;
2428
0
            }
2429
0
            mac_bytes =
2430
0
                ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
2431
        /* fall through */
2432
0
        case CKM_RC2_MAC:
2433
            /* this works because ulEffectiveBits is in the same place in both the
2434
             * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */
2435
0
            rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *)
2436
0
                                              pMechanism->pParameter)
2437
0
                                             ->ulEffectiveBits;
2438
0
            PORT_Memset(rc2_params.iv, 0, sizeof(rc2_params.iv));
2439
0
            cbc_mechanism.mechanism = CKM_RC2_CBC;
2440
0
            cbc_mechanism.pParameter = &rc2_params;
2441
0
            cbc_mechanism.ulParameterLen = sizeof(rc2_params);
2442
0
            blockSize = 8;
2443
0
            break;
2444
0
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
2445
2446
#if NSS_SOFTOKEN_DOES_RC5
2447
        case CKM_RC5_MAC_GENERAL:
2448
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
2449
                return CKR_MECHANISM_PARAM_INVALID;
2450
            }
2451
            mac_bytes =
2452
                ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
2453
        /* fall through */
2454
        case CKM_RC5_MAC:
2455
            /* this works because ulEffectiveBits is in the same place in both the
2456
             * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */
2457
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
2458
                return CKR_MECHANISM_PARAM_INVALID;
2459
            }
2460
            rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter;
2461
            rc5_params.ulWordsize = rc5_mac->ulWordsize;
2462
            rc5_params.ulRounds = rc5_mac->ulRounds;
2463
            rc5_params.pIv = ivBlock;
2464
            if ((blockSize = rc5_mac->ulWordsize * 2) > SFTK_MAX_BLOCK_SIZE)
2465
                return CKR_MECHANISM_PARAM_INVALID;
2466
            rc5_params.ulIvLen = blockSize;
2467
            PORT_Memset(ivBlock, 0, blockSize);
2468
            cbc_mechanism.mechanism = CKM_RC5_CBC;
2469
            cbc_mechanism.pParameter = &rc5_params;
2470
            cbc_mechanism.ulParameterLen = sizeof(rc5_params);
2471
            break;
2472
#endif
2473
        /* add cast and idea later */
2474
0
        case CKM_DES_MAC_GENERAL:
2475
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2476
        /* fall through */
2477
0
        case CKM_DES_MAC:
2478
0
            blockSize = 8;
2479
0
            PORT_Memset(ivBlock, 0, blockSize);
2480
0
            cbc_mechanism.mechanism = CKM_DES_CBC;
2481
0
            cbc_mechanism.pParameter = &ivBlock;
2482
0
            cbc_mechanism.ulParameterLen = blockSize;
2483
0
            break;
2484
0
        case CKM_DES3_MAC_GENERAL:
2485
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2486
        /* fall through */
2487
0
        case CKM_DES3_MAC:
2488
0
            blockSize = 8;
2489
0
            PORT_Memset(ivBlock, 0, blockSize);
2490
0
            cbc_mechanism.mechanism = CKM_DES3_CBC;
2491
0
            cbc_mechanism.pParameter = &ivBlock;
2492
0
            cbc_mechanism.ulParameterLen = blockSize;
2493
0
            break;
2494
0
        case CKM_CDMF_MAC_GENERAL:
2495
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2496
        /* fall through */
2497
0
        case CKM_CDMF_MAC:
2498
0
            blockSize = 8;
2499
0
            PORT_Memset(ivBlock, 0, blockSize);
2500
0
            cbc_mechanism.mechanism = CKM_CDMF_CBC;
2501
0
            cbc_mechanism.pParameter = &ivBlock;
2502
0
            cbc_mechanism.ulParameterLen = blockSize;
2503
0
            break;
2504
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
2505
0
        case CKM_SEED_MAC_GENERAL:
2506
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2507
        /* fall through */
2508
0
        case CKM_SEED_MAC:
2509
0
            blockSize = 16;
2510
0
            PORT_Memset(ivBlock, 0, blockSize);
2511
0
            cbc_mechanism.mechanism = CKM_SEED_CBC;
2512
0
            cbc_mechanism.pParameter = &ivBlock;
2513
0
            cbc_mechanism.ulParameterLen = blockSize;
2514
0
            break;
2515
0
#endif /* NSS_DISABLE_DEPRECATED_SEED */
2516
0
        case CKM_CAMELLIA_MAC_GENERAL:
2517
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2518
        /* fall through */
2519
0
        case CKM_CAMELLIA_MAC:
2520
0
            blockSize = 16;
2521
0
            PORT_Memset(ivBlock, 0, blockSize);
2522
0
            cbc_mechanism.mechanism = CKM_CAMELLIA_CBC;
2523
0
            cbc_mechanism.pParameter = &ivBlock;
2524
0
            cbc_mechanism.ulParameterLen = blockSize;
2525
0
            break;
2526
0
        case CKM_AES_MAC_GENERAL:
2527
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2528
        /* fall through */
2529
0
        case CKM_AES_MAC:
2530
0
            blockSize = 16;
2531
0
            PORT_Memset(ivBlock, 0, blockSize);
2532
0
            cbc_mechanism.mechanism = CKM_AES_CBC;
2533
0
            cbc_mechanism.pParameter = &ivBlock;
2534
0
            cbc_mechanism.ulParameterLen = blockSize;
2535
0
            break;
2536
0
        case CKM_AES_XCBC_MAC_96:
2537
0
        case CKM_AES_XCBC_MAC:
2538
            /* The only difference between CKM_AES_XCBC_MAC
2539
             * and CKM_AES_XCBC_MAC_96 is the size of the returned mac. */
2540
0
            mac_bytes = pMechanism->mechanism == CKM_AES_XCBC_MAC_96 ? 12 : 16;
2541
0
            blockSize = 16;
2542
0
            PORT_Memset(ivBlock, 0, blockSize);
2543
0
            cbc_mechanism.mechanism = CKM_AES_CBC;
2544
0
            cbc_mechanism.pParameter = &ivBlock;
2545
0
            cbc_mechanism.ulParameterLen = blockSize;
2546
            /* is XCBC requires extra processing at the end of the operation */
2547
0
            isXCBC = PR_TRUE;
2548
            /* The input key is used to generate k1, k2, and k3. k2 and k3
2549
             * are used at the end in the pad step. k1 replaces the input
2550
             * key in the aes cbc mac */
2551
0
            crv = sftk_aes_xcbc_new_keys(hSession, hKey, &hKey, k2, k3);
2552
0
            if (crv != CKR_OK) {
2553
0
                return crv;
2554
0
            }
2555
0
            break;
2556
95
        default:
2557
95
            return CKR_FUNCTION_NOT_SUPPORTED;
2558
95
    }
2559
2560
    /* if MAC size is externally supplied, it should be checked.
2561
     */
2562
0
    if (mac_bytes == SFTK_INVALID_MAC_SIZE)
2563
0
        mac_bytes = blockSize >> 1;
2564
0
    else {
2565
0
        if (mac_bytes > blockSize) {
2566
0
            crv = CKR_MECHANISM_PARAM_INVALID;
2567
0
            goto fail;
2568
0
        }
2569
0
    }
2570
2571
0
    crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey,
2572
0
                         CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */
2573
0
                         keyUsage, contextType, PR_TRUE);
2574
0
    if (crv != CKR_OK)
2575
0
        goto fail;
2576
0
    crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL);
2577
2578
    /* this shouldn't happen! */
2579
0
    PORT_Assert(crv == CKR_OK);
2580
0
    if (crv != CKR_OK)
2581
0
        goto fail;
2582
0
    context->blockSize = blockSize;
2583
0
    context->macSize = mac_bytes;
2584
0
    context->isXCBC = isXCBC;
2585
0
    if (isXCBC) {
2586
        /* save the xcbc specific parameters */
2587
0
        PORT_Memcpy(context->k2, k2, blockSize);
2588
0
        PORT_Memcpy(context->k3, k3, blockSize);
2589
0
        PORT_Memset(k2, 0, blockSize);
2590
0
        PORT_Memset(k3, 0, blockSize);
2591
        /* get rid of the temp key now that the context has been created */
2592
0
        NSC_DestroyObject(hSession, hKey);
2593
0
    }
2594
0
    return CKR_OK;
2595
0
fail:
2596
0
    if (isXCBC) {
2597
0
        PORT_Memset(k2, 0, blockSize);
2598
0
        PORT_Memset(k3, 0, blockSize);
2599
0
        NSC_DestroyObject(hSession, hKey); /* get rid of our temp key */
2600
0
    }
2601
0
    return crv;
2602
0
}
2603
2604
/*
2605
 * encode RSA PKCS #1 Signature data before signing...
2606
 */
2607
static SECStatus
2608
sftk_RSAHashSign(void *ctx, unsigned char *sig,
2609
                 unsigned int *sigLen, unsigned int maxLen,
2610
                 const unsigned char *hash, unsigned int hashLen)
2611
0
{
2612
0
    SFTKHashSignInfo *info = ctx;
2613
0
    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
2614
0
    if (info->key->keyType != NSSLOWKEYRSAKey) {
2615
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
2616
0
        return SECFailure;
2617
0
    }
2618
2619
0
    return RSA_HashSign(info->hashOid, info->key, sig, sigLen, maxLen,
2620
0
                        hash, hashLen);
2621
0
}
2622
2623
/* XXX Old template; want to expunge it eventually. */
2624
static DERTemplate SECAlgorithmIDTemplate[] = {
2625
    { DER_SEQUENCE,
2626
      0, NULL, sizeof(SECAlgorithmID) },
2627
    { DER_OBJECT_ID,
2628
      offsetof(SECAlgorithmID, algorithm) },
2629
    { DER_OPTIONAL | DER_ANY,
2630
      offsetof(SECAlgorithmID, parameters) },
2631
    { 0 }
2632
};
2633
2634
/*
2635
 * XXX OLD Template.  Once all uses have been switched over to new one,
2636
 * remove this.
2637
 */
2638
static DERTemplate SGNDigestInfoTemplate[] = {
2639
    { DER_SEQUENCE,
2640
      0, NULL, sizeof(SGNDigestInfo) },
2641
    { DER_INLINE,
2642
      offsetof(SGNDigestInfo, digestAlgorithm),
2643
      SECAlgorithmIDTemplate },
2644
    { DER_OCTET_STRING,
2645
      offsetof(SGNDigestInfo, digest) },
2646
    { 0 }
2647
};
2648
2649
/*
2650
 * encode RSA PKCS #1 Signature data before signing...
2651
 */
2652
SECStatus
2653
RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key,
2654
             unsigned char *sig, unsigned int *sigLen, unsigned int maxLen,
2655
             const unsigned char *hash, unsigned int hashLen)
2656
6
{
2657
6
    SECStatus rv = SECFailure;
2658
6
    SECItem digder;
2659
6
    PLArenaPool *arena = NULL;
2660
6
    SGNDigestInfo *di = NULL;
2661
2662
6
    digder.data = NULL;
2663
2664
6
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2665
6
    if (!arena) {
2666
0
        goto loser;
2667
0
    }
2668
2669
    /* Construct digest info */
2670
6
    di = SGN_CreateDigestInfo(hashOid, hash, hashLen);
2671
6
    if (!di) {
2672
0
        goto loser;
2673
0
    }
2674
2675
    /* Der encode the digest as a DigestInfo */
2676
6
    rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di);
2677
6
    if (rv != SECSuccess) {
2678
0
        goto loser;
2679
0
    }
2680
2681
    /*
2682
    ** Encrypt signature after constructing appropriate PKCS#1 signature
2683
    ** block
2684
    */
2685
6
    rv = RSA_Sign(&key->u.rsa, sig, sigLen, maxLen, digder.data,
2686
6
                  digder.len);
2687
6
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2688
0
        sftk_fatalError = PR_TRUE;
2689
0
    }
2690
2691
6
loser:
2692
6
    SGN_DestroyDigestInfo(di);
2693
6
    if (arena != NULL) {
2694
6
        PORT_FreeArena(arena, PR_TRUE);
2695
6
    }
2696
6
    return rv;
2697
6
}
2698
2699
static SECStatus
2700
sftk_RSASign(void *ctx, unsigned char *output,
2701
             unsigned int *outputLen, unsigned int maxOutputLen,
2702
             const unsigned char *input, unsigned int inputLen)
2703
0
{
2704
0
    NSSLOWKEYPrivateKey *key = ctx;
2705
0
    SECStatus rv = SECFailure;
2706
2707
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
2708
0
    if (key->keyType != NSSLOWKEYRSAKey) {
2709
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
2710
0
        return SECFailure;
2711
0
    }
2712
2713
0
    rv = RSA_Sign(&key->u.rsa, output, outputLen, maxOutputLen, input,
2714
0
                  inputLen);
2715
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2716
0
        sftk_fatalError = PR_TRUE;
2717
0
    }
2718
0
    return rv;
2719
0
}
2720
2721
static SECStatus
2722
sftk_RSASignRaw(void *ctx, unsigned char *output,
2723
                unsigned int *outputLen, unsigned int maxOutputLen,
2724
                const unsigned char *input, unsigned int inputLen)
2725
0
{
2726
0
    NSSLOWKEYPrivateKey *key = ctx;
2727
0
    SECStatus rv = SECFailure;
2728
2729
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
2730
0
    if (key->keyType != NSSLOWKEYRSAKey) {
2731
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
2732
0
        return SECFailure;
2733
0
    }
2734
2735
0
    rv = RSA_SignRaw(&key->u.rsa, output, outputLen, maxOutputLen, input,
2736
0
                     inputLen);
2737
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2738
0
        sftk_fatalError = PR_TRUE;
2739
0
    }
2740
0
    return rv;
2741
0
}
2742
2743
static SECStatus
2744
sftk_RSASignPSS(void *ctx, unsigned char *sig,
2745
                unsigned int *sigLen, unsigned int maxLen,
2746
                const unsigned char *hash, unsigned int hashLen)
2747
0
{
2748
0
    SFTKPSSSignInfo *info = ctx;
2749
0
    SECStatus rv = SECFailure;
2750
0
    HASH_HashType hashAlg;
2751
0
    HASH_HashType maskHashAlg;
2752
0
    CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
2753
2754
0
    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
2755
0
    if (info->key->keyType != NSSLOWKEYRSAKey) {
2756
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
2757
0
        return SECFailure;
2758
0
    }
2759
2760
0
    hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg);
2761
0
    maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf);
2762
2763
0
    rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL,
2764
0
                     params->sLen, sig, sigLen, maxLen, hash, hashLen);
2765
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2766
0
        sftk_fatalError = PR_TRUE;
2767
0
    }
2768
0
    return rv;
2769
0
}
2770
2771
static SECStatus
2772
nsc_DSA_Verify_Stub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen,
2773
                    const unsigned char *dataBuf, unsigned int dataLen)
2774
0
{
2775
0
    NSSLOWKEYPublicKey *key = ctx;
2776
0
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen };
2777
0
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2778
0
    return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest);
2779
0
}
2780
2781
static SECStatus
2782
nsc_DSA_Sign_Stub(void *ctx, unsigned char *sigBuf,
2783
                  unsigned int *sigLen, unsigned int maxSigLen,
2784
                  const unsigned char *dataBuf, unsigned int dataLen)
2785
0
{
2786
0
    NSSLOWKEYPrivateKey *key = ctx;
2787
0
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen };
2788
0
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2789
0
    SECStatus rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest);
2790
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2791
0
        sftk_fatalError = PR_TRUE;
2792
0
    }
2793
0
    *sigLen = signature.len;
2794
0
    return rv;
2795
0
}
2796
2797
static SECStatus
2798
nsc_ECDSAVerifyStub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen,
2799
                    const unsigned char *dataBuf, unsigned int dataLen)
2800
0
{
2801
0
    NSSLOWKEYPublicKey *key = ctx;
2802
0
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen };
2803
0
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2804
0
    return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest);
2805
0
}
2806
2807
static SECStatus
2808
nsc_ECDSASignStub(void *ctx, unsigned char *sigBuf,
2809
                  unsigned int *sigLen, unsigned int maxSigLen,
2810
                  const unsigned char *dataBuf, unsigned int dataLen)
2811
0
{
2812
0
    NSSLOWKEYPrivateKey *key = ctx;
2813
0
    SECItem signature = { siBuffer, sigBuf, maxSigLen };
2814
0
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2815
2816
0
    SECStatus rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest);
2817
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2818
0
        sftk_fatalError = PR_TRUE;
2819
0
    }
2820
0
    *sigLen = signature.len;
2821
0
    return rv;
2822
0
}
2823
2824
static SECStatus
2825
nsc_EDDSAVerifyStub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen,
2826
                    const unsigned char *dataBuf, unsigned int dataLen)
2827
0
{
2828
0
    NSSLOWKEYPublicKey *key = ctx;
2829
0
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen };
2830
0
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2831
0
    return ED_VerifyMessage(&(key->u.ec), &signature, &digest);
2832
0
}
2833
2834
static SECStatus
2835
nsc_EDDSASignStub(void *ctx, unsigned char *sigBuf,
2836
                  unsigned int *sigLen, unsigned int maxSigLen,
2837
                  const unsigned char *dataBuf, unsigned int dataLen)
2838
0
{
2839
0
    NSSLOWKEYPrivateKey *key = ctx;
2840
0
    SECItem signature = { siBuffer, sigBuf, maxSigLen };
2841
0
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2842
2843
0
    SECStatus rv = ED_SignMessage(&(key->u.ec), &signature, &digest);
2844
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2845
0
        sftk_fatalError = PR_TRUE;
2846
0
    }
2847
0
    *sigLen = signature.len;
2848
0
    return rv;
2849
0
}
2850
2851
/* NSC_SignInit setups up the signing operations. There are three basic
2852
 * types of signing:
2853
 *      (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied
2854
 *  to data in a single Sign operation (which often looks a lot like an
2855
 *  encrypt, with data coming in and data going out).
2856
 *      (2) Hash based signing, where we continually hash the data, then apply
2857
 *  some sort of signature to the end.
2858
 *      (3) Block Encryption CBC MAC's, where the Data is encrypted with a key,
2859
 *  and only the final block is part of the mac.
2860
 *
2861
 *  For case number 3, we initialize a context much like the Encryption Context
2862
 *  (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and
2863
 *  C_Final by the following method... if it's not multi-part, and it's doesn't
2864
 *  have a hash context, it must be a block Encryption CBC MAC.
2865
 *
2866
 *  For case number 2, we initialize a hash structure, as well as make it
2867
 *  multi-part. Updates are simple calls to the hash update function. Final
2868
 *  calls the hashend, then passes the result to the 'update' function (which
2869
 *  operates as a final signature function). In some hash based MAC'ing (as
2870
 *  opposed to hash base signatures), the update function is can be simply a
2871
 *  copy (as is the case with HMAC).
2872
 */
2873
CK_RV
2874
NSC_SignInit(CK_SESSION_HANDLE hSession,
2875
             CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2876
95
{
2877
95
    SFTKSession *session;
2878
95
    SFTKObject *key;
2879
95
    SFTKSessionContext *context;
2880
95
    CK_KEY_TYPE key_type;
2881
95
    CK_RV crv = CKR_OK;
2882
95
    NSSLOWKEYPrivateKey *privKey;
2883
95
    SFTKHashSignInfo *info = NULL;
2884
95
    SFTKPSSSignInfo *pinfo = NULL;
2885
2886
95
    CHECK_FORK();
2887
2888
    /* Block Cipher MACing Algorithms use a different Context init method..*/
2889
95
    crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN);
2890
95
    if (crv != CKR_FUNCTION_NOT_SUPPORTED)
2891
0
        return crv;
2892
2893
    /* we're not using a block cipher mac */
2894
95
    session = sftk_SessionFromHandle(hSession);
2895
95
    if (session == NULL)
2896
0
        return CKR_SESSION_HANDLE_INVALID;
2897
95
    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_SIGN, &key,
2898
95
                           hKey, &key_type, CKO_PRIVATE_KEY, CKA_SIGN);
2899
95
    if (crv != CKR_OK) {
2900
0
        sftk_FreeSession(session);
2901
0
        return crv;
2902
0
    }
2903
2904
95
    context->multi = PR_FALSE;
2905
2906
95
#define INIT_RSA_SIGN_MECH(mmm)             \
2907
95
    case CKM_##mmm##_RSA_PKCS:              \
2908
0
        context->multi = PR_TRUE;           \
2909
0
        crv = sftk_doSub##mmm(context);     \
2910
0
        if (crv != CKR_OK)                  \
2911
0
            break;                          \
2912
0
        context->update = sftk_RSAHashSign; \
2913
0
        info = PORT_New(SFTKHashSignInfo);  \
2914
0
        if (info == NULL) {                 \
2915
0
            crv = CKR_HOST_MEMORY;          \
2916
0
            break;                          \
2917
0
        }                                   \
2918
0
        info->hashOid = SEC_OID_##mmm;      \
2919
0
        goto finish_rsa;
2920
2921
95
    switch (pMechanism->mechanism) {
2922
0
        INIT_RSA_SIGN_MECH(MD5)
2923
0
        INIT_RSA_SIGN_MECH(MD2)
2924
0
        INIT_RSA_SIGN_MECH(SHA1)
2925
0
        INIT_RSA_SIGN_MECH(SHA224)
2926
0
        INIT_RSA_SIGN_MECH(SHA256)
2927
0
        INIT_RSA_SIGN_MECH(SHA384)
2928
0
        INIT_RSA_SIGN_MECH(SHA512)
2929
2930
0
        case CKM_RSA_PKCS:
2931
0
            context->update = sftk_RSASign;
2932
0
            goto finish_rsa;
2933
0
        case CKM_RSA_X_509:
2934
0
            context->update = sftk_RSASignRaw;
2935
0
        finish_rsa:
2936
0
            if (key_type != CKK_RSA) {
2937
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
2938
0
                break;
2939
0
            }
2940
0
            context->rsa = PR_TRUE;
2941
0
            privKey = sftk_GetPrivKey(key, CKK_RSA, &crv);
2942
0
            if (privKey == NULL) {
2943
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
2944
0
                break;
2945
0
            }
2946
            /* OK, info is allocated only if we're doing hash and sign mechanism.
2947
             * It's necessary to be able to set the correct OID in the final
2948
             * signature.
2949
             */
2950
0
            if (info) {
2951
0
                info->key = privKey;
2952
0
                context->cipherInfo = info;
2953
0
                context->destroy = sftk_Space;
2954
0
            } else {
2955
0
                context->cipherInfo = privKey;
2956
0
                context->destroy = sftk_Null;
2957
0
            }
2958
0
            context->maxLen = nsslowkey_PrivateModulusLen(privKey);
2959
0
            break;
2960
2961
0
#define INIT_RSA_PSS_SIG_MECH(mmm)                                                            \
2962
0
    case CKM_##mmm##_RSA_PKCS_PSS:                                                            \
2963
0
        context->multi = PR_TRUE;                                                             \
2964
0
        crv = sftk_doSub##mmm(context);                                                       \
2965
0
        if (crv != CKR_OK)                                                                    \
2966
0
            break;                                                                            \
2967
0
        if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) {                   \
2968
0
            crv = CKR_MECHANISM_PARAM_INVALID;                                                \
2969
0
            break;                                                                            \
2970
0
        }                                                                                     \
2971
0
        if (((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)->hashAlg != CKM_##mmm) { \
2972
0
            crv = CKR_MECHANISM_PARAM_INVALID;                                                \
2973
0
            break;                                                                            \
2974
0
        }                                                                                     \
2975
0
        goto finish_rsa_pss;
2976
0
            INIT_RSA_PSS_SIG_MECH(SHA1)
2977
0
            INIT_RSA_PSS_SIG_MECH(SHA224)
2978
0
            INIT_RSA_PSS_SIG_MECH(SHA256)
2979
0
            INIT_RSA_PSS_SIG_MECH(SHA384)
2980
0
            INIT_RSA_PSS_SIG_MECH(SHA512)
2981
0
        case CKM_RSA_PKCS_PSS:
2982
0
        finish_rsa_pss:
2983
0
            if (key_type != CKK_RSA) {
2984
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
2985
0
                break;
2986
0
            }
2987
0
            context->rsa = PR_TRUE;
2988
0
            if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
2989
0
                !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) {
2990
0
                crv = CKR_MECHANISM_PARAM_INVALID;
2991
0
                break;
2992
0
            }
2993
0
            pinfo = PORT_New(SFTKPSSSignInfo);
2994
0
            if (pinfo == NULL) {
2995
0
                crv = CKR_HOST_MEMORY;
2996
0
                break;
2997
0
            }
2998
0
            pinfo->size = sizeof(SFTKPSSSignInfo);
2999
0
            pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter;
3000
0
            pinfo->key = sftk_GetPrivKey(key, CKK_RSA, &crv);
3001
0
            if (pinfo->key == NULL) {
3002
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3003
0
                break;
3004
0
            }
3005
0
            context->cipherInfo = pinfo;
3006
0
            context->destroy = sftk_ZSpace;
3007
0
            context->update = sftk_RSASignPSS;
3008
0
            context->maxLen = nsslowkey_PrivateModulusLen(pinfo->key);
3009
0
            break;
3010
3011
0
#define INIT_DSA_SIG_MECH(mmm)          \
3012
0
    case CKM_DSA_##mmm:                 \
3013
0
        context->multi = PR_TRUE;       \
3014
0
        crv = sftk_doSub##mmm(context); \
3015
0
        if (crv != CKR_OK)              \
3016
0
            break;                      \
3017
0
        goto finish_dsa;
3018
0
            INIT_DSA_SIG_MECH(SHA1)
3019
0
            INIT_DSA_SIG_MECH(SHA224)
3020
0
            INIT_DSA_SIG_MECH(SHA256)
3021
0
            INIT_DSA_SIG_MECH(SHA384)
3022
0
            INIT_DSA_SIG_MECH(SHA512)
3023
0
        case CKM_DSA:
3024
0
        finish_dsa:
3025
0
            if (key_type != CKK_DSA) {
3026
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3027
0
                break;
3028
0
            }
3029
0
            privKey = sftk_GetPrivKey(key, CKK_DSA, &crv);
3030
0
            if (privKey == NULL) {
3031
0
                break;
3032
0
            }
3033
0
            context->cipherInfo = privKey;
3034
0
            context->update = nsc_DSA_Sign_Stub;
3035
0
            context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey;
3036
0
            context->maxLen = DSA_MAX_SIGNATURE_LEN;
3037
3038
0
            break;
3039
3040
0
#define INIT_ECDSA_SIG_MECH(mmm)        \
3041
0
    case CKM_ECDSA_##mmm:               \
3042
0
        context->multi = PR_TRUE;       \
3043
0
        crv = sftk_doSub##mmm(context); \
3044
0
        if (crv != CKR_OK)              \
3045
0
            break;                      \
3046
0
        goto finish_ecdsa;
3047
0
            INIT_ECDSA_SIG_MECH(SHA1)
3048
0
            INIT_ECDSA_SIG_MECH(SHA224)
3049
0
            INIT_ECDSA_SIG_MECH(SHA256)
3050
0
            INIT_ECDSA_SIG_MECH(SHA384)
3051
0
            INIT_ECDSA_SIG_MECH(SHA512)
3052
0
        case CKM_ECDSA:
3053
0
        finish_ecdsa:
3054
0
            if (key_type != CKK_EC) {
3055
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3056
0
                break;
3057
0
            }
3058
0
            privKey = sftk_GetPrivKey(key, CKK_EC, &crv);
3059
0
            if (privKey == NULL) {
3060
0
                crv = CKR_HOST_MEMORY;
3061
0
                break;
3062
0
            }
3063
0
            context->cipherInfo = privKey;
3064
0
            context->update = nsc_ECDSASignStub;
3065
0
            context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey;
3066
0
            context->maxLen = MAX_ECKEY_LEN * 2;
3067
3068
0
            break;
3069
3070
0
        case CKM_EDDSA:
3071
0
            if (key_type != CKK_EC_EDWARDS) {
3072
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3073
0
                break;
3074
0
            }
3075
3076
0
            if (pMechanism->pParameter) {
3077
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3078
0
                break;
3079
0
            }
3080
3081
0
            privKey = sftk_GetPrivKey(key, CKK_EC_EDWARDS, &crv);
3082
0
            if (privKey == NULL) {
3083
0
                crv = CKR_HOST_MEMORY;
3084
0
                break;
3085
0
            }
3086
0
            context->cipherInfo = privKey;
3087
0
            context->update = nsc_EDDSASignStub;
3088
0
            context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey;
3089
0
            context->maxLen = MAX_ECKEY_LEN * 2;
3090
3091
0
            break;
3092
3093
0
#define INIT_HMAC_MECH(mmm)                                        \
3094
0
    case CKM_##mmm##_HMAC_GENERAL:                                 \
3095
0
        PORT_Assert(pMechanism->pParameter);                       \
3096
0
        if (!pMechanism->pParameter) {                             \
3097
0
            crv = CKR_MECHANISM_PARAM_INVALID;                     \
3098
0
            break;                                                 \
3099
0
        }                                                          \
3100
0
        crv = sftk_doMACInit(pMechanism->mechanism, context, key,  \
3101
0
                             *(CK_ULONG *)pMechanism->pParameter); \
3102
0
        break;                                                     \
3103
68
    case CKM_##mmm##_HMAC:                                         \
3104
68
        crv = sftk_doMACInit(pMechanism->mechanism, context, key,  \
3105
68
                             mmm##_LENGTH);                        \
3106
68
        break;
3107
3108
0
            INIT_HMAC_MECH(MD2)
3109
0
            INIT_HMAC_MECH(MD5)
3110
0
            INIT_HMAC_MECH(SHA1)
3111
0
            INIT_HMAC_MECH(SHA224)
3112
0
            INIT_HMAC_MECH(SHA256)
3113
0
            INIT_HMAC_MECH(SHA384)
3114
0
            INIT_HMAC_MECH(SHA512)
3115
0
            INIT_HMAC_MECH(SHA3_224)
3116
0
            INIT_HMAC_MECH(SHA3_256)
3117
0
            INIT_HMAC_MECH(SHA3_384)
3118
0
            INIT_HMAC_MECH(SHA3_512)
3119
3120
0
        case CKM_AES_CMAC_GENERAL:
3121
0
            PORT_Assert(pMechanism->pParameter);
3122
0
            if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) {
3123
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3124
0
                break;
3125
0
            }
3126
0
            crv = sftk_doMACInit(pMechanism->mechanism, context, key, *(CK_ULONG *)pMechanism->pParameter);
3127
0
            break;
3128
1
        case CKM_AES_CMAC:
3129
1
            crv = sftk_doMACInit(pMechanism->mechanism, context, key, AES_BLOCK_SIZE);
3130
1
            break;
3131
0
        case CKM_SSL3_MD5_MAC:
3132
0
            PORT_Assert(pMechanism->pParameter);
3133
0
            if (!pMechanism->pParameter) {
3134
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3135
0
                break;
3136
0
            }
3137
0
            crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key,
3138
0
                                    *(CK_ULONG *)pMechanism->pParameter);
3139
0
            break;
3140
0
        case CKM_SSL3_SHA1_MAC:
3141
0
            PORT_Assert(pMechanism->pParameter);
3142
0
            if (!pMechanism->pParameter) {
3143
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3144
0
                break;
3145
0
            }
3146
0
            crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key,
3147
0
                                    *(CK_ULONG *)pMechanism->pParameter);
3148
0
            break;
3149
0
        case CKM_TLS_PRF_GENERAL:
3150
0
            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0);
3151
0
            break;
3152
0
        case CKM_TLS_MAC: {
3153
0
            CK_TLS_MAC_PARAMS *tls12_mac_params;
3154
0
            HASH_HashType tlsPrfHash;
3155
0
            const char *label;
3156
3157
0
            if (pMechanism->ulParameterLen != sizeof(CK_TLS_MAC_PARAMS)) {
3158
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3159
0
                break;
3160
0
            }
3161
0
            tls12_mac_params = (CK_TLS_MAC_PARAMS *)pMechanism->pParameter;
3162
0
            if (tls12_mac_params->prfHashMechanism == CKM_TLS_PRF) {
3163
                /* The TLS 1.0 and 1.1 PRF */
3164
0
                tlsPrfHash = HASH_AlgNULL;
3165
0
                if (tls12_mac_params->ulMacLength != 12) {
3166
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
3167
0
                    break;
3168
0
                }
3169
0
            } else {
3170
                /* The hash function for the TLS 1.2 PRF */
3171
0
                tlsPrfHash =
3172
0
                    sftk_GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism);
3173
0
                if (tlsPrfHash == HASH_AlgNULL ||
3174
0
                    tls12_mac_params->ulMacLength < 12) {
3175
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
3176
0
                    break;
3177
0
                }
3178
0
            }
3179
0
            if (tls12_mac_params->ulServerOrClient == 1) {
3180
0
                label = "server finished";
3181
0
            } else if (tls12_mac_params->ulServerOrClient == 2) {
3182
0
                label = "client finished";
3183
0
            } else {
3184
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3185
0
                break;
3186
0
            }
3187
0
            crv = sftk_TLSPRFInit(context, key, key_type, tlsPrfHash,
3188
0
                                  tls12_mac_params->ulMacLength);
3189
0
            if (crv == CKR_OK) {
3190
0
                context->hashUpdate(context->hashInfo, (unsigned char *)label, 15);
3191
0
            }
3192
0
            break;
3193
0
        }
3194
0
        case CKM_NSS_TLS_PRF_GENERAL_SHA256:
3195
0
            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0);
3196
0
            break;
3197
3198
0
        case CKM_NSS_HMAC_CONSTANT_TIME: {
3199
0
            sftk_MACConstantTimeCtx *ctx =
3200
0
                sftk_HMACConstantTime_New(pMechanism, key);
3201
0
            CK_ULONG *intpointer;
3202
3203
0
            if (ctx == NULL) {
3204
0
                crv = CKR_ARGUMENTS_BAD;
3205
0
                break;
3206
0
            }
3207
0
            intpointer = PORT_New(CK_ULONG);
3208
0
            if (intpointer == NULL) {
3209
0
                PORT_Free(ctx);
3210
0
                crv = CKR_HOST_MEMORY;
3211
0
                break;
3212
0
            }
3213
0
            *intpointer = ctx->hash->length;
3214
3215
0
            context->cipherInfo = intpointer;
3216
0
            context->hashInfo = ctx;
3217
0
            context->currentMech = pMechanism->mechanism;
3218
0
            context->hashUpdate = sftk_HMACConstantTime_Update;
3219
0
            context->hashdestroy = sftk_MACConstantTime_DestroyContext;
3220
0
            context->end = sftk_MACConstantTime_EndHash;
3221
0
            context->update = sftk_SignCopy;
3222
0
            context->destroy = sftk_Space;
3223
0
            context->maxLen = 64;
3224
0
            context->multi = PR_TRUE;
3225
0
            break;
3226
0
        }
3227
3228
0
        case CKM_NSS_SSL3_MAC_CONSTANT_TIME: {
3229
0
            sftk_MACConstantTimeCtx *ctx =
3230
0
                sftk_SSLv3MACConstantTime_New(pMechanism, key);
3231
0
            CK_ULONG *intpointer;
3232
3233
0
            if (ctx == NULL) {
3234
0
                crv = CKR_ARGUMENTS_BAD;
3235
0
                break;
3236
0
            }
3237
0
            intpointer = PORT_New(CK_ULONG);
3238
0
            if (intpointer == NULL) {
3239
0
                PORT_Free(ctx);
3240
0
                crv = CKR_HOST_MEMORY;
3241
0
                break;
3242
0
            }
3243
0
            *intpointer = ctx->hash->length;
3244
3245
0
            context->cipherInfo = intpointer;
3246
0
            context->hashInfo = ctx;
3247
0
            context->currentMech = pMechanism->mechanism;
3248
0
            context->hashUpdate = sftk_SSLv3MACConstantTime_Update;
3249
0
            context->hashdestroy = sftk_MACConstantTime_DestroyContext;
3250
0
            context->end = sftk_MACConstantTime_EndHash;
3251
0
            context->update = sftk_SignCopy;
3252
0
            context->destroy = sftk_Space;
3253
0
            context->maxLen = 64;
3254
0
            context->multi = PR_TRUE;
3255
0
            break;
3256
0
        }
3257
3258
26
        default:
3259
26
            crv = CKR_MECHANISM_INVALID;
3260
26
            break;
3261
95
    }
3262
3263
95
    if (crv != CKR_OK) {
3264
26
        if (info)
3265
0
            PORT_Free(info);
3266
26
        if (pinfo)
3267
0
            PORT_ZFree(pinfo, pinfo->size);
3268
26
        sftk_FreeContext(context);
3269
26
        sftk_FreeSession(session);
3270
26
        return crv;
3271
26
    }
3272
69
    sftk_SetContextByType(session, SFTK_SIGN, context);
3273
69
    sftk_FreeSession(session);
3274
69
    return CKR_OK;
3275
95
}
3276
3277
/** MAC one block of data by block cipher
3278
 */
3279
static CK_RV
3280
sftk_MACBlock(SFTKSessionContext *ctx, void *blk)
3281
0
{
3282
0
    unsigned int outlen;
3283
0
    return (SECSuccess == (ctx->update)(ctx->cipherInfo, ctx->macBuf, &outlen,
3284
0
                                        SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize))
3285
0
               ? CKR_OK
3286
0
               : sftk_MapCryptError(PORT_GetError());
3287
0
}
3288
3289
/** MAC last (incomplete) block of data by block cipher
3290
 *
3291
 *  Call once, then terminate MACing operation.
3292
 */
3293
static CK_RV
3294
sftk_MACFinal(SFTKSessionContext *ctx)
3295
0
{
3296
0
    unsigned int padLen = ctx->padDataLength;
3297
    /* pad and proceed the residual */
3298
0
    if (ctx->isXCBC) {
3299
0
        CK_RV crv = sftk_xcbc_mac_pad(ctx->padBuf, padLen, ctx->blockSize,
3300
0
                                      ctx->k2, ctx->k3);
3301
0
        if (crv != CKR_OK)
3302
0
            return crv;
3303
0
        return sftk_MACBlock(ctx, ctx->padBuf);
3304
0
    }
3305
0
    if (padLen) {
3306
        /* shd clr ctx->padLen to make sftk_MACFinal idempotent */
3307
0
        PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen);
3308
0
        return sftk_MACBlock(ctx, ctx->padBuf);
3309
0
    } else
3310
0
        return CKR_OK;
3311
0
}
3312
3313
/** The common implementation for {Sign,Verify}Update. (S/V only vary in their
3314
 * setup and final operations).
3315
 *
3316
 * A call which results in an error terminates the operation [PKCS#11,v2.11]
3317
 */
3318
static CK_RV
3319
sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
3320
               CK_ULONG ulPartLen, SFTKContextType type)
3321
524
{
3322
524
    SFTKSession *session;
3323
524
    SFTKSessionContext *context;
3324
524
    CK_RV crv;
3325
3326
    /* make sure we're legal */
3327
524
    crv = sftk_GetContext(hSession, &context, type, PR_TRUE, &session);
3328
524
    if (crv != CKR_OK)
3329
0
        return crv;
3330
3331
524
    if (context->hashInfo) {
3332
524
#if (ULONG_MAX > UINT_MAX)
3333
524
        while (ulPartLen > UINT_MAX) {
3334
0
            (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX);
3335
0
            pPart += UINT_MAX;
3336
0
            ulPartLen -= UINT_MAX;
3337
0
        }
3338
524
#endif
3339
524
        (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen);
3340
524
    } else {
3341
        /* must be block cipher MACing */
3342
3343
0
        unsigned int blkSize = context->blockSize;
3344
0
        unsigned char *residual = /* free room in context->padBuf */
3345
0
            context->padBuf + context->padDataLength;
3346
0
        unsigned int minInput = /* min input for MACing at least one block */
3347
0
            blkSize - context->padDataLength;
3348
3349
        /* not enough data even for one block */
3350
0
        if (ulPartLen <= minInput) {
3351
0
            PORT_Memcpy(residual, pPart, ulPartLen);
3352
0
            context->padDataLength += ulPartLen;
3353
0
            goto cleanup;
3354
0
        }
3355
        /* MACing residual */
3356
0
        if (context->padDataLength) {
3357
0
            PORT_Memcpy(residual, pPart, minInput);
3358
0
            ulPartLen -= minInput;
3359
0
            pPart += minInput;
3360
0
            if (CKR_OK != (crv = sftk_MACBlock(context, context->padBuf)))
3361
0
                goto terminate;
3362
0
        }
3363
        /* MACing full blocks */
3364
0
        while (ulPartLen > blkSize) {
3365
0
            if (CKR_OK != (crv = sftk_MACBlock(context, pPart)))
3366
0
                goto terminate;
3367
0
            ulPartLen -= blkSize;
3368
0
            pPart += blkSize;
3369
0
        }
3370
        /* save the residual */
3371
0
        if ((context->padDataLength = ulPartLen))
3372
0
            PORT_Memcpy(context->padBuf, pPart, ulPartLen);
3373
0
    } /* blk cipher MACing */
3374
3375
524
    goto cleanup;
3376
3377
524
terminate:
3378
0
    sftk_TerminateOp(session, type, context);
3379
524
cleanup:
3380
524
    sftk_FreeSession(session);
3381
524
    return crv;
3382
0
}
3383
3384
/* NSC_SignUpdate continues a multiple-part signature operation,
3385
 * where the signature is (will be) an appendix to the data,
3386
 * and plaintext cannot be recovered from the signature
3387
 *
3388
 * A call which results in an error terminates the operation [PKCS#11,v2.11]
3389
 */
3390
CK_RV
3391
NSC_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
3392
               CK_ULONG ulPartLen)
3393
524
{
3394
524
    CHECK_FORK();
3395
524
    return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN);
3396
524
}
3397
3398
struct SFTK_SESSION_FLAGS {
3399
    CK_FLAGS flag;
3400
    SFTKContextType type;
3401
};
3402
3403
const static struct SFTK_SESSION_FLAGS sftk_session_flags[] = {
3404
    { CKF_ENCRYPT, SFTK_ENCRYPT },
3405
    { CKF_DECRYPT, SFTK_DECRYPT },
3406
    { CKF_DIGEST, SFTK_HASH },
3407
    { CKF_SIGN, SFTK_SIGN },
3408
    { CKF_SIGN_RECOVER, SFTK_SIGN_RECOVER },
3409
    { CKF_VERIFY, SFTK_VERIFY },
3410
    { CKF_VERIFY_RECOVER, SFTK_VERIFY_RECOVER },
3411
    { CKF_MESSAGE_ENCRYPT, SFTK_MESSAGE_ENCRYPT },
3412
    { CKF_MESSAGE_DECRYPT, SFTK_MESSAGE_DECRYPT },
3413
    { CKF_MESSAGE_SIGN, SFTK_MESSAGE_SIGN },
3414
    { CKF_MESSAGE_VERIFY, SFTK_MESSAGE_VERIFY },
3415
};
3416
const static int sftk_flag_count = PR_ARRAY_SIZE(sftk_session_flags);
3417
3418
/*
3419
 * Cancel one or more operations running on the existing session.
3420
 */
3421
CK_RV
3422
NSC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags)
3423
0
{
3424
0
    SFTKSession *session;
3425
0
    SFTKSessionContext *context;
3426
0
    CK_RV gcrv = CKR_OK;
3427
0
    CK_RV crv;
3428
0
    int i;
3429
3430
0
    for (i = 0; i < sftk_flag_count; i++) {
3431
0
        if (flags & sftk_session_flags[i].flag) {
3432
0
            flags &= ~sftk_session_flags[i].flag;
3433
0
            crv = sftk_GetContext(hSession, &context, sftk_session_flags[i].type, PR_TRUE, &session);
3434
0
            if (crv != CKR_OK) {
3435
0
                gcrv = CKR_OPERATION_CANCEL_FAILED;
3436
0
                continue;
3437
0
            }
3438
0
            sftk_TerminateOp(session, sftk_session_flags[i].type, context);
3439
0
        }
3440
0
    }
3441
0
    if (flags & CKF_FIND_OBJECTS) {
3442
0
        flags &= ~CKF_FIND_OBJECTS;
3443
0
        crv = NSC_FindObjectsFinal(hSession);
3444
0
        if (crv != CKR_OK) {
3445
0
            gcrv = CKR_OPERATION_CANCEL_FAILED;
3446
0
        }
3447
0
    }
3448
0
    if (flags) {
3449
0
        gcrv = CKR_OPERATION_CANCEL_FAILED;
3450
0
    }
3451
0
    return gcrv;
3452
0
}
3453
3454
/* NSC_SignFinal finishes a multiple-part signature operation,
3455
 * returning the signature. */
3456
CK_RV
3457
NSC_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
3458
              CK_ULONG_PTR pulSignatureLen)
3459
69
{
3460
69
    SFTKSession *session;
3461
69
    SFTKSessionContext *context;
3462
69
    unsigned int outlen;
3463
69
    unsigned int maxoutlen = *pulSignatureLen;
3464
69
    CK_RV crv;
3465
3466
69
    CHECK_FORK();
3467
3468
    /* make sure we're legal */
3469
69
    crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_TRUE, &session);
3470
69
    if (crv != CKR_OK)
3471
0
        return crv;
3472
3473
69
    if (context->hashInfo) {
3474
69
        unsigned int digestLen;
3475
69
        unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
3476
3477
69
        if (!pSignature) {
3478
0
            outlen = context->maxLen;
3479
0
            goto finish;
3480
0
        }
3481
69
        (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
3482
69
        if (SECSuccess != (context->update)(context->cipherInfo, pSignature,
3483
69
                                            &outlen, maxoutlen, tmpbuf, digestLen))
3484
0
            crv = sftk_MapCryptError(PORT_GetError());
3485
        /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate.
3486
         * Keeping "too small" CK_RV intact is a standard violation, but allows
3487
         * application read EXACT signature length */
3488
69
        PORT_Memset(tmpbuf, 0, sizeof tmpbuf);
3489
69
    } else {
3490
        /* must be block cipher MACing */
3491
0
        outlen = context->macSize;
3492
        /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/
3493
0
        if (!pSignature || maxoutlen < outlen) {
3494
0
            if (pSignature)
3495
0
                crv = CKR_BUFFER_TOO_SMALL;
3496
0
            goto finish;
3497
0
        }
3498
0
        if (CKR_OK == (crv = sftk_MACFinal(context)))
3499
0
            PORT_Memcpy(pSignature, context->macBuf, outlen);
3500
0
    }
3501
3502
69
    sftk_TerminateOp(session, SFTK_SIGN, context);
3503
69
finish:
3504
69
    *pulSignatureLen = outlen;
3505
69
    sftk_FreeSession(session);
3506
69
    return crv;
3507
69
}
3508
3509
/* NSC_Sign signs (encrypts with private key) data in a single part,
3510
 * where the signature is (will be) an appendix to the data,
3511
 * and plaintext cannot be recovered from the signature */
3512
CK_RV
3513
NSC_Sign(CK_SESSION_HANDLE hSession,
3514
         CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
3515
         CK_ULONG_PTR pulSignatureLen)
3516
1
{
3517
1
    SFTKSession *session;
3518
1
    SFTKSessionContext *context;
3519
1
    CK_RV crv;
3520
3521
1
    CHECK_FORK();
3522
3523
    /* make sure we're legal */
3524
1
    crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_FALSE, &session);
3525
1
    if (crv != CKR_OK)
3526
0
        return crv;
3527
3528
1
    if (!pSignature) {
3529
        /* see also how C_SignUpdate implements this */
3530
0
        *pulSignatureLen = (!context->multi || context->hashInfo)
3531
0
                               ? context->maxLen
3532
0
                               : context->macSize; /* must be block cipher MACing */
3533
0
        goto finish;
3534
0
    }
3535
3536
    /* multi part Signing are completely implemented by SignUpdate and
3537
     * sign Final */
3538
1
    if (context->multi) {
3539
        /* SignFinal can't follow failed SignUpdate */
3540
1
        if (CKR_OK == (crv = NSC_SignUpdate(hSession, pData, ulDataLen)))
3541
1
            crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen);
3542
1
    } else {
3543
        /* single-part PKC signature (e.g. CKM_ECDSA) */
3544
0
        unsigned int outlen;
3545
0
        unsigned int maxoutlen = *pulSignatureLen;
3546
0
        if (SECSuccess != (*context->update)(context->cipherInfo, pSignature,
3547
0
                                             &outlen, maxoutlen, pData, ulDataLen))
3548
0
            crv = sftk_MapCryptError(PORT_GetError());
3549
0
        *pulSignatureLen = (CK_ULONG)outlen;
3550
        /*  "too small" here is certainly continuable */
3551
0
        if (crv != CKR_BUFFER_TOO_SMALL)
3552
0
            sftk_TerminateOp(session, SFTK_SIGN, context);
3553
0
    } /* single-part */
3554
3555
1
finish:
3556
1
    sftk_FreeSession(session);
3557
1
    return crv;
3558
1
}
3559
3560
/*
3561
 ************** Crypto Functions:     Sign Recover  ************************
3562
 */
3563
/* NSC_SignRecoverInit initializes a signature operation,
3564
 * where the (digest) data can be recovered from the signature.
3565
 * E.g. encryption with the user's private key */
3566
CK_RV
3567
NSC_SignRecoverInit(CK_SESSION_HANDLE hSession,
3568
                    CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3569
0
{
3570
0
    CHECK_FORK();
3571
3572
0
    switch (pMechanism->mechanism) {
3573
0
        case CKM_RSA_PKCS:
3574
0
        case CKM_RSA_X_509:
3575
0
            return NSC_SignInit(hSession, pMechanism, hKey);
3576
0
        default:
3577
0
            break;
3578
0
    }
3579
0
    return CKR_MECHANISM_INVALID;
3580
0
}
3581
3582
/* NSC_SignRecover signs data in a single operation
3583
 * where the (digest) data can be recovered from the signature.
3584
 * E.g. encryption with the user's private key */
3585
CK_RV
3586
NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
3587
                CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
3588
0
{
3589
0
    CHECK_FORK();
3590
3591
0
    return NSC_Sign(hSession, pData, ulDataLen, pSignature, pulSignatureLen);
3592
0
}
3593
3594
/*
3595
 ************** Crypto Functions:     verify  ************************
3596
 */
3597
3598
/* Handle RSA Signature formatting */
3599
static SECStatus
3600
sftk_hashCheckSign(void *ctx, const unsigned char *sig,
3601
                   unsigned int sigLen, const unsigned char *digest,
3602
                   unsigned int digestLen)
3603
0
{
3604
0
    SFTKHashVerifyInfo *info = ctx;
3605
0
    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
3606
0
    if (info->key->keyType != NSSLOWKEYRSAKey) {
3607
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
3608
0
        return SECFailure;
3609
0
    }
3610
3611
0
    return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, digest,
3612
0
                             digestLen);
3613
0
}
3614
3615
SECStatus
3616
RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key,
3617
                  const unsigned char *sig, unsigned int sigLen,
3618
                  const unsigned char *digestData, unsigned int digestLen)
3619
6
{
3620
6
    unsigned char *pkcs1DigestInfoData;
3621
6
    SECItem pkcs1DigestInfo;
3622
6
    SECItem digest;
3623
6
    unsigned int bufferSize;
3624
6
    SECStatus rv;
3625
3626
    /* pkcs1DigestInfo.data must be less than key->u.rsa.modulus.len */
3627
6
    bufferSize = key->u.rsa.modulus.len;
3628
6
    pkcs1DigestInfoData = PORT_ZAlloc(bufferSize);
3629
6
    if (!pkcs1DigestInfoData) {
3630
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
3631
0
        return SECFailure;
3632
0
    }
3633
3634
6
    pkcs1DigestInfo.data = pkcs1DigestInfoData;
3635
6
    pkcs1DigestInfo.len = bufferSize;
3636
3637
    /* decrypt the block */
3638
6
    rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data,
3639
6
                              &pkcs1DigestInfo.len, pkcs1DigestInfo.len,
3640
6
                              sig, sigLen);
3641
6
    if (rv != SECSuccess) {
3642
0
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
3643
6
    } else {
3644
6
        digest.data = (PRUint8 *)digestData;
3645
6
        digest.len = digestLen;
3646
6
        rv = _SGN_VerifyPKCS1DigestInfo(
3647
6
            digestOid, &digest, &pkcs1DigestInfo,
3648
6
            PR_FALSE /*XXX: unsafeAllowMissingParameters*/);
3649
6
    }
3650
3651
6
    PORT_ZFree(pkcs1DigestInfoData, bufferSize);
3652
6
    return rv;
3653
6
}
3654
3655
static SECStatus
3656
sftk_RSACheckSign(void *ctx, const unsigned char *sig,
3657
                  unsigned int sigLen, const unsigned char *digest,
3658
                  unsigned int digestLen)
3659
0
{
3660
0
    NSSLOWKEYPublicKey *key = ctx;
3661
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
3662
0
    if (key->keyType != NSSLOWKEYRSAKey) {
3663
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
3664
0
        return SECFailure;
3665
0
    }
3666
3667
0
    return RSA_CheckSign(&key->u.rsa, sig, sigLen, digest, digestLen);
3668
0
}
3669
3670
static SECStatus
3671
sftk_RSACheckSignRaw(void *ctx, const unsigned char *sig,
3672
                     unsigned int sigLen, const unsigned char *digest,
3673
                     unsigned int digestLen)
3674
0
{
3675
0
    NSSLOWKEYPublicKey *key = ctx;
3676
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
3677
0
    if (key->keyType != NSSLOWKEYRSAKey) {
3678
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
3679
0
        return SECFailure;
3680
0
    }
3681
3682
0
    return RSA_CheckSignRaw(&key->u.rsa, sig, sigLen, digest, digestLen);
3683
0
}
3684
3685
static SECStatus
3686
sftk_RSACheckSignPSS(void *ctx, const unsigned char *sig,
3687
                     unsigned int sigLen, const unsigned char *digest,
3688
                     unsigned int digestLen)
3689
0
{
3690
0
    SFTKPSSVerifyInfo *info = ctx;
3691
0
    HASH_HashType hashAlg;
3692
0
    HASH_HashType maskHashAlg;
3693
0
    CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
3694
3695
0
    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
3696
0
    if (info->key->keyType != NSSLOWKEYRSAKey) {
3697
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
3698
0
        return SECFailure;
3699
0
    }
3700
3701
0
    hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg);
3702
0
    maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf);
3703
3704
0
    return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg,
3705
0
                            params->sLen, sig, sigLen, digest, digestLen);
3706
0
}
3707
3708
/* NSC_VerifyInit initializes a verification operation,
3709
 * where the signature is an appendix to the data,
3710
 * and plaintext cannot be recovered from the signature (e.g. DSA) */
3711
CK_RV
3712
NSC_VerifyInit(CK_SESSION_HANDLE hSession,
3713
               CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3714
0
{
3715
0
    SFTKSession *session;
3716
0
    SFTKObject *key;
3717
0
    SFTKSessionContext *context;
3718
0
    CK_KEY_TYPE key_type;
3719
0
    CK_RV crv = CKR_OK;
3720
0
    NSSLOWKEYPublicKey *pubKey;
3721
0
    SFTKHashVerifyInfo *info = NULL;
3722
0
    SFTKPSSVerifyInfo *pinfo = NULL;
3723
3724
0
    CHECK_FORK();
3725
3726
    /* Block Cipher MACing Algorithms use a different Context init method..*/
3727
0
    crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY);
3728
0
    if (crv != CKR_FUNCTION_NOT_SUPPORTED)
3729
0
        return crv;
3730
3731
0
    session = sftk_SessionFromHandle(hSession);
3732
0
    if (session == NULL)
3733
0
        return CKR_SESSION_HANDLE_INVALID;
3734
0
    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY, &key,
3735
0
                           hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY);
3736
0
    if (crv != CKR_OK) {
3737
0
        sftk_FreeSession(session);
3738
0
        return crv;
3739
0
    }
3740
3741
0
    context->multi = PR_FALSE;
3742
3743
0
#define INIT_RSA_VFY_MECH(mmm)                \
3744
0
    case CKM_##mmm##_RSA_PKCS:                \
3745
0
        context->multi = PR_TRUE;             \
3746
0
        crv = sftk_doSub##mmm(context);       \
3747
0
        if (crv != CKR_OK)                    \
3748
0
            break;                            \
3749
0
        context->verify = sftk_hashCheckSign; \
3750
0
        info = PORT_New(SFTKHashVerifyInfo);  \
3751
0
        if (info == NULL) {                   \
3752
0
            crv = CKR_HOST_MEMORY;            \
3753
0
            break;                            \
3754
0
        }                                     \
3755
0
        info->hashOid = SEC_OID_##mmm;        \
3756
0
        goto finish_rsa;
3757
3758
0
    switch (pMechanism->mechanism) {
3759
0
        INIT_RSA_VFY_MECH(MD5)
3760
0
        INIT_RSA_VFY_MECH(MD2)
3761
0
        INIT_RSA_VFY_MECH(SHA1)
3762
0
        INIT_RSA_VFY_MECH(SHA224)
3763
0
        INIT_RSA_VFY_MECH(SHA256)
3764
0
        INIT_RSA_VFY_MECH(SHA384)
3765
0
        INIT_RSA_VFY_MECH(SHA512)
3766
3767
0
        case CKM_RSA_PKCS:
3768
0
            context->verify = sftk_RSACheckSign;
3769
0
            goto finish_rsa;
3770
0
        case CKM_RSA_X_509:
3771
0
            context->verify = sftk_RSACheckSignRaw;
3772
0
        finish_rsa:
3773
0
            if (key_type != CKK_RSA) {
3774
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3775
0
                break;
3776
0
            }
3777
0
            context->rsa = PR_TRUE;
3778
0
            pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
3779
0
            if (pubKey == NULL) {
3780
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3781
0
                break;
3782
0
            }
3783
0
            if (info) {
3784
0
                info->key = pubKey;
3785
0
                context->cipherInfo = info;
3786
0
                context->destroy = sftk_Space;
3787
0
            } else {
3788
0
                context->cipherInfo = pubKey;
3789
0
                context->destroy = sftk_Null;
3790
0
            }
3791
0
            break;
3792
3793
0
            INIT_RSA_PSS_SIG_MECH(SHA1)
3794
0
            INIT_RSA_PSS_SIG_MECH(SHA224)
3795
0
            INIT_RSA_PSS_SIG_MECH(SHA256)
3796
0
            INIT_RSA_PSS_SIG_MECH(SHA384)
3797
0
            INIT_RSA_PSS_SIG_MECH(SHA512)
3798
0
        case CKM_RSA_PKCS_PSS:
3799
0
        finish_rsa_pss:
3800
0
            if (key_type != CKK_RSA) {
3801
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3802
0
                break;
3803
0
            }
3804
0
            context->rsa = PR_TRUE;
3805
0
            if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
3806
0
                !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) {
3807
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3808
0
                break;
3809
0
            }
3810
0
            pinfo = PORT_New(SFTKPSSVerifyInfo);
3811
0
            if (pinfo == NULL) {
3812
0
                crv = CKR_HOST_MEMORY;
3813
0
                break;
3814
0
            }
3815
0
            pinfo->size = sizeof(SFTKPSSVerifyInfo);
3816
0
            pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter;
3817
0
            pinfo->key = sftk_GetPubKey(key, CKK_RSA, &crv);
3818
0
            if (pinfo->key == NULL) {
3819
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3820
0
                break;
3821
0
            }
3822
0
            context->cipherInfo = pinfo;
3823
0
            context->destroy = sftk_ZSpace;
3824
0
            context->verify = sftk_RSACheckSignPSS;
3825
0
            break;
3826
3827
0
            INIT_DSA_SIG_MECH(SHA1)
3828
0
            INIT_DSA_SIG_MECH(SHA224)
3829
0
            INIT_DSA_SIG_MECH(SHA256)
3830
0
            INIT_DSA_SIG_MECH(SHA384)
3831
0
            INIT_DSA_SIG_MECH(SHA512)
3832
0
        case CKM_DSA:
3833
0
        finish_dsa:
3834
0
            if (key_type != CKK_DSA) {
3835
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3836
0
                break;
3837
0
            }
3838
0
            pubKey = sftk_GetPubKey(key, CKK_DSA, &crv);
3839
0
            if (pubKey == NULL) {
3840
0
                break;
3841
0
            }
3842
0
            context->cipherInfo = pubKey;
3843
0
            context->verify = nsc_DSA_Verify_Stub;
3844
0
            context->destroy = sftk_Null;
3845
0
            break;
3846
3847
0
            INIT_ECDSA_SIG_MECH(SHA1)
3848
0
            INIT_ECDSA_SIG_MECH(SHA224)
3849
0
            INIT_ECDSA_SIG_MECH(SHA256)
3850
0
            INIT_ECDSA_SIG_MECH(SHA384)
3851
0
            INIT_ECDSA_SIG_MECH(SHA512)
3852
0
        case CKM_ECDSA:
3853
0
        finish_ecdsa:
3854
0
            if (key_type != CKK_EC) {
3855
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3856
0
                break;
3857
0
            }
3858
0
            pubKey = sftk_GetPubKey(key, CKK_EC, &crv);
3859
0
            if (pubKey == NULL) {
3860
0
                crv = CKR_HOST_MEMORY;
3861
0
                break;
3862
0
            }
3863
0
            context->cipherInfo = pubKey;
3864
0
            context->verify = nsc_ECDSAVerifyStub;
3865
0
            context->destroy = sftk_Null;
3866
0
            break;
3867
3868
0
            INIT_HMAC_MECH(MD2)
3869
0
            INIT_HMAC_MECH(MD5)
3870
0
            INIT_HMAC_MECH(SHA1)
3871
0
            INIT_HMAC_MECH(SHA224)
3872
0
            INIT_HMAC_MECH(SHA256)
3873
0
            INIT_HMAC_MECH(SHA384)
3874
0
            INIT_HMAC_MECH(SHA512)
3875
0
            INIT_HMAC_MECH(SHA3_224)
3876
0
            INIT_HMAC_MECH(SHA3_256)
3877
0
            INIT_HMAC_MECH(SHA3_384)
3878
0
            INIT_HMAC_MECH(SHA3_512)
3879
3880
0
        case CKM_EDDSA:
3881
0
            if (key_type != CKK_EC_EDWARDS) {
3882
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3883
0
                break;
3884
0
            }
3885
0
            pubKey = sftk_GetPubKey(key, CKK_EC_EDWARDS, &crv);
3886
0
            if (pubKey == NULL) {
3887
0
                crv = CKR_HOST_MEMORY;
3888
0
                break;
3889
0
            }
3890
3891
0
            if (pMechanism->pParameter) {
3892
0
                crv = CKR_FUNCTION_NOT_SUPPORTED;
3893
0
                break;
3894
0
            }
3895
3896
0
            context->cipherInfo = pubKey;
3897
0
            context->verify = nsc_EDDSAVerifyStub;
3898
0
            context->destroy = sftk_Null;
3899
0
            break;
3900
3901
0
        case CKM_SSL3_MD5_MAC:
3902
0
            PORT_Assert(pMechanism->pParameter);
3903
0
            if (!pMechanism->pParameter) {
3904
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3905
0
                break;
3906
0
            }
3907
0
            crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key,
3908
0
                                    *(CK_ULONG *)pMechanism->pParameter);
3909
0
            break;
3910
0
        case CKM_SSL3_SHA1_MAC:
3911
0
            PORT_Assert(pMechanism->pParameter);
3912
0
            if (!pMechanism->pParameter) {
3913
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3914
0
                break;
3915
0
            }
3916
0
            crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key,
3917
0
                                    *(CK_ULONG *)pMechanism->pParameter);
3918
0
            break;
3919
0
        case CKM_TLS_PRF_GENERAL:
3920
0
            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0);
3921
0
            break;
3922
0
        case CKM_NSS_TLS_PRF_GENERAL_SHA256:
3923
0
            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0);
3924
0
            break;
3925
3926
0
        default:
3927
0
            crv = CKR_MECHANISM_INVALID;
3928
0
            break;
3929
0
    }
3930
3931
0
    if (crv != CKR_OK) {
3932
0
        if (info)
3933
0
            PORT_Free(info);
3934
0
        if (pinfo)
3935
0
            PORT_ZFree(pinfo, pinfo->size);
3936
0
        sftk_FreeContext(context);
3937
0
        sftk_FreeSession(session);
3938
0
        return crv;
3939
0
    }
3940
0
    sftk_SetContextByType(session, SFTK_VERIFY, context);
3941
0
    sftk_FreeSession(session);
3942
0
    return CKR_OK;
3943
0
}
3944
3945
/* NSC_Verify verifies a signature in a single-part operation,
3946
 * where the signature is an appendix to the data,
3947
 * and plaintext cannot be recovered from the signature */
3948
CK_RV
3949
NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
3950
           CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
3951
0
{
3952
0
    SFTKSession *session;
3953
0
    SFTKSessionContext *context;
3954
0
    CK_RV crv;
3955
3956
0
    CHECK_FORK();
3957
3958
    /* make sure we're legal */
3959
0
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session);
3960
0
    if (crv != CKR_OK)
3961
0
        return crv;
3962
3963
    /* multi part Verifying are completely implemented by VerifyUpdate and
3964
     * VerifyFinal */
3965
0
    if (context->multi) {
3966
        /* VerifyFinal can't follow failed VerifyUpdate */
3967
0
        if (CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen)))
3968
0
            crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen);
3969
0
    } else {
3970
0
        if (SECSuccess != (*context->verify)(context->cipherInfo, pSignature,
3971
0
                                             ulSignatureLen, pData, ulDataLen))
3972
0
            crv = sftk_MapCryptError(PORT_GetError());
3973
3974
0
        sftk_TerminateOp(session, SFTK_VERIFY, context);
3975
0
    }
3976
0
    sftk_FreeSession(session);
3977
0
    return crv;
3978
0
}
3979
3980
/* NSC_VerifyUpdate continues a multiple-part verification operation,
3981
 * where the signature is an appendix to the data,
3982
 * and plaintext cannot be recovered from the signature
3983
 *
3984
 * A call which results in an error terminates the operation [PKCS#11,v2.11]
3985
 */
3986
CK_RV
3987
NSC_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
3988
                 CK_ULONG ulPartLen)
3989
0
{
3990
0
    CHECK_FORK();
3991
0
    return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY);
3992
0
}
3993
3994
/* NSC_VerifyFinal finishes a multiple-part verification operation,
3995
 * checking the signature. */
3996
CK_RV
3997
NSC_VerifyFinal(CK_SESSION_HANDLE hSession,
3998
                CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
3999
0
{
4000
0
    SFTKSession *session;
4001
0
    SFTKSessionContext *context;
4002
0
    CK_RV crv;
4003
4004
0
    CHECK_FORK();
4005
4006
0
    if (!pSignature)
4007
0
        return CKR_ARGUMENTS_BAD;
4008
4009
    /* make sure we're legal */
4010
0
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session);
4011
0
    if (crv != CKR_OK)
4012
0
        return crv;
4013
4014
0
    if (context->hashInfo) {
4015
0
        unsigned int digestLen;
4016
0
        unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
4017
4018
0
        (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
4019
0
        if (SECSuccess != (context->verify)(context->cipherInfo, pSignature,
4020
0
                                            ulSignatureLen, tmpbuf, digestLen))
4021
0
            crv = sftk_MapCryptError(PORT_GetError());
4022
0
        PORT_Memset(tmpbuf, 0, sizeof tmpbuf);
4023
0
    } else if (ulSignatureLen != context->macSize) {
4024
        /* must be block cipher MACing */
4025
0
        crv = CKR_SIGNATURE_LEN_RANGE;
4026
0
    } else if (CKR_OK == (crv = sftk_MACFinal(context))) {
4027
0
        if (NSS_SecureMemcmp(pSignature, context->macBuf, ulSignatureLen))
4028
0
            crv = CKR_SIGNATURE_INVALID;
4029
0
    }
4030
4031
0
    sftk_TerminateOp(session, SFTK_VERIFY, context);
4032
0
    sftk_FreeSession(session);
4033
0
    return crv;
4034
0
}
4035
4036
/*
4037
 ************** Crypto Functions:     Verify  Recover ************************
4038
 */
4039
static SECStatus
4040
sftk_RSACheckSignRecover(void *ctx, unsigned char *data,
4041
                         unsigned int *dataLen, unsigned int maxDataLen,
4042
                         const unsigned char *sig, unsigned int sigLen)
4043
0
{
4044
0
    NSSLOWKEYPublicKey *key = ctx;
4045
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
4046
0
    if (key->keyType != NSSLOWKEYRSAKey) {
4047
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
4048
0
        return SECFailure;
4049
0
    }
4050
4051
0
    return RSA_CheckSignRecover(&key->u.rsa, data, dataLen, maxDataLen,
4052
0
                                sig, sigLen);
4053
0
}
4054
4055
static SECStatus
4056
sftk_RSACheckSignRecoverRaw(void *ctx, unsigned char *data,
4057
                            unsigned int *dataLen, unsigned int maxDataLen,
4058
                            const unsigned char *sig, unsigned int sigLen)
4059
0
{
4060
0
    NSSLOWKEYPublicKey *key = ctx;
4061
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
4062
0
    if (key->keyType != NSSLOWKEYRSAKey) {
4063
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
4064
0
        return SECFailure;
4065
0
    }
4066
4067
0
    return RSA_CheckSignRecoverRaw(&key->u.rsa, data, dataLen, maxDataLen,
4068
0
                                   sig, sigLen);
4069
0
}
4070
4071
/* NSC_VerifyRecoverInit initializes a signature verification operation,
4072
 * where the data is recovered from the signature.
4073
 * E.g. Decryption with the user's public key */
4074
CK_RV
4075
NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
4076
                      CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4077
0
{
4078
0
    SFTKSession *session;
4079
0
    SFTKObject *key;
4080
0
    SFTKSessionContext *context;
4081
0
    CK_KEY_TYPE key_type;
4082
0
    CK_RV crv = CKR_OK;
4083
0
    NSSLOWKEYPublicKey *pubKey;
4084
4085
0
    CHECK_FORK();
4086
4087
0
    session = sftk_SessionFromHandle(hSession);
4088
0
    if (session == NULL)
4089
0
        return CKR_SESSION_HANDLE_INVALID;
4090
0
    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY_RECOVER,
4091
0
                           &key, hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY_RECOVER);
4092
0
    if (crv != CKR_OK) {
4093
0
        sftk_FreeSession(session);
4094
0
        return crv;
4095
0
    }
4096
4097
0
    context->multi = PR_TRUE;
4098
4099
0
    switch (pMechanism->mechanism) {
4100
0
        case CKM_RSA_PKCS:
4101
0
        case CKM_RSA_X_509:
4102
0
            if (key_type != CKK_RSA) {
4103
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
4104
0
                break;
4105
0
            }
4106
0
            context->multi = PR_FALSE;
4107
0
            context->rsa = PR_TRUE;
4108
0
            pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
4109
0
            if (pubKey == NULL) {
4110
0
                break;
4111
0
            }
4112
0
            context->cipherInfo = pubKey;
4113
0
            context->update = pMechanism->mechanism == CKM_RSA_X_509
4114
0
                                  ? sftk_RSACheckSignRecoverRaw
4115
0
                                  : sftk_RSACheckSignRecover;
4116
0
            context->destroy = sftk_Null;
4117
0
            break;
4118
0
        default:
4119
0
            crv = CKR_MECHANISM_INVALID;
4120
0
            break;
4121
0
    }
4122
4123
0
    if (crv != CKR_OK) {
4124
0
        PORT_Free(context);
4125
0
        sftk_FreeSession(session);
4126
0
        return crv;
4127
0
    }
4128
0
    sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context);
4129
0
    sftk_FreeSession(session);
4130
0
    return CKR_OK;
4131
0
}
4132
4133
/* NSC_VerifyRecover verifies a signature in a single-part operation,
4134
 * where the data is recovered from the signature.
4135
 * E.g. Decryption with the user's public key */
4136
CK_RV
4137
NSC_VerifyRecover(CK_SESSION_HANDLE hSession,
4138
                  CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen,
4139
                  CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
4140
0
{
4141
0
    SFTKSession *session;
4142
0
    SFTKSessionContext *context;
4143
0
    unsigned int outlen;
4144
0
    unsigned int maxoutlen = *pulDataLen;
4145
0
    CK_RV crv;
4146
0
    SECStatus rv;
4147
4148
0
    CHECK_FORK();
4149
4150
    /* make sure we're legal */
4151
0
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY_RECOVER,
4152
0
                          PR_FALSE, &session);
4153
0
    if (crv != CKR_OK)
4154
0
        return crv;
4155
0
    if (pData == NULL) {
4156
        /* to return the actual size, we need  to do the decrypt, just return
4157
         * the max size, which is the size of the input signature. */
4158
0
        *pulDataLen = ulSignatureLen;
4159
0
        rv = SECSuccess;
4160
0
        goto finish;
4161
0
    }
4162
4163
0
    rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
4164
0
                            pSignature, ulSignatureLen);
4165
0
    *pulDataLen = (CK_ULONG)outlen;
4166
4167
0
    sftk_TerminateOp(session, SFTK_VERIFY_RECOVER, context);
4168
0
finish:
4169
0
    sftk_FreeSession(session);
4170
0
    return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError());
4171
0
}
4172
4173
/*
4174
 **************************** Random Functions:  ************************
4175
 */
4176
4177
/* NSC_SeedRandom mixes additional seed material into the token's random number
4178
 * generator. */
4179
CK_RV
4180
NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
4181
               CK_ULONG ulSeedLen)
4182
0
{
4183
0
    SECStatus rv;
4184
4185
0
    CHECK_FORK();
4186
4187
0
    rv = RNG_RandomUpdate(pSeed, ulSeedLen);
4188
0
    return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
4189
0
}
4190
4191
/* NSC_GenerateRandom generates random data. */
4192
CK_RV
4193
NSC_GenerateRandom(CK_SESSION_HANDLE hSession,
4194
                   CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
4195
62
{
4196
62
    SECStatus rv;
4197
4198
62
    CHECK_FORK();
4199
4200
62
    rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen);
4201
    /*
4202
     * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't
4203
     * seeded with enough entropy.
4204
     */
4205
62
    return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
4206
62
}
4207
4208
/*
4209
 **************************** Key Functions:  ************************
4210
 */
4211
4212
/*
4213
 * generate a password based encryption key. This code uses
4214
 * PKCS5 to do the work.
4215
 */
4216
static CK_RV
4217
nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism,
4218
                void *buf, CK_ULONG *key_length, PRBool faulty3DES)
4219
56
{
4220
56
    SECItem *pbe_key = NULL, iv, pwitem;
4221
56
    CK_PBE_PARAMS *pbe_params = NULL;
4222
56
    CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL;
4223
4224
56
    *key_length = 0;
4225
56
    iv.data = NULL;
4226
56
    iv.len = 0;
4227
4228
56
    if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
4229
56
        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PKCS5_PBKD2_PARAMS))) {
4230
0
            return CKR_MECHANISM_PARAM_INVALID;
4231
0
        }
4232
56
        pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
4233
56
        pwitem.data = (unsigned char *)pbkd2_params->pPassword;
4234
        /* was this a typo in the PKCS #11 spec? */
4235
56
        pwitem.len = *pbkd2_params->ulPasswordLen;
4236
56
    } else {
4237
0
        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
4238
0
            return CKR_MECHANISM_PARAM_INVALID;
4239
0
        }
4240
0
        pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
4241
0
        pwitem.data = (unsigned char *)pbe_params->pPassword;
4242
0
        pwitem.len = pbe_params->ulPasswordLen;
4243
0
    }
4244
56
    pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES);
4245
56
    if (pbe_key == NULL) {
4246
0
        return CKR_HOST_MEMORY;
4247
0
    }
4248
4249
56
    PORT_Memcpy(buf, pbe_key->data, pbe_key->len);
4250
56
    *key_length = pbe_key->len;
4251
56
    SECITEM_ZfreeItem(pbe_key, PR_TRUE);
4252
56
    pbe_key = NULL;
4253
4254
56
    if (iv.data) {
4255
0
        if (pbe_params && pbe_params->pInitVector != NULL) {
4256
0
            PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len);
4257
0
        }
4258
0
        PORT_Free(iv.data);
4259
0
    }
4260
4261
56
    return CKR_OK;
4262
56
}
4263
4264
/*
4265
 * this is coded for "full" support. These selections will be limitted to
4266
 * the official subset by freebl.
4267
 */
4268
static unsigned int
4269
sftk_GetSubPrimeFromPrime(unsigned int primeBits)
4270
0
{
4271
0
    if (primeBits <= 1024) {
4272
0
        return 160;
4273
0
    } else if (primeBits <= 2048) {
4274
0
        return 224;
4275
0
    } else if (primeBits <= 3072) {
4276
0
        return 256;
4277
0
    } else if (primeBits <= 7680) {
4278
0
        return 384;
4279
0
    } else {
4280
0
        return 512;
4281
0
    }
4282
0
}
4283
4284
static CK_RV
4285
nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key)
4286
0
{
4287
0
    SFTKAttribute *attribute;
4288
0
    CK_ULONG counter;
4289
0
    unsigned int seedBits = 0;
4290
0
    unsigned int subprimeBits = 0;
4291
0
    unsigned int primeBits;
4292
0
    unsigned int j = 8; /* default to 1024 bits */
4293
0
    CK_RV crv = CKR_OK;
4294
0
    PQGParams *params = NULL;
4295
0
    PQGVerify *vfy = NULL;
4296
0
    SECStatus rv;
4297
4298
0
    attribute = sftk_FindAttribute(key, CKA_PRIME_BITS);
4299
0
    if (attribute == NULL) {
4300
0
        attribute = sftk_FindAttribute(key, CKA_PRIME);
4301
0
        if (attribute == NULL) {
4302
0
            return CKR_TEMPLATE_INCOMPLETE;
4303
0
        } else {
4304
0
            primeBits = attribute->attrib.ulValueLen;
4305
0
            sftk_FreeAttribute(attribute);
4306
0
        }
4307
0
    } else {
4308
0
        primeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
4309
0
        sftk_FreeAttribute(attribute);
4310
0
    }
4311
0
    if (primeBits < 1024) {
4312
0
        j = PQG_PBITS_TO_INDEX(primeBits);
4313
0
        if (j == (unsigned int)-1) {
4314
0
            return CKR_ATTRIBUTE_VALUE_INVALID;
4315
0
        }
4316
0
    }
4317
4318
0
    attribute = sftk_FindAttribute(key, CKA_NSS_PQG_SEED_BITS);
4319
0
    if (attribute != NULL) {
4320
0
        seedBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
4321
0
        sftk_FreeAttribute(attribute);
4322
0
    }
4323
4324
0
    attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS);
4325
0
    if (attribute != NULL) {
4326
0
        subprimeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
4327
0
        sftk_FreeAttribute(attribute);
4328
0
    }
4329
4330
    /* if P and Q are supplied, we want to generate a new G */
4331
0
    attribute = sftk_FindAttribute(key, CKA_PRIME);
4332
0
    if (attribute != NULL) {
4333
0
        PLArenaPool *arena;
4334
4335
0
        sftk_FreeAttribute(attribute);
4336
0
        arena = PORT_NewArena(1024);
4337
0
        if (arena == NULL) {
4338
0
            crv = CKR_HOST_MEMORY;
4339
0
            goto loser;
4340
0
        }
4341
0
        params = PORT_ArenaAlloc(arena, sizeof(*params));
4342
0
        if (params == NULL) {
4343
0
            crv = CKR_HOST_MEMORY;
4344
0
            goto loser;
4345
0
        }
4346
0
        params->arena = arena;
4347
0
        crv = sftk_Attribute2SSecItem(arena, &params->prime, key, CKA_PRIME);
4348
0
        if (crv != CKR_OK) {
4349
0
            goto loser;
4350
0
        }
4351
0
        crv = sftk_Attribute2SSecItem(arena, &params->subPrime,
4352
0
                                      key, CKA_SUBPRIME);
4353
0
        if (crv != CKR_OK) {
4354
0
            goto loser;
4355
0
        }
4356
4357
0
        arena = PORT_NewArena(1024);
4358
0
        if (arena == NULL) {
4359
0
            crv = CKR_HOST_MEMORY;
4360
0
            goto loser;
4361
0
        }
4362
0
        vfy = PORT_ArenaAlloc(arena, sizeof(*vfy));
4363
0
        if (vfy == NULL) {
4364
0
            crv = CKR_HOST_MEMORY;
4365
0
            goto loser;
4366
0
        }
4367
0
        vfy->arena = arena;
4368
0
        crv = sftk_Attribute2SSecItem(arena, &vfy->seed, key, CKA_NSS_PQG_SEED);
4369
0
        if (crv != CKR_OK) {
4370
0
            goto loser;
4371
0
        }
4372
0
        crv = sftk_Attribute2SSecItem(arena, &vfy->h, key, CKA_NSS_PQG_H);
4373
0
        if (crv != CKR_OK) {
4374
0
            goto loser;
4375
0
        }
4376
0
        sftk_DeleteAttributeType(key, CKA_PRIME);
4377
0
        sftk_DeleteAttributeType(key, CKA_SUBPRIME);
4378
0
        sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED);
4379
0
        sftk_DeleteAttributeType(key, CKA_NSS_PQG_H);
4380
0
    }
4381
4382
0
    sftk_DeleteAttributeType(key, CKA_PRIME_BITS);
4383
0
    sftk_DeleteAttributeType(key, CKA_SUBPRIME_BITS);
4384
0
    sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED_BITS);
4385
4386
    /* use the old PQG interface if we have old input data */
4387
0
    if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) {
4388
0
        if (seedBits == 0) {
4389
0
            rv = PQG_ParamGen(j, &params, &vfy);
4390
0
        } else {
4391
0
            rv = PQG_ParamGenSeedLen(j, seedBits / 8, &params, &vfy);
4392
0
        }
4393
0
    } else {
4394
0
        if (subprimeBits == 0) {
4395
0
            subprimeBits = sftk_GetSubPrimeFromPrime(primeBits);
4396
0
        }
4397
0
        if (seedBits == 0) {
4398
0
            seedBits = primeBits;
4399
0
        }
4400
0
        rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits / 8, &params, &vfy);
4401
0
    }
4402
4403
0
    if (rv != SECSuccess) {
4404
0
        if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
4405
0
            sftk_fatalError = PR_TRUE;
4406
0
        }
4407
0
        return sftk_MapCryptError(PORT_GetError());
4408
0
    }
4409
0
    crv = sftk_AddAttributeType(key, CKA_PRIME,
4410
0
                                params->prime.data, params->prime.len);
4411
0
    if (crv != CKR_OK)
4412
0
        goto loser;
4413
0
    crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
4414
0
                                params->subPrime.data, params->subPrime.len);
4415
0
    if (crv != CKR_OK)
4416
0
        goto loser;
4417
0
    crv = sftk_AddAttributeType(key, CKA_BASE,
4418
0
                                params->base.data, params->base.len);
4419
0
    if (crv != CKR_OK)
4420
0
        goto loser;
4421
0
    counter = vfy->counter;
4422
0
    crv = sftk_AddAttributeType(key, CKA_NSS_PQG_COUNTER,
4423
0
                                &counter, sizeof(counter));
4424
0
    if (crv != CKR_OK)
4425
0
        goto loser;
4426
0
    crv = sftk_AddAttributeType(key, CKA_NSS_PQG_SEED,
4427
0
                                vfy->seed.data, vfy->seed.len);
4428
0
    if (crv != CKR_OK)
4429
0
        goto loser;
4430
0
    crv = sftk_AddAttributeType(key, CKA_NSS_PQG_H,
4431
0
                                vfy->h.data, vfy->h.len);
4432
0
    if (crv != CKR_OK)
4433
0
        goto loser;
4434
4435
0
loser:
4436
0
    if (params) {
4437
0
        PQG_DestroyParams(params);
4438
0
    }
4439
4440
0
    if (vfy) {
4441
0
        PQG_DestroyVerify(vfy);
4442
0
    }
4443
0
    return crv;
4444
0
}
4445
4446
static CK_RV
4447
nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type,
4448
                    CK_ULONG *key_length)
4449
0
{
4450
0
    CK_RV crv = CKR_OK;
4451
4452
0
    switch (mechanism) {
4453
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
4454
0
        case CKM_RC2_KEY_GEN:
4455
0
            *key_type = CKK_RC2;
4456
0
            if (*key_length == 0)
4457
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4458
0
            break;
4459
0
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
4460
#if NSS_SOFTOKEN_DOES_RC5
4461
        case CKM_RC5_KEY_GEN:
4462
            *key_type = CKK_RC5;
4463
            if (*key_length == 0)
4464
                crv = CKR_TEMPLATE_INCOMPLETE;
4465
            break;
4466
#endif
4467
0
        case CKM_RC4_KEY_GEN:
4468
0
            *key_type = CKK_RC4;
4469
0
            if (*key_length == 0)
4470
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4471
0
            break;
4472
0
        case CKM_GENERIC_SECRET_KEY_GEN:
4473
0
            *key_type = CKK_GENERIC_SECRET;
4474
0
            if (*key_length == 0)
4475
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4476
0
            break;
4477
0
        case CKM_CDMF_KEY_GEN:
4478
0
            *key_type = CKK_CDMF;
4479
0
            *key_length = 8;
4480
0
            break;
4481
0
        case CKM_DES_KEY_GEN:
4482
0
            *key_type = CKK_DES;
4483
0
            *key_length = 8;
4484
0
            break;
4485
0
        case CKM_DES2_KEY_GEN:
4486
0
            *key_type = CKK_DES2;
4487
0
            *key_length = 16;
4488
0
            break;
4489
0
        case CKM_DES3_KEY_GEN:
4490
0
            *key_type = CKK_DES3;
4491
0
            *key_length = 24;
4492
0
            break;
4493
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
4494
0
        case CKM_SEED_KEY_GEN:
4495
0
            *key_type = CKK_SEED;
4496
0
            *key_length = 16;
4497
0
            break;
4498
0
#endif /* NSS_DISABLE_DEPRECATED_SEED */
4499
0
        case CKM_CAMELLIA_KEY_GEN:
4500
0
            *key_type = CKK_CAMELLIA;
4501
0
            if (*key_length == 0)
4502
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4503
0
            break;
4504
0
        case CKM_AES_KEY_GEN:
4505
0
            *key_type = CKK_AES;
4506
0
            if (*key_length == 0)
4507
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4508
0
            break;
4509
0
        case CKM_NSS_CHACHA20_KEY_GEN:
4510
0
            *key_type = CKK_NSS_CHACHA20;
4511
0
            *key_length = 32;
4512
0
            break;
4513
0
        case CKM_CHACHA20_KEY_GEN:
4514
0
            *key_type = CKK_CHACHA20;
4515
0
            *key_length = 32;
4516
0
            break;
4517
0
        case CKM_HKDF_KEY_GEN:
4518
0
            *key_type = CKK_HKDF;
4519
0
            if (*key_length == 0)
4520
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4521
0
            break;
4522
0
        default:
4523
0
            PORT_Assert(0);
4524
0
            crv = CKR_MECHANISM_INVALID;
4525
0
            break;
4526
0
    }
4527
4528
0
    return crv;
4529
0
}
4530
4531
CK_RV
4532
nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe)
4533
0
{
4534
0
    SECItem salt;
4535
0
    CK_PBE_PARAMS *pbe_params = NULL;
4536
0
    NSSPKCS5PBEParameter *params;
4537
0
    PLArenaPool *arena = NULL;
4538
0
    SECStatus rv;
4539
4540
0
    *pbe = NULL;
4541
4542
0
    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
4543
0
    if (arena == NULL) {
4544
0
        return CKR_HOST_MEMORY;
4545
0
    }
4546
4547
0
    params = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena,
4548
0
                                                      sizeof(NSSPKCS5PBEParameter));
4549
0
    if (params == NULL) {
4550
0
        PORT_FreeArena(arena, PR_TRUE);
4551
0
        return CKR_HOST_MEMORY;
4552
0
    }
4553
0
    if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
4554
0
        PORT_FreeArena(arena, PR_TRUE);
4555
0
        return CKR_MECHANISM_PARAM_INVALID;
4556
0
    }
4557
4558
0
    params->poolp = arena;
4559
0
    params->ivLen = 0;
4560
0
    params->pbeType = NSSPKCS5_PKCS12_V2;
4561
0
    params->hashType = HASH_AlgSHA1;
4562
0
    params->encAlg = SEC_OID_SHA1; /* any invalid value */
4563
0
    params->is2KeyDES = PR_FALSE;
4564
0
    params->keyID = pbeBitGenIntegrityKey;
4565
0
    pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
4566
0
    params->iter = pbe_params->ulIteration;
4567
4568
0
    salt.data = (unsigned char *)pbe_params->pSalt;
4569
0
    salt.len = (unsigned int)pbe_params->ulSaltLen;
4570
0
    salt.type = siBuffer;
4571
0
    rv = SECITEM_CopyItem(arena, &params->salt, &salt);
4572
0
    if (rv != SECSuccess) {
4573
0
        PORT_FreeArena(arena, PR_TRUE);
4574
0
        return CKR_HOST_MEMORY;
4575
0
    }
4576
0
    switch (pMechanism->mechanism) {
4577
0
        case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN:
4578
0
        case CKM_PBA_SHA1_WITH_SHA1_HMAC:
4579
0
            params->hashType = HASH_AlgSHA1;
4580
0
            params->keyLen = 20;
4581
0
            break;
4582
0
        case CKM_NSS_PBE_MD5_HMAC_KEY_GEN:
4583
0
            params->hashType = HASH_AlgMD5;
4584
0
            params->keyLen = 16;
4585
0
            break;
4586
0
        case CKM_NSS_PBE_MD2_HMAC_KEY_GEN:
4587
0
            params->hashType = HASH_AlgMD2;
4588
0
            params->keyLen = 16;
4589
0
            break;
4590
0
        case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
4591
0
            params->hashType = HASH_AlgSHA224;
4592
0
            params->keyLen = 28;
4593
0
            break;
4594
0
        case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
4595
0
            params->hashType = HASH_AlgSHA256;
4596
0
            params->keyLen = 32;
4597
0
            break;
4598
0
        case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
4599
0
            params->hashType = HASH_AlgSHA384;
4600
0
            params->keyLen = 48;
4601
0
            break;
4602
0
        case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
4603
0
            params->hashType = HASH_AlgSHA512;
4604
0
            params->keyLen = 64;
4605
0
            break;
4606
0
        default:
4607
0
            PORT_FreeArena(arena, PR_TRUE);
4608
0
            return CKR_MECHANISM_INVALID;
4609
0
    }
4610
0
    *pbe = params;
4611
0
    return CKR_OK;
4612
0
}
4613
4614
/* maybe this should be table driven? */
4615
static CK_RV
4616
nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
4617
                   CK_KEY_TYPE *key_type, CK_ULONG *key_length)
4618
56
{
4619
56
    CK_RV crv = CKR_OK;
4620
56
    SECOidData *oid;
4621
56
    CK_PBE_PARAMS *pbe_params = NULL;
4622
56
    NSSPKCS5PBEParameter *params = NULL;
4623
56
    HASH_HashType hashType = HASH_AlgSHA1;
4624
56
    CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL;
4625
56
    SECItem salt;
4626
56
    CK_ULONG iteration = 0;
4627
4628
56
    *pbe = NULL;
4629
4630
56
    oid = SECOID_FindOIDByMechanism(pMechanism->mechanism);
4631
56
    if (oid == NULL) {
4632
0
        return CKR_MECHANISM_INVALID;
4633
0
    }
4634
4635
56
    if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
4636
56
        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PKCS5_PBKD2_PARAMS))) {
4637
0
            return CKR_MECHANISM_PARAM_INVALID;
4638
0
        }
4639
56
        pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter;
4640
56
        switch (pbkd2_params->prf) {
4641
12
            case CKP_PKCS5_PBKD2_HMAC_SHA1:
4642
12
                hashType = HASH_AlgSHA1;
4643
12
                break;
4644
12
            case CKP_PKCS5_PBKD2_HMAC_SHA224:
4645
12
                hashType = HASH_AlgSHA224;
4646
12
                break;
4647
11
            case CKP_PKCS5_PBKD2_HMAC_SHA256:
4648
11
                hashType = HASH_AlgSHA256;
4649
11
                break;
4650
6
            case CKP_PKCS5_PBKD2_HMAC_SHA384:
4651
6
                hashType = HASH_AlgSHA384;
4652
6
                break;
4653
15
            case CKP_PKCS5_PBKD2_HMAC_SHA512:
4654
15
                hashType = HASH_AlgSHA512;
4655
15
                break;
4656
0
            default:
4657
0
                return CKR_MECHANISM_PARAM_INVALID;
4658
56
        }
4659
56
        if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) {
4660
0
            return CKR_MECHANISM_PARAM_INVALID;
4661
0
        }
4662
56
        salt.data = (unsigned char *)pbkd2_params->pSaltSourceData;
4663
56
        salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen;
4664
56
        iteration = pbkd2_params->iterations;
4665
56
    } else {
4666
0
        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
4667
0
            return CKR_MECHANISM_PARAM_INVALID;
4668
0
        }
4669
0
        pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
4670
0
        salt.data = (unsigned char *)pbe_params->pSalt;
4671
0
        salt.len = (unsigned int)pbe_params->ulSaltLen;
4672
0
        iteration = pbe_params->ulIteration;
4673
0
    }
4674
56
    params = nsspkcs5_NewParam(oid->offset, hashType, &salt, iteration);
4675
56
    if (params == NULL) {
4676
0
        return CKR_MECHANISM_INVALID;
4677
0
    }
4678
4679
56
    switch (params->encAlg) {
4680
0
        case SEC_OID_DES_CBC:
4681
0
            *key_type = CKK_DES;
4682
0
            *key_length = params->keyLen;
4683
0
            break;
4684
0
        case SEC_OID_DES_EDE3_CBC:
4685
0
            *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3;
4686
0
            *key_length = params->keyLen;
4687
0
            break;
4688
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
4689
0
        case SEC_OID_RC2_CBC:
4690
0
            *key_type = CKK_RC2;
4691
0
            *key_length = params->keyLen;
4692
0
            break;
4693
0
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
4694
0
        case SEC_OID_RC4:
4695
0
            *key_type = CKK_RC4;
4696
0
            *key_length = params->keyLen;
4697
0
            break;
4698
56
        case SEC_OID_PKCS5_PBKDF2:
4699
            /* key type must already be set */
4700
56
            if (*key_type == CKK_INVALID_KEY_TYPE) {
4701
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4702
0
                break;
4703
0
            }
4704
            /* PBKDF2 needs to calculate the key length from the other parameters
4705
             */
4706
56
            if (*key_length == 0) {
4707
0
                *key_length = sftk_MapKeySize(*key_type);
4708
0
            }
4709
56
            if (*key_length == 0) {
4710
0
                crv = CKR_TEMPLATE_INCOMPLETE;
4711
0
                break;
4712
0
            }
4713
56
            params->keyLen = *key_length;
4714
56
            break;
4715
0
        default:
4716
0
            crv = CKR_MECHANISM_INVALID;
4717
0
            break;
4718
56
    }
4719
56
    if (crv == CKR_OK) {
4720
56
        *pbe = params;
4721
56
    } else {
4722
0
        nsspkcs5_DestroyPBEParameter(params);
4723
0
    }
4724
56
    return crv;
4725
56
}
4726
4727
/* NSC_GenerateKey generates a secret key, creating a new key object. */
4728
CK_RV
4729
NSC_GenerateKey(CK_SESSION_HANDLE hSession,
4730
                CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
4731
                CK_OBJECT_HANDLE_PTR phKey)
4732
56
{
4733
56
    SFTKObject *key;
4734
56
    SFTKSession *session;
4735
56
    PRBool checkWeak = PR_FALSE;
4736
56
    CK_ULONG key_length = 0;
4737
56
    CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE;
4738
56
    CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
4739
56
    CK_RV crv = CKR_OK;
4740
56
    CK_BBOOL cktrue = CK_TRUE;
4741
56
    NSSPKCS5PBEParameter *pbe_param = NULL;
4742
56
    int i;
4743
56
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
4744
56
    unsigned char buf[MAX_KEY_LEN];
4745
56
    enum { nsc_pbe,
4746
56
           nsc_ssl,
4747
56
           nsc_bulk,
4748
56
           nsc_param,
4749
56
           nsc_jpake } key_gen_type;
4750
56
    SSL3RSAPreMasterSecret *rsa_pms;
4751
56
    CK_VERSION *version;
4752
    /* in very old versions of NSS, there were implementation errors with key
4753
     * generation methods.  We want to beable to read these, but not
4754
     * produce them any more.  The affected algorithm was 3DES.
4755
     */
4756
56
    PRBool faultyPBE3DES = PR_FALSE;
4757
56
    HASH_HashType hashType = HASH_AlgNULL;
4758
4759
56
    CHECK_FORK();
4760
4761
56
    if (!slot) {
4762
0
        return CKR_SESSION_HANDLE_INVALID;
4763
0
    }
4764
    /*
4765
     * now lets create an object to hang the attributes off of
4766
     */
4767
56
    key = sftk_NewObject(slot); /* fill in the handle later */
4768
56
    if (key == NULL) {
4769
0
        return CKR_HOST_MEMORY;
4770
0
    }
4771
4772
    /*
4773
     * load the template values into the object
4774
     */
4775
448
    for (i = 0; i < (int)ulCount; i++) {
4776
392
        if (pTemplate[i].type == CKA_VALUE_LEN) {
4777
56
            key_length = *(CK_ULONG *)pTemplate[i].pValue;
4778
56
            continue;
4779
56
        }
4780
        /* some algorithms need keytype specified */
4781
336
        if (pTemplate[i].type == CKA_KEY_TYPE) {
4782
56
            key_type = *(CK_ULONG *)pTemplate[i].pValue;
4783
56
            continue;
4784
56
        }
4785
4786
280
        crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
4787
280
        if (crv != CKR_OK) {
4788
0
            break;
4789
0
        }
4790
280
    }
4791
56
    if (crv != CKR_OK) {
4792
0
        goto loser;
4793
0
    }
4794
4795
    /* make sure we don't have any class, key_type, or value fields */
4796
56
    sftk_DeleteAttributeType(key, CKA_CLASS);
4797
56
    sftk_DeleteAttributeType(key, CKA_KEY_TYPE);
4798
56
    sftk_DeleteAttributeType(key, CKA_VALUE);
4799
4800
    /* Now Set up the parameters to generate the key (based on mechanism) */
4801
56
    key_gen_type = nsc_bulk; /* bulk key by default */
4802
56
    switch (pMechanism->mechanism) {
4803
0
        case CKM_CDMF_KEY_GEN:
4804
0
        case CKM_DES_KEY_GEN:
4805
0
        case CKM_DES2_KEY_GEN:
4806
0
        case CKM_DES3_KEY_GEN:
4807
0
            checkWeak = PR_TRUE;
4808
/* fall through */
4809
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
4810
0
        case CKM_RC2_KEY_GEN:
4811
0
#endif
4812
0
        case CKM_RC4_KEY_GEN:
4813
0
        case CKM_GENERIC_SECRET_KEY_GEN:
4814
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
4815
0
        case CKM_SEED_KEY_GEN:
4816
0
#endif
4817
0
        case CKM_CAMELLIA_KEY_GEN:
4818
0
        case CKM_AES_KEY_GEN:
4819
0
        case CKM_NSS_CHACHA20_KEY_GEN:
4820
0
        case CKM_CHACHA20_KEY_GEN:
4821
#if NSS_SOFTOKEN_DOES_RC5
4822
        case CKM_RC5_KEY_GEN:
4823
#endif
4824
0
            crv = nsc_SetupBulkKeyGen(pMechanism->mechanism, &key_type, &key_length);
4825
0
            break;
4826
0
        case CKM_SSL3_PRE_MASTER_KEY_GEN:
4827
0
            key_type = CKK_GENERIC_SECRET;
4828
0
            key_length = 48;
4829
0
            key_gen_type = nsc_ssl;
4830
0
            break;
4831
0
        case CKM_PBA_SHA1_WITH_SHA1_HMAC:
4832
0
        case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN:
4833
0
        case CKM_NSS_PBE_MD5_HMAC_KEY_GEN:
4834
0
        case CKM_NSS_PBE_MD2_HMAC_KEY_GEN:
4835
0
        case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
4836
0
        case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
4837
0
        case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
4838
0
        case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
4839
0
            key_gen_type = nsc_pbe;
4840
0
            key_type = CKK_GENERIC_SECRET;
4841
0
            crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param);
4842
0
            break;
4843
0
        case CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC:
4844
0
            faultyPBE3DES = PR_TRUE;
4845
        /* fall through */
4846
0
        case CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC:
4847
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
4848
0
        case CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC:
4849
0
        case CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC:
4850
0
        case CKM_PBE_SHA1_RC2_128_CBC:
4851
0
        case CKM_PBE_SHA1_RC2_40_CBC:
4852
0
#endif
4853
0
        case CKM_NSS_PBE_SHA1_DES_CBC:
4854
0
        case CKM_NSS_PBE_SHA1_40_BIT_RC4:
4855
0
        case CKM_NSS_PBE_SHA1_128_BIT_RC4:
4856
0
        case CKM_PBE_SHA1_DES3_EDE_CBC:
4857
0
        case CKM_PBE_SHA1_DES2_EDE_CBC:
4858
0
        case CKM_PBE_SHA1_RC4_128:
4859
0
        case CKM_PBE_SHA1_RC4_40:
4860
0
        case CKM_PBE_MD5_DES_CBC:
4861
0
        case CKM_PBE_MD2_DES_CBC:
4862
56
        case CKM_PKCS5_PBKD2:
4863
56
            key_gen_type = nsc_pbe;
4864
56
            crv = nsc_SetupPBEKeyGen(pMechanism, &pbe_param, &key_type, &key_length);
4865
56
            break;
4866
0
        case CKM_DSA_PARAMETER_GEN:
4867
0
            key_gen_type = nsc_param;
4868
0
            key_type = CKK_DSA;
4869
0
            objclass = CKO_DOMAIN_PARAMETERS;
4870
0
            crv = CKR_OK;
4871
0
            break;
4872
0
        case CKM_NSS_JPAKE_ROUND1_SHA1:
4873
0
            hashType = HASH_AlgSHA1;
4874
0
            goto jpake1;
4875
0
        case CKM_NSS_JPAKE_ROUND1_SHA256:
4876
0
            hashType = HASH_AlgSHA256;
4877
0
            goto jpake1;
4878
0
        case CKM_NSS_JPAKE_ROUND1_SHA384:
4879
0
            hashType = HASH_AlgSHA384;
4880
0
            goto jpake1;
4881
0
        case CKM_NSS_JPAKE_ROUND1_SHA512:
4882
0
            hashType = HASH_AlgSHA512;
4883
0
            goto jpake1;
4884
0
        jpake1:
4885
0
            key_gen_type = nsc_jpake;
4886
0
            key_type = CKK_NSS_JPAKE_ROUND1;
4887
0
            objclass = CKO_PRIVATE_KEY;
4888
0
            if (pMechanism->pParameter == NULL ||
4889
0
                pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) {
4890
0
                crv = CKR_MECHANISM_PARAM_INVALID;
4891
0
                break;
4892
0
            }
4893
0
            if (sftk_isTrue(key, CKA_TOKEN)) {
4894
0
                crv = CKR_TEMPLATE_INCONSISTENT;
4895
0
                break;
4896
0
            }
4897
0
            crv = CKR_OK;
4898
0
            break;
4899
0
        default:
4900
0
            crv = CKR_MECHANISM_INVALID;
4901
0
            break;
4902
56
    }
4903
4904
    /* make sure we aren't going to overflow the buffer */
4905
56
    if (sizeof(buf) < key_length) {
4906
        /* someone is getting pretty optimistic about how big their key can
4907
         * be... */
4908
0
        crv = CKR_TEMPLATE_INCONSISTENT;
4909
0
    }
4910
4911
56
    if (crv != CKR_OK) {
4912
0
        if (pbe_param) {
4913
0
            nsspkcs5_DestroyPBEParameter(pbe_param);
4914
0
        }
4915
0
        goto loser;
4916
0
    }
4917
4918
    /* if there was no error,
4919
     * key_type *MUST* be set in the switch statement above */
4920
56
    PORT_Assert(key_type != CKK_INVALID_KEY_TYPE);
4921
4922
    /*
4923
     * now to the actual key gen.
4924
     */
4925
56
    switch (key_gen_type) {
4926
56
        case nsc_pbe:
4927
56
            crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length,
4928
56
                                  faultyPBE3DES);
4929
56
            nsspkcs5_DestroyPBEParameter(pbe_param);
4930
56
            break;
4931
0
        case nsc_ssl:
4932
0
            rsa_pms = (SSL3RSAPreMasterSecret *)buf;
4933
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_VERSION))) {
4934
0
                crv = CKR_MECHANISM_PARAM_INVALID;
4935
0
                goto loser;
4936
0
            }
4937
0
            version = (CK_VERSION *)pMechanism->pParameter;
4938
0
            rsa_pms->client_version[0] = version->major;
4939
0
            rsa_pms->client_version[1] = version->minor;
4940
0
            crv =
4941
0
                NSC_GenerateRandom(0, &rsa_pms->random[0], sizeof(rsa_pms->random));
4942
0
            break;
4943
0
        case nsc_bulk:
4944
            /* get the key, check for weak keys and repeat if found */
4945
0
            do {
4946
0
                crv = NSC_GenerateRandom(0, buf, key_length);
4947
0
            } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf, key_type));
4948
0
            break;
4949
0
        case nsc_param:
4950
            /* generate parameters */
4951
0
            *buf = 0;
4952
0
            crv = nsc_parameter_gen(key_type, key);
4953
0
            break;
4954
0
        case nsc_jpake:
4955
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_NSS_JPAKERound1Params))) {
4956
0
                crv = CKR_MECHANISM_PARAM_INVALID;
4957
0
                goto loser;
4958
0
            }
4959
0
            crv = jpake_Round1(hashType,
4960
0
                               (CK_NSS_JPAKERound1Params *)pMechanism->pParameter,
4961
0
                               key);
4962
0
            break;
4963
56
    }
4964
4965
56
    if (crv != CKR_OK) {
4966
0
        goto loser;
4967
0
    }
4968
4969
    /* Add the class, key_type, and value */
4970
56
    crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS));
4971
56
    if (crv != CKR_OK) {
4972
0
        goto loser;
4973
0
    }
4974
56
    crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE));
4975
56
    if (crv != CKR_OK) {
4976
0
        goto loser;
4977
0
    }
4978
56
    if (key_length != 0) {
4979
56
        crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length);
4980
56
        if (crv != CKR_OK) {
4981
0
            goto loser;
4982
0
        }
4983
56
    }
4984
4985
    /* get the session */
4986
56
    session = sftk_SessionFromHandle(hSession);
4987
56
    if (session == NULL) {
4988
0
        crv = CKR_SESSION_HANDLE_INVALID;
4989
0
        goto loser;
4990
0
    }
4991
4992
    /*
4993
     * handle the base object stuff
4994
     */
4995
56
    crv = sftk_handleObject(key, session);
4996
56
    sftk_FreeSession(session);
4997
56
    if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) {
4998
0
        crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL));
4999
0
    }
5000
56
    if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) {
5001
0
        crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL));
5002
0
    }
5003
56
    if (crv == CKR_OK) {
5004
56
        *phKey = key->handle;
5005
56
    }
5006
56
loser:
5007
56
    PORT_Memset(buf, 0, sizeof buf);
5008
56
    sftk_FreeObject(key);
5009
56
    return crv;
5010
56
}
5011
5012
0
#define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */
5013
0
#define PAIRWISE_MESSAGE_LENGTH 20         /* 160-bits */
5014
5015
/*
5016
 * FIPS 140-2 pairwise consistency check utilized to validate key pair.
5017
 *
5018
 * This function returns
5019
 *   CKR_OK               if pairwise consistency check passed
5020
 *   CKR_GENERAL_ERROR    if pairwise consistency check failed
5021
 *   other error codes    if paiswise consistency check could not be
5022
 *                        performed, for example, CKR_HOST_MEMORY.
5023
 */
5024
static CK_RV
5025
sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, SFTKSlot *slot,
5026
                              SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType)
5027
0
{
5028
    /*
5029
     *                      Key type    Mechanism type
5030
     *                      --------------------------------
5031
     * For encrypt/decrypt: CKK_RSA  => CKM_RSA_PKCS
5032
     *                      others   => CKM_INVALID_MECHANISM
5033
     *
5034
     * For sign/verify:     CKK_RSA  => CKM_RSA_PKCS
5035
     *                      CKK_DSA  => CKM_DSA
5036
     *                      CKK_EC   => CKM_ECDSA
5037
     *                      others   => CKM_INVALID_MECHANISM
5038
     *
5039
     * None of these mechanisms has a parameter.
5040
     *
5041
     * For derive           CKK_DH   => CKM_DH_PKCS_DERIVE
5042
     *                      CKK_EC   => CKM_ECDH1_DERIVE
5043
     *                      CKK_EC_MONTGOMERY   => CKM_ECDH1_DERIVE
5044
     *                      others   => CKM_INVALID_MECHANISM
5045
     *
5046
     * The parameters for these mechanisms is the public key.
5047
     */
5048
0
    CK_MECHANISM mech = { 0, NULL, 0 };
5049
5050
0
    CK_ULONG modulusLen = 0;
5051
0
    CK_ULONG subPrimeLen = 0;
5052
0
    PRBool isEncryptable = PR_FALSE;
5053
0
    PRBool canSignVerify = PR_FALSE;
5054
0
    PRBool isDerivable = PR_FALSE;
5055
0
    CK_RV crv;
5056
5057
    /* Variables used for Encrypt/Decrypt functions. */
5058
0
    unsigned char *known_message = (unsigned char *)"Known Crypto Message";
5059
0
    unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH];
5060
0
    CK_ULONG bytes_decrypted;
5061
0
    unsigned char *ciphertext;
5062
0
    unsigned char *text_compared;
5063
0
    CK_ULONG bytes_encrypted;
5064
0
    CK_ULONG bytes_compared;
5065
0
    CK_ULONG pairwise_digest_length = PAIRWISE_DIGEST_LENGTH;
5066
5067
    /* Variables used for Signature/Verification functions. */
5068
    /* Must be at least 256 bits for DSA2 digest */
5069
0
    unsigned char *known_digest = (unsigned char *)"Mozilla Rules the World through NSS!";
5070
0
    unsigned char *signature;
5071
0
    CK_ULONG signature_length;
5072
5073
0
    if (keyType == CKK_RSA) {
5074
0
        SFTKAttribute *attribute;
5075
5076
        /* Get modulus length of private key. */
5077
0
        attribute = sftk_FindAttribute(privateKey, CKA_MODULUS);
5078
0
        if (attribute == NULL) {
5079
0
            return CKR_DEVICE_ERROR;
5080
0
        }
5081
0
        modulusLen = attribute->attrib.ulValueLen;
5082
0
        if (*(unsigned char *)attribute->attrib.pValue == 0) {
5083
0
            modulusLen--;
5084
0
        }
5085
0
        sftk_FreeAttribute(attribute);
5086
0
    } else if (keyType == CKK_DSA) {
5087
0
        SFTKAttribute *attribute;
5088
5089
        /* Get subprime length of private key. */
5090
0
        attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME);
5091
0
        if (attribute == NULL) {
5092
0
            return CKR_DEVICE_ERROR;
5093
0
        }
5094
0
        subPrimeLen = attribute->attrib.ulValueLen;
5095
0
        if (subPrimeLen > 1 && *(unsigned char *)attribute->attrib.pValue == 0) {
5096
0
            subPrimeLen--;
5097
0
        }
5098
0
        sftk_FreeAttribute(attribute);
5099
0
    }
5100
5101
    /**************************************************/
5102
    /* Pairwise Consistency Check of Encrypt/Decrypt. */
5103
    /**************************************************/
5104
5105
0
    isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT);
5106
5107
    /*
5108
     * If the decryption attribute is set, attempt to encrypt
5109
     * with the public key and decrypt with the private key.
5110
     */
5111
0
    if (isEncryptable) {
5112
0
        if (keyType != CKK_RSA) {
5113
0
            return CKR_DEVICE_ERROR;
5114
0
        }
5115
0
        bytes_encrypted = modulusLen;
5116
0
        mech.mechanism = CKM_RSA_PKCS;
5117
5118
        /* Allocate space for ciphertext. */
5119
0
        ciphertext = (unsigned char *)PORT_ZAlloc(bytes_encrypted);
5120
0
        if (ciphertext == NULL) {
5121
0
            return CKR_HOST_MEMORY;
5122
0
        }
5123
5124
        /* Prepare for encryption using the public key. */
5125
0
        crv = NSC_EncryptInit(hSession, &mech, publicKey->handle);
5126
0
        if (crv != CKR_OK) {
5127
0
            PORT_Free(ciphertext);
5128
0
            return crv;
5129
0
        }
5130
5131
        /* Encrypt using the public key. */
5132
0
        crv = NSC_Encrypt(hSession,
5133
0
                          known_message,
5134
0
                          PAIRWISE_MESSAGE_LENGTH,
5135
0
                          ciphertext,
5136
0
                          &bytes_encrypted);
5137
0
        if (crv != CKR_OK) {
5138
0
            PORT_Free(ciphertext);
5139
0
            return crv;
5140
0
        }
5141
5142
        /* Always use the smaller of these two values . . . */
5143
0
        bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH);
5144
5145
        /*
5146
         * If there was a failure, the plaintext
5147
         * goes at the end, therefore . . .
5148
         */
5149
0
        text_compared = ciphertext + bytes_encrypted - bytes_compared;
5150
5151
        /*
5152
         * Check to ensure that ciphertext does
5153
         * NOT EQUAL known input message text
5154
         * per FIPS PUB 140-2 directive.
5155
         */
5156
0
        if (PORT_Memcmp(text_compared, known_message,
5157
0
                        bytes_compared) == 0) {
5158
            /* Set error to Invalid PRIVATE Key. */
5159
0
            PORT_SetError(SEC_ERROR_INVALID_KEY);
5160
0
            PORT_Free(ciphertext);
5161
0
            return CKR_GENERAL_ERROR;
5162
0
        }
5163
5164
        /* Prepare for decryption using the private key. */
5165
0
        crv = NSC_DecryptInit(hSession, &mech, privateKey->handle);
5166
0
        if (crv != CKR_OK) {
5167
0
            PORT_Free(ciphertext);
5168
0
            return crv;
5169
0
        }
5170
5171
0
        memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH);
5172
5173
        /*
5174
         * Initialize bytes decrypted to be the
5175
         * expected PAIRWISE_MESSAGE_LENGTH.
5176
         */
5177
0
        bytes_decrypted = PAIRWISE_MESSAGE_LENGTH;
5178
5179
        /*
5180
         * Decrypt using the private key.
5181
         * NOTE:  No need to reset the
5182
         *        value of bytes_encrypted.
5183
         */
5184
0
        crv = NSC_Decrypt(hSession,
5185
0
                          ciphertext,
5186
0
                          bytes_encrypted,
5187
0
                          plaintext,
5188
0
                          &bytes_decrypted);
5189
5190
        /* Finished with ciphertext; free it. */
5191
0
        PORT_Free(ciphertext);
5192
5193
0
        if (crv != CKR_OK) {
5194
0
            return crv;
5195
0
        }
5196
5197
        /*
5198
         * Check to ensure that the output plaintext
5199
         * does EQUAL known input message text.
5200
         */
5201
0
        if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) ||
5202
0
            (PORT_Memcmp(plaintext, known_message,
5203
0
                         PAIRWISE_MESSAGE_LENGTH) != 0)) {
5204
            /* Set error to Bad PUBLIC Key. */
5205
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
5206
0
            return CKR_GENERAL_ERROR;
5207
0
        }
5208
0
    }
5209
5210
    /**********************************************/
5211
    /* Pairwise Consistency Check of Sign/Verify. */
5212
    /**********************************************/
5213
5214
0
    canSignVerify = sftk_isTrue(privateKey, CKA_SIGN);
5215
    /* Unfortunately CKA_SIGN is always true in lg dbs. We have to check the
5216
     * actual curve to determine if we can do sign/verify. */
5217
0
    if (canSignVerify && keyType == CKK_EC) {
5218
0
        NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(privateKey, CKK_EC, &crv);
5219
0
        if (privKey && privKey->u.ec.ecParams.name == ECCurve25519) {
5220
0
            canSignVerify = PR_FALSE;
5221
0
        }
5222
0
    }
5223
5224
0
    if (canSignVerify) {
5225
        /* Determine length of signature. */
5226
0
        switch (keyType) {
5227
0
            case CKK_RSA:
5228
0
                signature_length = modulusLen;
5229
0
                mech.mechanism = CKM_RSA_PKCS;
5230
0
                break;
5231
0
            case CKK_DSA:
5232
0
                signature_length = DSA_MAX_SIGNATURE_LEN;
5233
0
                pairwise_digest_length = subPrimeLen;
5234
0
                mech.mechanism = CKM_DSA;
5235
0
                break;
5236
0
            case CKK_EC:
5237
0
                signature_length = MAX_ECKEY_LEN * 2;
5238
0
                mech.mechanism = CKM_ECDSA;
5239
0
                break;
5240
0
            case CKK_EC_EDWARDS:
5241
0
                signature_length = ED25519_SIGN_LEN;
5242
0
                mech.mechanism = CKM_EDDSA;
5243
0
                break;
5244
0
            default:
5245
0
                return CKR_DEVICE_ERROR;
5246
0
        }
5247
5248
        /* Allocate space for signature data. */
5249
0
        signature = (unsigned char *)PORT_ZAlloc(signature_length);
5250
0
        if (signature == NULL) {
5251
0
            return CKR_HOST_MEMORY;
5252
0
        }
5253
5254
        /* Sign the known hash using the private key. */
5255
0
        crv = NSC_SignInit(hSession, &mech, privateKey->handle);
5256
0
        if (crv != CKR_OK) {
5257
0
            PORT_Free(signature);
5258
0
            return crv;
5259
0
        }
5260
5261
0
        crv = NSC_Sign(hSession,
5262
0
                       known_digest,
5263
0
                       pairwise_digest_length,
5264
0
                       signature,
5265
0
                       &signature_length);
5266
0
        if (crv != CKR_OK) {
5267
0
            PORT_Free(signature);
5268
0
            return crv;
5269
0
        }
5270
5271
        /* detect trivial signing transforms */
5272
0
        if ((signature_length >= pairwise_digest_length) &&
5273
0
            (PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) {
5274
0
            PORT_Free(signature);
5275
0
            return CKR_DEVICE_ERROR;
5276
0
        }
5277
5278
        /* Verify the known hash using the public key. */
5279
0
        crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
5280
0
        if (crv != CKR_OK) {
5281
0
            PORT_Free(signature);
5282
0
            return crv;
5283
0
        }
5284
5285
0
        crv = NSC_Verify(hSession,
5286
0
                         known_digest,
5287
0
                         pairwise_digest_length,
5288
0
                         signature,
5289
0
                         signature_length);
5290
5291
        /* Free signature data. */
5292
0
        PORT_Free(signature);
5293
5294
0
        if ((crv == CKR_SIGNATURE_LEN_RANGE) ||
5295
0
            (crv == CKR_SIGNATURE_INVALID)) {
5296
0
            return CKR_GENERAL_ERROR;
5297
0
        }
5298
0
        if (crv != CKR_OK) {
5299
0
            return crv;
5300
0
        }
5301
0
    }
5302
5303
    /**********************************************/
5304
    /* Pairwise Consistency Check for Derivation  */
5305
    /**********************************************/
5306
5307
0
    isDerivable = sftk_isTrue(privateKey, CKA_DERIVE);
5308
5309
0
    if (isDerivable) {
5310
0
        SFTKAttribute *pubAttribute = NULL;
5311
0
        CK_OBJECT_HANDLE newKey;
5312
0
        PRBool isFIPS = sftk_isFIPS(slot->slotID);
5313
0
        CK_RV crv2;
5314
0
        CK_OBJECT_CLASS secret = CKO_SECRET_KEY;
5315
0
        CK_KEY_TYPE generic = CKK_GENERIC_SECRET;
5316
0
        CK_ULONG keyLen = 128;
5317
0
        CK_BBOOL ckTrue = CK_TRUE;
5318
0
        CK_ATTRIBUTE template[] = {
5319
0
            { CKA_CLASS, &secret, sizeof(secret) },
5320
0
            { CKA_KEY_TYPE, &generic, sizeof(generic) },
5321
0
            { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) },
5322
0
            { CKA_DERIVE, &ckTrue, sizeof(ckTrue) }
5323
0
        };
5324
0
        CK_ULONG templateCount = PR_ARRAY_SIZE(template);
5325
0
        CK_ECDH1_DERIVE_PARAMS ecParams;
5326
5327
0
        crv = CKR_OK; /*paranoia, already get's set before we drop to the end */
5328
        /* FIPS 140-2 requires we verify that the resulting key is a valid key.
5329
         * The easiest way to do this is to do a derive operation, which checks
5330
         * the validity of the key */
5331
5332
0
        switch (keyType) {
5333
0
            case CKK_DH:
5334
0
                mech.mechanism = CKM_DH_PKCS_DERIVE;
5335
0
                pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE);
5336
0
                if (pubAttribute == NULL) {
5337
0
                    return CKR_DEVICE_ERROR;
5338
0
                }
5339
0
                mech.pParameter = pubAttribute->attrib.pValue;
5340
0
                mech.ulParameterLen = pubAttribute->attrib.ulValueLen;
5341
0
                break;
5342
0
            case CKK_EC_MONTGOMERY:
5343
0
            case CKK_EC:
5344
0
                mech.mechanism = CKM_ECDH1_DERIVE;
5345
0
                pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT);
5346
0
                if (pubAttribute == NULL) {
5347
0
                    return CKR_DEVICE_ERROR;
5348
0
                }
5349
0
                ecParams.kdf = CKD_NULL;
5350
0
                ecParams.ulSharedDataLen = 0;
5351
0
                ecParams.pSharedData = NULL;
5352
0
                ecParams.ulPublicDataLen = pubAttribute->attrib.ulValueLen;
5353
0
                ecParams.pPublicData = pubAttribute->attrib.pValue;
5354
0
                mech.pParameter = &ecParams;
5355
0
                mech.ulParameterLen = sizeof(ecParams);
5356
0
                break;
5357
0
            default:
5358
0
                return CKR_DEVICE_ERROR;
5359
0
        }
5360
5361
0
        crv = NSC_DeriveKey(hSession, &mech, privateKey->handle, template, templateCount, &newKey);
5362
0
        if (crv != CKR_OK) {
5363
0
            sftk_FreeAttribute(pubAttribute);
5364
0
            return crv;
5365
0
        }
5366
        /* FIPS requires full validation, but in fipx mode NSC_Derive
5367
         * only does partial validation with approved primes, now handle
5368
         * full validation */
5369
0
        if (isFIPS && keyType == CKK_DH) {
5370
0
            SECItem pubKey;
5371
0
            SECItem prime;
5372
0
            SECItem subPrime;
5373
0
            const SECItem *subPrimePtr = &subPrime;
5374
5375
0
            pubKey.data = pubAttribute->attrib.pValue;
5376
0
            pubKey.len = pubAttribute->attrib.ulValueLen;
5377
0
            prime.data = subPrime.data = NULL;
5378
0
            prime.len = subPrime.len = 0;
5379
0
            crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
5380
0
            if (crv != CKR_OK) {
5381
0
                goto done;
5382
0
            }
5383
0
            crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
5384
            /* we ignore the return code an only look at the length */
5385
0
            if (subPrime.len == 0) {
5386
                /* subprime not supplied, In this case look it up.
5387
                 * This only works with approved primes, but in FIPS mode
5388
                 * that's the only kine of prime that will get here */
5389
0
                subPrimePtr = sftk_VerifyDH_Prime(&prime, isFIPS);
5390
0
                if (subPrimePtr == NULL) {
5391
0
                    crv = CKR_GENERAL_ERROR;
5392
0
                    goto done;
5393
0
                }
5394
0
            }
5395
0
            if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) {
5396
0
                crv = CKR_GENERAL_ERROR;
5397
0
            }
5398
0
        done:
5399
0
            SECITEM_ZfreeItem(&subPrime, PR_FALSE);
5400
0
            SECITEM_ZfreeItem(&prime, PR_FALSE);
5401
0
        }
5402
        /* clean up before we return */
5403
0
        sftk_FreeAttribute(pubAttribute);
5404
0
        crv2 = NSC_DestroyObject(hSession, newKey);
5405
0
        if (crv != CKR_OK) {
5406
0
            return crv;
5407
0
        }
5408
0
        if (crv2 != CKR_OK) {
5409
0
            return crv2;
5410
0
        }
5411
0
    }
5412
5413
0
    return CKR_OK;
5414
0
}
5415
5416
/* NSC_GenerateKeyPair generates a public-key/private-key pair,
5417
 * creating new key objects. */
5418
CK_RV
5419
NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
5420
                    CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
5421
                    CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
5422
                    CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,
5423
                    CK_OBJECT_HANDLE_PTR phPrivateKey)
5424
0
{
5425
0
    SFTKObject *publicKey, *privateKey;
5426
0
    SFTKSession *session;
5427
0
    CK_KEY_TYPE key_type;
5428
0
    CK_RV crv = CKR_OK;
5429
0
    CK_BBOOL cktrue = CK_TRUE;
5430
0
    SECStatus rv;
5431
0
    CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
5432
0
    CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
5433
0
    int i;
5434
0
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
5435
0
    unsigned int bitSize;
5436
5437
    /* RSA */
5438
0
    int public_modulus_bits = 0;
5439
0
    SECItem pubExp;
5440
0
    RSAPrivateKey *rsaPriv;
5441
5442
    /* DSA */
5443
0
    PQGParams pqgParam;
5444
0
    DHParams dhParam;
5445
0
    DSAPrivateKey *dsaPriv;
5446
5447
    /* Diffie Hellman */
5448
0
    DHPrivateKey *dhPriv;
5449
5450
    /* Elliptic Curve Cryptography */
5451
0
    SECItem ecEncodedParams; /* DER Encoded parameters */
5452
0
    ECPrivateKey *ecPriv;
5453
0
    ECParams *ecParams;
5454
5455
    /* Kyber */
5456
0
    CK_NSS_KEM_PARAMETER_SET_TYPE ckKyberParamSet;
5457
5458
0
    CHECK_FORK();
5459
5460
0
    if (!slot) {
5461
0
        return CKR_SESSION_HANDLE_INVALID;
5462
0
    }
5463
    /*
5464
     * now lets create an object to hang the attributes off of
5465
     */
5466
0
    publicKey = sftk_NewObject(slot); /* fill in the handle later */
5467
0
    if (publicKey == NULL) {
5468
0
        return CKR_HOST_MEMORY;
5469
0
    }
5470
5471
    /*
5472
     * load the template values into the publicKey
5473
     */
5474
0
    for (i = 0; i < (int)ulPublicKeyAttributeCount; i++) {
5475
0
        if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) {
5476
0
            public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;
5477
0
            continue;
5478
0
        }
5479
5480
0
        if (pPublicKeyTemplate[i].type == CKA_NSS_PARAMETER_SET) {
5481
0
            ckKyberParamSet = *(CK_NSS_KEM_PARAMETER_SET_TYPE *)pPublicKeyTemplate[i].pValue;
5482
0
            continue;
5483
0
        }
5484
5485
0
        crv = sftk_AddAttributeType(publicKey,
5486
0
                                    sftk_attr_expand(&pPublicKeyTemplate[i]));
5487
0
        if (crv != CKR_OK)
5488
0
            break;
5489
0
    }
5490
5491
0
    if (crv != CKR_OK) {
5492
0
        sftk_FreeObject(publicKey);
5493
0
        return CKR_HOST_MEMORY;
5494
0
    }
5495
5496
0
    privateKey = sftk_NewObject(slot); /* fill in the handle later */
5497
0
    if (privateKey == NULL) {
5498
0
        sftk_FreeObject(publicKey);
5499
0
        return CKR_HOST_MEMORY;
5500
0
    }
5501
    /*
5502
     * now load the private key template
5503
     */
5504
0
    for (i = 0; i < (int)ulPrivateKeyAttributeCount; i++) {
5505
0
        if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) {
5506
0
            continue;
5507
0
        }
5508
5509
0
        crv = sftk_AddAttributeType(privateKey,
5510
0
                                    sftk_attr_expand(&pPrivateKeyTemplate[i]));
5511
0
        if (crv != CKR_OK)
5512
0
            break;
5513
0
    }
5514
5515
0
    if (crv != CKR_OK) {
5516
0
        sftk_FreeObject(publicKey);
5517
0
        sftk_FreeObject(privateKey);
5518
0
        return CKR_HOST_MEMORY;
5519
0
    }
5520
0
    sftk_DeleteAttributeType(privateKey, CKA_CLASS);
5521
0
    sftk_DeleteAttributeType(privateKey, CKA_KEY_TYPE);
5522
0
    sftk_DeleteAttributeType(privateKey, CKA_VALUE);
5523
0
    sftk_DeleteAttributeType(publicKey, CKA_CLASS);
5524
0
    sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE);
5525
0
    sftk_DeleteAttributeType(publicKey, CKA_VALUE);
5526
5527
    /* Now Set up the parameters to generate the key (based on mechanism) */
5528
0
    switch (pMechanism->mechanism) {
5529
0
        case CKM_RSA_PKCS_KEY_PAIR_GEN:
5530
            /* format the keys */
5531
0
            sftk_DeleteAttributeType(publicKey, CKA_MODULUS);
5532
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5533
0
            sftk_DeleteAttributeType(privateKey, CKA_MODULUS);
5534
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIVATE_EXPONENT);
5535
0
            sftk_DeleteAttributeType(privateKey, CKA_PUBLIC_EXPONENT);
5536
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIME_1);
5537
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIME_2);
5538
0
            sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_1);
5539
0
            sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_2);
5540
0
            sftk_DeleteAttributeType(privateKey, CKA_COEFFICIENT);
5541
0
            key_type = CKK_RSA;
5542
0
            if (public_modulus_bits == 0) {
5543
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5544
0
                break;
5545
0
            }
5546
0
            if (public_modulus_bits < RSA_MIN_MODULUS_BITS) {
5547
0
                crv = CKR_ATTRIBUTE_VALUE_INVALID;
5548
0
                break;
5549
0
            }
5550
0
            if (public_modulus_bits % 2 != 0) {
5551
0
                crv = CKR_ATTRIBUTE_VALUE_INVALID;
5552
0
                break;
5553
0
            }
5554
5555
            /* extract the exponent */
5556
0
            crv = sftk_Attribute2SSecItem(NULL, &pubExp, publicKey, CKA_PUBLIC_EXPONENT);
5557
0
            if (crv != CKR_OK)
5558
0
                break;
5559
0
            bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len);
5560
0
            if (bitSize < 2) {
5561
0
                crv = CKR_ATTRIBUTE_VALUE_INVALID;
5562
0
                SECITEM_ZfreeItem(&pubExp, PR_FALSE);
5563
0
                break;
5564
0
            }
5565
0
            crv = sftk_AddAttributeType(privateKey, CKA_PUBLIC_EXPONENT,
5566
0
                                        sftk_item_expand(&pubExp));
5567
0
            if (crv != CKR_OK) {
5568
0
                SECITEM_ZfreeItem(&pubExp, PR_FALSE);
5569
0
                break;
5570
0
            }
5571
5572
0
            rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp);
5573
0
            SECITEM_ZfreeItem(&pubExp, PR_FALSE);
5574
0
            if (rsaPriv == NULL) {
5575
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5576
0
                    sftk_fatalError = PR_TRUE;
5577
0
                }
5578
0
                crv = sftk_MapCryptError(PORT_GetError());
5579
0
                break;
5580
0
            }
5581
            /* now fill in the RSA dependent paramenters in the public key */
5582
0
            crv = sftk_AddAttributeType(publicKey, CKA_MODULUS,
5583
0
                                        sftk_item_expand(&rsaPriv->modulus));
5584
0
            if (crv != CKR_OK)
5585
0
                goto kpg_done;
5586
            /* now fill in the RSA dependent paramenters in the private key */
5587
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5588
0
                                        sftk_item_expand(&rsaPriv->modulus));
5589
0
            if (crv != CKR_OK)
5590
0
                goto kpg_done;
5591
0
            crv = sftk_AddAttributeType(privateKey, CKA_MODULUS,
5592
0
                                        sftk_item_expand(&rsaPriv->modulus));
5593
0
            if (crv != CKR_OK)
5594
0
                goto kpg_done;
5595
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIVATE_EXPONENT,
5596
0
                                        sftk_item_expand(&rsaPriv->privateExponent));
5597
0
            if (crv != CKR_OK)
5598
0
                goto kpg_done;
5599
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIME_1,
5600
0
                                        sftk_item_expand(&rsaPriv->prime1));
5601
0
            if (crv != CKR_OK)
5602
0
                goto kpg_done;
5603
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIME_2,
5604
0
                                        sftk_item_expand(&rsaPriv->prime2));
5605
0
            if (crv != CKR_OK)
5606
0
                goto kpg_done;
5607
0
            crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_1,
5608
0
                                        sftk_item_expand(&rsaPriv->exponent1));
5609
0
            if (crv != CKR_OK)
5610
0
                goto kpg_done;
5611
0
            crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_2,
5612
0
                                        sftk_item_expand(&rsaPriv->exponent2));
5613
0
            if (crv != CKR_OK)
5614
0
                goto kpg_done;
5615
0
            crv = sftk_AddAttributeType(privateKey, CKA_COEFFICIENT,
5616
0
                                        sftk_item_expand(&rsaPriv->coefficient));
5617
0
        kpg_done:
5618
            /* Should zeroize the contents first, since this func doesn't. */
5619
0
            PORT_FreeArena(rsaPriv->arena, PR_TRUE);
5620
0
            break;
5621
0
        case CKM_DSA_KEY_PAIR_GEN:
5622
0
            sftk_DeleteAttributeType(publicKey, CKA_VALUE);
5623
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5624
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIME);
5625
0
            sftk_DeleteAttributeType(privateKey, CKA_SUBPRIME);
5626
0
            sftk_DeleteAttributeType(privateKey, CKA_BASE);
5627
0
            key_type = CKK_DSA;
5628
5629
            /* extract the necessary parameters and copy them to the private key */
5630
0
            crv = sftk_Attribute2SSecItem(NULL, &pqgParam.prime, publicKey, CKA_PRIME);
5631
0
            if (crv != CKR_OK)
5632
0
                break;
5633
0
            crv = sftk_Attribute2SSecItem(NULL, &pqgParam.subPrime, publicKey,
5634
0
                                          CKA_SUBPRIME);
5635
0
            if (crv != CKR_OK) {
5636
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5637
0
                break;
5638
0
            }
5639
0
            crv = sftk_Attribute2SSecItem(NULL, &pqgParam.base, publicKey, CKA_BASE);
5640
0
            if (crv != CKR_OK) {
5641
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5642
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5643
0
                break;
5644
0
            }
5645
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
5646
0
                                        sftk_item_expand(&pqgParam.prime));
5647
0
            if (crv != CKR_OK) {
5648
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5649
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5650
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5651
0
                break;
5652
0
            }
5653
0
            crv = sftk_AddAttributeType(privateKey, CKA_SUBPRIME,
5654
0
                                        sftk_item_expand(&pqgParam.subPrime));
5655
0
            if (crv != CKR_OK) {
5656
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5657
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5658
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5659
0
                break;
5660
0
            }
5661
0
            crv = sftk_AddAttributeType(privateKey, CKA_BASE,
5662
0
                                        sftk_item_expand(&pqgParam.base));
5663
0
            if (crv != CKR_OK) {
5664
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5665
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5666
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5667
0
                break;
5668
0
            }
5669
5670
            /*
5671
             * these are checked by DSA_NewKey
5672
             */
5673
0
            bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data,
5674
0
                                           pqgParam.subPrime.len);
5675
0
            if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) {
5676
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5677
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5678
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5679
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5680
0
                break;
5681
0
            }
5682
0
            bitSize = sftk_GetLengthInBits(pqgParam.prime.data, pqgParam.prime.len);
5683
0
            if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) {
5684
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5685
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5686
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5687
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5688
0
                break;
5689
0
            }
5690
0
            bitSize = sftk_GetLengthInBits(pqgParam.base.data, pqgParam.base.len);
5691
0
            if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) {
5692
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5693
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5694
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5695
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5696
0
                break;
5697
0
            }
5698
5699
            /* Generate the key */
5700
0
            rv = DSA_NewKey(&pqgParam, &dsaPriv);
5701
5702
0
            SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
5703
0
            SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
5704
0
            SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
5705
5706
0
            if (rv != SECSuccess) {
5707
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5708
0
                    sftk_fatalError = PR_TRUE;
5709
0
                }
5710
0
                crv = sftk_MapCryptError(PORT_GetError());
5711
0
                break;
5712
0
            }
5713
5714
            /* store the generated key into the attributes */
5715
0
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
5716
0
                                        sftk_item_expand(&dsaPriv->publicValue));
5717
0
            if (crv != CKR_OK)
5718
0
                goto dsagn_done;
5719
5720
            /* now fill in the RSA dependent paramenters in the private key */
5721
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5722
0
                                        sftk_item_expand(&dsaPriv->publicValue));
5723
0
            if (crv != CKR_OK)
5724
0
                goto dsagn_done;
5725
0
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5726
0
                                        sftk_item_expand(&dsaPriv->privateValue));
5727
5728
0
        dsagn_done:
5729
            /* should zeroize, since this function doesn't. */
5730
0
            PORT_FreeArena(dsaPriv->params.arena, PR_TRUE);
5731
0
            break;
5732
5733
0
        case CKM_DH_PKCS_KEY_PAIR_GEN:
5734
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIME);
5735
0
            sftk_DeleteAttributeType(privateKey, CKA_BASE);
5736
0
            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
5737
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5738
0
            key_type = CKK_DH;
5739
5740
            /* extract the necessary parameters and copy them to private keys */
5741
0
            crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey,
5742
0
                                          CKA_PRIME);
5743
0
            if (crv != CKR_OK)
5744
0
                break;
5745
0
            crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);
5746
0
            if (crv != CKR_OK) {
5747
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5748
0
                break;
5749
0
            }
5750
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
5751
0
                                        sftk_item_expand(&dhParam.prime));
5752
0
            if (crv != CKR_OK) {
5753
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5754
0
                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5755
0
                break;
5756
0
            }
5757
0
            crv = sftk_AddAttributeType(privateKey, CKA_BASE,
5758
0
                                        sftk_item_expand(&dhParam.base));
5759
0
            if (crv != CKR_OK) {
5760
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5761
0
                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5762
0
                break;
5763
0
            }
5764
0
            bitSize = sftk_GetLengthInBits(dhParam.prime.data, dhParam.prime.len);
5765
0
            if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) {
5766
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5767
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5768
0
                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5769
0
                break;
5770
0
            }
5771
0
            bitSize = sftk_GetLengthInBits(dhParam.base.data, dhParam.base.len);
5772
0
            if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) {
5773
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5774
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5775
0
                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5776
0
                break;
5777
0
            }
5778
5779
0
            rv = DH_NewKey(&dhParam, &dhPriv);
5780
0
            SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
5781
0
            SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
5782
0
            if (rv != SECSuccess) {
5783
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5784
0
                    sftk_fatalError = PR_TRUE;
5785
0
                }
5786
0
                crv = sftk_MapCryptError(PORT_GetError());
5787
0
                break;
5788
0
            }
5789
5790
0
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
5791
0
                                        sftk_item_expand(&dhPriv->publicValue));
5792
0
            if (crv != CKR_OK)
5793
0
                goto dhgn_done;
5794
5795
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5796
0
                                        sftk_item_expand(&dhPriv->publicValue));
5797
0
            if (crv != CKR_OK)
5798
0
                goto dhgn_done;
5799
5800
0
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5801
0
                                        sftk_item_expand(&dhPriv->privateValue));
5802
5803
0
        dhgn_done:
5804
            /* should zeroize, since this function doesn't. */
5805
0
            PORT_FreeArena(dhPriv->arena, PR_TRUE);
5806
0
            break;
5807
5808
0
        case CKM_EC_KEY_PAIR_GEN:
5809
0
        case CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN:
5810
0
            sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS);
5811
0
            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
5812
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5813
0
            key_type = CKK_EC;
5814
5815
            /* extract the necessary parameters and copy them to private keys */
5816
0
            crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey,
5817
0
                                          CKA_EC_PARAMS);
5818
0
            if (crv != CKR_OK)
5819
0
                break;
5820
5821
0
            crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS,
5822
0
                                        sftk_item_expand(&ecEncodedParams));
5823
0
            if (crv != CKR_OK) {
5824
0
                SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
5825
0
                break;
5826
0
            }
5827
5828
            /* Decode ec params before calling EC_NewKey */
5829
0
            rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
5830
0
            SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
5831
0
            if (rv != SECSuccess) {
5832
0
                crv = sftk_MapCryptError(PORT_GetError());
5833
0
                break;
5834
0
            }
5835
0
            rv = EC_NewKey(ecParams, &ecPriv);
5836
0
            if (rv != SECSuccess) {
5837
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5838
0
                    sftk_fatalError = PR_TRUE;
5839
0
                }
5840
0
                PORT_FreeArena(ecParams->arena, PR_TRUE);
5841
0
                crv = sftk_MapCryptError(PORT_GetError());
5842
0
                break;
5843
0
            }
5844
5845
0
            if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") ||
5846
0
                ecParams->type != ec_params_named) {
5847
0
                PORT_FreeArena(ecParams->arena, PR_TRUE);
5848
0
                crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
5849
0
                                            sftk_item_expand(&ecPriv->publicValue));
5850
0
            } else {
5851
0
                PORT_FreeArena(ecParams->arena, PR_TRUE);
5852
0
                SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
5853
0
                                                       &ecPriv->publicValue,
5854
0
                                                       SEC_ASN1_GET(SEC_OctetStringTemplate));
5855
0
                if (!pubValue) {
5856
0
                    crv = CKR_ARGUMENTS_BAD;
5857
0
                    goto ecgn_done;
5858
0
                }
5859
0
                crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
5860
0
                                            sftk_item_expand(pubValue));
5861
0
                SECITEM_ZfreeItem(pubValue, PR_TRUE);
5862
0
            }
5863
0
            if (crv != CKR_OK)
5864
0
                goto ecgn_done;
5865
5866
0
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5867
0
                                        sftk_item_expand(&ecPriv->privateValue));
5868
0
            if (crv != CKR_OK)
5869
0
                goto ecgn_done;
5870
5871
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5872
0
                                        sftk_item_expand(&ecPriv->publicValue));
5873
0
        ecgn_done:
5874
            /* should zeroize, since this function doesn't. */
5875
0
            PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
5876
0
            break;
5877
5878
0
        case CKM_NSS_KYBER_KEY_PAIR_GEN:
5879
0
        case CKM_NSS_ML_KEM_KEY_PAIR_GEN:
5880
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5881
0
            key_type = CKK_NSS_KYBER;
5882
5883
0
            SECItem privKey = { siBuffer, NULL, 0 };
5884
0
            SECItem pubKey = { siBuffer, NULL, 0 };
5885
0
            KyberParams kyberParams = sftk_kyber_PK11ParamToInternal(ckKyberParamSet);
5886
0
            if (!sftk_kyber_AllocPrivKeyItem(kyberParams, &privKey)) {
5887
0
                crv = CKR_HOST_MEMORY;
5888
0
                goto kyber_done;
5889
0
            }
5890
0
            if (!sftk_kyber_AllocPubKeyItem(kyberParams, &pubKey)) {
5891
0
                crv = CKR_HOST_MEMORY;
5892
0
                goto kyber_done;
5893
0
            }
5894
0
            rv = Kyber_NewKey(kyberParams, NULL, &privKey, &pubKey);
5895
0
            if (rv != SECSuccess) {
5896
0
                crv = sftk_MapCryptError(PORT_GetError());
5897
0
                goto kyber_done;
5898
0
            }
5899
5900
0
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE, sftk_item_expand(&pubKey));
5901
0
            if (crv != CKR_OK) {
5902
0
                goto kyber_done;
5903
0
            }
5904
0
            crv = sftk_AddAttributeType(publicKey, CKA_NSS_PARAMETER_SET,
5905
0
                                        &ckKyberParamSet, sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE));
5906
0
            if (crv != CKR_OK) {
5907
0
                goto kyber_done;
5908
0
            }
5909
0
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5910
0
                                        sftk_item_expand(&privKey));
5911
0
            if (crv != CKR_OK) {
5912
0
                goto kyber_done;
5913
0
            }
5914
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_PARAMETER_SET,
5915
0
                                        &ckKyberParamSet, sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE));
5916
0
            if (crv != CKR_OK) {
5917
0
                goto kyber_done;
5918
0
            }
5919
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5920
0
                                        sftk_item_expand(&pubKey));
5921
0
        kyber_done:
5922
0
            SECITEM_ZfreeItem(&privKey, PR_FALSE);
5923
0
            SECITEM_FreeItem(&pubKey, PR_FALSE);
5924
0
            break;
5925
5926
0
        case CKM_EC_MONTGOMERY_KEY_PAIR_GEN:
5927
0
        case CKM_EC_EDWARDS_KEY_PAIR_GEN:
5928
0
            sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS);
5929
0
            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
5930
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
5931
0
            key_type = (pMechanism->mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN) ? CKK_EC_EDWARDS : CKK_EC_MONTGOMERY;
5932
5933
            /* extract the necessary parameters and copy them to private keys */
5934
0
            crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey,
5935
0
                                          CKA_EC_PARAMS);
5936
0
            if (crv != CKR_OK) {
5937
0
                break;
5938
0
            }
5939
5940
0
            crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS,
5941
0
                                        sftk_item_expand(&ecEncodedParams));
5942
0
            if (crv != CKR_OK) {
5943
0
                SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
5944
0
                break;
5945
0
            }
5946
5947
            /* Decode ec params before calling EC_NewKey */
5948
0
            rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
5949
0
            SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
5950
0
            if (rv != SECSuccess) {
5951
0
                crv = sftk_MapCryptError(PORT_GetError());
5952
0
                break;
5953
0
            }
5954
5955
0
            rv = EC_NewKey(ecParams, &ecPriv);
5956
0
            if (rv != SECSuccess) {
5957
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
5958
0
                    sftk_fatalError = PR_TRUE;
5959
0
                }
5960
0
                PORT_FreeArena(ecParams->arena, PR_TRUE);
5961
0
                crv = sftk_MapCryptError(PORT_GetError());
5962
0
                break;
5963
0
            }
5964
0
            PORT_FreeArena(ecParams->arena, PR_TRUE);
5965
0
            crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
5966
0
                                        sftk_item_expand(&ecPriv->publicValue));
5967
0
            if (crv != CKR_OK)
5968
0
                goto edgn_done;
5969
5970
0
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
5971
0
                                        sftk_item_expand(&ecPriv->privateValue));
5972
0
            if (crv != CKR_OK)
5973
0
                goto edgn_done;
5974
5975
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
5976
0
                                        sftk_item_expand(&ecPriv->publicValue));
5977
0
        edgn_done:
5978
            /* should zeroize, since this function doesn't. */
5979
0
            PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
5980
0
            break;
5981
5982
0
        default:
5983
0
            crv = CKR_MECHANISM_INVALID;
5984
0
    }
5985
5986
0
    if (crv != CKR_OK) {
5987
0
        sftk_FreeObject(privateKey);
5988
0
        sftk_FreeObject(publicKey);
5989
0
        return crv;
5990
0
    }
5991
5992
    /* Add the class, key_type The loop lets us check errors blow out
5993
     *  on errors and clean up at the bottom */
5994
0
    session = NULL; /* make pedtantic happy... session cannot leave the*/
5995
                    /* loop below NULL unless an error is set... */
5996
0
    do {
5997
0
        crv = sftk_AddAttributeType(privateKey, CKA_CLASS, &privClass,
5998
0
                                    sizeof(CK_OBJECT_CLASS));
5999
0
        if (crv != CKR_OK)
6000
0
            break;
6001
0
        crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &pubClass,
6002
0
                                    sizeof(CK_OBJECT_CLASS));
6003
0
        if (crv != CKR_OK)
6004
0
            break;
6005
0
        crv = sftk_AddAttributeType(privateKey, CKA_KEY_TYPE, &key_type,
6006
0
                                    sizeof(CK_KEY_TYPE));
6007
0
        if (crv != CKR_OK)
6008
0
            break;
6009
0
        crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &key_type,
6010
0
                                    sizeof(CK_KEY_TYPE));
6011
0
        if (crv != CKR_OK)
6012
0
            break;
6013
0
        session = sftk_SessionFromHandle(hSession);
6014
0
        if (session == NULL)
6015
0
            crv = CKR_SESSION_HANDLE_INVALID;
6016
0
    } while (0);
6017
6018
0
    if (crv != CKR_OK) {
6019
0
        sftk_FreeObject(privateKey);
6020
0
        sftk_FreeObject(publicKey);
6021
0
        return crv;
6022
0
    }
6023
6024
    /*
6025
     * handle the base object cleanup for the public Key
6026
     */
6027
0
    crv = sftk_handleObject(privateKey, session);
6028
0
    if (crv != CKR_OK) {
6029
0
        sftk_FreeSession(session);
6030
0
        sftk_FreeObject(privateKey);
6031
0
        sftk_FreeObject(publicKey);
6032
0
        return crv;
6033
0
    }
6034
6035
    /*
6036
     * handle the base object cleanup for the private Key
6037
     * If we have any problems, we destroy the public Key we've
6038
     * created and linked.
6039
     */
6040
0
    crv = sftk_handleObject(publicKey, session);
6041
0
    sftk_FreeSession(session);
6042
0
    if (crv != CKR_OK) {
6043
0
        sftk_FreeObject(publicKey);
6044
0
        NSC_DestroyObject(hSession, privateKey->handle);
6045
0
        sftk_FreeObject(privateKey);
6046
0
        return crv;
6047
0
    }
6048
0
    if (sftk_isTrue(privateKey, CKA_SENSITIVE)) {
6049
0
        crv = sftk_forceAttribute(privateKey, CKA_ALWAYS_SENSITIVE,
6050
0
                                  &cktrue, sizeof(CK_BBOOL));
6051
0
    }
6052
0
    if (crv == CKR_OK && sftk_isTrue(publicKey, CKA_SENSITIVE)) {
6053
0
        crv = sftk_forceAttribute(publicKey, CKA_ALWAYS_SENSITIVE,
6054
0
                                  &cktrue, sizeof(CK_BBOOL));
6055
0
    }
6056
0
    if (crv == CKR_OK && !sftk_isTrue(privateKey, CKA_EXTRACTABLE)) {
6057
0
        crv = sftk_forceAttribute(privateKey, CKA_NEVER_EXTRACTABLE,
6058
0
                                  &cktrue, sizeof(CK_BBOOL));
6059
0
    }
6060
0
    if (crv == CKR_OK && !sftk_isTrue(publicKey, CKA_EXTRACTABLE)) {
6061
0
        crv = sftk_forceAttribute(publicKey, CKA_NEVER_EXTRACTABLE,
6062
0
                                  &cktrue, sizeof(CK_BBOOL));
6063
0
    }
6064
6065
0
    if (crv == CKR_OK && pMechanism->mechanism != CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN && key_type != CKK_NSS_KYBER) {
6066
        /* Perform FIPS 140-2 pairwise consistency check. */
6067
0
        crv = sftk_PairwiseConsistencyCheck(hSession, slot,
6068
0
                                            publicKey, privateKey, key_type);
6069
0
        if (crv != CKR_OK) {
6070
0
            if (sftk_audit_enabled) {
6071
0
                char msg[128];
6072
0
                PR_snprintf(msg, sizeof msg,
6073
0
                            "C_GenerateKeyPair(hSession=0x%08lX, "
6074
0
                            "pMechanism->mechanism=0x%08lX)=0x%08lX "
6075
0
                            "self-test: pair-wise consistency test failed",
6076
0
                            (PRUint32)hSession, (PRUint32)pMechanism->mechanism,
6077
0
                            (PRUint32)crv);
6078
0
                sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg);
6079
0
            }
6080
0
        }
6081
0
    }
6082
6083
0
    if (crv != CKR_OK) {
6084
0
        NSC_DestroyObject(hSession, publicKey->handle);
6085
0
        sftk_FreeObject(publicKey);
6086
0
        NSC_DestroyObject(hSession, privateKey->handle);
6087
0
        sftk_FreeObject(privateKey);
6088
0
        return crv;
6089
0
    }
6090
6091
0
    *phPrivateKey = privateKey->handle;
6092
0
    *phPublicKey = publicKey->handle;
6093
0
    sftk_FreeObject(publicKey);
6094
0
    sftk_FreeObject(privateKey);
6095
6096
0
    return CKR_OK;
6097
0
}
6098
6099
static SECItem *
6100
sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp)
6101
0
{
6102
0
    NSSLOWKEYPrivateKey *lk = NULL;
6103
0
    NSSLOWKEYPrivateKeyInfo *pki = NULL;
6104
0
    SFTKAttribute *attribute = NULL;
6105
0
    PLArenaPool *arena = NULL;
6106
0
    SECOidTag algorithm = SEC_OID_UNKNOWN;
6107
0
    void *dummy, *param = NULL;
6108
0
    SECStatus rv = SECSuccess;
6109
0
    SECItem *encodedKey = NULL;
6110
#ifdef EC_DEBUG
6111
    SECItem *fordebug;
6112
#endif
6113
0
    int savelen;
6114
6115
0
    if (!key) {
6116
0
        *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */
6117
0
        return NULL;
6118
0
    }
6119
6120
0
    attribute = sftk_FindAttribute(key, CKA_KEY_TYPE);
6121
0
    if (!attribute) {
6122
0
        *crvp = CKR_KEY_TYPE_INCONSISTENT;
6123
0
        return NULL;
6124
0
    }
6125
6126
0
    lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp);
6127
0
    sftk_FreeAttribute(attribute);
6128
0
    if (!lk) {
6129
0
        return NULL;
6130
0
    }
6131
6132
0
    arena = PORT_NewArena(2048); /* XXX different size? */
6133
0
    if (!arena) {
6134
0
        *crvp = CKR_HOST_MEMORY;
6135
0
        rv = SECFailure;
6136
0
        goto loser;
6137
0
    }
6138
6139
0
    pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena,
6140
0
                                                      sizeof(NSSLOWKEYPrivateKeyInfo));
6141
0
    if (!pki) {
6142
0
        *crvp = CKR_HOST_MEMORY;
6143
0
        rv = SECFailure;
6144
0
        goto loser;
6145
0
    }
6146
0
    pki->arena = arena;
6147
6148
0
    param = NULL;
6149
0
    switch (lk->keyType) {
6150
0
        case NSSLOWKEYRSAKey:
6151
0
            prepare_low_rsa_priv_key_for_asn1(lk);
6152
0
            dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
6153
0
                                       nsslowkey_RSAPrivateKeyTemplate);
6154
6155
            /* determine RSA key type from the CKA_PUBLIC_KEY_INFO if present */
6156
0
            attribute = sftk_FindAttribute(key, CKA_PUBLIC_KEY_INFO);
6157
0
            if (attribute) {
6158
0
                NSSLOWKEYSubjectPublicKeyInfo *publicKeyInfo;
6159
0
                SECItem spki;
6160
6161
0
                spki.data = attribute->attrib.pValue;
6162
0
                spki.len = attribute->attrib.ulValueLen;
6163
6164
0
                publicKeyInfo = PORT_ArenaZAlloc(arena,
6165
0
                                                 sizeof(NSSLOWKEYSubjectPublicKeyInfo));
6166
0
                if (!publicKeyInfo) {
6167
0
                    sftk_FreeAttribute(attribute);
6168
0
                    *crvp = CKR_HOST_MEMORY;
6169
0
                    rv = SECFailure;
6170
0
                    goto loser;
6171
0
                }
6172
0
                rv = SEC_QuickDERDecodeItem(arena, publicKeyInfo,
6173
0
                                            nsslowkey_SubjectPublicKeyInfoTemplate,
6174
0
                                            &spki);
6175
0
                if (rv != SECSuccess) {
6176
0
                    sftk_FreeAttribute(attribute);
6177
0
                    *crvp = CKR_KEY_TYPE_INCONSISTENT;
6178
0
                    goto loser;
6179
0
                }
6180
0
                algorithm = SECOID_GetAlgorithmTag(&publicKeyInfo->algorithm);
6181
0
                if (algorithm != SEC_OID_PKCS1_RSA_ENCRYPTION &&
6182
0
                    algorithm != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
6183
0
                    sftk_FreeAttribute(attribute);
6184
0
                    rv = SECFailure;
6185
0
                    *crvp = CKR_KEY_TYPE_INCONSISTENT;
6186
0
                    goto loser;
6187
0
                }
6188
0
                param = SECITEM_DupItem(&publicKeyInfo->algorithm.parameters);
6189
0
                if (!param) {
6190
0
                    sftk_FreeAttribute(attribute);
6191
0
                    rv = SECFailure;
6192
0
                    *crvp = CKR_HOST_MEMORY;
6193
0
                    goto loser;
6194
0
                }
6195
0
                sftk_FreeAttribute(attribute);
6196
0
            } else {
6197
                /* default to PKCS #1 */
6198
0
                algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
6199
0
            }
6200
0
            break;
6201
0
        case NSSLOWKEYDSAKey:
6202
0
            prepare_low_dsa_priv_key_export_for_asn1(lk);
6203
0
            dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
6204
0
                                       nsslowkey_DSAPrivateKeyExportTemplate);
6205
0
            prepare_low_pqg_params_for_asn1(&lk->u.dsa.params);
6206
0
            param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params),
6207
0
                                       nsslowkey_PQGParamsTemplate);
6208
0
            algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE;
6209
0
            break;
6210
0
        case NSSLOWKEYECKey:
6211
0
            prepare_low_ec_priv_key_for_asn1(lk);
6212
            /* Public value is encoded as a bit string so adjust length
6213
             * to be in bits before ASN encoding and readjust
6214
             * immediately after.
6215
             *
6216
             * Since the SECG specification recommends not including the
6217
             * parameters as part of ECPrivateKey, we zero out the curveOID
6218
             * length before encoding and restore it later.
6219
             */
6220
0
            lk->u.ec.publicValue.len <<= 3;
6221
0
            savelen = lk->u.ec.ecParams.curveOID.len;
6222
0
            lk->u.ec.ecParams.curveOID.len = 0;
6223
0
            dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
6224
0
                                       nsslowkey_ECPrivateKeyTemplate);
6225
0
            lk->u.ec.ecParams.curveOID.len = savelen;
6226
0
            lk->u.ec.publicValue.len >>= 3;
6227
6228
#ifdef EC_DEBUG
6229
            fordebug = &pki->privateKey;
6230
            SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType,
6231
                      fordebug);
6232
#endif
6233
6234
0
            param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding);
6235
6236
0
            algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
6237
0
            break;
6238
0
        case NSSLOWKEYDHKey:
6239
0
        default:
6240
0
            dummy = NULL;
6241
0
            break;
6242
0
    }
6243
6244
0
    if (!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) {
6245
0
        *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
6246
0
        rv = SECFailure;
6247
0
        goto loser;
6248
0
    }
6249
6250
0
    rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm,
6251
0
                               (SECItem *)param);
6252
0
    if (rv != SECSuccess) {
6253
0
        *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
6254
0
        rv = SECFailure;
6255
0
        goto loser;
6256
0
    }
6257
6258
0
    dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
6259
0
                                  NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
6260
0
    if (!dummy) {
6261
0
        *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
6262
0
        rv = SECFailure;
6263
0
        goto loser;
6264
0
    }
6265
6266
0
    encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki,
6267
0
                                    nsslowkey_PrivateKeyInfoTemplate);
6268
0
    *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR;
6269
6270
#ifdef EC_DEBUG
6271
    fordebug = encodedKey;
6272
    SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType,
6273
              fordebug);
6274
#endif
6275
0
loser:
6276
0
    if (arena) {
6277
0
        PORT_FreeArena(arena, PR_TRUE);
6278
0
    }
6279
6280
0
    if (lk && (lk != key->objectInfo)) {
6281
0
        nsslowkey_DestroyPrivateKey(lk);
6282
0
    }
6283
6284
0
    if (param) {
6285
0
        SECITEM_ZfreeItem((SECItem *)param, PR_TRUE);
6286
0
    }
6287
6288
0
    if (rv != SECSuccess) {
6289
0
        return NULL;
6290
0
    }
6291
6292
0
    return encodedKey;
6293
0
}
6294
6295
/* it doesn't matter yet, since we colapse error conditions in the
6296
 * level above, but we really should map those few key error differences */
6297
static CK_RV
6298
sftk_mapWrap(CK_RV crv)
6299
0
{
6300
0
    switch (crv) {
6301
0
        case CKR_ENCRYPTED_DATA_INVALID:
6302
0
            crv = CKR_WRAPPED_KEY_INVALID;
6303
0
            break;
6304
0
    }
6305
0
    return crv;
6306
0
}
6307
6308
/* NSC_WrapKey wraps (i.e., encrypts) a key. */
6309
CK_RV
6310
NSC_WrapKey(CK_SESSION_HANDLE hSession,
6311
            CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
6312
            CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
6313
            CK_ULONG_PTR pulWrappedKeyLen)
6314
0
{
6315
0
    SFTKSession *session;
6316
0
    SFTKAttribute *attribute;
6317
0
    SFTKObject *key;
6318
0
    CK_RV crv;
6319
6320
0
    CHECK_FORK();
6321
6322
0
    session = sftk_SessionFromHandle(hSession);
6323
0
    if (session == NULL) {
6324
0
        return CKR_SESSION_HANDLE_INVALID;
6325
0
    }
6326
6327
0
    key = sftk_ObjectFromHandle(hKey, session);
6328
0
    if (key == NULL) {
6329
0
        sftk_FreeSession(session);
6330
0
        return CKR_KEY_HANDLE_INVALID;
6331
0
    }
6332
6333
0
    switch (key->objclass) {
6334
0
        case CKO_SECRET_KEY: {
6335
0
            SFTKSessionContext *context = NULL;
6336
0
            SECItem pText;
6337
6338
0
            attribute = sftk_FindAttribute(key, CKA_VALUE);
6339
6340
0
            if (attribute == NULL) {
6341
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
6342
0
                break;
6343
0
            }
6344
0
            crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
6345
0
                                 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
6346
0
            if (crv != CKR_OK) {
6347
0
                sftk_FreeAttribute(attribute);
6348
0
                break;
6349
0
            }
6350
6351
0
            pText.type = siBuffer;
6352
0
            pText.data = (unsigned char *)attribute->attrib.pValue;
6353
0
            pText.len = attribute->attrib.ulValueLen;
6354
6355
            /* Find out if this is a block cipher. */
6356
0
            crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, NULL);
6357
0
            if (crv != CKR_OK || !context)
6358
0
                break;
6359
0
            if (context->blockSize > 1) {
6360
0
                unsigned int remainder = pText.len % context->blockSize;
6361
0
                if (!context->doPad && remainder) {
6362
                    /* When wrapping secret keys with unpadded block ciphers,
6363
                    ** the keys are zero padded, if necessary, to fill out
6364
                    ** a full block.
6365
                    */
6366
0
                    pText.len += context->blockSize - remainder;
6367
0
                    pText.data = PORT_ZAlloc(pText.len);
6368
0
                    if (pText.data)
6369
0
                        memcpy(pText.data, attribute->attrib.pValue,
6370
0
                               attribute->attrib.ulValueLen);
6371
0
                    else {
6372
0
                        crv = CKR_HOST_MEMORY;
6373
0
                        break;
6374
0
                    }
6375
0
                }
6376
0
            }
6377
6378
0
            crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data,
6379
0
                              pText.len, pWrappedKey, pulWrappedKeyLen);
6380
            /* always force a finalize, both on errors and when
6381
             * we are just getting the size */
6382
0
            if (crv != CKR_OK || pWrappedKey == NULL) {
6383
0
                CK_RV lcrv;
6384
0
                lcrv = sftk_GetContext(hSession, &context,
6385
0
                                       SFTK_ENCRYPT, PR_FALSE, NULL);
6386
0
                sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
6387
0
                if (lcrv == CKR_OK && context) {
6388
0
                    sftk_FreeContext(context);
6389
0
                }
6390
0
            }
6391
6392
0
            if (pText.data != (unsigned char *)attribute->attrib.pValue)
6393
0
                PORT_ZFree(pText.data, pText.len);
6394
0
            sftk_FreeAttribute(attribute);
6395
0
            break;
6396
0
        }
6397
6398
0
        case CKO_PRIVATE_KEY: {
6399
0
            SECItem *bpki = sftk_PackagePrivateKey(key, &crv);
6400
0
            SFTKSessionContext *context = NULL;
6401
6402
0
            if (!bpki) {
6403
0
                break;
6404
0
            }
6405
6406
0
            crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
6407
0
                                 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
6408
0
            if (crv != CKR_OK) {
6409
0
                SECITEM_ZfreeItem(bpki, PR_TRUE);
6410
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
6411
0
                break;
6412
0
            }
6413
6414
0
            crv = NSC_Encrypt(hSession, bpki->data, bpki->len,
6415
0
                              pWrappedKey, pulWrappedKeyLen);
6416
            /* always force a finalize */
6417
0
            if (crv != CKR_OK || pWrappedKey == NULL) {
6418
0
                CK_RV lcrv;
6419
0
                lcrv = sftk_GetContext(hSession, &context,
6420
0
                                       SFTK_ENCRYPT, PR_FALSE, NULL);
6421
0
                sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
6422
0
                if (lcrv == CKR_OK && context) {
6423
0
                    sftk_FreeContext(context);
6424
0
                }
6425
0
            }
6426
0
            SECITEM_ZfreeItem(bpki, PR_TRUE);
6427
0
            break;
6428
0
        }
6429
6430
0
        default:
6431
0
            crv = CKR_KEY_TYPE_INCONSISTENT;
6432
0
            break;
6433
0
    }
6434
0
    sftk_FreeObject(key);
6435
0
    sftk_FreeSession(session);
6436
0
    return sftk_mapWrap(crv);
6437
0
}
6438
6439
/*
6440
 * import a pprivate key info into the desired slot
6441
 */
6442
static SECStatus
6443
sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki)
6444
0
{
6445
0
    CK_BBOOL cktrue = CK_TRUE;
6446
0
    CK_KEY_TYPE keyType = CKK_RSA;
6447
0
    SECStatus rv = SECFailure;
6448
0
    const SEC_ASN1Template *keyTemplate, *paramTemplate;
6449
0
    void *paramDest = NULL;
6450
0
    PLArenaPool *arena;
6451
0
    NSSLOWKEYPrivateKey *lpk = NULL;
6452
0
    NSSLOWKEYPrivateKeyInfo *pki = NULL;
6453
0
    CK_RV crv = CKR_KEY_TYPE_INCONSISTENT;
6454
6455
0
    arena = PORT_NewArena(2048);
6456
0
    if (!arena) {
6457
0
        return SECFailure;
6458
0
    }
6459
6460
0
    pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena,
6461
0
                                                      sizeof(NSSLOWKEYPrivateKeyInfo));
6462
0
    if (!pki) {
6463
0
        PORT_FreeArena(arena, PR_FALSE);
6464
0
        return SECFailure;
6465
0
    }
6466
6467
0
    if (SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) != SECSuccess) {
6468
0
        PORT_FreeArena(arena, PR_TRUE);
6469
0
        return SECFailure;
6470
0
    }
6471
6472
0
    lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena,
6473
0
                                                  sizeof(NSSLOWKEYPrivateKey));
6474
0
    if (lpk == NULL) {
6475
0
        goto loser;
6476
0
    }
6477
0
    lpk->arena = arena;
6478
6479
0
    switch (SECOID_GetAlgorithmTag(&pki->algorithm)) {
6480
0
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
6481
0
        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
6482
0
            keyTemplate = nsslowkey_RSAPrivateKeyTemplate;
6483
0
            paramTemplate = NULL;
6484
0
            paramDest = NULL;
6485
0
            lpk->keyType = NSSLOWKEYRSAKey;
6486
0
            prepare_low_rsa_priv_key_for_asn1(lpk);
6487
0
            break;
6488
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
6489
0
            keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate;
6490
0
            paramTemplate = nsslowkey_PQGParamsTemplate;
6491
0
            paramDest = &(lpk->u.dsa.params);
6492
0
            lpk->keyType = NSSLOWKEYDSAKey;
6493
0
            prepare_low_dsa_priv_key_export_for_asn1(lpk);
6494
0
            prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params);
6495
0
            break;
6496
        /* case NSSLOWKEYDHKey: */
6497
0
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
6498
0
            keyTemplate = nsslowkey_ECPrivateKeyTemplate;
6499
0
            paramTemplate = NULL;
6500
0
            paramDest = &(lpk->u.ec.ecParams.DEREncoding);
6501
0
            lpk->keyType = NSSLOWKEYECKey;
6502
0
            prepare_low_ec_priv_key_for_asn1(lpk);
6503
0
            prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams);
6504
0
            break;
6505
0
        default:
6506
0
            keyTemplate = NULL;
6507
0
            paramTemplate = NULL;
6508
0
            paramDest = NULL;
6509
0
            break;
6510
0
    }
6511
6512
0
    if (!keyTemplate) {
6513
0
        goto loser;
6514
0
    }
6515
6516
    /* decode the private key and any algorithm parameters */
6517
0
    rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
6518
6519
0
    if (lpk->keyType == NSSLOWKEYECKey) {
6520
        /* convert length in bits to length in bytes */
6521
0
        lpk->u.ec.publicValue.len >>= 3;
6522
0
        rv = SECITEM_CopyItem(arena,
6523
0
                              &(lpk->u.ec.ecParams.DEREncoding),
6524
0
                              &(pki->algorithm.parameters));
6525
0
        if (rv != SECSuccess) {
6526
0
            goto loser;
6527
0
        }
6528
0
    }
6529
6530
0
    if (rv != SECSuccess) {
6531
0
        goto loser;
6532
0
    }
6533
0
    if (paramDest && paramTemplate) {
6534
0
        rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate,
6535
0
                                    &(pki->algorithm.parameters));
6536
0
        if (rv != SECSuccess) {
6537
0
            goto loser;
6538
0
        }
6539
0
    }
6540
6541
0
    rv = SECFailure;
6542
6543
0
    switch (lpk->keyType) {
6544
0
        case NSSLOWKEYRSAKey:
6545
0
            keyType = CKK_RSA;
6546
0
            if (sftk_hasAttribute(key, CKA_NSS_DB)) {
6547
0
                sftk_DeleteAttributeType(key, CKA_NSS_DB);
6548
0
            }
6549
0
            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
6550
0
                                        sizeof(keyType));
6551
0
            if (crv != CKR_OK)
6552
0
                break;
6553
0
            crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue,
6554
0
                                        sizeof(CK_BBOOL));
6555
0
            if (crv != CKR_OK)
6556
0
                break;
6557
0
            crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue,
6558
0
                                        sizeof(CK_BBOOL));
6559
0
            if (crv != CKR_OK)
6560
0
                break;
6561
0
            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
6562
0
                                        sizeof(CK_BBOOL));
6563
0
            if (crv != CKR_OK)
6564
0
                break;
6565
0
            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
6566
0
                                        sizeof(CK_BBOOL));
6567
0
            if (crv != CKR_OK)
6568
0
                break;
6569
0
            crv = sftk_AddAttributeType(key, CKA_MODULUS,
6570
0
                                        sftk_item_expand(&lpk->u.rsa.modulus));
6571
0
            if (crv != CKR_OK)
6572
0
                break;
6573
0
            crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT,
6574
0
                                        sftk_item_expand(&lpk->u.rsa.publicExponent));
6575
0
            if (crv != CKR_OK)
6576
0
                break;
6577
0
            crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT,
6578
0
                                        sftk_item_expand(&lpk->u.rsa.privateExponent));
6579
0
            if (crv != CKR_OK)
6580
0
                break;
6581
0
            crv = sftk_AddAttributeType(key, CKA_PRIME_1,
6582
0
                                        sftk_item_expand(&lpk->u.rsa.prime1));
6583
0
            if (crv != CKR_OK)
6584
0
                break;
6585
0
            crv = sftk_AddAttributeType(key, CKA_PRIME_2,
6586
0
                                        sftk_item_expand(&lpk->u.rsa.prime2));
6587
0
            if (crv != CKR_OK)
6588
0
                break;
6589
0
            crv = sftk_AddAttributeType(key, CKA_EXPONENT_1,
6590
0
                                        sftk_item_expand(&lpk->u.rsa.exponent1));
6591
0
            if (crv != CKR_OK)
6592
0
                break;
6593
0
            crv = sftk_AddAttributeType(key, CKA_EXPONENT_2,
6594
0
                                        sftk_item_expand(&lpk->u.rsa.exponent2));
6595
0
            if (crv != CKR_OK)
6596
0
                break;
6597
0
            crv = sftk_AddAttributeType(key, CKA_COEFFICIENT,
6598
0
                                        sftk_item_expand(&lpk->u.rsa.coefficient));
6599
0
            break;
6600
0
        case NSSLOWKEYDSAKey:
6601
0
            keyType = CKK_DSA;
6602
0
            crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
6603
0
            if (crv != CKR_OK)
6604
0
                break;
6605
0
            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
6606
0
                                        sizeof(keyType));
6607
0
            if (crv != CKR_OK)
6608
0
                break;
6609
0
            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
6610
0
                                        sizeof(CK_BBOOL));
6611
0
            if (crv != CKR_OK)
6612
0
                break;
6613
0
            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
6614
0
                                        sizeof(CK_BBOOL));
6615
0
            if (crv != CKR_OK)
6616
0
                break;
6617
0
            crv = sftk_AddAttributeType(key, CKA_PRIME,
6618
0
                                        sftk_item_expand(&lpk->u.dsa.params.prime));
6619
0
            if (crv != CKR_OK)
6620
0
                break;
6621
0
            crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
6622
0
                                        sftk_item_expand(&lpk->u.dsa.params.subPrime));
6623
0
            if (crv != CKR_OK)
6624
0
                break;
6625
0
            crv = sftk_AddAttributeType(key, CKA_BASE,
6626
0
                                        sftk_item_expand(&lpk->u.dsa.params.base));
6627
0
            if (crv != CKR_OK)
6628
0
                break;
6629
0
            crv = sftk_AddAttributeType(key, CKA_VALUE,
6630
0
                                        sftk_item_expand(&lpk->u.dsa.privateValue));
6631
0
            if (crv != CKR_OK)
6632
0
                break;
6633
0
            break;
6634
#ifdef notdef
6635
        case NSSLOWKEYDHKey:
6636
            template = dhTemplate;
6637
            templateCount = sizeof(dhTemplate) / sizeof(CK_ATTRIBUTE);
6638
            keyType = CKK_DH;
6639
            break;
6640
#endif
6641
        /* what about fortezza??? */
6642
0
        case NSSLOWKEYECKey:
6643
0
            keyType = CKK_EC;
6644
0
            crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
6645
0
            if (crv != CKR_OK)
6646
0
                break;
6647
0
            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
6648
0
                                        sizeof(keyType));
6649
0
            if (crv != CKR_OK)
6650
0
                break;
6651
0
            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
6652
0
                                        sizeof(CK_BBOOL));
6653
0
            if (crv != CKR_OK)
6654
0
                break;
6655
0
            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
6656
0
                                        sizeof(CK_BBOOL));
6657
0
            if (crv != CKR_OK)
6658
0
                break;
6659
0
            crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue,
6660
0
                                        sizeof(CK_BBOOL));
6661
0
            if (crv != CKR_OK)
6662
0
                break;
6663
0
            crv = sftk_AddAttributeType(key, CKA_EC_PARAMS,
6664
0
                                        sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding));
6665
0
            if (crv != CKR_OK)
6666
0
                break;
6667
0
            crv = sftk_AddAttributeType(key, CKA_VALUE,
6668
0
                                        sftk_item_expand(&lpk->u.ec.privateValue));
6669
0
            if (crv != CKR_OK)
6670
0
                break;
6671
            /* XXX Do we need to decode the EC Params here ?? */
6672
0
            break;
6673
0
        default:
6674
0
            crv = CKR_KEY_TYPE_INCONSISTENT;
6675
0
            break;
6676
0
    }
6677
6678
0
    if (crv != CKR_OK) {
6679
0
        goto loser;
6680
0
    }
6681
6682
    /* For RSA-PSS, record the original algorithm parameters so
6683
     * they can be encrypted altoghether when wrapping */
6684
0
    if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
6685
0
        NSSLOWKEYSubjectPublicKeyInfo spki;
6686
0
        NSSLOWKEYPublicKey pubk;
6687
0
        SECItem *publicKeyInfo;
6688
6689
0
        memset(&spki, 0, sizeof(NSSLOWKEYSubjectPublicKeyInfo));
6690
0
        rv = SECOID_CopyAlgorithmID(arena, &spki.algorithm, &pki->algorithm);
6691
0
        if (rv != SECSuccess) {
6692
0
            crv = CKR_HOST_MEMORY;
6693
0
            goto loser;
6694
0
        }
6695
6696
0
        prepare_low_rsa_pub_key_for_asn1(&pubk);
6697
6698
0
        rv = SECITEM_CopyItem(arena, &pubk.u.rsa.modulus, &lpk->u.rsa.modulus);
6699
0
        if (rv != SECSuccess) {
6700
0
            crv = CKR_HOST_MEMORY;
6701
0
            goto loser;
6702
0
        }
6703
0
        rv = SECITEM_CopyItem(arena, &pubk.u.rsa.publicExponent, &lpk->u.rsa.publicExponent);
6704
0
        if (rv != SECSuccess) {
6705
0
            crv = CKR_HOST_MEMORY;
6706
0
            goto loser;
6707
0
        }
6708
6709
0
        if (SEC_ASN1EncodeItem(arena, &spki.subjectPublicKey,
6710
0
                               &pubk, nsslowkey_RSAPublicKeyTemplate) == NULL) {
6711
0
            crv = CKR_HOST_MEMORY;
6712
0
            goto loser;
6713
0
        }
6714
6715
0
        publicKeyInfo = SEC_ASN1EncodeItem(arena, NULL,
6716
0
                                           &spki, nsslowkey_SubjectPublicKeyInfoTemplate);
6717
0
        if (!publicKeyInfo) {
6718
0
            crv = CKR_HOST_MEMORY;
6719
0
            goto loser;
6720
0
        }
6721
0
        crv = sftk_AddAttributeType(key, CKA_PUBLIC_KEY_INFO,
6722
0
                                    sftk_item_expand(publicKeyInfo));
6723
0
    }
6724
6725
0
loser:
6726
0
    if (lpk) {
6727
0
        nsslowkey_DestroyPrivateKey(lpk);
6728
0
    }
6729
6730
0
    if (crv != CKR_OK) {
6731
0
        return SECFailure;
6732
0
    }
6733
6734
0
    return SECSuccess;
6735
0
}
6736
6737
/* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
6738
CK_RV
6739
NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
6740
              CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
6741
              CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
6742
              CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
6743
              CK_OBJECT_HANDLE_PTR phKey)
6744
0
{
6745
0
    SFTKObject *key = NULL;
6746
0
    SFTKSession *session;
6747
0
    CK_ULONG key_length = 0;
6748
0
    unsigned char *buf = NULL;
6749
0
    CK_RV crv = CKR_OK;
6750
0
    int i;
6751
0
    CK_ULONG bsize = ulWrappedKeyLen;
6752
0
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
6753
0
    SECItem bpki;
6754
0
    CK_OBJECT_CLASS target_type = CKO_SECRET_KEY;
6755
6756
0
    CHECK_FORK();
6757
6758
0
    if (!slot) {
6759
0
        return CKR_SESSION_HANDLE_INVALID;
6760
0
    }
6761
    /*
6762
     * now lets create an object to hang the attributes off of
6763
     */
6764
0
    key = sftk_NewObject(slot); /* fill in the handle later */
6765
0
    if (key == NULL) {
6766
0
        return CKR_HOST_MEMORY;
6767
0
    }
6768
6769
    /*
6770
     * load the template values into the object
6771
     */
6772
0
    for (i = 0; i < (int)ulAttributeCount; i++) {
6773
0
        if (pTemplate[i].type == CKA_VALUE_LEN) {
6774
0
            key_length = *(CK_ULONG *)pTemplate[i].pValue;
6775
0
            continue;
6776
0
        }
6777
0
        if (pTemplate[i].type == CKA_CLASS) {
6778
0
            target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
6779
0
        }
6780
0
        crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
6781
0
        if (crv != CKR_OK)
6782
0
            break;
6783
0
    }
6784
0
    if (crv != CKR_OK) {
6785
0
        sftk_FreeObject(key);
6786
0
        return crv;
6787
0
    }
6788
6789
0
    crv = sftk_CryptInit(hSession, pMechanism, hUnwrappingKey, CKA_UNWRAP,
6790
0
                         CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE);
6791
0
    if (crv != CKR_OK) {
6792
0
        sftk_FreeObject(key);
6793
0
        return sftk_mapWrap(crv);
6794
0
    }
6795
6796
    /* allocate the buffer to decrypt into
6797
     * this assumes the unwrapped key is never larger than the
6798
     * wrapped key. For all the mechanisms we support this is true */
6799
0
    buf = (unsigned char *)PORT_Alloc(ulWrappedKeyLen);
6800
0
    bsize = ulWrappedKeyLen;
6801
6802
0
    crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize);
6803
0
    if (crv != CKR_OK) {
6804
0
        sftk_FreeObject(key);
6805
0
        PORT_Free(buf);
6806
0
        return sftk_mapWrap(crv);
6807
0
    }
6808
6809
0
    switch (target_type) {
6810
0
        case CKO_SECRET_KEY:
6811
0
            if (!sftk_hasAttribute(key, CKA_KEY_TYPE)) {
6812
0
                crv = CKR_TEMPLATE_INCOMPLETE;
6813
0
                break;
6814
0
            }
6815
6816
0
            if (key_length == 0 || key_length > bsize) {
6817
0
                key_length = bsize;
6818
0
            }
6819
0
            if (key_length > MAX_KEY_LEN) {
6820
0
                crv = CKR_TEMPLATE_INCONSISTENT;
6821
0
                break;
6822
0
            }
6823
6824
            /* add the value */
6825
0
            crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length);
6826
0
            break;
6827
0
        case CKO_PRIVATE_KEY:
6828
0
            bpki.data = (unsigned char *)buf;
6829
0
            bpki.len = bsize;
6830
0
            crv = CKR_OK;
6831
0
            if (sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) {
6832
0
                crv = CKR_TEMPLATE_INCOMPLETE;
6833
0
            }
6834
0
            break;
6835
0
        default:
6836
0
            crv = CKR_TEMPLATE_INCONSISTENT;
6837
0
            break;
6838
0
    }
6839
6840
0
    PORT_ZFree(buf, bsize);
6841
0
    if (crv != CKR_OK) {
6842
0
        sftk_FreeObject(key);
6843
0
        return crv;
6844
0
    }
6845
6846
    /* get the session */
6847
0
    session = sftk_SessionFromHandle(hSession);
6848
0
    if (session == NULL) {
6849
0
        sftk_FreeObject(key);
6850
0
        return CKR_SESSION_HANDLE_INVALID;
6851
0
    }
6852
6853
    /* mark the key as FIPS if the previous operation was all FIPS */
6854
0
    key->isFIPS = session->lastOpWasFIPS;
6855
6856
    /*
6857
     * handle the base object stuff
6858
     */
6859
0
    crv = sftk_handleObject(key, session);
6860
0
    *phKey = key->handle;
6861
0
    sftk_FreeSession(session);
6862
0
    sftk_FreeObject(key);
6863
6864
0
    return crv;
6865
0
}
6866
6867
/*
6868
 * The SSL key gen mechanism create's lots of keys. This function handles the
6869
 * details of each of these key creation.
6870
 */
6871
static CK_RV
6872
sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey,
6873
                 PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize,
6874
                 CK_OBJECT_HANDLE *keyHandle)
6875
0
{
6876
0
    SFTKObject *key;
6877
0
    SFTKSession *session;
6878
0
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
6879
0
    CK_BBOOL cktrue = CK_TRUE;
6880
0
    CK_BBOOL ckfalse = CK_FALSE;
6881
0
    CK_RV crv = CKR_HOST_MEMORY;
6882
6883
    /*
6884
     * now lets create an object to hang the attributes off of
6885
     */
6886
0
    *keyHandle = CK_INVALID_HANDLE;
6887
0
    key = sftk_NewObject(baseKey->slot);
6888
0
    if (key == NULL)
6889
0
        return CKR_HOST_MEMORY;
6890
0
    sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE;
6891
6892
0
    crv = sftk_CopyObject(key, baseKey);
6893
0
    if (crv != CKR_OK)
6894
0
        goto loser;
6895
0
    if (isMacKey) {
6896
0
        crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType));
6897
0
        if (crv != CKR_OK)
6898
0
            goto loser;
6899
0
        crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
6900
0
        if (crv != CKR_OK)
6901
0
            goto loser;
6902
0
        crv = sftk_forceAttribute(key, CKA_ENCRYPT, &ckfalse, sizeof(CK_BBOOL));
6903
0
        if (crv != CKR_OK)
6904
0
            goto loser;
6905
0
        crv = sftk_forceAttribute(key, CKA_DECRYPT, &ckfalse, sizeof(CK_BBOOL));
6906
0
        if (crv != CKR_OK)
6907
0
            goto loser;
6908
0
        crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
6909
0
        if (crv != CKR_OK)
6910
0
            goto loser;
6911
0
        crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
6912
0
        if (crv != CKR_OK)
6913
0
            goto loser;
6914
0
        crv = sftk_forceAttribute(key, CKA_WRAP, &ckfalse, sizeof(CK_BBOOL));
6915
0
        if (crv != CKR_OK)
6916
0
            goto loser;
6917
0
        crv = sftk_forceAttribute(key, CKA_UNWRAP, &ckfalse, sizeof(CK_BBOOL));
6918
0
        if (crv != CKR_OK)
6919
0
            goto loser;
6920
0
    }
6921
0
    crv = sftk_forceAttribute(key, CKA_VALUE, keyBlock, keySize);
6922
0
    if (crv != CKR_OK)
6923
0
        goto loser;
6924
6925
    /* get the session */
6926
0
    crv = CKR_HOST_MEMORY;
6927
0
    session = sftk_SessionFromHandle(hSession);
6928
0
    if (session == NULL) {
6929
0
        goto loser;
6930
0
    }
6931
6932
0
    crv = sftk_handleObject(key, session);
6933
0
    sftk_FreeSession(session);
6934
0
    *keyHandle = key->handle;
6935
0
loser:
6936
0
    if (key)
6937
0
        sftk_FreeObject(key);
6938
0
    return crv;
6939
0
}
6940
6941
/*
6942
 * if there is an error, we need to free the keys we already created in SSL
6943
 * This is the routine that will do it..
6944
 */
6945
static void
6946
sftk_freeSSLKeys(CK_SESSION_HANDLE session,
6947
                 CK_SSL3_KEY_MAT_OUT *returnedMaterial)
6948
0
{
6949
0
    if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) {
6950
0
        NSC_DestroyObject(session, returnedMaterial->hClientMacSecret);
6951
0
    }
6952
0
    if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) {
6953
0
        NSC_DestroyObject(session, returnedMaterial->hServerMacSecret);
6954
0
    }
6955
0
    if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) {
6956
0
        NSC_DestroyObject(session, returnedMaterial->hClientKey);
6957
0
    }
6958
0
    if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) {
6959
0
        NSC_DestroyObject(session, returnedMaterial->hServerKey);
6960
0
    }
6961
0
}
6962
6963
/*
6964
 * when deriving from sensitive and extractable keys, we need to preserve some
6965
 * of the semantics in the derived key. This helper routine maintains these
6966
 * semantics.
6967
 */
6968
static CK_RV
6969
sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey,
6970
                          PRBool canBeData)
6971
43
{
6972
43
    PRBool hasSensitive;
6973
43
    PRBool sensitive = PR_FALSE;
6974
43
    CK_BBOOL bFalse = CK_FALSE;
6975
43
    PRBool hasExtractable;
6976
43
    PRBool extractable = PR_TRUE;
6977
43
    CK_BBOOL bTrue = CK_TRUE;
6978
43
    CK_RV crv = CKR_OK;
6979
43
    SFTKAttribute *att;
6980
43
    PRBool isData = PR_TRUE;
6981
6982
43
    if (canBeData) {
6983
0
        CK_OBJECT_CLASS objClass;
6984
6985
        /* if the target key is actually data, don't set the unexpected
6986
         * attributes */
6987
0
        crv = sftk_GetULongAttribute(destKey, CKA_CLASS, &objClass);
6988
0
        if (crv != CKR_OK) {
6989
0
            return crv;
6990
0
        }
6991
0
        if (objClass == CKO_DATA) {
6992
0
            return CKR_OK;
6993
0
        }
6994
6995
        /* if the base key is data, it doesn't have sensitive attributes,
6996
         * allow the destKey to get it's own */
6997
0
        crv = sftk_GetULongAttribute(baseKey, CKA_CLASS, &objClass);
6998
0
        if (crv != CKR_OK) {
6999
0
            return crv;
7000
0
        }
7001
0
        if (objClass == CKO_DATA) {
7002
0
            isData = PR_TRUE;
7003
0
        }
7004
0
    }
7005
7006
43
    hasSensitive = PR_FALSE;
7007
43
    att = sftk_FindAttribute(destKey, CKA_SENSITIVE);
7008
43
    if (att) {
7009
0
        hasSensitive = PR_TRUE;
7010
0
        sensitive = (PRBool) * (CK_BBOOL *)att->attrib.pValue;
7011
0
        sftk_FreeAttribute(att);
7012
0
    }
7013
7014
43
    hasExtractable = PR_FALSE;
7015
43
    att = sftk_FindAttribute(destKey, CKA_EXTRACTABLE);
7016
43
    if (att) {
7017
0
        hasExtractable = PR_TRUE;
7018
0
        extractable = (PRBool) * (CK_BBOOL *)att->attrib.pValue;
7019
0
        sftk_FreeAttribute(att);
7020
0
    }
7021
7022
    /* don't make a key more accessible */
7023
43
    if (sftk_isTrue(baseKey, CKA_SENSITIVE) && hasSensitive &&
7024
43
        (sensitive == PR_FALSE)) {
7025
0
        return CKR_KEY_FUNCTION_NOT_PERMITTED;
7026
0
    }
7027
43
    if (!sftk_isTrue(baseKey, CKA_EXTRACTABLE) && hasExtractable &&
7028
43
        (extractable == PR_TRUE)) {
7029
0
        return CKR_KEY_FUNCTION_NOT_PERMITTED;
7030
0
    }
7031
7032
    /* inherit parent's sensitivity */
7033
43
    if (!hasSensitive) {
7034
43
        att = sftk_FindAttribute(baseKey, CKA_SENSITIVE);
7035
43
        if (att != NULL) {
7036
43
            crv = sftk_defaultAttribute(destKey,
7037
43
                                        sftk_attr_expand(&att->attrib));
7038
43
            sftk_FreeAttribute(att);
7039
43
        } else if (isData) {
7040
0
            crv = sftk_defaultAttribute(destKey, CKA_SENSITIVE,
7041
0
                                        &bFalse, sizeof(bFalse));
7042
0
        } else {
7043
0
            return CKR_KEY_TYPE_INCONSISTENT;
7044
0
        }
7045
43
        if (crv != CKR_OK)
7046
0
            return crv;
7047
43
    }
7048
43
    if (!hasExtractable) {
7049
43
        att = sftk_FindAttribute(baseKey, CKA_EXTRACTABLE);
7050
43
        if (att != NULL) {
7051
43
            crv = sftk_defaultAttribute(destKey,
7052
43
                                        sftk_attr_expand(&att->attrib));
7053
43
            sftk_FreeAttribute(att);
7054
43
        } else if (isData) {
7055
0
            crv = sftk_defaultAttribute(destKey, CKA_EXTRACTABLE,
7056
0
                                        &bTrue, sizeof(bTrue));
7057
0
        } else {
7058
0
            return CKR_KEY_TYPE_INCONSISTENT;
7059
0
        }
7060
43
        if (crv != CKR_OK)
7061
0
            return crv;
7062
43
    }
7063
7064
    /* we should inherit the parent's always extractable/ never sensitive info,
7065
     * but handleObject always forces this attributes, so we would need to do
7066
     * something special. */
7067
43
    return CKR_OK;
7068
43
}
7069
7070
/*
7071
 * make known fixed PKCS #11 key types to their sizes in bytes
7072
 */
7073
unsigned long
7074
sftk_MapKeySize(CK_KEY_TYPE keyType)
7075
9
{
7076
9
    switch (keyType) {
7077
0
        case CKK_CDMF:
7078
0
            return 8;
7079
9
        case CKK_DES:
7080
9
            return 8;
7081
0
        case CKK_DES2:
7082
0
            return 16;
7083
0
        case CKK_DES3:
7084
0
            return 24;
7085
        /* IDEA and CAST need to be added */
7086
0
        default:
7087
0
            break;
7088
9
    }
7089
0
    return 0;
7090
9
}
7091
7092
/* Inputs:
7093
 *  key_len: Length of derived key to be generated.
7094
 *  SharedSecret: a shared secret that is the output of a key agreement primitive.
7095
 *  SharedInfo: (Optional) some data shared by the entities computing the secret key.
7096
 *  SharedInfoLen: the length in octets of SharedInfo
7097
 *  Hash: The hash function to be used in the KDF
7098
 *  HashLen: the length in octets of the output of Hash
7099
 * Output:
7100
 *  key: Pointer to a buffer containing derived key, if return value is SECSuccess.
7101
 */
7102
static CK_RV
7103
sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret,
7104
                            CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
7105
                            SECStatus Hash(unsigned char *, const unsigned char *, PRUint32),
7106
                            CK_ULONG HashLen)
7107
0
{
7108
0
    unsigned char *buffer = NULL, *output_buffer = NULL;
7109
0
    PRUint32 buffer_len, max_counter, i;
7110
0
    SECStatus rv;
7111
0
    CK_RV crv;
7112
7113
    /* Check that key_len isn't too long.  The maximum key length could be
7114
     * greatly increased if the code below did not limit the 4-byte counter
7115
     * to a maximum value of 255. */
7116
0
    if (key_len > 254 * HashLen)
7117
0
        return CKR_ARGUMENTS_BAD;
7118
7119
0
    if (SharedInfo == NULL)
7120
0
        SharedInfoLen = 0;
7121
7122
0
    buffer_len = SharedSecret->len + 4 + SharedInfoLen;
7123
0
    buffer = (CK_BYTE *)PORT_Alloc(buffer_len);
7124
0
    if (buffer == NULL) {
7125
0
        crv = CKR_HOST_MEMORY;
7126
0
        goto loser;
7127
0
    }
7128
7129
0
    max_counter = key_len / HashLen;
7130
0
    if (key_len > max_counter * HashLen)
7131
0
        max_counter++;
7132
7133
0
    output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen);
7134
0
    if (output_buffer == NULL) {
7135
0
        crv = CKR_HOST_MEMORY;
7136
0
        goto loser;
7137
0
    }
7138
7139
    /* Populate buffer with SharedSecret || Counter || [SharedInfo]
7140
     * where Counter is 0x00000001 */
7141
0
    PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len);
7142
0
    buffer[SharedSecret->len] = 0;
7143
0
    buffer[SharedSecret->len + 1] = 0;
7144
0
    buffer[SharedSecret->len + 2] = 0;
7145
0
    buffer[SharedSecret->len + 3] = 1;
7146
0
    if (SharedInfo) {
7147
0
        PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen);
7148
0
    }
7149
7150
0
    for (i = 0; i < max_counter; i++) {
7151
0
        rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len);
7152
0
        if (rv != SECSuccess) {
7153
            /* 'Hash' should not fail. */
7154
0
            crv = CKR_FUNCTION_FAILED;
7155
0
            goto loser;
7156
0
        }
7157
7158
        /* Increment counter (assumes max_counter < 255) */
7159
0
        buffer[SharedSecret->len + 3]++;
7160
0
    }
7161
7162
0
    PORT_ZFree(buffer, buffer_len);
7163
0
    if (key_len < max_counter * HashLen) {
7164
0
        PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len);
7165
0
    }
7166
0
    *key = output_buffer;
7167
7168
0
    return CKR_OK;
7169
7170
0
loser:
7171
0
    if (buffer) {
7172
0
        PORT_ZFree(buffer, buffer_len);
7173
0
    }
7174
0
    if (output_buffer) {
7175
0
        PORT_ZFree(output_buffer, max_counter * HashLen);
7176
0
    }
7177
0
    return crv;
7178
0
}
7179
7180
static CK_RV
7181
sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len,
7182
                    SECItem *SharedSecret,
7183
                    CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
7184
                    CK_EC_KDF_TYPE kdf)
7185
0
{
7186
0
    if (kdf == CKD_SHA1_KDF)
7187
0
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
7188
0
                                           SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH);
7189
0
    else if (kdf == CKD_SHA224_KDF)
7190
0
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
7191
0
                                           SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH);
7192
0
    else if (kdf == CKD_SHA256_KDF)
7193
0
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
7194
0
                                           SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH);
7195
0
    else if (kdf == CKD_SHA384_KDF)
7196
0
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
7197
0
                                           SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH);
7198
0
    else if (kdf == CKD_SHA512_KDF)
7199
0
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
7200
0
                                           SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH);
7201
0
    else
7202
0
        return CKR_MECHANISM_INVALID;
7203
0
}
7204
7205
/*
7206
 *  Handle the derive from a block encryption cipher
7207
 */
7208
CK_RV
7209
sftk_DeriveEncrypt(SFTKCipher encrypt, void *cipherInfo,
7210
                   int blockSize, SFTKObject *key, CK_ULONG keySize,
7211
                   unsigned char *data, CK_ULONG len)
7212
0
{
7213
    /* large enough for a 512-bit key */
7214
0
    unsigned char tmpdata[SFTK_MAX_DERIVE_KEY_SIZE];
7215
0
    SECStatus rv;
7216
0
    unsigned int outLen;
7217
0
    CK_RV crv;
7218
7219
0
    if ((len % blockSize) != 0) {
7220
0
        return CKR_MECHANISM_PARAM_INVALID;
7221
0
    }
7222
0
    if (len > SFTK_MAX_DERIVE_KEY_SIZE) {
7223
0
        return CKR_MECHANISM_PARAM_INVALID;
7224
0
    }
7225
0
    if (keySize && (len < keySize)) {
7226
0
        return CKR_MECHANISM_PARAM_INVALID;
7227
0
    }
7228
0
    if (keySize == 0) {
7229
0
        keySize = len;
7230
0
    }
7231
7232
0
    rv = (*encrypt)(cipherInfo, (unsigned char *)&tmpdata, &outLen, len, data, len);
7233
0
    if (rv != SECSuccess) {
7234
0
        crv = sftk_MapCryptError(PORT_GetError());
7235
0
        return crv;
7236
0
    }
7237
7238
0
    crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize);
7239
0
    PORT_Memset(tmpdata, 0, sizeof tmpdata);
7240
0
    return crv;
7241
0
}
7242
7243
CK_RV
7244
sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession,
7245
          SFTKObject *sourceKey, const unsigned char *sourceKeyBytes,
7246
          int sourceKeyLen, SFTKObject *key, unsigned char *outKeyBytes,
7247
          int keySize, PRBool canBeData, PRBool isFIPS)
7248
52
{
7249
52
    SFTKSession *session;
7250
52
    SFTKAttribute *saltKey_att = NULL;
7251
52
    const SECHashObject *rawHash;
7252
52
    unsigned hashLen;
7253
52
    unsigned genLen = 0;
7254
52
    unsigned char hashbuf[HASH_LENGTH_MAX];
7255
52
    unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH];
7256
52
    unsigned char *keyBlockAlloc = NULL;    /* allocated keyBlock */
7257
52
    unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */
7258
52
    const unsigned char *prk;               /* psuedo-random key */
7259
52
    CK_ULONG prkLen;
7260
52
    const unsigned char *okm; /* output keying material */
7261
52
    HASH_HashType hashType = sftk_GetHashTypeFromMechanism(params->prfHashMechanism);
7262
52
    SFTKObject *saltKey = NULL;
7263
52
    CK_RV crv = CKR_OK;
7264
7265
    /* Spec says it should be the base hash, but also accept the HMAC */
7266
52
    if (hashType == HASH_AlgNULL) {
7267
0
        hashType = sftk_HMACMechanismToHash(params->prfHashMechanism);
7268
0
    }
7269
52
    rawHash = HASH_GetRawHashObject(hashType);
7270
52
    if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) {
7271
0
        return CKR_MECHANISM_INVALID;
7272
0
    }
7273
52
    hashLen = rawHash->length;
7274
7275
52
    if ((!params->bExpand && !params->bExtract) ||
7276
52
        (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) ||
7277
52
        (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) {
7278
0
        return CKR_MECHANISM_PARAM_INVALID;
7279
0
    }
7280
52
    if ((params->bExpand && keySize == 0) ||
7281
52
        (!params->bExpand && keySize > hashLen) ||
7282
52
        (params->bExpand && keySize > 255 * hashLen)) {
7283
9
        return CKR_TEMPLATE_INCONSISTENT;
7284
9
    }
7285
7286
    /* sourceKey is NULL if we are called from the POST, skip the
7287
     * sensitiveCheck */
7288
43
    if (sourceKey != NULL) {
7289
43
        crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData);
7290
43
        if (crv != CKR_OK)
7291
0
            return crv;
7292
43
    }
7293
7294
    /* HKDF-Extract(salt, base key value) */
7295
43
    if (params->bExtract) {
7296
43
        CK_BYTE *salt;
7297
43
        CK_ULONG saltLen;
7298
43
        HMACContext *hmac;
7299
43
        unsigned int bufLen;
7300
7301
43
        switch (params->ulSaltType) {
7302
5
            case CKF_HKDF_SALT_NULL:
7303
5
                saltLen = hashLen;
7304
5
                salt = hashbuf;
7305
5
                memset(salt, 0, saltLen);
7306
5
                break;
7307
38
            case CKF_HKDF_SALT_DATA:
7308
38
                salt = params->pSalt;
7309
38
                saltLen = params->ulSaltLen;
7310
38
                if ((salt == NULL) || (params->ulSaltLen == 0)) {
7311
0
                    return CKR_MECHANISM_PARAM_INVALID;
7312
0
                }
7313
38
                break;
7314
38
            case CKF_HKDF_SALT_KEY:
7315
                /* lookup key */
7316
0
                session = sftk_SessionFromHandle(hSession);
7317
0
                if (session == NULL) {
7318
0
                    return CKR_SESSION_HANDLE_INVALID;
7319
0
                }
7320
7321
0
                saltKey = sftk_ObjectFromHandle(params->hSaltKey, session);
7322
0
                sftk_FreeSession(session);
7323
0
                if (saltKey == NULL) {
7324
0
                    return CKR_KEY_HANDLE_INVALID;
7325
0
                }
7326
                /* if the base key is not fips, but the salt key is, the
7327
                 * resulting key can be fips */
7328
0
                if (isFIPS && (key->isFIPS == 0) && (saltKey->isFIPS == 1)) {
7329
0
                    CK_MECHANISM mech;
7330
0
                    mech.mechanism = CKM_HKDF_DERIVE;
7331
0
                    mech.pParameter = params;
7332
0
                    mech.ulParameterLen = sizeof(*params);
7333
0
                    key->isFIPS = sftk_operationIsFIPS(saltKey->slot, &mech,
7334
0
                                                       CKA_DERIVE, saltKey);
7335
0
                }
7336
0
                saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE);
7337
0
                if (saltKey_att == NULL) {
7338
0
                    sftk_FreeObject(saltKey);
7339
0
                    return CKR_KEY_HANDLE_INVALID;
7340
0
                }
7341
                /* save the resulting salt */
7342
0
                salt = saltKey_att->attrib.pValue;
7343
0
                saltLen = saltKey_att->attrib.ulValueLen;
7344
0
                break;
7345
0
            default:
7346
0
                return CKR_MECHANISM_PARAM_INVALID;
7347
0
                break;
7348
43
        }
7349
7350
43
        hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
7351
43
        if (saltKey_att) {
7352
0
            sftk_FreeAttribute(saltKey_att);
7353
0
        }
7354
43
        if (saltKey) {
7355
0
            sftk_FreeObject(saltKey);
7356
0
        }
7357
43
        if (!hmac) {
7358
0
            return CKR_HOST_MEMORY;
7359
0
        }
7360
43
        HMAC_Begin(hmac);
7361
43
        HMAC_Update(hmac, sourceKeyBytes, sourceKeyLen);
7362
43
        HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf));
7363
43
        HMAC_Destroy(hmac, PR_TRUE);
7364
43
        PORT_Assert(bufLen == rawHash->length);
7365
43
        prk = hashbuf;
7366
43
        prkLen = bufLen;
7367
43
    } else {
7368
        /* PRK = base key value */
7369
0
        prk = sourceKeyBytes;
7370
0
        prkLen = sourceKeyLen;
7371
0
    }
7372
7373
    /* HKDF-Expand */
7374
43
    if (!params->bExpand) {
7375
0
        okm = prk;
7376
0
        keySize = genLen = hashLen;
7377
43
    } else {
7378
        /* T(1) = HMAC-Hash(prk, "" | info | 0x01)
7379
         * T(n) = HMAC-Hash(prk, T(n-1) | info | n
7380
         * key material = T(1) | ... | T(n)
7381
         */
7382
43
        HMACContext *hmac;
7383
43
        CK_BYTE bi;
7384
43
        unsigned iterations;
7385
7386
43
        genLen = PR_ROUNDUP(keySize, hashLen);
7387
43
        iterations = genLen / hashLen;
7388
7389
43
        if (genLen > sizeof(keyBlock)) {
7390
40
            keyBlockAlloc = PORT_Alloc(genLen);
7391
40
            if (keyBlockAlloc == NULL) {
7392
0
                return CKR_HOST_MEMORY;
7393
0
            }
7394
40
            keyBlockData = keyBlockAlloc;
7395
40
        }
7396
43
        hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS);
7397
43
        if (hmac == NULL) {
7398
0
            PORT_Free(keyBlockAlloc);
7399
0
            return CKR_HOST_MEMORY;
7400
0
        }
7401
5.54k
        for (bi = 1; bi <= iterations && bi > 0; ++bi) {
7402
5.50k
            unsigned len;
7403
5.50k
            HMAC_Begin(hmac);
7404
5.50k
            if (bi > 1) {
7405
5.46k
                HMAC_Update(hmac, &keyBlockData[(bi - 2) * hashLen], hashLen);
7406
5.46k
            }
7407
5.50k
            if (params->ulInfoLen != 0) {
7408
5.50k
                HMAC_Update(hmac, params->pInfo, params->ulInfoLen);
7409
5.50k
            }
7410
5.50k
            HMAC_Update(hmac, &bi, 1);
7411
5.50k
            HMAC_Finish(hmac, &keyBlockData[(bi - 1) * hashLen], &len,
7412
5.50k
                        hashLen);
7413
5.50k
            PORT_Assert(len == hashLen);
7414
5.50k
        }
7415
43
        HMAC_Destroy(hmac, PR_TRUE);
7416
43
        okm = &keyBlockData[0];
7417
43
    }
7418
    /* key material = okm */
7419
43
    crv = CKR_OK;
7420
43
    if (key) {
7421
43
        crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize);
7422
43
    } else {
7423
0
        PORT_Assert(outKeyBytes != NULL);
7424
0
        PORT_Memcpy(outKeyBytes, okm, keySize);
7425
0
    }
7426
43
    PORT_Memset(keyBlockData, 0, genLen);
7427
43
    PORT_Memset(hashbuf, 0, sizeof(hashbuf));
7428
43
    PORT_Free(keyBlockAlloc);
7429
43
    return crv;
7430
43
}
7431
7432
/*
7433
 * SSL Key generation given pre master secret
7434
 */
7435
0
#define NUM_MIXERS 9
7436
static const char *const mixers[NUM_MIXERS] = {
7437
    "A",
7438
    "BB",
7439
    "CCC",
7440
    "DDDD",
7441
    "EEEEE",
7442
    "FFFFFF",
7443
    "GGGGGGG",
7444
    "HHHHHHHH",
7445
    "IIIIIIIII"
7446
};
7447
0
#define SSL3_PMS_LENGTH 48
7448
0
#define SSL3_MASTER_SECRET_LENGTH 48
7449
0
#define SSL3_RANDOM_LENGTH 32
7450
7451
/* NSC_DeriveKey derives a key from a base key, creating a new key object. */
7452
CK_RV
7453
NSC_DeriveKey(CK_SESSION_HANDLE hSession,
7454
              CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
7455
              CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
7456
              CK_OBJECT_HANDLE_PTR phKey)
7457
52
{
7458
52
    SFTKSession *session;
7459
52
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
7460
52
    SFTKObject *key;
7461
52
    SFTKObject *sourceKey;
7462
52
    SFTKAttribute *att = NULL;
7463
52
    SFTKAttribute *att2 = NULL;
7464
52
    unsigned char *buf;
7465
52
    SHA1Context *sha;
7466
52
    MD5Context *md5;
7467
52
    MD2Context *md2;
7468
52
    CK_ULONG macSize;
7469
52
    CK_ULONG tmpKeySize;
7470
52
    CK_ULONG IVSize;
7471
52
    CK_ULONG keySize = 0;
7472
52
    CK_RV crv = CKR_OK;
7473
52
    CK_BBOOL cktrue = CK_TRUE;
7474
52
    CK_BBOOL ckfalse = CK_FALSE;
7475
52
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
7476
52
    CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
7477
52
    CK_KEY_DERIVATION_STRING_DATA *stringPtr;
7478
52
    PRBool isTLS = PR_FALSE;
7479
52
    PRBool isDH = PR_FALSE;
7480
52
    HASH_HashType tlsPrfHash = HASH_AlgNULL;
7481
52
    SECStatus rv;
7482
52
    int i;
7483
52
    unsigned int outLen;
7484
52
    unsigned char sha_out[SHA1_LENGTH];
7485
52
    unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH];
7486
52
    PRBool isFIPS;
7487
52
    HASH_HashType hashType;
7488
52
    CK_MECHANISM_TYPE hashMech;
7489
52
    PRBool extractValue = PR_TRUE;
7490
52
    CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS ikeAppB;
7491
52
    CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *pIkeAppB;
7492
7493
52
    CHECK_FORK();
7494
7495
52
    if (!slot) {
7496
0
        return CKR_SESSION_HANDLE_INVALID;
7497
0
    }
7498
52
    if (!pMechanism) {
7499
0
        return CKR_MECHANISM_PARAM_INVALID;
7500
0
    }
7501
52
    CK_MECHANISM_TYPE mechanism = pMechanism->mechanism;
7502
7503
    /*
7504
     * now lets create an object to hang the attributes off of
7505
     */
7506
52
    if (phKey) {
7507
52
        *phKey = CK_INVALID_HANDLE;
7508
52
    }
7509
7510
52
    key = sftk_NewObject(slot); /* fill in the handle later */
7511
52
    if (key == NULL) {
7512
0
        return CKR_HOST_MEMORY;
7513
0
    }
7514
52
    isFIPS = sftk_isFIPS(slot->slotID);
7515
7516
    /*
7517
     * load the template values into the object
7518
     */
7519
260
    for (i = 0; i < (int)ulAttributeCount; i++) {
7520
208
        crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
7521
208
        if (crv != CKR_OK)
7522
0
            break;
7523
7524
208
        if (pTemplate[i].type == CKA_KEY_TYPE) {
7525
52
            keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue;
7526
52
        }
7527
208
        if (pTemplate[i].type == CKA_VALUE_LEN) {
7528
52
            keySize = *(CK_ULONG *)pTemplate[i].pValue;
7529
52
        }
7530
208
    }
7531
52
    if (crv != CKR_OK) {
7532
0
        sftk_FreeObject(key);
7533
0
        return crv;
7534
0
    }
7535
7536
52
    if (keySize == 0) {
7537
0
        keySize = sftk_MapKeySize(keyType);
7538
0
    }
7539
7540
52
    switch (mechanism) {
7541
0
        case CKM_NSS_JPAKE_ROUND2_SHA1:   /* fall through */
7542
0
        case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */
7543
0
        case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */
7544
0
        case CKM_NSS_JPAKE_ROUND2_SHA512:
7545
0
            extractValue = PR_FALSE;
7546
0
            classType = CKO_PRIVATE_KEY;
7547
0
            break;
7548
0
        case CKM_NSS_PUB_FROM_PRIV:
7549
0
            extractValue = PR_FALSE;
7550
0
            classType = CKO_PUBLIC_KEY;
7551
0
            break;
7552
0
        case CKM_HKDF_DATA:                              /* fall through */
7553
0
        case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA:  /* fall through */
7554
0
        case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */
7555
0
        case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA:
7556
0
            classType = CKO_DATA;
7557
0
            break;
7558
0
        case CKM_NSS_JPAKE_FINAL_SHA1:   /* fall through */
7559
0
        case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
7560
0
        case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
7561
0
        case CKM_NSS_JPAKE_FINAL_SHA512:
7562
0
            extractValue = PR_FALSE;
7563
        /* fall through */
7564
52
        default:
7565
52
            classType = CKO_SECRET_KEY;
7566
52
    }
7567
7568
52
    crv = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType));
7569
52
    if (crv != CKR_OK) {
7570
0
        sftk_FreeObject(key);
7571
0
        return crv;
7572
0
    }
7573
7574
    /* look up the base key we're deriving with */
7575
52
    session = sftk_SessionFromHandle(hSession);
7576
52
    if (session == NULL) {
7577
0
        sftk_FreeObject(key);
7578
0
        return CKR_SESSION_HANDLE_INVALID;
7579
0
    }
7580
7581
52
    sourceKey = sftk_ObjectFromHandle(hBaseKey, session);
7582
52
    sftk_FreeSession(session);
7583
    /* is this eventually succeeds, lastOpWasFIPS will be set the resulting key's
7584
     * FIPS state below. */
7585
52
    session->lastOpWasFIPS = PR_FALSE;
7586
52
    if (sourceKey == NULL) {
7587
0
        sftk_FreeObject(key);
7588
0
        return CKR_KEY_HANDLE_INVALID;
7589
0
    }
7590
7591
52
    if (extractValue) {
7592
        /* get the value of the base key */
7593
52
        att = sftk_FindAttribute(sourceKey, CKA_VALUE);
7594
52
        if (att == NULL) {
7595
0
            sftk_FreeObject(key);
7596
0
            sftk_FreeObject(sourceKey);
7597
0
            return CKR_KEY_HANDLE_INVALID;
7598
0
        }
7599
52
    }
7600
52
    key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DERIVE, sourceKey);
7601
7602
52
    switch (mechanism) {
7603
        /* get a public key from a private key. nsslowkey_ConvertToPublickey()
7604
         * will generate the public portion if it doesn't already exist. */
7605
0
        case CKM_NSS_PUB_FROM_PRIV: {
7606
0
            NSSLOWKEYPrivateKey *privKey;
7607
0
            NSSLOWKEYPublicKey *pubKey;
7608
0
            int error;
7609
7610
0
            crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType);
7611
0
            if (crv != CKR_OK) {
7612
0
                break;
7613
0
            }
7614
7615
            /* privKey is stored in sourceKey and will be destroyed when
7616
             * the sourceKey is freed. */
7617
0
            privKey = sftk_GetPrivKey(sourceKey, keyType, &crv);
7618
0
            if (privKey == NULL) {
7619
0
                break;
7620
0
            }
7621
0
            pubKey = nsslowkey_ConvertToPublicKey(privKey);
7622
0
            if (pubKey == NULL) {
7623
0
                error = PORT_GetError();
7624
0
                crv = sftk_MapCryptError(error);
7625
0
                break;
7626
0
            }
7627
0
            crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey);
7628
0
            nsslowkey_DestroyPublicKey(pubKey);
7629
0
            break;
7630
0
        }
7631
0
        case CKM_NSS_IKE_PRF_DERIVE:
7632
0
            if (pMechanism->ulParameterLen !=
7633
0
                sizeof(CK_NSS_IKE_PRF_DERIVE_PARAMS)) {
7634
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7635
0
                break;
7636
0
            }
7637
0
            crv = sftk_ike_prf(hSession, att,
7638
0
                               (CK_NSS_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key);
7639
0
            break;
7640
0
        case CKM_NSS_IKE1_PRF_DERIVE:
7641
0
            if (pMechanism->ulParameterLen !=
7642
0
                sizeof(CK_NSS_IKE1_PRF_DERIVE_PARAMS)) {
7643
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7644
0
                break;
7645
0
            }
7646
0
            crv = sftk_ike1_prf(hSession, att,
7647
0
                                (CK_NSS_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter,
7648
0
                                key, keySize);
7649
0
            break;
7650
0
        case CKM_NSS_IKE1_APP_B_PRF_DERIVE:
7651
0
            pIkeAppB = (CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *)pMechanism->pParameter;
7652
0
            if (pMechanism->ulParameterLen ==
7653
0
                sizeof(CK_MECHANISM_TYPE)) {
7654
0
                ikeAppB.prfMechanism = *(CK_MECHANISM_TYPE *)pMechanism->pParameter;
7655
0
                ikeAppB.bHasKeygxy = PR_FALSE;
7656
0
                ikeAppB.hKeygxy = CK_INVALID_HANDLE;
7657
0
                ikeAppB.pExtraData = NULL;
7658
0
                ikeAppB.ulExtraDataLen = 0;
7659
0
                pIkeAppB = &ikeAppB;
7660
0
            } else if (pMechanism->ulParameterLen !=
7661
0
                       sizeof(CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS)) {
7662
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7663
0
                break;
7664
0
            }
7665
0
            crv = sftk_ike1_appendix_b_prf(hSession, att, pIkeAppB, key,
7666
0
                                           keySize);
7667
0
            break;
7668
0
        case CKM_NSS_IKE_PRF_PLUS_DERIVE:
7669
0
            if (pMechanism->ulParameterLen !=
7670
0
                sizeof(CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS)) {
7671
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7672
0
                break;
7673
0
            }
7674
0
            crv = sftk_ike_prf_plus(hSession, att,
7675
0
                                    (CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter,
7676
0
                                    key, keySize);
7677
0
            break;
7678
        /*
7679
         * generate the master secret
7680
         */
7681
0
        case CKM_TLS12_MASTER_KEY_DERIVE:
7682
0
        case CKM_TLS12_MASTER_KEY_DERIVE_DH:
7683
0
        case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256:
7684
0
        case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256:
7685
0
        case CKM_TLS_MASTER_KEY_DERIVE:
7686
0
        case CKM_TLS_MASTER_KEY_DERIVE_DH:
7687
0
        case CKM_SSL3_MASTER_KEY_DERIVE:
7688
0
        case CKM_SSL3_MASTER_KEY_DERIVE_DH: {
7689
0
            CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master;
7690
0
            SSL3RSAPreMasterSecret *rsa_pms;
7691
0
            unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
7692
7693
0
            if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) ||
7694
0
                (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
7695
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) {
7696
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
7697
0
                    break;
7698
0
                }
7699
0
                CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master =
7700
0
                    (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter;
7701
0
                tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_master->prfHashMechanism);
7702
0
                if (tlsPrfHash == HASH_AlgNULL) {
7703
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
7704
0
                    break;
7705
0
                }
7706
0
            } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) ||
7707
0
                       (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) {
7708
0
                tlsPrfHash = HASH_AlgSHA256;
7709
0
            }
7710
7711
0
            if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) &&
7712
0
                (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) {
7713
0
                isTLS = PR_TRUE;
7714
0
            }
7715
0
            if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) ||
7716
0
                (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) ||
7717
0
                (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) ||
7718
0
                (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
7719
0
                isDH = PR_TRUE;
7720
0
            }
7721
7722
            /* first do the consistency checks */
7723
0
            if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
7724
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
7725
0
                break;
7726
0
            }
7727
0
            att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
7728
0
            if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
7729
0
                                   CKK_GENERIC_SECRET)) {
7730
0
                if (att2)
7731
0
                    sftk_FreeAttribute(att2);
7732
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7733
0
                break;
7734
0
            }
7735
0
            sftk_FreeAttribute(att2);
7736
0
            if (keyType != CKK_GENERIC_SECRET) {
7737
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7738
0
                break;
7739
0
            }
7740
0
            if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
7741
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7742
0
                break;
7743
0
            }
7744
7745
            /* finally do the key gen */
7746
0
            ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)
7747
0
                              pMechanism->pParameter;
7748
7749
0
            if (ssl3_master->pVersion) {
7750
0
                SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
7751
0
                rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue;
7752
                /* don't leak more key material then necessary for SSL to work */
7753
0
                if ((sessKey == NULL) || sessKey->wasDerived) {
7754
0
                    ssl3_master->pVersion->major = 0xff;
7755
0
                    ssl3_master->pVersion->minor = 0xff;
7756
0
                } else {
7757
0
                    ssl3_master->pVersion->major = rsa_pms->client_version[0];
7758
0
                    ssl3_master->pVersion->minor = rsa_pms->client_version[1];
7759
0
                }
7760
0
            }
7761
0
            if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) {
7762
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7763
0
                break;
7764
0
            }
7765
0
            if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) {
7766
0
                crv = CKR_MECHANISM_PARAM_INVALID;
7767
0
                break;
7768
0
            }
7769
0
            PORT_Memcpy(crsrdata,
7770
0
                        ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
7771
0
            PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
7772
0
                        ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
7773
7774
0
            if (isTLS) {
7775
0
                SECStatus status;
7776
0
                SECItem crsr = { siBuffer, NULL, 0 };
7777
0
                SECItem master = { siBuffer, NULL, 0 };
7778
0
                SECItem pms = { siBuffer, NULL, 0 };
7779
7780
0
                crsr.data = crsrdata;
7781
0
                crsr.len = sizeof crsrdata;
7782
0
                master.data = key_block;
7783
0
                master.len = SSL3_MASTER_SECRET_LENGTH;
7784
0
                pms.data = (unsigned char *)att->attrib.pValue;
7785
0
                pms.len = att->attrib.ulValueLen;
7786
7787
0
                if (tlsPrfHash != HASH_AlgNULL) {
7788
0
                    status = TLS_P_hash(tlsPrfHash, &pms, "master secret",
7789
0
                                        &crsr, &master, isFIPS);
7790
0
                } else {
7791
0
                    status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS);
7792
0
                }
7793
0
                if (status != SECSuccess) {
7794
0
                    PORT_Memset(crsrdata, 0, sizeof crsrdata);
7795
0
                    crv = CKR_FUNCTION_FAILED;
7796
0
                    break;
7797
0
                }
7798
0
            } else {
7799
                /* now allocate the hash contexts */
7800
0
                md5 = MD5_NewContext();
7801
0
                if (md5 == NULL) {
7802
0
                    PORT_Memset(crsrdata, 0, sizeof crsrdata);
7803
0
                    crv = CKR_HOST_MEMORY;
7804
0
                    break;
7805
0
                }
7806
0
                sha = SHA1_NewContext();
7807
0
                if (sha == NULL) {
7808
0
                    PORT_Memset(crsrdata, 0, sizeof crsrdata);
7809
0
                    PORT_Free(md5);
7810
0
                    crv = CKR_HOST_MEMORY;
7811
0
                    break;
7812
0
                }
7813
0
                for (i = 0; i < 3; i++) {
7814
0
                    SHA1_Begin(sha);
7815
0
                    SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i]));
7816
0
                    SHA1_Update(sha, (const unsigned char *)att->attrib.pValue,
7817
0
                                att->attrib.ulValueLen);
7818
0
                    SHA1_Update(sha, crsrdata, sizeof crsrdata);
7819
0
                    SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
7820
0
                    PORT_Assert(outLen == SHA1_LENGTH);
7821
7822
0
                    MD5_Begin(md5);
7823
0
                    MD5_Update(md5, (const unsigned char *)att->attrib.pValue,
7824
0
                               att->attrib.ulValueLen);
7825
0
                    MD5_Update(md5, sha_out, outLen);
7826
0
                    MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH);
7827
0
                    PORT_Assert(outLen == MD5_LENGTH);
7828
0
                }
7829
0
                PORT_Free(md5);
7830
0
                PORT_Free(sha);
7831
0
                PORT_Memset(crsrdata, 0, sizeof crsrdata);
7832
0
                PORT_Memset(sha_out, 0, sizeof sha_out);
7833
0
            }
7834
7835
            /* store the results */
7836
0
            crv = sftk_forceAttribute(key, CKA_VALUE, key_block, SSL3_MASTER_SECRET_LENGTH);
7837
0
            PORT_Memset(key_block, 0, sizeof key_block);
7838
0
            if (crv != CKR_OK)
7839
0
                break;
7840
0
            keyType = CKK_GENERIC_SECRET;
7841
0
            crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType));
7842
0
            if (isTLS) {
7843
                /* TLS's master secret is used to "sign" finished msgs with PRF. */
7844
                /* XXX This seems like a hack.   But SFTK_Derive only accepts
7845
                 * one "operation" argument. */
7846
0
                crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
7847
0
                if (crv != CKR_OK)
7848
0
                    break;
7849
0
                crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
7850
0
                if (crv != CKR_OK)
7851
0
                    break;
7852
                /* While we're here, we might as well force this, too. */
7853
0
                crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
7854
0
                if (crv != CKR_OK)
7855
0
                    break;
7856
0
            }
7857
0
            break;
7858
0
        }
7859
7860
        /* Extended master key derivation [draft-ietf-tls-session-hash] */
7861
0
        case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE:
7862
0
        case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: {
7863
0
            CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params;
7864
0
            SSL3RSAPreMasterSecret *rsa_pms;
7865
0
            SECStatus status;
7866
0
            SECItem pms = { siBuffer, NULL, 0 };
7867
0
            SECItem seed = { siBuffer, NULL, 0 };
7868
0
            SECItem master = { siBuffer, NULL, 0 };
7869
7870
0
            ems_params = (CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *)
7871
0
                             pMechanism->pParameter;
7872
7873
            /* First do the consistency checks */
7874
0
            if ((mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE) &&
7875
0
                (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
7876
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
7877
0
                break;
7878
0
            }
7879
0
            att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
7880
0
            if ((att2 == NULL) ||
7881
0
                (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) {
7882
0
                if (att2)
7883
0
                    sftk_FreeAttribute(att2);
7884
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7885
0
                break;
7886
0
            }
7887
0
            sftk_FreeAttribute(att2);
7888
0
            if (keyType != CKK_GENERIC_SECRET) {
7889
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7890
0
                break;
7891
0
            }
7892
0
            if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
7893
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7894
0
                break;
7895
0
            }
7896
7897
            /* Do the key derivation */
7898
0
            pms.data = (unsigned char *)att->attrib.pValue;
7899
0
            pms.len = att->attrib.ulValueLen;
7900
0
            seed.data = ems_params->pSessionHash;
7901
0
            seed.len = ems_params->ulSessionHashLen;
7902
0
            master.data = key_block;
7903
0
            master.len = SSL3_MASTER_SECRET_LENGTH;
7904
0
            if (ems_params->prfHashMechanism == CKM_TLS_PRF) {
7905
                /*
7906
                 * In this case, the session hash is the concatenation of SHA-1
7907
                 * and MD5, so it should be 36 bytes long.
7908
                 */
7909
0
                if (seed.len != MD5_LENGTH + SHA1_LENGTH) {
7910
0
                    crv = CKR_TEMPLATE_INCONSISTENT;
7911
0
                    break;
7912
0
                }
7913
7914
0
                status = TLS_PRF(&pms, "extended master secret",
7915
0
                                 &seed, &master, isFIPS);
7916
0
            } else {
7917
0
                const SECHashObject *hashObj;
7918
7919
0
                tlsPrfHash = sftk_GetHashTypeFromMechanism(ems_params->prfHashMechanism);
7920
0
                if (tlsPrfHash == HASH_AlgNULL) {
7921
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
7922
0
                    break;
7923
0
                }
7924
7925
0
                hashObj = HASH_GetRawHashObject(tlsPrfHash);
7926
0
                if (seed.len != hashObj->length) {
7927
0
                    crv = CKR_TEMPLATE_INCONSISTENT;
7928
0
                    break;
7929
0
                }
7930
7931
0
                status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret",
7932
0
                                    &seed, &master, isFIPS);
7933
0
            }
7934
0
            if (status != SECSuccess) {
7935
0
                crv = CKR_FUNCTION_FAILED;
7936
0
                break;
7937
0
            }
7938
7939
            /* Reflect the version if required */
7940
0
            if (ems_params->pVersion) {
7941
0
                SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
7942
0
                rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue;
7943
                /* don't leak more key material than necessary for SSL to work */
7944
0
                if ((sessKey == NULL) || sessKey->wasDerived) {
7945
0
                    ems_params->pVersion->major = 0xff;
7946
0
                    ems_params->pVersion->minor = 0xff;
7947
0
                } else {
7948
0
                    ems_params->pVersion->major = rsa_pms->client_version[0];
7949
0
                    ems_params->pVersion->minor = rsa_pms->client_version[1];
7950
0
                }
7951
0
            }
7952
7953
            /* Store the results */
7954
0
            crv = sftk_forceAttribute(key, CKA_VALUE, key_block,
7955
0
                                      SSL3_MASTER_SECRET_LENGTH);
7956
0
            PORT_Memset(key_block, 0, sizeof key_block);
7957
0
            break;
7958
0
        }
7959
7960
0
        case CKM_TLS12_KEY_AND_MAC_DERIVE:
7961
0
        case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256:
7962
0
        case CKM_TLS_KEY_AND_MAC_DERIVE:
7963
0
        case CKM_SSL3_KEY_AND_MAC_DERIVE: {
7964
0
            CK_SSL3_KEY_MAT_PARAMS *ssl3_keys;
7965
0
            CK_SSL3_KEY_MAT_OUT *ssl3_keys_out;
7966
0
            CK_ULONG effKeySize;
7967
0
            unsigned int block_needed;
7968
0
            unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
7969
7970
0
            if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) {
7971
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) {
7972
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
7973
0
                    break;
7974
0
                }
7975
0
                CK_TLS12_KEY_MAT_PARAMS *tls12_keys =
7976
0
                    (CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter;
7977
0
                tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_keys->prfHashMechanism);
7978
0
                if (tlsPrfHash == HASH_AlgNULL) {
7979
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
7980
0
                    break;
7981
0
                }
7982
0
            } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) {
7983
0
                tlsPrfHash = HASH_AlgSHA256;
7984
0
            }
7985
7986
0
            if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) {
7987
0
                isTLS = PR_TRUE;
7988
0
            }
7989
7990
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
7991
0
            if (crv != CKR_OK)
7992
0
                break;
7993
7994
0
            if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) {
7995
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
7996
0
                break;
7997
0
            }
7998
0
            att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
7999
0
            if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
8000
0
                                   CKK_GENERIC_SECRET)) {
8001
0
                if (att2)
8002
0
                    sftk_FreeAttribute(att2);
8003
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
8004
0
                break;
8005
0
            }
8006
0
            sftk_FreeAttribute(att2);
8007
0
            md5 = MD5_NewContext();
8008
0
            if (md5 == NULL) {
8009
0
                crv = CKR_HOST_MEMORY;
8010
0
                break;
8011
0
            }
8012
0
            sha = SHA1_NewContext();
8013
0
            if (sha == NULL) {
8014
0
                MD5_DestroyContext(md5, PR_TRUE);
8015
0
                crv = CKR_HOST_MEMORY;
8016
0
                break;
8017
0
            }
8018
8019
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_SSL3_KEY_MAT_PARAMS))) {
8020
0
                MD5_DestroyContext(md5, PR_TRUE);
8021
0
                SHA1_DestroyContext(sha, PR_TRUE);
8022
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8023
0
                break;
8024
0
            }
8025
0
            ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter;
8026
8027
0
            PORT_Memcpy(srcrdata,
8028
0
                        ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
8029
0
            PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH,
8030
0
                        ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
8031
8032
            /*
8033
             * clear out our returned keys so we can recover on failure
8034
             */
8035
0
            ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;
8036
0
            ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE;
8037
0
            ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE;
8038
0
            ssl3_keys_out->hClientKey = CK_INVALID_HANDLE;
8039
0
            ssl3_keys_out->hServerKey = CK_INVALID_HANDLE;
8040
8041
            /*
8042
             * How much key material do we need?
8043
             */
8044
0
            macSize = ssl3_keys->ulMacSizeInBits / 8;
8045
0
            effKeySize = ssl3_keys->ulKeySizeInBits / 8;
8046
0
            IVSize = ssl3_keys->ulIVSizeInBits / 8;
8047
0
            if (keySize == 0) {
8048
0
                effKeySize = keySize;
8049
0
            }
8050
8051
            /* bIsExport must be false. */
8052
0
            if (ssl3_keys->bIsExport) {
8053
0
                MD5_DestroyContext(md5, PR_TRUE);
8054
0
                SHA1_DestroyContext(sha, PR_TRUE);
8055
0
                PORT_Memset(srcrdata, 0, sizeof srcrdata);
8056
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8057
0
                break;
8058
0
            }
8059
8060
0
            block_needed = 2 * (macSize + effKeySize + IVSize);
8061
0
            PORT_Assert(block_needed <= sizeof key_block);
8062
0
            if (block_needed > sizeof key_block)
8063
0
                block_needed = sizeof key_block;
8064
8065
            /*
8066
             * generate the key material: This looks amazingly similar to the
8067
             * PMS code, and is clearly crying out for a function to provide it.
8068
             */
8069
0
            if (isTLS) {
8070
0
                SECStatus status;
8071
0
                SECItem srcr = { siBuffer, NULL, 0 };
8072
0
                SECItem keyblk = { siBuffer, NULL, 0 };
8073
0
                SECItem master = { siBuffer, NULL, 0 };
8074
8075
0
                srcr.data = srcrdata;
8076
0
                srcr.len = sizeof srcrdata;
8077
0
                keyblk.data = key_block;
8078
0
                keyblk.len = block_needed;
8079
0
                master.data = (unsigned char *)att->attrib.pValue;
8080
0
                master.len = att->attrib.ulValueLen;
8081
8082
0
                if (tlsPrfHash != HASH_AlgNULL) {
8083
0
                    status = TLS_P_hash(tlsPrfHash, &master, "key expansion",
8084
0
                                        &srcr, &keyblk, isFIPS);
8085
0
                } else {
8086
0
                    status = TLS_PRF(&master, "key expansion", &srcr, &keyblk,
8087
0
                                     isFIPS);
8088
0
                }
8089
0
                if (status != SECSuccess) {
8090
0
                    goto key_and_mac_derive_fail;
8091
0
                }
8092
0
            } else {
8093
0
                unsigned int block_bytes = 0;
8094
                /* key_block =
8095
                 *     MD5(master_secret + SHA('A' + master_secret +
8096
                 *                      ServerHello.random + ClientHello.random)) +
8097
                 *     MD5(master_secret + SHA('BB' + master_secret +
8098
                 *                      ServerHello.random + ClientHello.random)) +
8099
                 *     MD5(master_secret + SHA('CCC' + master_secret +
8100
                 *                      ServerHello.random + ClientHello.random)) +
8101
                 *     [...];
8102
                 */
8103
0
                for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) {
8104
0
                    SHA1_Begin(sha);
8105
0
                    SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i]));
8106
0
                    SHA1_Update(sha, (const unsigned char *)att->attrib.pValue,
8107
0
                                att->attrib.ulValueLen);
8108
0
                    SHA1_Update(sha, srcrdata, sizeof srcrdata);
8109
0
                    SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
8110
0
                    PORT_Assert(outLen == SHA1_LENGTH);
8111
0
                    MD5_Begin(md5);
8112
0
                    MD5_Update(md5, (const unsigned char *)att->attrib.pValue,
8113
0
                               att->attrib.ulValueLen);
8114
0
                    MD5_Update(md5, sha_out, outLen);
8115
0
                    MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH);
8116
0
                    PORT_Assert(outLen == MD5_LENGTH);
8117
0
                    block_bytes += outLen;
8118
0
                }
8119
0
                PORT_Memset(sha_out, 0, sizeof sha_out);
8120
0
            }
8121
8122
            /*
8123
             * Put the key material where it goes.
8124
             */
8125
0
            i = 0; /* now shows how much consumed */
8126
8127
            /*
8128
             * The key_block is partitioned as follows:
8129
             * client_write_MAC_secret[CipherSpec.hash_size]
8130
             */
8131
0
            crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
8132
0
                                   &ssl3_keys_out->hClientMacSecret);
8133
0
            if (crv != CKR_OK)
8134
0
                goto key_and_mac_derive_fail;
8135
8136
0
            i += macSize;
8137
8138
            /*
8139
             * server_write_MAC_secret[CipherSpec.hash_size]
8140
             */
8141
0
            crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
8142
0
                                   &ssl3_keys_out->hServerMacSecret);
8143
0
            if (crv != CKR_OK) {
8144
0
                goto key_and_mac_derive_fail;
8145
0
            }
8146
0
            i += macSize;
8147
8148
0
            if (keySize) {
8149
                /*
8150
                ** Generate Domestic write keys and IVs.
8151
                ** client_write_key[CipherSpec.key_material]
8152
                */
8153
0
                crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
8154
0
                                       keySize, &ssl3_keys_out->hClientKey);
8155
0
                if (crv != CKR_OK) {
8156
0
                    goto key_and_mac_derive_fail;
8157
0
                }
8158
0
                i += keySize;
8159
8160
                /*
8161
                ** server_write_key[CipherSpec.key_material]
8162
                */
8163
0
                crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
8164
0
                                       keySize, &ssl3_keys_out->hServerKey);
8165
0
                if (crv != CKR_OK) {
8166
0
                    goto key_and_mac_derive_fail;
8167
0
                }
8168
0
                i += keySize;
8169
8170
                /*
8171
                ** client_write_IV[CipherSpec.IV_size]
8172
                */
8173
0
                if (IVSize > 0) {
8174
0
                    PORT_Memcpy(ssl3_keys_out->pIVClient,
8175
0
                                &key_block[i], IVSize);
8176
0
                    i += IVSize;
8177
0
                }
8178
8179
                /*
8180
                ** server_write_IV[CipherSpec.IV_size]
8181
                */
8182
0
                if (IVSize > 0) {
8183
0
                    PORT_Memcpy(ssl3_keys_out->pIVServer,
8184
0
                                &key_block[i], IVSize);
8185
0
                    i += IVSize;
8186
0
                }
8187
0
                PORT_Assert(i <= sizeof key_block);
8188
0
            }
8189
8190
0
            crv = CKR_OK;
8191
8192
0
            if (0) {
8193
0
            key_and_mac_derive_fail:
8194
0
                if (crv == CKR_OK)
8195
0
                    crv = CKR_FUNCTION_FAILED;
8196
0
                sftk_freeSSLKeys(hSession, ssl3_keys_out);
8197
0
            }
8198
0
            PORT_Memset(srcrdata, 0, sizeof srcrdata);
8199
0
            PORT_Memset(key_block, 0, sizeof key_block);
8200
0
            MD5_DestroyContext(md5, PR_TRUE);
8201
0
            SHA1_DestroyContext(sha, PR_TRUE);
8202
0
            sftk_FreeObject(key);
8203
0
            key = NULL;
8204
0
            break;
8205
0
        }
8206
8207
0
        case CKM_DES3_ECB_ENCRYPT_DATA:
8208
0
        case CKM_DES3_CBC_ENCRYPT_DATA: {
8209
0
            void *cipherInfo;
8210
0
            unsigned char des3key[MAX_DES3_KEY_SIZE];
8211
0
            CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr;
8212
0
            int mode;
8213
0
            unsigned char *iv;
8214
0
            unsigned char *data;
8215
0
            CK_ULONG len;
8216
8217
0
            if (mechanism == CKM_DES3_ECB_ENCRYPT_DATA) {
8218
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8219
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8220
0
                    break;
8221
0
                }
8222
0
                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
8223
0
                                pMechanism->pParameter;
8224
0
                mode = NSS_DES_EDE3;
8225
0
                iv = NULL;
8226
0
                data = stringPtr->pData;
8227
0
                len = stringPtr->ulLen;
8228
0
            } else {
8229
0
                mode = NSS_DES_EDE3_CBC;
8230
0
                desEncryptPtr =
8231
0
                    (CK_DES_CBC_ENCRYPT_DATA_PARAMS *)
8232
0
                        pMechanism->pParameter;
8233
0
                iv = desEncryptPtr->iv;
8234
0
                data = desEncryptPtr->pData;
8235
0
                len = desEncryptPtr->length;
8236
0
            }
8237
0
            if (att->attrib.ulValueLen == 16) {
8238
0
                PORT_Memcpy(des3key, att->attrib.pValue, 16);
8239
0
                PORT_Memcpy(des3key + 16, des3key, 8);
8240
0
            } else if (att->attrib.ulValueLen == 24) {
8241
0
                PORT_Memcpy(des3key, att->attrib.pValue, 24);
8242
0
            } else {
8243
0
                crv = CKR_KEY_SIZE_RANGE;
8244
0
                break;
8245
0
            }
8246
0
            cipherInfo = DES_CreateContext(des3key, iv, mode, PR_TRUE);
8247
0
            PORT_Memset(des3key, 0, 24);
8248
0
            if (cipherInfo == NULL) {
8249
0
                crv = CKR_HOST_MEMORY;
8250
0
                break;
8251
0
            }
8252
0
            crv = sftk_DeriveEncrypt(SFTKCipher_DES_Encrypt,
8253
0
                                     cipherInfo, 8, key, keySize,
8254
0
                                     data, len);
8255
0
            DES_DestroyContext(cipherInfo, PR_TRUE);
8256
0
            break;
8257
0
        }
8258
8259
0
        case CKM_AES_ECB_ENCRYPT_DATA:
8260
0
        case CKM_AES_CBC_ENCRYPT_DATA: {
8261
0
            void *cipherInfo;
8262
0
            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
8263
0
            int mode;
8264
0
            unsigned char *iv;
8265
0
            unsigned char *data;
8266
0
            CK_ULONG len;
8267
8268
0
            if (mechanism == CKM_AES_ECB_ENCRYPT_DATA) {
8269
0
                mode = NSS_AES;
8270
0
                iv = NULL;
8271
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8272
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8273
0
                    break;
8274
0
                }
8275
0
                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8276
0
                data = stringPtr->pData;
8277
0
                len = stringPtr->ulLen;
8278
0
            } else {
8279
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
8280
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8281
0
                    break;
8282
0
                }
8283
0
                aesEncryptPtr =
8284
0
                    (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)pMechanism->pParameter;
8285
0
                mode = NSS_AES_CBC;
8286
0
                iv = aesEncryptPtr->iv;
8287
0
                data = aesEncryptPtr->pData;
8288
0
                len = aesEncryptPtr->length;
8289
0
            }
8290
8291
0
            cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue,
8292
0
                                           iv, mode, PR_TRUE,
8293
0
                                           att->attrib.ulValueLen, 16);
8294
0
            if (cipherInfo == NULL) {
8295
0
                crv = CKR_HOST_MEMORY;
8296
0
                break;
8297
0
            }
8298
0
            crv = sftk_DeriveEncrypt(SFTKCipher_AES_Encrypt,
8299
0
                                     cipherInfo, 16, key, keySize,
8300
0
                                     data, len);
8301
0
            AES_DestroyContext(cipherInfo, PR_TRUE);
8302
0
            break;
8303
0
        }
8304
8305
0
        case CKM_CAMELLIA_ECB_ENCRYPT_DATA:
8306
0
        case CKM_CAMELLIA_CBC_ENCRYPT_DATA: {
8307
0
            void *cipherInfo;
8308
0
            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
8309
0
            int mode;
8310
0
            unsigned char *iv;
8311
0
            unsigned char *data;
8312
0
            CK_ULONG len;
8313
8314
0
            if (mechanism == CKM_CAMELLIA_ECB_ENCRYPT_DATA) {
8315
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8316
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8317
0
                    break;
8318
0
                }
8319
0
                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
8320
0
                                pMechanism->pParameter;
8321
0
                aesEncryptPtr = NULL;
8322
0
                mode = NSS_CAMELLIA;
8323
0
                data = stringPtr->pData;
8324
0
                len = stringPtr->ulLen;
8325
0
                iv = NULL;
8326
0
            } else {
8327
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
8328
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8329
0
                    break;
8330
0
                }
8331
0
                stringPtr = NULL;
8332
0
                aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
8333
0
                                    pMechanism->pParameter;
8334
0
                mode = NSS_CAMELLIA_CBC;
8335
0
                iv = aesEncryptPtr->iv;
8336
0
                data = aesEncryptPtr->pData;
8337
0
                len = aesEncryptPtr->length;
8338
0
            }
8339
8340
0
            cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue,
8341
0
                                                iv, mode, PR_TRUE,
8342
0
                                                att->attrib.ulValueLen);
8343
0
            if (cipherInfo == NULL) {
8344
0
                crv = CKR_HOST_MEMORY;
8345
0
                break;
8346
0
            }
8347
0
            crv = sftk_DeriveEncrypt(SFTKCipher_Camellia_Encrypt,
8348
0
                                     cipherInfo, 16, key, keySize,
8349
0
                                     data, len);
8350
0
            Camellia_DestroyContext(cipherInfo, PR_TRUE);
8351
0
            break;
8352
0
        }
8353
8354
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
8355
0
        case CKM_SEED_ECB_ENCRYPT_DATA:
8356
0
        case CKM_SEED_CBC_ENCRYPT_DATA: {
8357
0
            void *cipherInfo;
8358
0
            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
8359
0
            int mode;
8360
0
            unsigned char *iv;
8361
0
            unsigned char *data;
8362
0
            CK_ULONG len;
8363
8364
0
            if (mechanism == CKM_SEED_ECB_ENCRYPT_DATA) {
8365
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8366
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8367
0
                    break;
8368
0
                }
8369
0
                mode = NSS_SEED;
8370
0
                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
8371
0
                                pMechanism->pParameter;
8372
0
                aesEncryptPtr = NULL;
8373
0
                data = stringPtr->pData;
8374
0
                len = stringPtr->ulLen;
8375
0
                iv = NULL;
8376
0
            } else {
8377
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
8378
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8379
0
                    break;
8380
0
                }
8381
0
                mode = NSS_SEED_CBC;
8382
0
                aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
8383
0
                                    pMechanism->pParameter;
8384
0
                iv = aesEncryptPtr->iv;
8385
0
                data = aesEncryptPtr->pData;
8386
0
                len = aesEncryptPtr->length;
8387
0
            }
8388
8389
0
            cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue,
8390
0
                                            iv, mode, PR_TRUE);
8391
0
            if (cipherInfo == NULL) {
8392
0
                crv = CKR_HOST_MEMORY;
8393
0
                break;
8394
0
            }
8395
0
            crv = sftk_DeriveEncrypt(SFTKCipher_SEED_Encrypt,
8396
0
                                     cipherInfo, 16, key, keySize,
8397
0
                                     data, len);
8398
0
            SEED_DestroyContext(cipherInfo, PR_TRUE);
8399
0
            break;
8400
0
        }
8401
0
#endif /* NSS_DISABLE_DEPRECATED_SEED */
8402
8403
0
        case CKM_CONCATENATE_BASE_AND_KEY: {
8404
0
            SFTKObject *paramKey;
8405
8406
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8407
0
            if (crv != CKR_OK)
8408
0
                break;
8409
8410
0
            session = sftk_SessionFromHandle(hSession);
8411
0
            if (session == NULL) {
8412
0
                crv = CKR_SESSION_HANDLE_INVALID;
8413
0
                break;
8414
0
            }
8415
8416
0
            paramKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *)
8417
0
                                                  pMechanism->pParameter,
8418
0
                                             session);
8419
0
            sftk_FreeSession(session);
8420
0
            if (paramKey == NULL) {
8421
0
                crv = CKR_KEY_HANDLE_INVALID;
8422
0
                break;
8423
0
            }
8424
8425
0
            if (sftk_isTrue(paramKey, CKA_SENSITIVE)) {
8426
0
                crv = sftk_forceAttribute(key, CKA_SENSITIVE, &cktrue,
8427
0
                                          sizeof(CK_BBOOL));
8428
0
                if (crv != CKR_OK) {
8429
0
                    sftk_FreeObject(paramKey);
8430
0
                    break;
8431
0
                }
8432
0
            }
8433
8434
0
            if (sftk_hasAttribute(paramKey, CKA_EXTRACTABLE) && !sftk_isTrue(paramKey, CKA_EXTRACTABLE)) {
8435
0
                crv = sftk_forceAttribute(key, CKA_EXTRACTABLE, &ckfalse, sizeof(CK_BBOOL));
8436
0
                if (crv != CKR_OK) {
8437
0
                    sftk_FreeObject(paramKey);
8438
0
                    break;
8439
0
                }
8440
0
            }
8441
8442
0
            att2 = sftk_FindAttribute(paramKey, CKA_VALUE);
8443
0
            if (att2 == NULL) {
8444
0
                sftk_FreeObject(paramKey);
8445
0
                crv = CKR_KEY_HANDLE_INVALID;
8446
0
                break;
8447
0
            }
8448
0
            tmpKeySize = att->attrib.ulValueLen + att2->attrib.ulValueLen;
8449
0
            if (keySize == 0)
8450
0
                keySize = tmpKeySize;
8451
0
            if (keySize > tmpKeySize) {
8452
0
                sftk_FreeObject(paramKey);
8453
0
                sftk_FreeAttribute(att2);
8454
0
                crv = CKR_TEMPLATE_INCONSISTENT;
8455
0
                break;
8456
0
            }
8457
0
            buf = (unsigned char *)PORT_Alloc(tmpKeySize);
8458
0
            if (buf == NULL) {
8459
0
                sftk_FreeAttribute(att2);
8460
0
                sftk_FreeObject(paramKey);
8461
0
                crv = CKR_HOST_MEMORY;
8462
0
                break;
8463
0
            }
8464
8465
0
            PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
8466
0
            PORT_Memcpy(buf + att->attrib.ulValueLen,
8467
0
                        att2->attrib.pValue, att2->attrib.ulValueLen);
8468
8469
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8470
0
            PORT_ZFree(buf, tmpKeySize);
8471
0
            sftk_FreeAttribute(att2);
8472
0
            sftk_FreeObject(paramKey);
8473
0
            break;
8474
0
        }
8475
8476
0
        case CKM_CONCATENATE_BASE_AND_DATA:
8477
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8478
0
            if (crv != CKR_OK)
8479
0
                break;
8480
8481
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8482
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8483
0
                break;
8484
0
            }
8485
0
            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8486
0
            tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
8487
0
            if (keySize == 0)
8488
0
                keySize = tmpKeySize;
8489
0
            if (keySize > tmpKeySize) {
8490
0
                crv = CKR_TEMPLATE_INCONSISTENT;
8491
0
                break;
8492
0
            }
8493
0
            buf = (unsigned char *)PORT_Alloc(tmpKeySize);
8494
0
            if (buf == NULL) {
8495
0
                crv = CKR_HOST_MEMORY;
8496
0
                break;
8497
0
            }
8498
8499
0
            PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
8500
0
            PORT_Memcpy(buf + att->attrib.ulValueLen, stringPtr->pData,
8501
0
                        stringPtr->ulLen);
8502
8503
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8504
0
            PORT_ZFree(buf, tmpKeySize);
8505
0
            break;
8506
0
        case CKM_CONCATENATE_DATA_AND_BASE:
8507
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8508
0
            if (crv != CKR_OK)
8509
0
                break;
8510
8511
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8512
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8513
0
                break;
8514
0
            }
8515
0
            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8516
0
            tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
8517
0
            if (keySize == 0)
8518
0
                keySize = tmpKeySize;
8519
0
            if (keySize > tmpKeySize) {
8520
0
                crv = CKR_TEMPLATE_INCONSISTENT;
8521
0
                break;
8522
0
            }
8523
0
            buf = (unsigned char *)PORT_Alloc(tmpKeySize);
8524
0
            if (buf == NULL) {
8525
0
                crv = CKR_HOST_MEMORY;
8526
0
                break;
8527
0
            }
8528
8529
0
            PORT_Memcpy(buf, stringPtr->pData, stringPtr->ulLen);
8530
0
            PORT_Memcpy(buf + stringPtr->ulLen, att->attrib.pValue,
8531
0
                        att->attrib.ulValueLen);
8532
8533
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8534
0
            PORT_ZFree(buf, tmpKeySize);
8535
0
            break;
8536
0
        case CKM_XOR_BASE_AND_DATA:
8537
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8538
0
            if (crv != CKR_OK)
8539
0
                break;
8540
8541
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
8542
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8543
0
                break;
8544
0
            }
8545
0
            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
8546
0
            tmpKeySize = PR_MIN(att->attrib.ulValueLen, stringPtr->ulLen);
8547
0
            if (keySize == 0)
8548
0
                keySize = tmpKeySize;
8549
0
            if (keySize > tmpKeySize) {
8550
0
                crv = CKR_TEMPLATE_INCONSISTENT;
8551
0
                break;
8552
0
            }
8553
0
            buf = (unsigned char *)PORT_Alloc(keySize);
8554
0
            if (buf == NULL) {
8555
0
                crv = CKR_HOST_MEMORY;
8556
0
                break;
8557
0
            }
8558
8559
0
            PORT_Memcpy(buf, att->attrib.pValue, keySize);
8560
0
            for (i = 0; i < (int)keySize; i++) {
8561
0
                buf[i] ^= stringPtr->pData[i];
8562
0
            }
8563
8564
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8565
0
            PORT_ZFree(buf, keySize);
8566
0
            break;
8567
8568
0
        case CKM_EXTRACT_KEY_FROM_KEY: {
8569
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_EXTRACT_PARAMS))) {
8570
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8571
0
                break;
8572
0
            }
8573
            /* the following assumes 8 bits per byte */
8574
0
            CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;
8575
0
            CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */
8576
0
            CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */
8577
8578
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8579
0
            if (crv != CKR_OK)
8580
0
                break;
8581
8582
0
            if (keySize == 0) {
8583
0
                crv = CKR_TEMPLATE_INCOMPLETE;
8584
0
                break;
8585
0
            }
8586
            /* make sure we have enough bits in the original key */
8587
0
            if (att->attrib.ulValueLen <
8588
0
                (offset + keySize + ((shift != 0) ? 1 : 0))) {
8589
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8590
0
                break;
8591
0
            }
8592
0
            buf = (unsigned char *)PORT_Alloc(keySize);
8593
0
            if (buf == NULL) {
8594
0
                crv = CKR_HOST_MEMORY;
8595
0
                break;
8596
0
            }
8597
8598
            /* copy the bits we need into the new key */
8599
0
            for (i = 0; i < (int)keySize; i++) {
8600
0
                unsigned char *value =
8601
0
                    ((unsigned char *)att->attrib.pValue) + offset + i;
8602
0
                if (shift) {
8603
0
                    buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift));
8604
0
                } else {
8605
0
                    buf[i] = value[0];
8606
0
                }
8607
0
            }
8608
8609
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
8610
0
            PORT_ZFree(buf, keySize);
8611
0
            break;
8612
0
        }
8613
0
        case CKM_MD2_KEY_DERIVATION:
8614
0
            if (keySize == 0)
8615
0
                keySize = MD2_LENGTH;
8616
0
            if (keySize > MD2_LENGTH) {
8617
0
                crv = CKR_TEMPLATE_INCONSISTENT;
8618
0
                break;
8619
0
            }
8620
            /* now allocate the hash contexts */
8621
0
            md2 = MD2_NewContext();
8622
0
            if (md2 == NULL) {
8623
0
                crv = CKR_HOST_MEMORY;
8624
0
                break;
8625
0
            }
8626
0
            MD2_Begin(md2);
8627
0
            MD2_Update(md2, (const unsigned char *)att->attrib.pValue,
8628
0
                       att->attrib.ulValueLen);
8629
0
            MD2_End(md2, key_block, &outLen, MD2_LENGTH);
8630
0
            MD2_DestroyContext(md2, PR_TRUE);
8631
8632
0
            crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);
8633
0
            PORT_Memset(key_block, 0, MD2_LENGTH);
8634
0
            break;
8635
0
#define DERIVE_KEY_HASH(hash)                                                \
8636
0
    case CKM_##hash##_KEY_DERIVATION:                                        \
8637
0
        if (keySize == 0)                                                    \
8638
0
            keySize = hash##_LENGTH;                                         \
8639
0
        if (keySize > hash##_LENGTH) {                                       \
8640
0
            crv = CKR_TEMPLATE_INCONSISTENT;                                 \
8641
0
            break;                                                           \
8642
0
        }                                                                    \
8643
0
        hash##_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, \
8644
0
                       att->attrib.ulValueLen);                              \
8645
0
        crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);       \
8646
0
        PORT_Memset(key_block, 0, hash##_LENGTH);                            \
8647
0
        break;
8648
0
            DERIVE_KEY_HASH(MD5)
8649
0
            DERIVE_KEY_HASH(SHA1)
8650
0
            DERIVE_KEY_HASH(SHA224)
8651
0
            DERIVE_KEY_HASH(SHA256)
8652
0
            DERIVE_KEY_HASH(SHA384)
8653
0
            DERIVE_KEY_HASH(SHA512)
8654
0
            DERIVE_KEY_HASH(SHA3_224)
8655
0
            DERIVE_KEY_HASH(SHA3_256)
8656
0
            DERIVE_KEY_HASH(SHA3_384)
8657
0
            DERIVE_KEY_HASH(SHA3_512)
8658
8659
0
        case CKM_DH_PKCS_DERIVE: {
8660
0
            SECItem derived, dhPublic;
8661
0
            SECItem dhPrime, dhValue;
8662
0
            const SECItem *subPrime;
8663
            /* sourceKey - values for the local existing low key */
8664
            /* get prime and value attributes */
8665
0
            crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
8666
0
            if (crv != CKR_OK)
8667
0
                break;
8668
8669
0
            dhPublic.data = pMechanism->pParameter;
8670
0
            dhPublic.len = pMechanism->ulParameterLen;
8671
8672
            /* if the prime is an approved prime, we can skip all the other
8673
             * checks. */
8674
0
            subPrime = sftk_VerifyDH_Prime(&dhPrime, isFIPS);
8675
0
            if (subPrime == NULL) {
8676
0
                SECItem dhSubPrime;
8677
                /* If the caller set the subprime value, it means that
8678
                 * either the caller knows the subprime value and wants us
8679
                 * to validate the key against the subprime, or that the
8680
                 * caller wants us to verify that the prime is a safe prime
8681
                 * by passing in subprime = (prime-1)/2 */
8682
0
                dhSubPrime.data = NULL;
8683
0
                dhSubPrime.len = 0;
8684
0
                crv = sftk_Attribute2SecItem(NULL, &dhSubPrime,
8685
0
                                             sourceKey, CKA_SUBPRIME);
8686
                /* we ignore the value of crv here, We treat a valid
8687
                 * return of len = 0 and a failure to find a subrime the same
8688
                 * NOTE: we free the subprime in both cases depending on
8689
                 * PORT_Free of NULL to be a noop */
8690
0
                if (dhSubPrime.len != 0) {
8691
0
                    PRBool isSafe = PR_FALSE;
8692
8693
                    /* Callers can set dhSubPrime to q=(p-1)/2 to force
8694
                     * checks for safe primes. If so we only need to check
8695
                     * q and p for primality and skip the group test.  */
8696
0
                    rv = sftk_IsSafePrime(&dhPrime, &dhSubPrime, &isSafe);
8697
0
                    if (rv != SECSuccess) {
8698
                        /* either p or q was even and therefore not prime,
8699
                         * we can stop processing here and fail now */
8700
0
                        crv = CKR_ARGUMENTS_BAD;
8701
0
                        SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8702
0
                        SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8703
0
                        break;
8704
0
                    }
8705
8706
                    /* first make sure the primes are really prime */
8707
0
                    if (!KEA_PrimeCheck(&dhPrime)) {
8708
0
                        crv = CKR_ARGUMENTS_BAD;
8709
0
                        SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8710
0
                        SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8711
0
                        break;
8712
0
                    }
8713
0
                    if (!KEA_PrimeCheck(&dhSubPrime)) {
8714
0
                        crv = CKR_ARGUMENTS_BAD;
8715
0
                        SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8716
0
                        SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8717
0
                        break;
8718
0
                    }
8719
0
                    if (isFIPS || !isSafe) {
8720
                        /* With safe primes, there is only one other small
8721
                         * subgroup. As long as y isn't 0, 1, or -1 mod p,
8722
                         * any other y is safe. Only do the full check for
8723
                         * non-safe primes, except in FIPS mode we need
8724
                         * to do this check on all primes in which
8725
                         * we receive the subprime value */
8726
0
                        if (!KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime)) {
8727
0
                            crv = CKR_ARGUMENTS_BAD;
8728
0
                            SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8729
0
                            SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8730
0
                            break;
8731
0
                        }
8732
0
                    }
8733
0
                } else if (isFIPS) {
8734
                    /* In FIPS mode we only accept approved primes, or
8735
                     * primes with the full subprime value */
8736
0
                    crv = CKR_ARGUMENTS_BAD;
8737
0
                    SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8738
0
                    break;
8739
0
                }
8740
                /* checks are complete, no need for the subPrime any longer */
8741
0
                SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
8742
0
            }
8743
8744
            /* now that the prime is validated, get the private value */
8745
0
            crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
8746
0
            if (crv != CKR_OK) {
8747
0
                SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8748
0
                break;
8749
0
            }
8750
8751
            /* calculate private value - oct */
8752
0
            rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
8753
8754
0
            SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
8755
0
            SECITEM_ZfreeItem(&dhValue, PR_FALSE);
8756
8757
0
            if (rv == SECSuccess) {
8758
0
                sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
8759
0
                SECITEM_ZfreeItem(&derived, PR_FALSE);
8760
0
                crv = CKR_OK;
8761
0
            } else
8762
0
                crv = CKR_HOST_MEMORY;
8763
8764
0
            break;
8765
0
        }
8766
8767
0
        case CKM_ECDH1_DERIVE:
8768
0
        case CKM_ECDH1_COFACTOR_DERIVE: {
8769
0
            SECItem ecScalar, ecPoint;
8770
0
            SECItem tmp;
8771
0
            PRBool withCofactor = PR_FALSE;
8772
0
            unsigned char *secret;
8773
0
            unsigned char *keyData = NULL;
8774
0
            unsigned int secretlen, pubKeyLen;
8775
0
            CK_ECDH1_DERIVE_PARAMS *mechParams;
8776
0
            NSSLOWKEYPrivateKey *privKey;
8777
0
            PLArenaPool *arena = NULL;
8778
8779
            /* Check mechanism parameters */
8780
0
            mechParams = (CK_ECDH1_DERIVE_PARAMS *)pMechanism->pParameter;
8781
0
            if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) ||
8782
0
                ((mechParams->kdf == CKD_NULL) &&
8783
0
                 ((mechParams->ulSharedDataLen != 0) ||
8784
0
                  (mechParams->pSharedData != NULL)))) {
8785
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8786
0
                break;
8787
0
            }
8788
8789
0
            privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv);
8790
0
            if (privKey == NULL) {
8791
0
                break;
8792
0
            }
8793
8794
            /* Now we are working with a non-NULL private key */
8795
0
            SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue);
8796
8797
0
            ecPoint.data = mechParams->pPublicData;
8798
0
            ecPoint.len = mechParams->ulPublicDataLen;
8799
8800
0
            pubKeyLen = EC_GetPointSize(&privKey->u.ec.ecParams);
8801
8802
            /* if the len is too large, might be an encoded point */
8803
0
            if (ecPoint.len > pubKeyLen) {
8804
0
                SECItem newPoint;
8805
8806
0
                arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
8807
0
                if (arena == NULL) {
8808
0
                    goto ec_loser;
8809
0
                }
8810
8811
0
                rv = SEC_QuickDERDecodeItem(arena, &newPoint,
8812
0
                                            SEC_ASN1_GET(SEC_OctetStringTemplate),
8813
0
                                            &ecPoint);
8814
0
                if (rv != SECSuccess) {
8815
0
                    goto ec_loser;
8816
0
                }
8817
0
                ecPoint = newPoint;
8818
0
            }
8819
8820
0
            if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) {
8821
0
                withCofactor = PR_TRUE;
8822
0
            }
8823
8824
0
            rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
8825
0
                             withCofactor, &tmp);
8826
0
            SECITEM_ZfreeItem(&ecScalar, PR_FALSE);
8827
0
            ecScalar.data = NULL;
8828
0
            if (privKey != sourceKey->objectInfo) {
8829
0
                nsslowkey_DestroyPrivateKey(privKey);
8830
0
                privKey = NULL;
8831
0
            }
8832
0
            if (arena) {
8833
0
                PORT_FreeArena(arena, PR_FALSE);
8834
0
                arena = NULL;
8835
0
            }
8836
8837
0
            if (rv != SECSuccess) {
8838
0
                crv = sftk_MapCryptError(PORT_GetError());
8839
0
                break;
8840
0
            }
8841
8842
            /*
8843
             * apply the kdf function.
8844
             */
8845
0
            if (mechParams->kdf == CKD_NULL) {
8846
                /*
8847
                 * tmp is the raw data created by ECDH_Derive,
8848
                 * secret and secretlen are the values we will
8849
                 * eventually pass as our generated key.
8850
                 */
8851
0
                secret = tmp.data;
8852
0
                secretlen = tmp.len;
8853
0
            } else {
8854
0
                secretlen = keySize;
8855
0
                crv = sftk_ANSI_X9_63_kdf(&secret, keySize,
8856
0
                                          &tmp, mechParams->pSharedData,
8857
0
                                          mechParams->ulSharedDataLen, mechParams->kdf);
8858
0
                PORT_ZFree(tmp.data, tmp.len);
8859
0
                if (crv != CKR_OK) {
8860
0
                    break;
8861
0
                }
8862
0
                tmp.data = secret;
8863
0
                tmp.len = secretlen;
8864
0
            }
8865
8866
            /*
8867
             * if keySize is supplied, then we are generating a key of a specific
8868
             * length. This is done by taking the least significant 'keySize'
8869
             * bytes from the unsigned value calculated by ECDH. Note: this may
8870
             * mean padding temp with extra leading zeros from what ECDH_Derive
8871
             * already returned (which itself may contain leading zeros).
8872
             */
8873
0
            if (keySize) {
8874
0
                if (secretlen < keySize) {
8875
0
                    keyData = PORT_ZAlloc(keySize);
8876
0
                    if (!keyData) {
8877
0
                        PORT_ZFree(tmp.data, tmp.len);
8878
0
                        crv = CKR_HOST_MEMORY;
8879
0
                        break;
8880
0
                    }
8881
0
                    PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen);
8882
0
                    secret = keyData;
8883
0
                } else {
8884
0
                    secret += (secretlen - keySize);
8885
0
                }
8886
0
                secretlen = keySize;
8887
0
            }
8888
8889
0
            sftk_forceAttribute(key, CKA_VALUE, secret, secretlen);
8890
0
            PORT_ZFree(tmp.data, tmp.len);
8891
0
            if (keyData) {
8892
0
                PORT_ZFree(keyData, keySize);
8893
0
            }
8894
0
            break;
8895
8896
0
        ec_loser:
8897
0
            crv = CKR_ARGUMENTS_BAD;
8898
0
            SECITEM_ZfreeItem(&ecScalar, PR_FALSE);
8899
0
            if (privKey != sourceKey->objectInfo)
8900
0
                nsslowkey_DestroyPrivateKey(privKey);
8901
0
            if (arena) {
8902
0
                PORT_FreeArena(arena, PR_TRUE);
8903
0
            }
8904
0
            break;
8905
0
        }
8906
        /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */
8907
17
        case CKM_NSS_HKDF_SHA1:
8908
17
            hashMech = CKM_SHA_1;
8909
17
            goto hkdf;
8910
9
        case CKM_NSS_HKDF_SHA256:
8911
9
            hashMech = CKM_SHA256;
8912
9
            goto hkdf;
8913
15
        case CKM_NSS_HKDF_SHA384:
8914
15
            hashMech = CKM_SHA384;
8915
15
            goto hkdf;
8916
11
        case CKM_NSS_HKDF_SHA512:
8917
11
            hashMech = CKM_SHA512;
8918
11
            goto hkdf;
8919
52
        hkdf : {
8920
52
            const CK_NSS_HKDFParams *params =
8921
52
                (const CK_NSS_HKDFParams *)pMechanism->pParameter;
8922
52
            CK_HKDF_PARAMS hkdfParams;
8923
8924
52
            if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams)) {
8925
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8926
0
                break;
8927
0
            }
8928
52
            hkdfParams.bExtract = params->bExtract;
8929
52
            hkdfParams.bExpand = params->bExpand;
8930
52
            if (params->pSalt) {
8931
47
                hkdfParams.ulSaltType = CKF_HKDF_SALT_DATA;
8932
47
            } else {
8933
5
                hkdfParams.ulSaltType = CKF_HKDF_SALT_NULL;
8934
5
            }
8935
52
            hkdfParams.pSalt = params->pSalt;
8936
52
            hkdfParams.ulSaltLen = params->ulSaltLen;
8937
52
            hkdfParams.hSaltKey = CK_INVALID_HANDLE;
8938
52
            hkdfParams.pInfo = params->pInfo;
8939
52
            hkdfParams.ulInfoLen = params->ulInfoLen;
8940
52
            hkdfParams.prfHashMechanism = hashMech;
8941
8942
52
            crv = sftk_HKDF(&hkdfParams, hSession, sourceKey,
8943
52
                            att->attrib.pValue, att->attrib.ulValueLen,
8944
52
                            key, NULL, keySize, PR_FALSE, isFIPS);
8945
52
        } break;
8946
0
        case CKM_HKDF_DERIVE:
8947
0
        case CKM_HKDF_DATA: /* only difference is the class of key */
8948
0
            if ((pMechanism->pParameter == NULL) ||
8949
0
                (pMechanism->ulParameterLen != sizeof(CK_HKDF_PARAMS))) {
8950
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8951
0
                break;
8952
0
            }
8953
0
            crv = sftk_HKDF((CK_HKDF_PARAMS_PTR)pMechanism->pParameter,
8954
0
                            hSession, sourceKey, att->attrib.pValue,
8955
0
                            att->attrib.ulValueLen, key, NULL, keySize, PR_TRUE,
8956
0
                            isFIPS);
8957
0
            break;
8958
0
        case CKM_NSS_JPAKE_ROUND2_SHA1:
8959
0
            hashType = HASH_AlgSHA1;
8960
0
            goto jpake2;
8961
0
        case CKM_NSS_JPAKE_ROUND2_SHA256:
8962
0
            hashType = HASH_AlgSHA256;
8963
0
            goto jpake2;
8964
0
        case CKM_NSS_JPAKE_ROUND2_SHA384:
8965
0
            hashType = HASH_AlgSHA384;
8966
0
            goto jpake2;
8967
0
        case CKM_NSS_JPAKE_ROUND2_SHA512:
8968
0
            hashType = HASH_AlgSHA512;
8969
0
            goto jpake2;
8970
0
        jpake2:
8971
0
            if (pMechanism->pParameter == NULL ||
8972
0
                pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params))
8973
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8974
0
            if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN))
8975
0
                crv = CKR_TEMPLATE_INCONSISTENT;
8976
0
            if (crv == CKR_OK)
8977
0
                crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
8978
0
            if (crv == CKR_OK)
8979
0
                crv = jpake_Round2(hashType,
8980
0
                                   (CK_NSS_JPAKERound2Params *)pMechanism->pParameter,
8981
0
                                   sourceKey, key);
8982
0
            break;
8983
8984
0
        case CKM_NSS_JPAKE_FINAL_SHA1:
8985
0
            hashType = HASH_AlgSHA1;
8986
0
            goto jpakeFinal;
8987
0
        case CKM_NSS_JPAKE_FINAL_SHA256:
8988
0
            hashType = HASH_AlgSHA256;
8989
0
            goto jpakeFinal;
8990
0
        case CKM_NSS_JPAKE_FINAL_SHA384:
8991
0
            hashType = HASH_AlgSHA384;
8992
0
            goto jpakeFinal;
8993
0
        case CKM_NSS_JPAKE_FINAL_SHA512:
8994
0
            hashType = HASH_AlgSHA512;
8995
0
            goto jpakeFinal;
8996
0
        jpakeFinal:
8997
0
            if (pMechanism->pParameter == NULL ||
8998
0
                pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams))
8999
0
                crv = CKR_MECHANISM_PARAM_INVALID;
9000
            /* We purposely do not do the derive sensitivity check; we want to be
9001
               able to derive non-sensitive keys while allowing the ROUND1 and
9002
               ROUND2 keys to be sensitive (which they always are, since they are
9003
               in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE
9004
               in the template in order for the resultant keyblock key to be
9005
               sensitive.
9006
             */
9007
0
            if (crv == CKR_OK)
9008
0
                crv = jpake_Final(hashType,
9009
0
                                  (CK_NSS_JPAKEFinalParams *)pMechanism->pParameter,
9010
0
                                  sourceKey, key);
9011
0
            break;
9012
9013
0
        case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA:         /* fall through */
9014
0
        case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA:        /* fall through */
9015
0
        case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */
9016
0
        case CKM_SP800_108_COUNTER_KDF:                         /* fall through */
9017
0
        case CKM_SP800_108_FEEDBACK_KDF:                        /* fall through */
9018
0
        case CKM_SP800_108_DOUBLE_PIPELINE_KDF:
9019
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
9020
0
            if (crv != CKR_OK) {
9021
0
                break;
9022
0
            }
9023
9024
0
            crv = kbkdf_Dispatch(mechanism, hSession, pMechanism, sourceKey, key, keySize);
9025
0
            break;
9026
0
        default:
9027
0
            crv = CKR_MECHANISM_INVALID;
9028
52
    }
9029
52
    if (att) {
9030
52
        sftk_FreeAttribute(att);
9031
52
    }
9032
52
    sftk_FreeObject(sourceKey);
9033
52
    if (crv != CKR_OK) {
9034
9
        if (key)
9035
9
            sftk_FreeObject(key);
9036
9
        return crv;
9037
9
    }
9038
9039
    /* link the key object into the list */
9040
43
    if (key) {
9041
43
        SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
9042
43
        PORT_Assert(sessKey);
9043
        /* get the session */
9044
43
        sessKey->wasDerived = PR_TRUE;
9045
43
        session = sftk_SessionFromHandle(hSession);
9046
43
        if (session == NULL) {
9047
0
            sftk_FreeObject(key);
9048
0
            return CKR_HOST_MEMORY;
9049
0
        }
9050
9051
43
        crv = sftk_handleObject(key, session);
9052
43
        session->lastOpWasFIPS = key->isFIPS;
9053
43
        sftk_FreeSession(session);
9054
43
        if (phKey) {
9055
43
            *phKey = key->handle;
9056
43
        }
9057
43
        sftk_FreeObject(key);
9058
43
    }
9059
43
    return crv;
9060
43
}
9061
9062
/* NSC_GetFunctionStatus obtains an updated status of a function running
9063
 * in parallel with an application. */
9064
CK_RV
9065
NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)
9066
0
{
9067
0
    CHECK_FORK();
9068
9069
0
    return CKR_FUNCTION_NOT_PARALLEL;
9070
0
}
9071
9072
/* NSC_CancelFunction cancels a function running in parallel */
9073
CK_RV
9074
NSC_CancelFunction(CK_SESSION_HANDLE hSession)
9075
0
{
9076
0
    CHECK_FORK();
9077
9078
0
    return CKR_FUNCTION_NOT_PARALLEL;
9079
0
}
9080
9081
/* NSC_GetOperationState saves the state of the cryptographic
9082
 * operation in a session.
9083
 * NOTE: This code only works for digest functions for now. eventually need
9084
 * to add full flatten/resurect to our state stuff so that all types of state
9085
 * can be saved */
9086
CK_RV
9087
NSC_GetOperationState(CK_SESSION_HANDLE hSession,
9088
                      CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
9089
0
{
9090
0
    SFTKSessionContext *context;
9091
0
    SFTKSession *session;
9092
0
    CK_RV crv;
9093
0
    CK_ULONG pOSLen = *pulOperationStateLen;
9094
9095
0
    CHECK_FORK();
9096
9097
    /* make sure we're legal */
9098
0
    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
9099
0
    if (crv != CKR_OK)
9100
0
        return crv;
9101
9102
    /* a zero cipherInfoLen signals that this context cannot be serialized */
9103
0
    if (context->cipherInfoLen == 0) {
9104
0
        return CKR_STATE_UNSAVEABLE;
9105
0
    }
9106
9107
0
    *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) + sizeof(SFTKContextType);
9108
0
    if (pOperationState == NULL) {
9109
0
        sftk_FreeSession(session);
9110
0
        return CKR_OK;
9111
0
    } else {
9112
0
        if (pOSLen < *pulOperationStateLen) {
9113
0
            return CKR_BUFFER_TOO_SMALL;
9114
0
        }
9115
0
    }
9116
0
    PORT_Memcpy(pOperationState, &context->type, sizeof(SFTKContextType));
9117
0
    pOperationState += sizeof(SFTKContextType);
9118
0
    PORT_Memcpy(pOperationState, &context->currentMech,
9119
0
                sizeof(CK_MECHANISM_TYPE));
9120
0
    pOperationState += sizeof(CK_MECHANISM_TYPE);
9121
0
    PORT_Memcpy(pOperationState, context->cipherInfo, context->cipherInfoLen);
9122
0
    sftk_FreeSession(session);
9123
0
    return CKR_OK;
9124
0
}
9125
9126
#define sftk_Decrement(stateSize, len) \
9127
0
    stateSize = ((stateSize) > (CK_ULONG)(len)) ? ((stateSize) - (CK_ULONG)(len)) : 0;
9128
9129
/* NSC_SetOperationState restores the state of the cryptographic
9130
 * operation in a session. This is coded like it can restore lots of
9131
 * states, but it only works for truly flat cipher structures. */
9132
CK_RV
9133
NSC_SetOperationState(CK_SESSION_HANDLE hSession,
9134
                      CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen,
9135
                      CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
9136
0
{
9137
0
    SFTKSessionContext *context;
9138
0
    SFTKSession *session;
9139
0
    SFTKContextType type;
9140
0
    CK_MECHANISM mech;
9141
0
    CK_RV crv = CKR_OK;
9142
9143
0
    CHECK_FORK();
9144
9145
0
    while (ulOperationStateLen != 0) {
9146
        /* get what type of state we're dealing with... */
9147
0
        PORT_Memcpy(&type, pOperationState, sizeof(SFTKContextType));
9148
9149
        /* fix up session contexts based on type */
9150
0
        session = sftk_SessionFromHandle(hSession);
9151
0
        if (session == NULL)
9152
0
            return CKR_SESSION_HANDLE_INVALID;
9153
0
        context = sftk_ReturnContextByType(session, type);
9154
0
        sftk_SetContextByType(session, type, NULL);
9155
0
        if (context) {
9156
0
            sftk_FreeContext(context);
9157
0
        }
9158
0
        pOperationState += sizeof(SFTKContextType);
9159
0
        sftk_Decrement(ulOperationStateLen, sizeof(SFTKContextType));
9160
9161
        /* get the mechanism structure */
9162
0
        PORT_Memcpy(&mech.mechanism, pOperationState, sizeof(CK_MECHANISM_TYPE));
9163
0
        pOperationState += sizeof(CK_MECHANISM_TYPE);
9164
0
        sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE));
9165
        /* should be filled in... but not necessary for hash */
9166
0
        mech.pParameter = NULL;
9167
0
        mech.ulParameterLen = 0;
9168
0
        switch (type) {
9169
0
            case SFTK_HASH:
9170
0
                crv = NSC_DigestInit(hSession, &mech);
9171
0
                if (crv != CKR_OK)
9172
0
                    break;
9173
0
                crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE,
9174
0
                                      NULL);
9175
0
                if (crv != CKR_OK)
9176
0
                    break;
9177
0
                if (context->cipherInfoLen == 0) {
9178
0
                    crv = CKR_SAVED_STATE_INVALID;
9179
0
                    break;
9180
0
                }
9181
0
                PORT_Memcpy(context->cipherInfo, pOperationState,
9182
0
                            context->cipherInfoLen);
9183
0
                pOperationState += context->cipherInfoLen;
9184
0
                sftk_Decrement(ulOperationStateLen, context->cipherInfoLen);
9185
0
                break;
9186
0
            default:
9187
                /* do sign/encrypt/decrypt later */
9188
0
                crv = CKR_SAVED_STATE_INVALID;
9189
0
        }
9190
0
        sftk_FreeSession(session);
9191
0
        if (crv != CKR_OK)
9192
0
            break;
9193
0
    }
9194
0
    return crv;
9195
0
}
9196
9197
/* Dual-function cryptographic operations */
9198
9199
/* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption
9200
 * operation. */
9201
CK_RV
9202
NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
9203
                        CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
9204
                        CK_ULONG_PTR pulEncryptedPartLen)
9205
0
{
9206
0
    CK_RV crv;
9207
9208
0
    CHECK_FORK();
9209
9210
0
    crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
9211
0
                            pulEncryptedPartLen);
9212
0
    if (crv != CKR_OK)
9213
0
        return crv;
9214
0
    crv = NSC_DigestUpdate(hSession, pPart, ulPartLen);
9215
9216
0
    return crv;
9217
0
}
9218
9219
/* NSC_DecryptDigestUpdate continues a multiple-part decryption and
9220
 * digesting operation. */
9221
CK_RV
9222
NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
9223
                        CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
9224
                        CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
9225
0
{
9226
0
    CK_RV crv;
9227
9228
0
    CHECK_FORK();
9229
9230
0
    crv = NSC_DecryptUpdate(hSession, pEncryptedPart, ulEncryptedPartLen,
9231
0
                            pPart, pulPartLen);
9232
0
    if (crv != CKR_OK)
9233
0
        return crv;
9234
0
    crv = NSC_DigestUpdate(hSession, pPart, *pulPartLen);
9235
9236
0
    return crv;
9237
0
}
9238
9239
/* NSC_SignEncryptUpdate continues a multiple-part signing and
9240
 * encryption operation. */
9241
CK_RV
9242
NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
9243
                      CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
9244
                      CK_ULONG_PTR pulEncryptedPartLen)
9245
0
{
9246
0
    CK_RV crv;
9247
9248
0
    CHECK_FORK();
9249
9250
0
    crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
9251
0
                            pulEncryptedPartLen);
9252
0
    if (crv != CKR_OK)
9253
0
        return crv;
9254
0
    crv = NSC_SignUpdate(hSession, pPart, ulPartLen);
9255
9256
0
    return crv;
9257
0
}
9258
9259
/* NSC_DecryptVerifyUpdate continues a multiple-part decryption
9260
 * and verify operation. */
9261
CK_RV
9262
NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
9263
                        CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
9264
                        CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
9265
0
{
9266
0
    CK_RV crv;
9267
9268
0
    CHECK_FORK();
9269
9270
0
    crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
9271
0
                            pData, pulDataLen);
9272
0
    if (crv != CKR_OK)
9273
0
        return crv;
9274
0
    crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen);
9275
9276
0
    return crv;
9277
0
}
9278
9279
/* NSC_DigestKey continues a multi-part message-digesting operation,
9280
 * by digesting the value of a secret key as part of the data already digested.
9281
 */
9282
CK_RV
9283
NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
9284
0
{
9285
0
    SFTKSession *session = NULL;
9286
0
    SFTKObject *key = NULL;
9287
0
    SFTKAttribute *att;
9288
0
    CK_RV crv;
9289
9290
0
    CHECK_FORK();
9291
9292
0
    session = sftk_SessionFromHandle(hSession);
9293
0
    if (session == NULL)
9294
0
        return CKR_SESSION_HANDLE_INVALID;
9295
9296
0
    key = sftk_ObjectFromHandle(hKey, session);
9297
0
    sftk_FreeSession(session);
9298
0
    if (key == NULL)
9299
0
        return CKR_KEY_HANDLE_INVALID;
9300
9301
    /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */
9302
9303
    /* make sure it's a valid  key for this operation */
9304
0
    if (key->objclass != CKO_SECRET_KEY) {
9305
0
        sftk_FreeObject(key);
9306
0
        return CKR_KEY_TYPE_INCONSISTENT;
9307
0
    }
9308
    /* get the key value */
9309
0
    att = sftk_FindAttribute(key, CKA_VALUE);
9310
0
    sftk_FreeObject(key);
9311
0
    if (!att) {
9312
0
        return CKR_KEY_HANDLE_INVALID;
9313
0
    }
9314
0
    crv = NSC_DigestUpdate(hSession, (CK_BYTE_PTR)att->attrib.pValue,
9315
0
                           att->attrib.ulValueLen);
9316
0
    sftk_FreeAttribute(att);
9317
0
    return crv;
9318
0
}