Coverage Report

Created: 2026-05-19 06:33

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