/src/nss-nspr/nss/lib/softoken/pkcs11c.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | /* |
5 | | * This file implements PKCS 11 on top of our existing security modules |
6 | | * |
7 | | * For more information about PKCS 11 See PKCS 11 Token Inteface Standard. |
8 | | * This implementation has two slots: |
9 | | * slot 1 is our generic crypto support. It does not require login. |
10 | | * It supports Public Key ops, and all they bulk ciphers and hashes. |
11 | | * It can also support Private Key ops for imported Private keys. It does |
12 | | * not have any token storage. |
13 | | * slot 2 is our private key support. It requires a login before use. It |
14 | | * can store Private Keys and Certs as token objects. Currently only private |
15 | | * keys and their associated Certificates are saved on the token. |
16 | | * |
17 | | * In this implementation, session objects are only visible to the session |
18 | | * that created or generated them. |
19 | | */ |
20 | | |
21 | | #include <limits.h> /* for UINT_MAX and ULONG_MAX */ |
22 | | |
23 | | #include "lowkeyti.h" |
24 | | #include "seccomon.h" |
25 | | #include "secitem.h" |
26 | | #include "secport.h" |
27 | | #include "blapi.h" |
28 | | #include "pkcs11.h" |
29 | | #include "pkcs11i.h" |
30 | | #include "pkcs1sig.h" |
31 | | #include "lowkeyi.h" |
32 | | #include "secder.h" |
33 | | #include "secdig.h" |
34 | | #include "lowpbe.h" /* We do PBE below */ |
35 | | #include "pkcs11t.h" |
36 | | #include "secoid.h" |
37 | | #include "cmac.h" |
38 | | #include "alghmac.h" |
39 | | #include "softoken.h" |
40 | | #include "secasn1.h" |
41 | | #include "secerr.h" |
42 | | #include "kem.h" |
43 | | #include "kyber.h" |
44 | | |
45 | | #include "prprf.h" |
46 | | #include "prenv.h" |
47 | | |
48 | | #define __PASTE(x, y) x##y |
49 | 115 | #define BAD_PARAM_CAST(pMech, typeSize) (!pMech->pParameter || pMech->ulParameterLen < typeSize) |
50 | | /* |
51 | | * we renamed all our internal functions, get the correct |
52 | | * definitions for them... |
53 | | */ |
54 | | #undef CK_PKCS11_FUNCTION_INFO |
55 | | #undef CK_NEED_ARG_LIST |
56 | | |
57 | | #define CK_PKCS11_3_0 1 |
58 | | |
59 | | #define CK_EXTERN extern |
60 | | #define CK_PKCS11_FUNCTION_INFO(func) \ |
61 | | CK_RV __PASTE(NS, func) |
62 | | #define CK_NEED_ARG_LIST 1 |
63 | | |
64 | | #include "pkcs11f.h" |
65 | | |
66 | | /* create a definition of SHA1 that's consistent |
67 | | * with the rest of the CKM_SHAxxx hashes*/ |
68 | 22 | #define CKM_SHA1 CKM_SHA_1 |
69 | 14 | #define CKM_SHA1_HMAC CKM_SHA_1_HMAC |
70 | 0 | #define CKM_SHA1_HMAC_GENERAL CKM_SHA_1_HMAC_GENERAL |
71 | | |
72 | | typedef struct { |
73 | | PRUint8 client_version[2]; |
74 | | PRUint8 random[46]; |
75 | | } SSL3RSAPreMasterSecret; |
76 | | |
77 | | static void |
78 | | sftk_Null(void *data, PRBool freeit) |
79 | 0 | { |
80 | 0 | return; |
81 | 0 | } |
82 | | |
83 | | #ifdef EC_DEBUG |
84 | | #define SEC_PRINT(str1, str2, num, sitem) \ |
85 | | printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \ |
86 | | str1, str2, num, sitem->len); \ |
87 | | for (i = 0; i < sitem->len; i++) { \ |
88 | | printf("%02x:", sitem->data[i]); \ |
89 | | } \ |
90 | | printf("\n") |
91 | | #else |
92 | | #undef EC_DEBUG |
93 | | #define SEC_PRINT(a, b, c, d) |
94 | | #endif |
95 | | |
96 | | /* Wrappers to avoid undefined behavior calling functions through a pointer of incorrect type. */ |
97 | | #define SFTKHashWrap(ctxtype, mmm) \ |
98 | | static void \ |
99 | | SFTKHash_##mmm##_Update(void *vctx, const unsigned char *input, unsigned int len) \ |
100 | 1.19k | { \ |
101 | 1.19k | ctxtype *ctx = vctx; \ |
102 | 1.19k | mmm##_Update(ctx, input, len); \ |
103 | 1.19k | } \ Unexecuted instantiation: pkcs11c.c:SFTKHash_MD2_Update pkcs11c.c:SFTKHash_MD5_Update Line | Count | Source | 100 | 98 | { \ | 101 | 98 | ctxtype *ctx = vctx; \ | 102 | 98 | mmm##_Update(ctx, input, len); \ | 103 | 98 | } \ |
pkcs11c.c:SFTKHash_SHA1_Update Line | Count | Source | 100 | 130 | { \ | 101 | 130 | ctxtype *ctx = vctx; \ | 102 | 130 | mmm##_Update(ctx, input, len); \ | 103 | 130 | } \ |
pkcs11c.c:SFTKHash_SHA224_Update Line | Count | Source | 100 | 56 | { \ | 101 | 56 | ctxtype *ctx = vctx; \ | 102 | 56 | mmm##_Update(ctx, input, len); \ | 103 | 56 | } \ |
pkcs11c.c:SFTKHash_SHA256_Update Line | Count | Source | 100 | 152 | { \ | 101 | 152 | ctxtype *ctx = vctx; \ | 102 | 152 | mmm##_Update(ctx, input, len); \ | 103 | 152 | } \ |
pkcs11c.c:SFTKHash_SHA384_Update Line | Count | Source | 100 | 99 | { \ | 101 | 99 | ctxtype *ctx = vctx; \ | 102 | 99 | mmm##_Update(ctx, input, len); \ | 103 | 99 | } \ |
pkcs11c.c:SFTKHash_SHA512_Update Line | Count | Source | 100 | 132 | { \ | 101 | 132 | ctxtype *ctx = vctx; \ | 102 | 132 | mmm##_Update(ctx, input, len); \ | 103 | 132 | } \ |
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_224_Update Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_256_Update Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_384_Update Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_512_Update pkcs11c.c:SFTKHash_sftk_MAC_Update Line | Count | Source | 100 | 524 | { \ | 101 | 524 | ctxtype *ctx = vctx; \ | 102 | 524 | mmm##_Update(ctx, input, len); \ | 103 | 524 | } \ |
|
104 | | static void \ |
105 | | SFTKHash_##mmm##_End(void *vctx, unsigned char *digest, \ |
106 | | unsigned int *len, unsigned int maxLen) \ |
107 | 133 | { \ |
108 | 133 | ctxtype *ctx = vctx; \ |
109 | 133 | mmm##_End(ctx, digest, len, maxLen); \ |
110 | 133 | } \ Unexecuted instantiation: pkcs11c.c:SFTKHash_MD2_End pkcs11c.c:SFTKHash_MD5_End Line | Count | Source | 107 | 9 | { \ | 108 | 9 | ctxtype *ctx = vctx; \ | 109 | 9 | mmm##_End(ctx, digest, len, maxLen); \ | 110 | 9 | } \ |
pkcs11c.c:SFTKHash_SHA1_End Line | Count | Source | 107 | 11 | { \ | 108 | 11 | ctxtype *ctx = vctx; \ | 109 | 11 | mmm##_End(ctx, digest, len, maxLen); \ | 110 | 11 | } \ |
pkcs11c.c:SFTKHash_SHA224_End Line | Count | Source | 107 | 5 | { \ | 108 | 5 | ctxtype *ctx = vctx; \ | 109 | 5 | mmm##_End(ctx, digest, len, maxLen); \ | 110 | 5 | } \ |
pkcs11c.c:SFTKHash_SHA256_End Line | Count | Source | 107 | 20 | { \ | 108 | 20 | ctxtype *ctx = vctx; \ | 109 | 20 | mmm##_End(ctx, digest, len, maxLen); \ | 110 | 20 | } \ |
pkcs11c.c:SFTKHash_SHA384_End Line | Count | Source | 107 | 9 | { \ | 108 | 9 | ctxtype *ctx = vctx; \ | 109 | 9 | mmm##_End(ctx, digest, len, maxLen); \ | 110 | 9 | } \ |
pkcs11c.c:SFTKHash_SHA512_End Line | Count | Source | 107 | 10 | { \ | 108 | 10 | ctxtype *ctx = vctx; \ | 109 | 10 | mmm##_End(ctx, digest, len, maxLen); \ | 110 | 10 | } \ |
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_224_End Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_256_End Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_384_End Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_512_End pkcs11c.c:SFTKHash_sftk_MAC_End Line | Count | Source | 107 | 69 | { \ | 108 | 69 | ctxtype *ctx = vctx; \ | 109 | 69 | mmm##_End(ctx, digest, len, maxLen); \ | 110 | 69 | } \ |
|
111 | | static void \ |
112 | | SFTKHash_##mmm##_DestroyContext(void *vctx, PRBool freeit) \ |
113 | 133 | { \ |
114 | 133 | ctxtype *ctx = vctx; \ |
115 | 133 | mmm##_DestroyContext(ctx, freeit); \ |
116 | 133 | } Unexecuted instantiation: pkcs11c.c:SFTKHash_MD2_DestroyContext pkcs11c.c:SFTKHash_MD5_DestroyContext Line | Count | Source | 113 | 9 | { \ | 114 | 9 | ctxtype *ctx = vctx; \ | 115 | 9 | mmm##_DestroyContext(ctx, freeit); \ | 116 | 9 | } |
pkcs11c.c:SFTKHash_SHA1_DestroyContext Line | Count | Source | 113 | 11 | { \ | 114 | 11 | ctxtype *ctx = vctx; \ | 115 | 11 | mmm##_DestroyContext(ctx, freeit); \ | 116 | 11 | } |
pkcs11c.c:SFTKHash_SHA224_DestroyContext Line | Count | Source | 113 | 5 | { \ | 114 | 5 | ctxtype *ctx = vctx; \ | 115 | 5 | mmm##_DestroyContext(ctx, freeit); \ | 116 | 5 | } |
pkcs11c.c:SFTKHash_SHA256_DestroyContext Line | Count | Source | 113 | 20 | { \ | 114 | 20 | ctxtype *ctx = vctx; \ | 115 | 20 | mmm##_DestroyContext(ctx, freeit); \ | 116 | 20 | } |
pkcs11c.c:SFTKHash_SHA384_DestroyContext Line | Count | Source | 113 | 9 | { \ | 114 | 9 | ctxtype *ctx = vctx; \ | 115 | 9 | mmm##_DestroyContext(ctx, freeit); \ | 116 | 9 | } |
pkcs11c.c:SFTKHash_SHA512_DestroyContext Line | Count | Source | 113 | 10 | { \ | 114 | 10 | ctxtype *ctx = vctx; \ | 115 | 10 | mmm##_DestroyContext(ctx, freeit); \ | 116 | 10 | } |
Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_224_DestroyContext Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_256_DestroyContext Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_384_DestroyContext Unexecuted instantiation: pkcs11c.c:SFTKHash_SHA3_512_DestroyContext pkcs11c.c:SFTKHash_sftk_MAC_DestroyContext Line | Count | Source | 113 | 69 | { \ | 114 | 69 | ctxtype *ctx = vctx; \ | 115 | 69 | mmm##_DestroyContext(ctx, freeit); \ | 116 | 69 | } |
|
117 | | |
118 | | SFTKHashWrap(MD2Context, MD2); |
119 | | SFTKHashWrap(MD5Context, MD5); |
120 | | SFTKHashWrap(SHA1Context, SHA1); |
121 | | SFTKHashWrap(SHA224Context, SHA224); |
122 | | SFTKHashWrap(SHA256Context, SHA256); |
123 | | SFTKHashWrap(SHA384Context, SHA384); |
124 | | SFTKHashWrap(SHA512Context, SHA512); |
125 | | SFTKHashWrap(SHA3_224Context, SHA3_224); |
126 | | SFTKHashWrap(SHA3_256Context, SHA3_256); |
127 | | SFTKHashWrap(SHA3_384Context, SHA3_384); |
128 | | SFTKHashWrap(SHA3_512Context, SHA3_512); |
129 | | SFTKHashWrap(sftk_MACCtx, sftk_MAC); |
130 | | |
131 | | static void |
132 | | SFTKHash_SHA1_Begin(void *vctx) |
133 | 0 | { |
134 | 0 | SHA1Context *ctx = vctx; |
135 | 0 | SHA1_Begin(ctx); |
136 | 0 | } |
137 | | |
138 | | static void |
139 | | SFTKHash_MD5_Begin(void *vctx) |
140 | 0 | { |
141 | 0 | MD5Context *ctx = vctx; |
142 | 0 | MD5_Begin(ctx); |
143 | 0 | } |
144 | | |
145 | | #define SFTKCipherWrap(ctxtype, mmm) \ |
146 | | static SECStatus \ |
147 | | SFTKCipher_##mmm(void *vctx, unsigned char *output, \ |
148 | | unsigned int *outputLen, unsigned int maxOutputLen, \ |
149 | | const unsigned char *input, unsigned int inputLen) \ |
150 | 18 | { \ |
151 | 18 | ctxtype *ctx = vctx; \ |
152 | 18 | return mmm(ctx, output, outputLen, maxOutputLen, \ |
153 | 18 | input, inputLen); \ |
154 | 18 | } Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC2_Encrypt Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC2_Decrypt Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC4_Encrypt Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC4_Decrypt pkcs11c.c:SFTKCipher_DES_Encrypt Line | Count | Source | 150 | 1 | { \ | 151 | 1 | ctxtype *ctx = vctx; \ | 152 | 1 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 153 | 1 | input, inputLen); \ | 154 | 1 | } |
pkcs11c.c:SFTKCipher_DES_Decrypt Line | Count | Source | 150 | 3 | { \ | 151 | 3 | ctxtype *ctx = vctx; \ | 152 | 3 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 153 | 3 | input, inputLen); \ | 154 | 3 | } |
pkcs11c.c:SFTKCipher_SEED_Encrypt Line | Count | Source | 150 | 4 | { \ | 151 | 4 | ctxtype *ctx = vctx; \ | 152 | 4 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 153 | 4 | input, inputLen); \ | 154 | 4 | } |
pkcs11c.c:SFTKCipher_SEED_Decrypt Line | Count | Source | 150 | 3 | { \ | 151 | 3 | ctxtype *ctx = vctx; \ | 152 | 3 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 153 | 3 | input, inputLen); \ | 154 | 3 | } |
Unexecuted instantiation: pkcs11c.c:SFTKCipher_Camellia_Encrypt Unexecuted instantiation: pkcs11c.c:SFTKCipher_Camellia_Decrypt pkcs11c.c:SFTKCipher_AES_Encrypt Line | Count | Source | 150 | 2 | { \ | 151 | 2 | ctxtype *ctx = vctx; \ | 152 | 2 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 153 | 2 | input, inputLen); \ | 154 | 2 | } |
pkcs11c.c:SFTKCipher_AES_Decrypt Line | Count | Source | 150 | 5 | { \ | 151 | 5 | ctxtype *ctx = vctx; \ | 152 | 5 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 153 | 5 | input, inputLen); \ | 154 | 5 | } |
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_EncryptKWP Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_DecryptKWP Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_Encrypt Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_Decrypt |
155 | | |
156 | | SFTKCipherWrap(AESKeyWrapContext, AESKeyWrap_EncryptKWP); |
157 | | SFTKCipherWrap(AESKeyWrapContext, AESKeyWrap_DecryptKWP); |
158 | | |
159 | | #define SFTKCipherWrap2(ctxtype, mmm) \ |
160 | | SFTKCipherWrap(ctxtype, mmm##_Encrypt); \ |
161 | | SFTKCipherWrap(ctxtype, mmm##_Decrypt); \ |
162 | | static void SFTKCipher_##mmm##_DestroyContext(void *vctx, PRBool freeit) \ |
163 | 17 | { \ |
164 | 17 | ctxtype *ctx = vctx; \ |
165 | 17 | mmm##_DestroyContext(ctx, freeit); \ |
166 | 17 | } Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC2_DestroyContext Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC4_DestroyContext pkcs11c.c:SFTKCipher_DES_DestroyContext Line | Count | Source | 163 | 3 | { \ | 164 | 3 | ctxtype *ctx = vctx; \ | 165 | 3 | mmm##_DestroyContext(ctx, freeit); \ | 166 | 3 | } |
pkcs11c.c:SFTKCipher_SEED_DestroyContext Line | Count | Source | 163 | 7 | { \ | 164 | 7 | ctxtype *ctx = vctx; \ | 165 | 7 | mmm##_DestroyContext(ctx, freeit); \ | 166 | 7 | } |
Unexecuted instantiation: pkcs11c.c:SFTKCipher_Camellia_DestroyContext pkcs11c.c:SFTKCipher_AES_DestroyContext Line | Count | Source | 163 | 7 | { \ | 164 | 7 | ctxtype *ctx = vctx; \ | 165 | 7 | mmm##_DestroyContext(ctx, freeit); \ | 166 | 7 | } |
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_DestroyContext |
167 | | |
168 | | SFTKCipherWrap2(RC2Context, RC2); |
169 | | SFTKCipherWrap2(RC4Context, RC4); |
170 | | SFTKCipherWrap2(DESContext, DES); |
171 | | SFTKCipherWrap2(SEEDContext, SEED); |
172 | | SFTKCipherWrap2(CamelliaContext, Camellia); |
173 | | SFTKCipherWrap2(AESContext, AES); |
174 | | SFTKCipherWrap2(AESKeyWrapContext, AESKeyWrap); |
175 | | |
176 | | #if NSS_SOFTOKEN_DOES_RC5 |
177 | | SFTKCipherWrap2(RC5Context, RC5); |
178 | | #endif |
179 | | |
180 | | /* |
181 | | * free routines.... Free local type allocated data, and convert |
182 | | * other free routines to the destroy signature. |
183 | | */ |
184 | | static void |
185 | | sftk_FreePrivKey(void *vkey, PRBool freeit) |
186 | 0 | { |
187 | 0 | NSSLOWKEYPrivateKey *key = vkey; |
188 | 0 | nsslowkey_DestroyPrivateKey(key); |
189 | 0 | } |
190 | | |
191 | | static void |
192 | | sftk_Space(void *data, PRBool freeit) |
193 | 69 | { |
194 | 69 | PORT_Free(data); |
195 | 69 | } |
196 | | |
197 | | static void |
198 | | sftk_ZSpace(void *data, PRBool freeit) |
199 | 0 | { |
200 | 0 | size_t len = *(size_t *)data; |
201 | 0 | PORT_ZFree(data, len); |
202 | 0 | } |
203 | | |
204 | | /* |
205 | | * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by |
206 | | * Deprecating a full des key to 40 bit key strenth. |
207 | | */ |
208 | | static CK_RV |
209 | | sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey) |
210 | 0 | { |
211 | 0 | unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae }; |
212 | 0 | unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 }; |
213 | 0 | unsigned char enc_src[8]; |
214 | 0 | unsigned char enc_dest[8]; |
215 | 0 | unsigned int leng, i; |
216 | 0 | DESContext *descx; |
217 | 0 | SECStatus rv; |
218 | 0 | CK_RV crv = CKR_OK; |
219 | | |
220 | | /* zero the parity bits */ |
221 | 0 | for (i = 0; i < 8; i++) { |
222 | 0 | enc_src[i] = cdmfkey[i] & 0xfe; |
223 | 0 | } |
224 | | |
225 | | /* encrypt with key 1 */ |
226 | 0 | descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE); |
227 | 0 | if (descx == NULL) { |
228 | 0 | crv = CKR_HOST_MEMORY; |
229 | 0 | goto done; |
230 | 0 | } |
231 | 0 | rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8); |
232 | 0 | DES_DestroyContext(descx, PR_TRUE); |
233 | 0 | if (rv != SECSuccess) { |
234 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
235 | 0 | goto done; |
236 | 0 | } |
237 | | |
238 | | /* xor source with des, zero the parity bits and deprecate the key*/ |
239 | 0 | for (i = 0; i < 8; i++) { |
240 | 0 | if (i & 1) { |
241 | 0 | enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe; |
242 | 0 | } else { |
243 | 0 | enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e; |
244 | 0 | } |
245 | 0 | } |
246 | | |
247 | | /* encrypt with key 2 */ |
248 | 0 | descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE); |
249 | 0 | if (descx == NULL) { |
250 | 0 | crv = CKR_HOST_MEMORY; |
251 | 0 | goto done; |
252 | 0 | } |
253 | 0 | rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8); |
254 | 0 | DES_DestroyContext(descx, PR_TRUE); |
255 | 0 | if (rv != SECSuccess) { |
256 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
257 | 0 | goto done; |
258 | 0 | } |
259 | | |
260 | | /* set the corret parity on our new des key */ |
261 | 0 | sftk_FormatDESKey(deskey, 8); |
262 | 0 | done: |
263 | 0 | PORT_Memset(enc_src, 0, sizeof enc_src); |
264 | 0 | PORT_Memset(enc_dest, 0, sizeof enc_dest); |
265 | 0 | return crv; |
266 | 0 | } |
267 | | |
268 | | /* NSC_DestroyObject destroys an object. */ |
269 | | CK_RV |
270 | | NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) |
271 | 326 | { |
272 | 326 | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
273 | 326 | SFTKSession *session; |
274 | 326 | SFTKObject *object; |
275 | 326 | SFTKFreeStatus status; |
276 | | |
277 | 326 | CHECK_FORK(); |
278 | | |
279 | 326 | if (slot == NULL) { |
280 | 0 | return CKR_SESSION_HANDLE_INVALID; |
281 | 0 | } |
282 | | /* |
283 | | * This whole block just makes sure we really can destroy the |
284 | | * requested object. |
285 | | */ |
286 | 326 | session = sftk_SessionFromHandle(hSession); |
287 | 326 | if (session == NULL) { |
288 | 0 | return CKR_SESSION_HANDLE_INVALID; |
289 | 0 | } |
290 | | |
291 | 326 | object = sftk_ObjectFromHandle(hObject, session); |
292 | 326 | if (object == NULL) { |
293 | 60 | sftk_FreeSession(session); |
294 | 60 | return CKR_OBJECT_HANDLE_INVALID; |
295 | 60 | } |
296 | | |
297 | | /* don't destroy a private object if we aren't logged in */ |
298 | 266 | if ((!slot->isLoggedIn) && (slot->needLogin) && |
299 | 266 | (sftk_isTrue(object, CKA_PRIVATE))) { |
300 | 0 | sftk_FreeSession(session); |
301 | 0 | sftk_FreeObject(object); |
302 | 0 | return CKR_USER_NOT_LOGGED_IN; |
303 | 0 | } |
304 | | |
305 | | /* don't destroy a token object if we aren't in a rw session */ |
306 | | |
307 | 266 | if (((session->info.flags & CKF_RW_SESSION) == 0) && |
308 | 266 | (sftk_isTrue(object, CKA_TOKEN))) { |
309 | 0 | sftk_FreeSession(session); |
310 | 0 | sftk_FreeObject(object); |
311 | 0 | return CKR_SESSION_READ_ONLY; |
312 | 0 | } |
313 | | |
314 | 266 | sftk_DeleteObject(session, object); |
315 | | |
316 | 266 | sftk_FreeSession(session); |
317 | | |
318 | | /* |
319 | | * get some indication if the object is destroyed. Note: this is not |
320 | | * 100%. Someone may have an object reference outstanding (though that |
321 | | * should not be the case by here. Also note that the object is "half" |
322 | | * destroyed. Our internal representation is destroyed, but it may still |
323 | | * be in the data base. |
324 | | */ |
325 | 266 | status = sftk_FreeObject(object); |
326 | | |
327 | 266 | return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR; |
328 | 266 | } |
329 | | |
330 | | /* |
331 | | * Returns true if "params" contains a valid set of PSS parameters |
332 | | */ |
333 | | static PRBool |
334 | | sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params) |
335 | 0 | { |
336 | 0 | if (!params) { |
337 | 0 | return PR_FALSE; |
338 | 0 | } |
339 | 0 | if (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL || |
340 | 0 | sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) { |
341 | 0 | return PR_FALSE; |
342 | 0 | } |
343 | 0 | return PR_TRUE; |
344 | 0 | } |
345 | | |
346 | | /* |
347 | | * Returns true if "params" contains a valid set of OAEP parameters |
348 | | */ |
349 | | static PRBool |
350 | | sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS *params) |
351 | 0 | { |
352 | 0 | if (!params) { |
353 | 0 | return PR_FALSE; |
354 | 0 | } |
355 | | /* The requirements of ulSourceLen/pSourceData come from PKCS #11, which |
356 | | * state: |
357 | | * If the parameter is empty, pSourceData must be NULL and |
358 | | * ulSourceDataLen must be zero. |
359 | | */ |
360 | 0 | if (params->source != CKZ_DATA_SPECIFIED || |
361 | 0 | (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) || |
362 | 0 | (sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) || |
363 | 0 | (params->ulSourceDataLen == 0 && params->pSourceData != NULL) || |
364 | 0 | (params->ulSourceDataLen != 0 && params->pSourceData == NULL)) { |
365 | 0 | return PR_FALSE; |
366 | 0 | } |
367 | 0 | return PR_TRUE; |
368 | 0 | } |
369 | | |
370 | | /* |
371 | | * return a context based on the SFTKContext type. |
372 | | */ |
373 | | SFTKSessionContext * |
374 | | sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type) |
375 | 1.55k | { |
376 | 1.55k | switch (type) { |
377 | 27 | case SFTK_ENCRYPT: |
378 | 74 | case SFTK_DECRYPT: |
379 | 74 | case SFTK_MESSAGE_ENCRYPT: |
380 | 74 | case SFTK_MESSAGE_DECRYPT: |
381 | 74 | return session->enc_context; |
382 | 795 | case SFTK_HASH: |
383 | 795 | return session->hash_context; |
384 | 689 | case SFTK_SIGN: |
385 | 689 | case SFTK_SIGN_RECOVER: |
386 | 689 | case SFTK_VERIFY: |
387 | 689 | case SFTK_VERIFY_RECOVER: |
388 | 689 | case SFTK_MESSAGE_SIGN: |
389 | 689 | case SFTK_MESSAGE_VERIFY: |
390 | 689 | return session->hash_context; |
391 | 1.55k | } |
392 | 0 | return NULL; |
393 | 1.55k | } |
394 | | |
395 | | /* |
396 | | * change a context based on the SFTKContext type. |
397 | | */ |
398 | | void |
399 | | sftk_SetContextByType(SFTKSession *session, SFTKContextType type, |
400 | | SFTKSessionContext *context) |
401 | 306 | { |
402 | 306 | switch (type) { |
403 | 11 | case SFTK_ENCRYPT: |
404 | 40 | case SFTK_DECRYPT: |
405 | 40 | case SFTK_MESSAGE_ENCRYPT: |
406 | 40 | case SFTK_MESSAGE_DECRYPT: |
407 | 40 | session->enc_context = context; |
408 | 40 | break; |
409 | 128 | case SFTK_HASH: |
410 | 128 | session->hash_context = context; |
411 | 128 | break; |
412 | 138 | case SFTK_SIGN: |
413 | 138 | case SFTK_SIGN_RECOVER: |
414 | 138 | case SFTK_VERIFY: |
415 | 138 | case SFTK_VERIFY_RECOVER: |
416 | 138 | case SFTK_MESSAGE_SIGN: |
417 | 138 | case SFTK_MESSAGE_VERIFY: |
418 | 138 | session->hash_context = context; |
419 | 138 | break; |
420 | 306 | } |
421 | 306 | return; |
422 | 306 | } |
423 | | |
424 | | /* |
425 | | * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal, |
426 | | * and C_XXX function. The function takes a session handle, the context type, |
427 | | * and wether or not the session needs to be multipart. It returns the context, |
428 | | * and optionally returns the session pointer (if sessionPtr != NULL) if session |
429 | | * pointer is returned, the caller is responsible for freeing it. |
430 | | */ |
431 | | CK_RV |
432 | | sftk_GetContext(CK_SESSION_HANDLE handle, SFTKSessionContext **contextPtr, |
433 | | SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr) |
434 | 1.35k | { |
435 | 1.35k | SFTKSession *session; |
436 | 1.35k | SFTKSessionContext *context; |
437 | | |
438 | 1.35k | session = sftk_SessionFromHandle(handle); |
439 | 1.35k | if (session == NULL) |
440 | 0 | return CKR_SESSION_HANDLE_INVALID; |
441 | 1.35k | context = sftk_ReturnContextByType(session, type); |
442 | | /* make sure the context is valid */ |
443 | 1.35k | if ((context == NULL) || (context->type != type) || (needMulti && !(context->multi))) { |
444 | 0 | sftk_FreeSession(session); |
445 | 0 | return CKR_OPERATION_NOT_INITIALIZED; |
446 | 0 | } |
447 | 1.35k | *contextPtr = context; |
448 | 1.35k | if (sessionPtr != NULL) { |
449 | 674 | *sessionPtr = session; |
450 | 676 | } else { |
451 | 676 | sftk_FreeSession(session); |
452 | 676 | } |
453 | 1.35k | return CKR_OK; |
454 | 1.35k | } |
455 | | |
456 | | /** Terminate operation (in the PKCS#11 spec sense). |
457 | | * Intuitive name for FreeContext/SetNullContext pair. |
458 | | */ |
459 | | void |
460 | | sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype, |
461 | | SFTKSessionContext *context) |
462 | 149 | { |
463 | 149 | session->lastOpWasFIPS = context->isFIPS; |
464 | 149 | sftk_FreeContext(context); |
465 | 149 | sftk_SetContextByType(session, ctype, NULL); |
466 | 149 | } |
467 | | |
468 | | /* |
469 | | ************** Crypto Functions: Encrypt ************************ |
470 | | */ |
471 | | |
472 | | /* |
473 | | * All the NSC_InitXXX functions have a set of common checks and processing they |
474 | | * all need to do at the beginning. This is done here. |
475 | | */ |
476 | | CK_RV |
477 | | sftk_InitGeneric(SFTKSession *session, CK_MECHANISM *pMechanism, |
478 | | SFTKSessionContext **contextPtr, |
479 | | SFTKContextType ctype, SFTKObject **keyPtr, |
480 | | CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr, |
481 | | CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation) |
482 | 208 | { |
483 | 208 | SFTKObject *key = NULL; |
484 | 208 | SFTKAttribute *att; |
485 | 208 | SFTKSessionContext *context; |
486 | | |
487 | | /* We can only init if there is not current context active */ |
488 | 208 | if (sftk_ReturnContextByType(session, ctype) != NULL) { |
489 | 0 | return CKR_OPERATION_ACTIVE; |
490 | 0 | } |
491 | | |
492 | | /* find the key */ |
493 | 208 | if (keyPtr) { |
494 | 144 | key = sftk_ObjectFromHandle(hKey, session); |
495 | 144 | if (key == NULL) { |
496 | 0 | return CKR_KEY_HANDLE_INVALID; |
497 | 0 | } |
498 | | |
499 | | /* make sure it's a valid key for this operation */ |
500 | 144 | if (((key->objclass != CKO_SECRET_KEY) && |
501 | 144 | (key->objclass != pubKeyType)) || |
502 | 144 | !sftk_isTrue(key, operation)) { |
503 | 0 | sftk_FreeObject(key); |
504 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
505 | 0 | } |
506 | | /* get the key type */ |
507 | 144 | att = sftk_FindAttribute(key, CKA_KEY_TYPE); |
508 | 144 | if (att == NULL) { |
509 | 0 | sftk_FreeObject(key); |
510 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
511 | 0 | } |
512 | 144 | PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE)); |
513 | 144 | if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) { |
514 | 0 | sftk_FreeAttribute(att); |
515 | 0 | sftk_FreeObject(key); |
516 | 0 | return CKR_ATTRIBUTE_VALUE_INVALID; |
517 | 0 | } |
518 | 144 | PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE)); |
519 | 144 | sftk_FreeAttribute(att); |
520 | 144 | *keyPtr = key; |
521 | 144 | } |
522 | | |
523 | | /* allocate the context structure */ |
524 | 208 | context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext)); |
525 | 208 | if (context == NULL) { |
526 | 0 | if (key) |
527 | 0 | sftk_FreeObject(key); |
528 | 0 | return CKR_HOST_MEMORY; |
529 | 0 | } |
530 | 208 | context->type = ctype; |
531 | 208 | context->multi = PR_TRUE; |
532 | 208 | context->rsa = PR_FALSE; |
533 | 208 | context->cipherInfo = NULL; |
534 | 208 | context->hashInfo = NULL; |
535 | 208 | context->doPad = PR_FALSE; |
536 | 208 | context->padDataLength = 0; |
537 | 208 | context->key = key; |
538 | 208 | context->blockSize = 0; |
539 | 208 | context->maxLen = 0; |
540 | 208 | context->isFIPS = sftk_operationIsFIPS(session->slot, pMechanism, |
541 | 208 | operation, key); |
542 | 208 | *contextPtr = context; |
543 | 208 | return CKR_OK; |
544 | 208 | } |
545 | | |
546 | | static int |
547 | | sftk_aes_mode(CK_MECHANISM_TYPE mechanism) |
548 | 18 | { |
549 | 18 | switch (mechanism) { |
550 | 0 | case CKM_AES_CBC_PAD: |
551 | 2 | case CKM_AES_CBC: |
552 | 2 | return NSS_AES_CBC; |
553 | 4 | case CKM_AES_ECB: |
554 | 4 | return NSS_AES; |
555 | 0 | case CKM_AES_CTS: |
556 | 0 | return NSS_AES_CTS; |
557 | 0 | case CKM_AES_CTR: |
558 | 0 | return NSS_AES_CTR; |
559 | 12 | case CKM_AES_GCM: |
560 | 12 | return NSS_AES_GCM; |
561 | 18 | } |
562 | 0 | return -1; |
563 | 18 | } |
564 | | |
565 | | static SECStatus |
566 | | sftk_RSAEncryptRaw(void *ctx, unsigned char *output, |
567 | | unsigned int *outputLen, unsigned int maxLen, |
568 | | const unsigned char *input, unsigned int inputLen) |
569 | 0 | { |
570 | 0 | NSSLOWKEYPublicKey *key = ctx; |
571 | 0 | SECStatus rv = SECFailure; |
572 | |
|
573 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
574 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
575 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
576 | 0 | return SECFailure; |
577 | 0 | } |
578 | | |
579 | 0 | rv = RSA_EncryptRaw(&key->u.rsa, output, outputLen, maxLen, input, |
580 | 0 | inputLen); |
581 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
582 | 0 | sftk_fatalError = PR_TRUE; |
583 | 0 | } |
584 | |
|
585 | 0 | return rv; |
586 | 0 | } |
587 | | |
588 | | static SECStatus |
589 | | sftk_RSADecryptRaw(void *ctx, unsigned char *output, |
590 | | unsigned int *outputLen, unsigned int maxLen, |
591 | | const unsigned char *input, unsigned int inputLen) |
592 | 0 | { |
593 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
594 | 0 | SECStatus rv = SECFailure; |
595 | |
|
596 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
597 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
598 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
599 | 0 | return SECFailure; |
600 | 0 | } |
601 | | |
602 | 0 | rv = RSA_DecryptRaw(&key->u.rsa, output, outputLen, maxLen, input, |
603 | 0 | inputLen); |
604 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
605 | 0 | sftk_fatalError = PR_TRUE; |
606 | 0 | } |
607 | |
|
608 | 0 | return rv; |
609 | 0 | } |
610 | | |
611 | | static SECStatus |
612 | | sftk_RSAEncrypt(void *ctx, unsigned char *output, |
613 | | unsigned int *outputLen, unsigned int maxLen, |
614 | | const unsigned char *input, unsigned int inputLen) |
615 | 0 | { |
616 | 0 | NSSLOWKEYPublicKey *key = ctx; |
617 | 0 | SECStatus rv = SECFailure; |
618 | |
|
619 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
620 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
621 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
622 | 0 | return SECFailure; |
623 | 0 | } |
624 | | |
625 | 0 | rv = RSA_EncryptBlock(&key->u.rsa, output, outputLen, maxLen, input, |
626 | 0 | inputLen); |
627 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
628 | 0 | sftk_fatalError = PR_TRUE; |
629 | 0 | } |
630 | |
|
631 | 0 | return rv; |
632 | 0 | } |
633 | | |
634 | | static SECStatus |
635 | | sftk_RSADecrypt(void *ctx, unsigned char *output, |
636 | | unsigned int *outputLen, unsigned int maxLen, |
637 | | const unsigned char *input, unsigned int inputLen) |
638 | 0 | { |
639 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
640 | 0 | SECStatus rv = SECFailure; |
641 | |
|
642 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
643 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
644 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
645 | 0 | return SECFailure; |
646 | 0 | } |
647 | | |
648 | 0 | rv = RSA_DecryptBlock(&key->u.rsa, output, outputLen, maxLen, input, |
649 | 0 | inputLen); |
650 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
651 | 0 | sftk_fatalError = PR_TRUE; |
652 | 0 | } |
653 | |
|
654 | 0 | return rv; |
655 | 0 | } |
656 | | |
657 | | static void |
658 | | sftk_freeRSAOAEPInfo(void *ctx, PRBool freeit) |
659 | 0 | { |
660 | 0 | SFTKOAEPInfo *info = ctx; |
661 | 0 | PORT_ZFree(info->params.pSourceData, info->params.ulSourceDataLen); |
662 | 0 | PORT_ZFree(info, sizeof(SFTKOAEPInfo)); |
663 | 0 | } |
664 | | |
665 | | static SECStatus |
666 | | sftk_RSAEncryptOAEP(void *ctx, unsigned char *output, |
667 | | unsigned int *outputLen, unsigned int maxLen, |
668 | | const unsigned char *input, unsigned int inputLen) |
669 | 0 | { |
670 | 0 | SFTKOAEPInfo *info = ctx; |
671 | 0 | HASH_HashType hashAlg; |
672 | 0 | HASH_HashType maskHashAlg; |
673 | |
|
674 | 0 | PORT_Assert(info->key.pub->keyType == NSSLOWKEYRSAKey); |
675 | 0 | if (info->key.pub->keyType != NSSLOWKEYRSAKey) { |
676 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
677 | 0 | return SECFailure; |
678 | 0 | } |
679 | | |
680 | 0 | hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg); |
681 | 0 | maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf); |
682 | |
|
683 | 0 | return RSA_EncryptOAEP(&info->key.pub->u.rsa, hashAlg, maskHashAlg, |
684 | 0 | (const unsigned char *)info->params.pSourceData, |
685 | 0 | info->params.ulSourceDataLen, NULL, 0, |
686 | 0 | output, outputLen, maxLen, input, inputLen); |
687 | 0 | } |
688 | | |
689 | | static SECStatus |
690 | | sftk_RSADecryptOAEP(void *ctx, unsigned char *output, |
691 | | unsigned int *outputLen, unsigned int maxLen, |
692 | | const unsigned char *input, unsigned int inputLen) |
693 | 0 | { |
694 | 0 | SFTKOAEPInfo *info = ctx; |
695 | 0 | SECStatus rv = SECFailure; |
696 | 0 | HASH_HashType hashAlg; |
697 | 0 | HASH_HashType maskHashAlg; |
698 | |
|
699 | 0 | PORT_Assert(info->key.priv->keyType == NSSLOWKEYRSAKey); |
700 | 0 | if (info->key.priv->keyType != NSSLOWKEYRSAKey) { |
701 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
702 | 0 | return SECFailure; |
703 | 0 | } |
704 | | |
705 | 0 | hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg); |
706 | 0 | maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf); |
707 | |
|
708 | 0 | rv = RSA_DecryptOAEP(&info->key.priv->u.rsa, hashAlg, maskHashAlg, |
709 | 0 | (const unsigned char *)info->params.pSourceData, |
710 | 0 | info->params.ulSourceDataLen, |
711 | 0 | output, outputLen, maxLen, input, inputLen); |
712 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
713 | 0 | sftk_fatalError = PR_TRUE; |
714 | 0 | } |
715 | 0 | return rv; |
716 | 0 | } |
717 | | |
718 | | static SFTKChaCha20Poly1305Info * |
719 | | sftk_ChaCha20Poly1305_CreateContext(const unsigned char *key, |
720 | | unsigned int keyLen, |
721 | | const CK_NSS_AEAD_PARAMS *params) |
722 | 14 | { |
723 | 14 | SFTKChaCha20Poly1305Info *ctx; |
724 | | |
725 | 14 | if (params->ulNonceLen != sizeof(ctx->nonce)) { |
726 | 6 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
727 | 6 | return NULL; |
728 | 6 | } |
729 | | |
730 | 8 | ctx = PORT_New(SFTKChaCha20Poly1305Info); |
731 | 8 | if (ctx == NULL) { |
732 | 0 | return NULL; |
733 | 0 | } |
734 | | |
735 | 8 | if (ChaCha20Poly1305_InitContext(&ctx->freeblCtx, key, keyLen, |
736 | 8 | params->ulTagLen) != SECSuccess) { |
737 | 1 | PORT_Free(ctx); |
738 | 1 | return NULL; |
739 | 1 | } |
740 | | |
741 | 7 | PORT_Memcpy(ctx->nonce, params->pNonce, sizeof(ctx->nonce)); |
742 | | |
743 | | /* AAD data and length must both be null, or both non-null. */ |
744 | 7 | PORT_Assert((params->pAAD == NULL) == (params->ulAADLen == 0)); |
745 | | |
746 | 7 | if (params->ulAADLen > sizeof(ctx->ad)) { |
747 | | /* Need to allocate an overflow buffer for the additional data. */ |
748 | 0 | ctx->adOverflow = (unsigned char *)PORT_Alloc(params->ulAADLen); |
749 | 0 | if (!ctx->adOverflow) { |
750 | 0 | PORT_Free(ctx); |
751 | 0 | return NULL; |
752 | 0 | } |
753 | 0 | PORT_Memcpy(ctx->adOverflow, params->pAAD, params->ulAADLen); |
754 | 7 | } else { |
755 | 7 | ctx->adOverflow = NULL; |
756 | 7 | if (params->pAAD) { |
757 | 0 | PORT_Memcpy(ctx->ad, params->pAAD, params->ulAADLen); |
758 | 0 | } |
759 | 7 | } |
760 | 7 | ctx->adLen = params->ulAADLen; |
761 | | |
762 | 7 | return ctx; |
763 | 7 | } |
764 | | |
765 | | static void |
766 | | sftk_ChaCha20Poly1305_DestroyContext(void *vctx, |
767 | | PRBool freeit) |
768 | 7 | { |
769 | 7 | SFTKChaCha20Poly1305Info *ctx = vctx; |
770 | 7 | ChaCha20Poly1305_DestroyContext(&ctx->freeblCtx, PR_FALSE); |
771 | 7 | if (ctx->adOverflow != NULL) { |
772 | 0 | PORT_ZFree(ctx->adOverflow, ctx->adLen); |
773 | 0 | ctx->adOverflow = NULL; |
774 | 7 | } else { |
775 | 7 | PORT_Memset(ctx->ad, 0, ctx->adLen); |
776 | 7 | } |
777 | 7 | ctx->adLen = 0; |
778 | 7 | if (freeit) { |
779 | 7 | PORT_Free(ctx); |
780 | 7 | } |
781 | 7 | } |
782 | | |
783 | | static SECStatus |
784 | | sftk_ChaCha20Poly1305_Encrypt(void *vctx, |
785 | | unsigned char *output, unsigned int *outputLen, |
786 | | unsigned int maxOutputLen, |
787 | | const unsigned char *input, unsigned int inputLen) |
788 | 0 | { |
789 | 0 | const SFTKChaCha20Poly1305Info *ctx = vctx; |
790 | 0 | const unsigned char *ad = ctx->adOverflow; |
791 | |
|
792 | 0 | if (ad == NULL) { |
793 | 0 | ad = ctx->ad; |
794 | 0 | } |
795 | |
|
796 | 0 | return ChaCha20Poly1305_Seal(&ctx->freeblCtx, output, outputLen, |
797 | 0 | maxOutputLen, input, inputLen, ctx->nonce, |
798 | 0 | sizeof(ctx->nonce), ad, ctx->adLen); |
799 | 0 | } |
800 | | |
801 | | static SECStatus |
802 | | sftk_ChaCha20Poly1305_Decrypt(void *vctx, |
803 | | unsigned char *output, unsigned int *outputLen, |
804 | | unsigned int maxOutputLen, |
805 | | const unsigned char *input, unsigned int inputLen) |
806 | 7 | { |
807 | 7 | const SFTKChaCha20Poly1305Info *ctx = vctx; |
808 | 7 | const unsigned char *ad = ctx->adOverflow; |
809 | | |
810 | 7 | if (ad == NULL) { |
811 | 7 | ad = ctx->ad; |
812 | 7 | } |
813 | | |
814 | 7 | return ChaCha20Poly1305_Open(&ctx->freeblCtx, output, outputLen, |
815 | 7 | maxOutputLen, input, inputLen, ctx->nonce, |
816 | 7 | sizeof(ctx->nonce), ad, ctx->adLen); |
817 | 7 | } |
818 | | |
819 | | static SECStatus |
820 | | sftk_ChaCha20Ctr(void *vctx, |
821 | | unsigned char *output, unsigned int *outputLen, |
822 | | unsigned int maxOutputLen, |
823 | | const unsigned char *input, unsigned int inputLen) |
824 | 0 | { |
825 | 0 | if (maxOutputLen < inputLen) { |
826 | 0 | PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
827 | 0 | return SECFailure; |
828 | 0 | } |
829 | 0 | SFTKChaCha20CtrInfo *ctx = vctx; |
830 | 0 | ChaCha20_Xor(output, input, inputLen, ctx->key, |
831 | 0 | ctx->nonce, ctx->counter); |
832 | 0 | *outputLen = inputLen; |
833 | 0 | return SECSuccess; |
834 | 0 | } |
835 | | |
836 | | static void |
837 | | sftk_ChaCha20Ctr_DestroyContext(void *vctx, |
838 | | PRBool freeit) |
839 | 0 | { |
840 | 0 | SFTKChaCha20CtrInfo *ctx = vctx; |
841 | 0 | memset(ctx, 0, sizeof(SFTKChaCha20CtrInfo)); |
842 | 0 | if (freeit) { |
843 | 0 | PORT_Free(ctx); |
844 | 0 | } |
845 | 0 | } |
846 | | |
847 | | /** NSC_CryptInit initializes an encryption/Decryption operation. |
848 | | * |
849 | | * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey. |
850 | | * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block |
851 | | * ciphers MAC'ing. |
852 | | */ |
853 | | CK_RV |
854 | | sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
855 | | CK_OBJECT_HANDLE hKey, |
856 | | CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage, |
857 | | SFTKContextType contextType, PRBool isEncrypt) |
858 | 61 | { |
859 | 61 | SFTKSession *session; |
860 | 61 | SFTKObject *key; |
861 | 61 | SFTKSessionContext *context; |
862 | 61 | SFTKAttribute *att; |
863 | 61 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
864 | 61 | CK_RC2_CBC_PARAMS *rc2_param; |
865 | 61 | unsigned effectiveKeyLength; |
866 | 61 | #endif |
867 | | #if NSS_SOFTOKEN_DOES_RC5 |
868 | | CK_RC5_CBC_PARAMS *rc5_param; |
869 | | SECItem rc5Key; |
870 | | #endif |
871 | 61 | CK_NSS_GCM_PARAMS nss_gcm_param; |
872 | 61 | void *aes_param; |
873 | 61 | CK_NSS_AEAD_PARAMS nss_aead_params; |
874 | 61 | CK_NSS_AEAD_PARAMS *nss_aead_params_ptr = NULL; |
875 | 61 | CK_KEY_TYPE key_type; |
876 | 61 | CK_RV crv = CKR_OK; |
877 | 61 | unsigned char newdeskey[24]; |
878 | 61 | PRBool useNewKey = PR_FALSE; |
879 | 61 | int t; |
880 | | |
881 | 61 | if (!pMechanism) { |
882 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
883 | 0 | } |
884 | | |
885 | 61 | crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage); |
886 | 61 | if (crv != CKR_OK) |
887 | 12 | return crv; |
888 | | |
889 | 49 | session = sftk_SessionFromHandle(hSession); |
890 | 49 | if (session == NULL) |
891 | 0 | return CKR_SESSION_HANDLE_INVALID; |
892 | | |
893 | 49 | crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key, |
894 | 49 | hKey, &key_type, |
895 | 49 | isEncrypt ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY, |
896 | 49 | keyUsage); |
897 | | |
898 | 49 | if (crv != CKR_OK) { |
899 | 0 | sftk_FreeSession(session); |
900 | 0 | return crv; |
901 | 0 | } |
902 | | |
903 | 49 | context->doPad = PR_FALSE; |
904 | 49 | switch (pMechanism->mechanism) { |
905 | 0 | case CKM_RSA_PKCS: |
906 | 0 | case CKM_RSA_X_509: |
907 | 0 | if (key_type != CKK_RSA) { |
908 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
909 | 0 | break; |
910 | 0 | } |
911 | 0 | context->multi = PR_FALSE; |
912 | 0 | context->rsa = PR_TRUE; |
913 | 0 | if (isEncrypt) { |
914 | 0 | NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); |
915 | 0 | if (pubKey == NULL) { |
916 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
917 | 0 | break; |
918 | 0 | } |
919 | 0 | context->maxLen = nsslowkey_PublicModulusLen(pubKey); |
920 | 0 | context->cipherInfo = (void *)pubKey; |
921 | 0 | context->update = pMechanism->mechanism == CKM_RSA_X_509 |
922 | 0 | ? sftk_RSAEncryptRaw |
923 | 0 | : sftk_RSAEncrypt; |
924 | 0 | } else { |
925 | 0 | NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key, CKK_RSA, &crv); |
926 | 0 | if (privKey == NULL) { |
927 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
928 | 0 | break; |
929 | 0 | } |
930 | 0 | context->maxLen = nsslowkey_PrivateModulusLen(privKey); |
931 | 0 | context->cipherInfo = (void *)privKey; |
932 | 0 | context->update = pMechanism->mechanism == CKM_RSA_X_509 |
933 | 0 | ? sftk_RSADecryptRaw |
934 | 0 | : sftk_RSADecrypt; |
935 | 0 | } |
936 | 0 | context->destroy = sftk_Null; |
937 | 0 | break; |
938 | 0 | case CKM_RSA_PKCS_OAEP: |
939 | 0 | if (key_type != CKK_RSA) { |
940 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
941 | 0 | break; |
942 | 0 | } |
943 | 0 | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) || |
944 | 0 | !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter)) { |
945 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
946 | 0 | break; |
947 | 0 | } |
948 | 0 | context->multi = PR_FALSE; |
949 | 0 | context->rsa = PR_TRUE; |
950 | 0 | { |
951 | 0 | SFTKOAEPInfo *info; |
952 | 0 | CK_RSA_PKCS_OAEP_PARAMS *params = |
953 | 0 | (CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter; |
954 | | /* make a copy of the source data value for future |
955 | | * use (once the user has reclaimed his data in pParameter)*/ |
956 | 0 | void *newSource = NULL; |
957 | 0 | if (params->pSourceData) { |
958 | 0 | newSource = PORT_Alloc(params->ulSourceDataLen); |
959 | 0 | if (newSource == NULL) { |
960 | 0 | crv = CKR_HOST_MEMORY; |
961 | 0 | break; |
962 | 0 | } |
963 | 0 | PORT_Memcpy(newSource, params->pSourceData, params->ulSourceDataLen); |
964 | 0 | } |
965 | 0 | info = PORT_New(SFTKOAEPInfo); |
966 | 0 | if (info == NULL) { |
967 | 0 | PORT_ZFree(newSource, params->ulSourceDataLen); |
968 | 0 | crv = CKR_HOST_MEMORY; |
969 | 0 | break; |
970 | 0 | } |
971 | 0 | info->params = *params; |
972 | 0 | info->params.pSourceData = newSource; |
973 | 0 | info->isEncrypt = isEncrypt; |
974 | | |
975 | | /* now setup encryption and decryption contexts */ |
976 | 0 | if (isEncrypt) { |
977 | 0 | info->key.pub = sftk_GetPubKey(key, CKK_RSA, &crv); |
978 | 0 | if (info->key.pub == NULL) { |
979 | 0 | sftk_freeRSAOAEPInfo(info, PR_TRUE); |
980 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
981 | 0 | break; |
982 | 0 | } |
983 | 0 | context->update = sftk_RSAEncryptOAEP; |
984 | 0 | context->maxLen = nsslowkey_PublicModulusLen(info->key.pub); |
985 | 0 | } else { |
986 | 0 | info->key.priv = sftk_GetPrivKey(key, CKK_RSA, &crv); |
987 | 0 | if (info->key.priv == NULL) { |
988 | 0 | sftk_freeRSAOAEPInfo(info, PR_TRUE); |
989 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
990 | 0 | break; |
991 | 0 | } |
992 | 0 | context->update = sftk_RSADecryptOAEP; |
993 | 0 | context->maxLen = nsslowkey_PrivateModulusLen(info->key.priv); |
994 | 0 | } |
995 | 0 | context->cipherInfo = info; |
996 | 0 | } |
997 | 0 | context->destroy = sftk_freeRSAOAEPInfo; |
998 | 0 | break; |
999 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
1000 | 0 | case CKM_RC2_CBC_PAD: |
1001 | 0 | context->doPad = PR_TRUE; |
1002 | | /* fall thru */ |
1003 | 0 | case CKM_RC2_ECB: |
1004 | 0 | case CKM_RC2_CBC: |
1005 | 0 | context->blockSize = 8; |
1006 | 0 | if (key_type != CKK_RC2) { |
1007 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1008 | 0 | break; |
1009 | 0 | } |
1010 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
1011 | 0 | if (att == NULL) { |
1012 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1013 | 0 | break; |
1014 | 0 | } |
1015 | | |
1016 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_CBC_PARAMS))) { |
1017 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1018 | 0 | break; |
1019 | 0 | } |
1020 | 0 | rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter; |
1021 | 0 | effectiveKeyLength = (rc2_param->ulEffectiveBits + 7) / 8; |
1022 | 0 | context->cipherInfo = |
1023 | 0 | RC2_CreateContext((unsigned char *)att->attrib.pValue, |
1024 | 0 | att->attrib.ulValueLen, rc2_param->iv, |
1025 | 0 | pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : NSS_RC2_CBC, effectiveKeyLength); |
1026 | 0 | sftk_FreeAttribute(att); |
1027 | 0 | if (context->cipherInfo == NULL) { |
1028 | 0 | crv = CKR_HOST_MEMORY; |
1029 | 0 | break; |
1030 | 0 | } |
1031 | 0 | context->update = isEncrypt ? SFTKCipher_RC2_Encrypt : SFTKCipher_RC2_Decrypt; |
1032 | 0 | context->destroy = SFTKCipher_RC2_DestroyContext; |
1033 | 0 | break; |
1034 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
1035 | | |
1036 | | #if NSS_SOFTOKEN_DOES_RC5 |
1037 | | case CKM_RC5_CBC_PAD: |
1038 | | context->doPad = PR_TRUE; |
1039 | | /* fall thru */ |
1040 | | case CKM_RC5_ECB: |
1041 | | case CKM_RC5_CBC: |
1042 | | if (key_type != CKK_RC5) { |
1043 | | crv = CKR_KEY_TYPE_INCONSISTENT; |
1044 | | break; |
1045 | | } |
1046 | | att = sftk_FindAttribute(key, CKA_VALUE); |
1047 | | if (att == NULL) { |
1048 | | crv = CKR_KEY_HANDLE_INVALID; |
1049 | | break; |
1050 | | } |
1051 | | |
1052 | | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_CBC_PARAMS))) { |
1053 | | crv = CKR_MECHANISM_PARAM_INVALID; |
1054 | | break; |
1055 | | } |
1056 | | rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter; |
1057 | | context->blockSize = rc5_param->ulWordsize * 2; |
1058 | | rc5Key.data = (unsigned char *)att->attrib.pValue; |
1059 | | rc5Key.len = att->attrib.ulValueLen; |
1060 | | context->cipherInfo = RC5_CreateContext(&rc5Key, rc5_param->ulRounds, |
1061 | | rc5_param->ulWordsize, rc5_param->pIv, |
1062 | | pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC); |
1063 | | sftk_FreeAttribute(att); |
1064 | | if (context->cipherInfo == NULL) { |
1065 | | crv = CKR_HOST_MEMORY; |
1066 | | break; |
1067 | | } |
1068 | | context->update = isEncrypt ? SFTKCipher_RC5_Encrypt : SFTKCipher_RC5_Decrypt; |
1069 | | context->destroy = SFTKCipher_RC5_DestroyContext; |
1070 | | break; |
1071 | | #endif |
1072 | 0 | case CKM_RC4: |
1073 | 0 | if (key_type != CKK_RC4) { |
1074 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1075 | 0 | break; |
1076 | 0 | } |
1077 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
1078 | 0 | if (att == NULL) { |
1079 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1080 | 0 | break; |
1081 | 0 | } |
1082 | 0 | context->cipherInfo = |
1083 | 0 | RC4_CreateContext((unsigned char *)att->attrib.pValue, |
1084 | 0 | att->attrib.ulValueLen); |
1085 | 0 | sftk_FreeAttribute(att); |
1086 | 0 | if (context->cipherInfo == NULL) { |
1087 | 0 | crv = CKR_HOST_MEMORY; /* WRONG !!! */ |
1088 | 0 | break; |
1089 | 0 | } |
1090 | 0 | context->update = isEncrypt ? SFTKCipher_RC4_Encrypt : SFTKCipher_RC4_Decrypt; |
1091 | 0 | context->destroy = SFTKCipher_RC4_DestroyContext; |
1092 | 0 | break; |
1093 | 0 | case CKM_CDMF_CBC_PAD: |
1094 | 0 | context->doPad = PR_TRUE; |
1095 | | /* fall thru */ |
1096 | 0 | case CKM_CDMF_ECB: |
1097 | 0 | case CKM_CDMF_CBC: |
1098 | 0 | if (key_type != CKK_CDMF) { |
1099 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1100 | 0 | break; |
1101 | 0 | } |
1102 | 0 | t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC; |
1103 | 0 | goto finish_des; |
1104 | 2 | case CKM_DES_ECB: |
1105 | 2 | if (key_type != CKK_DES) { |
1106 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1107 | 0 | break; |
1108 | 0 | } |
1109 | 2 | t = NSS_DES; |
1110 | 2 | goto finish_des; |
1111 | 0 | case CKM_DES_CBC_PAD: |
1112 | 0 | context->doPad = PR_TRUE; |
1113 | | /* fall thru */ |
1114 | 2 | case CKM_DES_CBC: |
1115 | 2 | if (key_type != CKK_DES) { |
1116 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1117 | 0 | break; |
1118 | 0 | } |
1119 | 2 | t = NSS_DES_CBC; |
1120 | 2 | goto finish_des; |
1121 | 0 | case CKM_DES3_ECB: |
1122 | 0 | if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { |
1123 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1124 | 0 | break; |
1125 | 0 | } |
1126 | 0 | t = NSS_DES_EDE3; |
1127 | 0 | goto finish_des; |
1128 | 0 | case CKM_DES3_CBC_PAD: |
1129 | 0 | context->doPad = PR_TRUE; |
1130 | | /* fall thru */ |
1131 | 0 | case CKM_DES3_CBC: |
1132 | 0 | if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { |
1133 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1134 | 0 | break; |
1135 | 0 | } |
1136 | 0 | t = NSS_DES_EDE3_CBC; |
1137 | 4 | finish_des: |
1138 | 4 | if ((t != NSS_DES && t != NSS_DES_EDE3) && (pMechanism->pParameter == NULL || |
1139 | 2 | pMechanism->ulParameterLen < 8)) { |
1140 | 1 | crv = CKR_DOMAIN_PARAMS_INVALID; |
1141 | 1 | break; |
1142 | 1 | } |
1143 | 3 | context->blockSize = 8; |
1144 | 3 | att = sftk_FindAttribute(key, CKA_VALUE); |
1145 | 3 | if (att == NULL) { |
1146 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1147 | 0 | break; |
1148 | 0 | } |
1149 | 3 | if (key_type == CKK_DES2 && |
1150 | 3 | (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) { |
1151 | | /* extend DES2 key to DES3 key. */ |
1152 | 0 | memcpy(newdeskey, att->attrib.pValue, 16); |
1153 | 0 | memcpy(newdeskey + 16, newdeskey, 8); |
1154 | 0 | useNewKey = PR_TRUE; |
1155 | 3 | } else if (key_type == CKK_CDMF) { |
1156 | 0 | crv = sftk_cdmf2des((unsigned char *)att->attrib.pValue, newdeskey); |
1157 | 0 | if (crv != CKR_OK) { |
1158 | 0 | sftk_FreeAttribute(att); |
1159 | 0 | break; |
1160 | 0 | } |
1161 | 0 | useNewKey = PR_TRUE; |
1162 | 0 | } |
1163 | 3 | context->cipherInfo = DES_CreateContext( |
1164 | 3 | useNewKey ? newdeskey : (unsigned char *)att->attrib.pValue, |
1165 | 3 | (unsigned char *)pMechanism->pParameter, t, isEncrypt); |
1166 | 3 | if (useNewKey) |
1167 | 0 | memset(newdeskey, 0, sizeof newdeskey); |
1168 | 3 | sftk_FreeAttribute(att); |
1169 | 3 | if (context->cipherInfo == NULL) { |
1170 | 0 | crv = CKR_HOST_MEMORY; |
1171 | 0 | break; |
1172 | 0 | } |
1173 | 3 | context->update = isEncrypt ? SFTKCipher_DES_Encrypt : SFTKCipher_DES_Decrypt; |
1174 | 3 | context->destroy = SFTKCipher_DES_DestroyContext; |
1175 | 3 | break; |
1176 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
1177 | 0 | case CKM_SEED_CBC_PAD: |
1178 | 0 | context->doPad = PR_TRUE; |
1179 | | /* fall thru */ |
1180 | 4 | case CKM_SEED_CBC: |
1181 | 4 | if (!pMechanism->pParameter || |
1182 | 4 | pMechanism->ulParameterLen != 16) { |
1183 | 2 | crv = CKR_MECHANISM_PARAM_INVALID; |
1184 | 2 | break; |
1185 | 2 | } |
1186 | | /* fall thru */ |
1187 | 7 | case CKM_SEED_ECB: |
1188 | 7 | context->blockSize = 16; |
1189 | 7 | if (key_type != CKK_SEED) { |
1190 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1191 | 0 | break; |
1192 | 0 | } |
1193 | 7 | att = sftk_FindAttribute(key, CKA_VALUE); |
1194 | 7 | if (att == NULL) { |
1195 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1196 | 0 | break; |
1197 | 0 | } |
1198 | 7 | context->cipherInfo = SEED_CreateContext( |
1199 | 7 | (unsigned char *)att->attrib.pValue, |
1200 | 7 | (unsigned char *)pMechanism->pParameter, |
1201 | 7 | pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC, |
1202 | 7 | isEncrypt); |
1203 | 7 | sftk_FreeAttribute(att); |
1204 | 7 | if (context->cipherInfo == NULL) { |
1205 | 0 | crv = CKR_HOST_MEMORY; |
1206 | 0 | break; |
1207 | 0 | } |
1208 | 7 | context->update = isEncrypt ? SFTKCipher_SEED_Encrypt : SFTKCipher_SEED_Decrypt; |
1209 | 7 | context->destroy = SFTKCipher_SEED_DestroyContext; |
1210 | 7 | break; |
1211 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
1212 | 0 | case CKM_CAMELLIA_CBC_PAD: |
1213 | 0 | context->doPad = PR_TRUE; |
1214 | | /* fall thru */ |
1215 | 2 | case CKM_CAMELLIA_CBC: |
1216 | 2 | if (!pMechanism->pParameter || |
1217 | 2 | pMechanism->ulParameterLen != 16) { |
1218 | 2 | crv = CKR_MECHANISM_PARAM_INVALID; |
1219 | 2 | break; |
1220 | 2 | } |
1221 | | /* fall thru */ |
1222 | 1 | case CKM_CAMELLIA_ECB: |
1223 | 1 | context->blockSize = 16; |
1224 | 1 | if (key_type != CKK_CAMELLIA) { |
1225 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1226 | 0 | break; |
1227 | 0 | } |
1228 | 1 | att = sftk_FindAttribute(key, CKA_VALUE); |
1229 | 1 | if (att == NULL) { |
1230 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1231 | 0 | break; |
1232 | 0 | } |
1233 | 1 | context->cipherInfo = Camellia_CreateContext( |
1234 | 1 | (unsigned char *)att->attrib.pValue, |
1235 | 1 | (unsigned char *)pMechanism->pParameter, |
1236 | 1 | pMechanism->mechanism == |
1237 | 1 | CKM_CAMELLIA_ECB |
1238 | 1 | ? NSS_CAMELLIA |
1239 | 1 | : NSS_CAMELLIA_CBC, |
1240 | 1 | isEncrypt, att->attrib.ulValueLen); |
1241 | 1 | sftk_FreeAttribute(att); |
1242 | 1 | if (context->cipherInfo == NULL) { |
1243 | 1 | crv = CKR_HOST_MEMORY; |
1244 | 1 | break; |
1245 | 1 | } |
1246 | 0 | context->update = isEncrypt ? SFTKCipher_Camellia_Encrypt : SFTKCipher_Camellia_Decrypt; |
1247 | 0 | context->destroy = SFTKCipher_Camellia_DestroyContext; |
1248 | 0 | break; |
1249 | | |
1250 | 0 | case CKM_AES_CBC_PAD: |
1251 | 0 | context->doPad = PR_TRUE; |
1252 | | /* fall thru */ |
1253 | 4 | case CKM_AES_ECB: |
1254 | 7 | case CKM_AES_CBC: |
1255 | 7 | context->blockSize = 16; |
1256 | 7 | case CKM_AES_CTS: |
1257 | 7 | case CKM_AES_CTR: |
1258 | 19 | case CKM_AES_GCM: |
1259 | 19 | aes_param = pMechanism->pParameter; |
1260 | | /* |
1261 | | * Due to a mismatch between the documentation and the header |
1262 | | * file, two different definitions for CK_GCM_PARAMS exist. |
1263 | | * The header file is normative according to Oasis, but NSS used |
1264 | | * the documentation. In PKCS #11 v3.0, this was reconciled in |
1265 | | * favor of the header file definition. To maintain binary |
1266 | | * compatibility, NSS now defines CK_GCM_PARAMS_V3 as the official |
1267 | | * version v3 (V2.4 header file) and CK_NSS_GCM_PARAMS as the |
1268 | | * legacy (V2.4 documentation, NSS version). CK_GCM_PARAMS |
1269 | | * is defined as CK_GCM_PARAMS_V3 if NSS_PKCS11_2_0_COMPAT is not |
1270 | | * defined and CK_NSS_GCM_PARAMS if it is. Internally |
1271 | | * softoken continues to use the legacy version. The code below |
1272 | | * automatically detects which parameter was passed in and |
1273 | | * converts CK_GCM_PARAMS_V3 to the CK_NSS_GCM_PARAMS (legacy |
1274 | | * version) on the fly. NSS proper will eventually start |
1275 | | * using the CK_GCM_PARAMS_V3 version and fall back to the |
1276 | | * CK_NSS_GCM_PARAMS if the CK_GCM_PARAMS_V3 version fails with |
1277 | | * CKR_MECHANISM_PARAM_INVALID. |
1278 | | */ |
1279 | 19 | if (pMechanism->mechanism == CKM_AES_GCM) { |
1280 | 12 | if (!aes_param) { |
1281 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1282 | 0 | break; |
1283 | 0 | } |
1284 | 12 | if (pMechanism->ulParameterLen == sizeof(CK_GCM_PARAMS_V3)) { |
1285 | | /* convert the true V3 parameters into the old NSS parameters */ |
1286 | 0 | CK_GCM_PARAMS_V3 *gcm_params = (CK_GCM_PARAMS_V3 *)aes_param; |
1287 | 0 | if (gcm_params->ulIvLen * 8 != gcm_params->ulIvBits) { |
1288 | | /* only support byte aligned IV lengths */ |
1289 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1290 | 0 | break; |
1291 | 0 | } |
1292 | 0 | aes_param = (void *)&nss_gcm_param; |
1293 | 0 | nss_gcm_param.pIv = gcm_params->pIv; |
1294 | 0 | nss_gcm_param.ulIvLen = gcm_params->ulIvLen; |
1295 | 0 | nss_gcm_param.pAAD = gcm_params->pAAD; |
1296 | 0 | nss_gcm_param.ulAADLen = gcm_params->ulAADLen; |
1297 | 0 | nss_gcm_param.ulTagBits = gcm_params->ulTagBits; |
1298 | 12 | } else if (pMechanism->ulParameterLen != sizeof(CK_NSS_GCM_PARAMS)) { |
1299 | | /* neither old nor new style params, must be invalid */ |
1300 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1301 | 0 | break; |
1302 | 0 | } |
1303 | 12 | } else if ((pMechanism->mechanism == CKM_AES_CTR && BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CTR_PARAMS))) || |
1304 | 7 | ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CTS) && BAD_PARAM_CAST(pMechanism, AES_BLOCK_SIZE))) { |
1305 | 1 | crv = CKR_MECHANISM_PARAM_INVALID; |
1306 | 1 | break; |
1307 | 1 | } |
1308 | | |
1309 | 18 | if (pMechanism->mechanism == CKM_AES_GCM) { |
1310 | 12 | context->multi = PR_FALSE; |
1311 | 12 | } |
1312 | 18 | if (key_type != CKK_AES) { |
1313 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1314 | 0 | break; |
1315 | 0 | } |
1316 | 18 | att = sftk_FindAttribute(key, CKA_VALUE); |
1317 | 18 | if (att == NULL) { |
1318 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1319 | 0 | break; |
1320 | 0 | } |
1321 | 18 | context->cipherInfo = AES_CreateContext( |
1322 | 18 | (unsigned char *)att->attrib.pValue, |
1323 | 18 | (unsigned char *)aes_param, |
1324 | 18 | sftk_aes_mode(pMechanism->mechanism), |
1325 | 18 | isEncrypt, att->attrib.ulValueLen, 16); |
1326 | 18 | sftk_FreeAttribute(att); |
1327 | 18 | if (context->cipherInfo == NULL) { |
1328 | 11 | crv = CKR_HOST_MEMORY; |
1329 | 11 | break; |
1330 | 11 | } |
1331 | 7 | context->update = isEncrypt ? SFTKCipher_AES_Encrypt : SFTKCipher_AES_Decrypt; |
1332 | 7 | context->destroy = SFTKCipher_AES_DestroyContext; |
1333 | 7 | break; |
1334 | | |
1335 | 14 | case CKM_NSS_CHACHA20_POLY1305: |
1336 | 14 | case CKM_CHACHA20_POLY1305: |
1337 | 14 | if (pMechanism->mechanism == CKM_NSS_CHACHA20_POLY1305) { |
1338 | 14 | if (key_type != CKK_NSS_CHACHA20) { |
1339 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1340 | 0 | break; |
1341 | 0 | } |
1342 | 14 | if ((pMechanism->pParameter == NULL) || |
1343 | 14 | (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS))) { |
1344 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1345 | 0 | break; |
1346 | 0 | } |
1347 | 14 | nss_aead_params_ptr = (CK_NSS_AEAD_PARAMS *)pMechanism->pParameter; |
1348 | 14 | } else { |
1349 | 0 | CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR chacha_poly_params; |
1350 | 0 | if (key_type != CKK_CHACHA20) { |
1351 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1352 | 0 | break; |
1353 | 0 | } |
1354 | 0 | if ((pMechanism->pParameter == NULL) || |
1355 | 0 | (pMechanism->ulParameterLen != |
1356 | 0 | sizeof(CK_SALSA20_CHACHA20_POLY1305_PARAMS))) { |
1357 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1358 | 0 | break; |
1359 | 0 | } |
1360 | 0 | chacha_poly_params = (CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR) |
1361 | 0 | pMechanism->pParameter; |
1362 | 0 | nss_aead_params_ptr = &nss_aead_params; |
1363 | 0 | nss_aead_params.pNonce = chacha_poly_params->pNonce; |
1364 | 0 | nss_aead_params.ulNonceLen = chacha_poly_params->ulNonceLen; |
1365 | 0 | nss_aead_params.pAAD = chacha_poly_params->pAAD; |
1366 | 0 | nss_aead_params.ulAADLen = chacha_poly_params->ulAADLen; |
1367 | 0 | nss_aead_params.ulTagLen = 16; /* Poly1305 is always 16 */ |
1368 | 0 | } |
1369 | | |
1370 | 14 | context->multi = PR_FALSE; |
1371 | 14 | att = sftk_FindAttribute(key, CKA_VALUE); |
1372 | 14 | if (att == NULL) { |
1373 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1374 | 0 | break; |
1375 | 0 | } |
1376 | 14 | context->cipherInfo = sftk_ChaCha20Poly1305_CreateContext( |
1377 | 14 | (unsigned char *)att->attrib.pValue, att->attrib.ulValueLen, |
1378 | 14 | nss_aead_params_ptr); |
1379 | 14 | sftk_FreeAttribute(att); |
1380 | 14 | if (context->cipherInfo == NULL) { |
1381 | 7 | crv = sftk_MapCryptError(PORT_GetError()); |
1382 | 7 | break; |
1383 | 7 | } |
1384 | 7 | context->update = isEncrypt ? sftk_ChaCha20Poly1305_Encrypt : sftk_ChaCha20Poly1305_Decrypt; |
1385 | 7 | context->destroy = sftk_ChaCha20Poly1305_DestroyContext; |
1386 | 7 | break; |
1387 | | |
1388 | 0 | case CKM_NSS_CHACHA20_CTR: /* old NSS private version */ |
1389 | 0 | case CKM_CHACHA20: /* PKCS #11 v3 version */ |
1390 | 0 | { |
1391 | 0 | unsigned char *counter; |
1392 | 0 | unsigned char *nonce; |
1393 | 0 | unsigned long counter_len; |
1394 | 0 | unsigned long nonce_len; |
1395 | 0 | context->multi = PR_FALSE; |
1396 | 0 | if (pMechanism->mechanism == CKM_NSS_CHACHA20_CTR) { |
1397 | 0 | if (key_type != CKK_NSS_CHACHA20) { |
1398 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1399 | 0 | break; |
1400 | 0 | } |
1401 | 0 | if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) { |
1402 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1403 | 0 | break; |
1404 | 0 | } |
1405 | 0 | counter_len = 4; |
1406 | 0 | counter = pMechanism->pParameter; |
1407 | 0 | nonce = counter + 4; |
1408 | 0 | nonce_len = 12; |
1409 | 0 | } else { |
1410 | 0 | CK_CHACHA20_PARAMS_PTR chacha20_param_ptr; |
1411 | 0 | if (key_type != CKK_CHACHA20) { |
1412 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1413 | 0 | break; |
1414 | 0 | } |
1415 | 0 | if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != sizeof(CK_CHACHA20_PARAMS)) { |
1416 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1417 | 0 | break; |
1418 | 0 | } |
1419 | 0 | chacha20_param_ptr = (CK_CHACHA20_PARAMS_PTR)pMechanism->pParameter; |
1420 | 0 | if ((chacha20_param_ptr->blockCounterBits != 32) && |
1421 | 0 | (chacha20_param_ptr->blockCounterBits != 64)) { |
1422 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1423 | 0 | break; |
1424 | 0 | } |
1425 | 0 | counter_len = chacha20_param_ptr->blockCounterBits / PR_BITS_PER_BYTE; |
1426 | 0 | counter = chacha20_param_ptr->pBlockCounter; |
1427 | 0 | nonce = chacha20_param_ptr->pNonce; |
1428 | 0 | nonce_len = chacha20_param_ptr->ulNonceBits / PR_BITS_PER_BYTE; |
1429 | 0 | } |
1430 | | |
1431 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
1432 | 0 | if (att == NULL) { |
1433 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1434 | 0 | break; |
1435 | 0 | } |
1436 | 0 | SFTKChaCha20CtrInfo *ctx = PORT_ZNew(SFTKChaCha20CtrInfo); |
1437 | 0 | if (!ctx) { |
1438 | 0 | sftk_FreeAttribute(att); |
1439 | 0 | crv = CKR_HOST_MEMORY; |
1440 | 0 | break; |
1441 | 0 | } |
1442 | 0 | if (att->attrib.ulValueLen != sizeof(ctx->key)) { |
1443 | 0 | sftk_FreeAttribute(att); |
1444 | 0 | PORT_Free(ctx); |
1445 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1446 | 0 | break; |
1447 | 0 | } |
1448 | 0 | memcpy(ctx->key, att->attrib.pValue, att->attrib.ulValueLen); |
1449 | 0 | sftk_FreeAttribute(att); |
1450 | | |
1451 | | /* make sure we don't overflow our parameters */ |
1452 | 0 | if ((sizeof(ctx->counter) < counter_len) || |
1453 | 0 | (sizeof(ctx->nonce) < nonce_len)) { |
1454 | 0 | PORT_Free(ctx); |
1455 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1456 | 0 | break; |
1457 | 0 | } |
1458 | | |
1459 | | /* The counter is little endian. */ |
1460 | 0 | int i = 0; |
1461 | 0 | for (; i < counter_len; ++i) { |
1462 | 0 | ctx->counter |= (PRUint32)counter[i] << (i * 8); |
1463 | 0 | } |
1464 | 0 | memcpy(ctx->nonce, nonce, nonce_len); |
1465 | 0 | context->cipherInfo = ctx; |
1466 | 0 | context->update = sftk_ChaCha20Ctr; |
1467 | 0 | context->destroy = sftk_ChaCha20Ctr_DestroyContext; |
1468 | 0 | break; |
1469 | 0 | } |
1470 | | |
1471 | 0 | case CKM_NSS_AES_KEY_WRAP_PAD: |
1472 | 0 | case CKM_AES_KEY_WRAP_PAD: |
1473 | 0 | context->doPad = PR_TRUE; |
1474 | | /* fall thru */ |
1475 | 0 | case CKM_NSS_AES_KEY_WRAP: |
1476 | 0 | case CKM_AES_KEY_WRAP: |
1477 | 0 | context->blockSize = 8; |
1478 | 0 | case CKM_AES_KEY_WRAP_KWP: |
1479 | 0 | context->multi = PR_FALSE; |
1480 | 0 | if (key_type != CKK_AES) { |
1481 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1482 | 0 | break; |
1483 | 0 | } |
1484 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
1485 | 0 | if (att == NULL) { |
1486 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1487 | 0 | break; |
1488 | 0 | } |
1489 | 0 | context->cipherInfo = AESKeyWrap_CreateContext( |
1490 | 0 | (unsigned char *)att->attrib.pValue, |
1491 | 0 | (unsigned char *)pMechanism->pParameter, |
1492 | 0 | isEncrypt, att->attrib.ulValueLen); |
1493 | 0 | sftk_FreeAttribute(att); |
1494 | 0 | if (context->cipherInfo == NULL) { |
1495 | 0 | crv = CKR_HOST_MEMORY; |
1496 | 0 | break; |
1497 | 0 | } |
1498 | 0 | if (pMechanism->mechanism == CKM_AES_KEY_WRAP_KWP) { |
1499 | 0 | context->update = isEncrypt ? SFTKCipher_AESKeyWrap_EncryptKWP |
1500 | 0 | : SFTKCipher_AESKeyWrap_DecryptKWP; |
1501 | 0 | } else { |
1502 | 0 | context->update = isEncrypt ? SFTKCipher_AESKeyWrap_Encrypt |
1503 | 0 | : SFTKCipher_AESKeyWrap_Decrypt; |
1504 | 0 | } |
1505 | 0 | context->destroy = SFTKCipher_AESKeyWrap_DestroyContext; |
1506 | 0 | break; |
1507 | | |
1508 | 0 | default: |
1509 | 0 | crv = CKR_MECHANISM_INVALID; |
1510 | 0 | break; |
1511 | 49 | } |
1512 | | |
1513 | 49 | if (crv != CKR_OK) { |
1514 | 25 | sftk_FreeContext(context); |
1515 | 25 | sftk_FreeSession(session); |
1516 | 25 | return crv; |
1517 | 25 | } |
1518 | 24 | sftk_SetContextByType(session, contextType, context); |
1519 | 24 | sftk_FreeSession(session); |
1520 | 24 | return CKR_OK; |
1521 | 49 | } |
1522 | | |
1523 | | /* NSC_EncryptInit initializes an encryption operation. */ |
1524 | | CK_RV |
1525 | | NSC_EncryptInit(CK_SESSION_HANDLE hSession, |
1526 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
1527 | 28 | { |
1528 | 28 | CHECK_FORK(); |
1529 | 28 | return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT, |
1530 | 28 | SFTK_ENCRYPT, PR_TRUE); |
1531 | 28 | } |
1532 | | |
1533 | | /* NSC_EncryptUpdate continues a multiple-part encryption operation. */ |
1534 | | CK_RV |
1535 | | NSC_EncryptUpdate(CK_SESSION_HANDLE hSession, |
1536 | | CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
1537 | | CK_ULONG_PTR pulEncryptedPartLen) |
1538 | 3 | { |
1539 | 3 | SFTKSessionContext *context; |
1540 | 3 | unsigned int outlen, i; |
1541 | 3 | unsigned int padoutlen = 0; |
1542 | 3 | unsigned int maxout = *pulEncryptedPartLen; |
1543 | 3 | CK_RV crv; |
1544 | 3 | SECStatus rv; |
1545 | | |
1546 | 3 | CHECK_FORK(); |
1547 | | |
1548 | | /* make sure we're legal */ |
1549 | 3 | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, NULL); |
1550 | 3 | if (crv != CKR_OK) |
1551 | 0 | return crv; |
1552 | | |
1553 | 3 | if (!pEncryptedPart) { |
1554 | 0 | if (context->doPad) { |
1555 | 0 | CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength; |
1556 | 0 | CK_ULONG blocksToSend = totalDataAvailable / context->blockSize; |
1557 | |
|
1558 | 0 | *pulEncryptedPartLen = blocksToSend * context->blockSize; |
1559 | 0 | return CKR_OK; |
1560 | 0 | } |
1561 | 0 | *pulEncryptedPartLen = ulPartLen; |
1562 | 0 | return CKR_OK; |
1563 | 0 | } |
1564 | | |
1565 | | /* do padding */ |
1566 | 3 | if (context->doPad) { |
1567 | | /* deal with previous buffered data */ |
1568 | 0 | if (context->padDataLength != 0) { |
1569 | | /* fill in the padded to a full block size */ |
1570 | 0 | for (i = context->padDataLength; |
1571 | 0 | (ulPartLen != 0) && i < context->blockSize; i++) { |
1572 | 0 | context->padBuf[i] = *pPart++; |
1573 | 0 | ulPartLen--; |
1574 | 0 | context->padDataLength++; |
1575 | 0 | } |
1576 | | |
1577 | | /* not enough data to encrypt yet? then return */ |
1578 | 0 | if (context->padDataLength != context->blockSize) { |
1579 | 0 | *pulEncryptedPartLen = 0; |
1580 | 0 | return CKR_OK; |
1581 | 0 | } |
1582 | | /* encrypt the current padded data */ |
1583 | 0 | rv = (*context->update)(context->cipherInfo, pEncryptedPart, |
1584 | 0 | &padoutlen, maxout, context->padBuf, |
1585 | 0 | context->blockSize); |
1586 | 0 | if (rv != SECSuccess) { |
1587 | 0 | return sftk_MapCryptError(PORT_GetError()); |
1588 | 0 | } |
1589 | 0 | pEncryptedPart += padoutlen; |
1590 | 0 | maxout -= padoutlen; |
1591 | 0 | } |
1592 | | /* save the residual */ |
1593 | 0 | context->padDataLength = ulPartLen % context->blockSize; |
1594 | 0 | if (context->padDataLength) { |
1595 | 0 | PORT_Memcpy(context->padBuf, |
1596 | 0 | &pPart[ulPartLen - context->padDataLength], |
1597 | 0 | context->padDataLength); |
1598 | 0 | ulPartLen -= context->padDataLength; |
1599 | 0 | } |
1600 | | /* if we've exhausted our new buffer, we're done */ |
1601 | 0 | if (ulPartLen == 0) { |
1602 | 0 | *pulEncryptedPartLen = padoutlen; |
1603 | 0 | return CKR_OK; |
1604 | 0 | } |
1605 | 0 | } |
1606 | | |
1607 | | /* do it: NOTE: this assumes buf size in is >= buf size out! */ |
1608 | 3 | rv = (*context->update)(context->cipherInfo, pEncryptedPart, |
1609 | 3 | &outlen, maxout, pPart, ulPartLen); |
1610 | 3 | if (rv != SECSuccess) { |
1611 | 3 | return sftk_MapCryptError(PORT_GetError()); |
1612 | 3 | } |
1613 | 0 | *pulEncryptedPartLen = (CK_ULONG)(outlen + padoutlen); |
1614 | 0 | return CKR_OK; |
1615 | 3 | } |
1616 | | |
1617 | | /* NSC_EncryptFinal finishes a multiple-part encryption operation. */ |
1618 | | CK_RV |
1619 | | NSC_EncryptFinal(CK_SESSION_HANDLE hSession, |
1620 | | CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) |
1621 | 0 | { |
1622 | 0 | SFTKSession *session; |
1623 | 0 | SFTKSessionContext *context; |
1624 | 0 | unsigned int outlen, i; |
1625 | 0 | unsigned int maxout = *pulLastEncryptedPartLen; |
1626 | 0 | CK_RV crv; |
1627 | 0 | SECStatus rv = SECSuccess; |
1628 | 0 | PRBool contextFinished = PR_TRUE; |
1629 | |
|
1630 | 0 | CHECK_FORK(); |
1631 | | |
1632 | | /* make sure we're legal */ |
1633 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, &session); |
1634 | 0 | if (crv != CKR_OK) |
1635 | 0 | return crv; |
1636 | | |
1637 | 0 | *pulLastEncryptedPartLen = 0; |
1638 | 0 | if (!pLastEncryptedPart) { |
1639 | | /* caller is checking the amount of remaining data */ |
1640 | 0 | if (context->blockSize > 0 && context->doPad) { |
1641 | 0 | *pulLastEncryptedPartLen = context->blockSize; |
1642 | 0 | contextFinished = PR_FALSE; /* still have padding to go */ |
1643 | 0 | } |
1644 | 0 | goto finish; |
1645 | 0 | } |
1646 | | |
1647 | | /* do padding */ |
1648 | 0 | if (context->doPad) { |
1649 | 0 | unsigned char padbyte = (unsigned char)(context->blockSize - context->padDataLength); |
1650 | | /* fill out rest of pad buffer with pad magic*/ |
1651 | 0 | for (i = context->padDataLength; i < context->blockSize; i++) { |
1652 | 0 | context->padBuf[i] = padbyte; |
1653 | 0 | } |
1654 | 0 | rv = (*context->update)(context->cipherInfo, pLastEncryptedPart, |
1655 | 0 | &outlen, maxout, context->padBuf, context->blockSize); |
1656 | 0 | if (rv == SECSuccess) |
1657 | 0 | *pulLastEncryptedPartLen = (CK_ULONG)outlen; |
1658 | 0 | } |
1659 | |
|
1660 | 0 | finish: |
1661 | 0 | if (contextFinished) |
1662 | 0 | sftk_TerminateOp(session, SFTK_ENCRYPT, context); |
1663 | 0 | sftk_FreeSession(session); |
1664 | 0 | return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
1665 | 0 | } |
1666 | | |
1667 | | /* NSC_Encrypt encrypts single-part data. */ |
1668 | | CK_RV |
1669 | | NSC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
1670 | | CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, |
1671 | | CK_ULONG_PTR pulEncryptedDataLen) |
1672 | 4 | { |
1673 | 4 | SFTKSession *session; |
1674 | 4 | SFTKSessionContext *context; |
1675 | 4 | unsigned int outlen; |
1676 | 4 | unsigned int maxoutlen = *pulEncryptedDataLen; |
1677 | 4 | CK_RV crv; |
1678 | 4 | CK_RV crv2; |
1679 | 4 | SECStatus rv = SECSuccess; |
1680 | 4 | SECItem pText; |
1681 | | |
1682 | 4 | pText.type = siBuffer; |
1683 | 4 | pText.data = pData; |
1684 | 4 | pText.len = ulDataLen; |
1685 | | |
1686 | 4 | CHECK_FORK(); |
1687 | | |
1688 | | /* make sure we're legal */ |
1689 | 4 | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, &session); |
1690 | 4 | if (crv != CKR_OK) |
1691 | 0 | return crv; |
1692 | | |
1693 | 4 | if (!pEncryptedData) { |
1694 | 0 | outlen = context->rsa ? context->maxLen : ulDataLen + 2 * context->blockSize; |
1695 | 0 | goto done; |
1696 | 0 | } |
1697 | | |
1698 | 4 | if (context->doPad) { |
1699 | 0 | if (context->multi) { |
1700 | 0 | CK_ULONG updateLen = maxoutlen; |
1701 | 0 | CK_ULONG finalLen; |
1702 | | /* padding is fairly complicated, have the update and final |
1703 | | * code deal with it */ |
1704 | 0 | sftk_FreeSession(session); |
1705 | 0 | crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData, |
1706 | 0 | &updateLen); |
1707 | 0 | if (crv != CKR_OK) { |
1708 | 0 | updateLen = 0; |
1709 | 0 | } |
1710 | 0 | maxoutlen -= updateLen; |
1711 | 0 | pEncryptedData += updateLen; |
1712 | 0 | finalLen = maxoutlen; |
1713 | 0 | crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen); |
1714 | 0 | if (crv == CKR_OK && crv2 == CKR_OK) { |
1715 | 0 | *pulEncryptedDataLen = updateLen + finalLen; |
1716 | 0 | } |
1717 | 0 | return crv == CKR_OK ? crv2 : crv; |
1718 | 0 | } |
1719 | | /* doPad without multi means that padding must be done on the first |
1720 | | ** and only update. There will be no final. |
1721 | | */ |
1722 | 0 | PORT_Assert(context->blockSize > 1); |
1723 | 0 | if (context->blockSize > 1) { |
1724 | 0 | CK_ULONG remainder = ulDataLen % context->blockSize; |
1725 | 0 | CK_ULONG padding = context->blockSize - remainder; |
1726 | 0 | pText.len += padding; |
1727 | 0 | pText.data = PORT_ZAlloc(pText.len); |
1728 | 0 | if (pText.data) { |
1729 | 0 | memcpy(pText.data, pData, ulDataLen); |
1730 | 0 | memset(pText.data + ulDataLen, padding, padding); |
1731 | 0 | } else { |
1732 | 0 | crv = CKR_HOST_MEMORY; |
1733 | 0 | goto fail; |
1734 | 0 | } |
1735 | 0 | } |
1736 | 0 | } |
1737 | | |
1738 | | /* do it: NOTE: this assumes buf size is big enough. */ |
1739 | 4 | rv = (*context->update)(context->cipherInfo, pEncryptedData, |
1740 | 4 | &outlen, maxoutlen, pText.data, pText.len); |
1741 | 4 | crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
1742 | 4 | if (pText.data != pData) |
1743 | 0 | PORT_ZFree(pText.data, pText.len); |
1744 | 4 | fail: |
1745 | 4 | sftk_TerminateOp(session, SFTK_ENCRYPT, context); |
1746 | 4 | done: |
1747 | 4 | sftk_FreeSession(session); |
1748 | 4 | if (crv == CKR_OK) { |
1749 | 0 | *pulEncryptedDataLen = (CK_ULONG)outlen; |
1750 | 0 | } |
1751 | 4 | return crv; |
1752 | 4 | } |
1753 | | |
1754 | | /* |
1755 | | ************** Crypto Functions: Decrypt ************************ |
1756 | | */ |
1757 | | |
1758 | | /* NSC_DecryptInit initializes a decryption operation. */ |
1759 | | CK_RV |
1760 | | NSC_DecryptInit(CK_SESSION_HANDLE hSession, |
1761 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
1762 | 33 | { |
1763 | 33 | CHECK_FORK(); |
1764 | 33 | return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT, |
1765 | 33 | SFTK_DECRYPT, PR_FALSE); |
1766 | 33 | } |
1767 | | |
1768 | | /* NSC_DecryptUpdate continues a multiple-part decryption operation. */ |
1769 | | CK_RV |
1770 | | NSC_DecryptUpdate(CK_SESSION_HANDLE hSession, |
1771 | | CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, |
1772 | | CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) |
1773 | 6 | { |
1774 | 6 | SFTKSessionContext *context; |
1775 | 6 | unsigned int padoutlen = 0; |
1776 | 6 | unsigned int outlen; |
1777 | 6 | unsigned int maxout = *pulPartLen; |
1778 | 6 | CK_RV crv; |
1779 | 6 | SECStatus rv; |
1780 | | |
1781 | 6 | CHECK_FORK(); |
1782 | | |
1783 | | /* make sure we're legal */ |
1784 | 6 | crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, NULL); |
1785 | 6 | if (crv != CKR_OK) |
1786 | 0 | return crv; |
1787 | | |
1788 | | /* this can only happen on an NSS programming error */ |
1789 | 6 | PORT_Assert((context->padDataLength == 0) || context->padDataLength == context->blockSize); |
1790 | | |
1791 | 6 | if (context->doPad) { |
1792 | | /* Check the data length for block ciphers. If we are padding, |
1793 | | * then we must be using a block cipher. In the non-padding case |
1794 | | * the error will be returned by the underlying decryption |
1795 | | * function when we do the actual decrypt. We need to do the |
1796 | | * check here to avoid returning a negative length to the caller |
1797 | | * or reading before the beginning of the pEncryptedPart buffer. |
1798 | | */ |
1799 | 0 | if ((ulEncryptedPartLen == 0) || |
1800 | 0 | (ulEncryptedPartLen % context->blockSize) != 0) { |
1801 | 0 | return CKR_ENCRYPTED_DATA_LEN_RANGE; |
1802 | 0 | } |
1803 | 0 | } |
1804 | | |
1805 | 6 | if (!pPart) { |
1806 | 0 | if (context->doPad) { |
1807 | 0 | *pulPartLen = |
1808 | 0 | ulEncryptedPartLen + context->padDataLength - context->blockSize; |
1809 | 0 | return CKR_OK; |
1810 | 0 | } |
1811 | | /* for stream ciphers there is are no constraints on ulEncryptedPartLen. |
1812 | | * for block ciphers, it must be a multiple of blockSize. The error is |
1813 | | * detected when this function is called again do decrypt the output. |
1814 | | */ |
1815 | 0 | *pulPartLen = ulEncryptedPartLen; |
1816 | 0 | return CKR_OK; |
1817 | 0 | } |
1818 | | |
1819 | 6 | if (context->doPad) { |
1820 | | /* first decrypt our saved buffer */ |
1821 | 0 | if (context->padDataLength != 0) { |
1822 | 0 | rv = (*context->update)(context->cipherInfo, pPart, &padoutlen, |
1823 | 0 | maxout, context->padBuf, context->blockSize); |
1824 | 0 | if (rv != SECSuccess) |
1825 | 0 | return sftk_MapDecryptError(PORT_GetError()); |
1826 | 0 | pPart += padoutlen; |
1827 | 0 | maxout -= padoutlen; |
1828 | 0 | } |
1829 | | /* now save the final block for the next decrypt or the final */ |
1830 | 0 | PORT_Memcpy(context->padBuf, &pEncryptedPart[ulEncryptedPartLen - context->blockSize], |
1831 | 0 | context->blockSize); |
1832 | 0 | context->padDataLength = context->blockSize; |
1833 | 0 | ulEncryptedPartLen -= context->padDataLength; |
1834 | 0 | } |
1835 | | |
1836 | | /* do it: NOTE: this assumes buf size in is >= buf size out! */ |
1837 | 6 | rv = (*context->update)(context->cipherInfo, pPart, &outlen, |
1838 | 6 | maxout, pEncryptedPart, ulEncryptedPartLen); |
1839 | 6 | if (rv != SECSuccess) { |
1840 | 5 | return sftk_MapDecryptError(PORT_GetError()); |
1841 | 5 | } |
1842 | 1 | *pulPartLen = (CK_ULONG)(outlen + padoutlen); |
1843 | 1 | return CKR_OK; |
1844 | 6 | } |
1845 | | |
1846 | | /* NSC_DecryptFinal finishes a multiple-part decryption operation. */ |
1847 | | CK_RV |
1848 | | NSC_DecryptFinal(CK_SESSION_HANDLE hSession, |
1849 | | CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) |
1850 | 0 | { |
1851 | 0 | SFTKSession *session; |
1852 | 0 | SFTKSessionContext *context; |
1853 | 0 | unsigned int outlen; |
1854 | 0 | unsigned int maxout = *pulLastPartLen; |
1855 | 0 | CK_RV crv; |
1856 | 0 | SECStatus rv = SECSuccess; |
1857 | |
|
1858 | 0 | CHECK_FORK(); |
1859 | | |
1860 | | /* make sure we're legal */ |
1861 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, &session); |
1862 | 0 | if (crv != CKR_OK) |
1863 | 0 | return crv; |
1864 | | |
1865 | 0 | *pulLastPartLen = 0; |
1866 | 0 | if (!pLastPart) { |
1867 | | /* caller is checking the amount of remaining data */ |
1868 | 0 | if (context->padDataLength > 0) { |
1869 | 0 | *pulLastPartLen = context->padDataLength; |
1870 | 0 | } |
1871 | 0 | goto finish; |
1872 | 0 | } |
1873 | | |
1874 | 0 | if (context->doPad) { |
1875 | | /* decrypt our saved buffer */ |
1876 | 0 | if (context->padDataLength != 0) { |
1877 | | /* this assumes that pLastPart is big enough to hold the *whole* |
1878 | | * buffer!!! */ |
1879 | 0 | rv = (*context->update)(context->cipherInfo, pLastPart, &outlen, |
1880 | 0 | maxout, context->padBuf, context->blockSize); |
1881 | 0 | if (rv != SECSuccess) { |
1882 | 0 | crv = sftk_MapDecryptError(PORT_GetError()); |
1883 | 0 | } else { |
1884 | 0 | unsigned int padSize = 0; |
1885 | 0 | crv = sftk_CheckCBCPadding(pLastPart, outlen, |
1886 | 0 | context->blockSize, &padSize); |
1887 | | /* Update pulLastPartLen, in constant time, if crv is OK */ |
1888 | 0 | *pulLastPartLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulLastPartLen); |
1889 | 0 | } |
1890 | 0 | } |
1891 | 0 | } |
1892 | |
|
1893 | 0 | sftk_TerminateOp(session, SFTK_DECRYPT, context); |
1894 | 0 | finish: |
1895 | 0 | sftk_FreeSession(session); |
1896 | 0 | return crv; |
1897 | 0 | } |
1898 | | |
1899 | | /* NSC_Decrypt decrypts encrypted data in a single part. */ |
1900 | | CK_RV |
1901 | | NSC_Decrypt(CK_SESSION_HANDLE hSession, |
1902 | | CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, |
1903 | | CK_ULONG_PTR pulDataLen) |
1904 | 12 | { |
1905 | 12 | SFTKSession *session; |
1906 | 12 | SFTKSessionContext *context; |
1907 | 12 | unsigned int outlen; |
1908 | 12 | unsigned int maxoutlen = *pulDataLen; |
1909 | 12 | CK_RV crv; |
1910 | 12 | CK_RV crv2; |
1911 | 12 | SECStatus rv = SECSuccess; |
1912 | | |
1913 | 12 | CHECK_FORK(); |
1914 | | |
1915 | | /* make sure we're legal */ |
1916 | 12 | crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_FALSE, &session); |
1917 | 12 | if (crv != CKR_OK) |
1918 | 0 | return crv; |
1919 | | |
1920 | 12 | if (!pData) { |
1921 | 0 | *pulDataLen = (CK_ULONG)(ulEncryptedDataLen + context->blockSize); |
1922 | 0 | goto done; |
1923 | 0 | } |
1924 | | |
1925 | 12 | if (context->doPad && context->multi) { |
1926 | 0 | CK_ULONG updateLen = maxoutlen; |
1927 | 0 | CK_ULONG finalLen; |
1928 | | /* padding is fairly complicated, have the update and final |
1929 | | * code deal with it */ |
1930 | 0 | sftk_FreeSession(session); |
1931 | 0 | crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, |
1932 | 0 | pData, &updateLen); |
1933 | 0 | if (crv == CKR_OK) { |
1934 | 0 | maxoutlen -= updateLen; |
1935 | 0 | pData += updateLen; |
1936 | 0 | } |
1937 | 0 | finalLen = maxoutlen; |
1938 | 0 | crv2 = NSC_DecryptFinal(hSession, pData, &finalLen); |
1939 | 0 | if (crv == CKR_OK) { |
1940 | 0 | *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv2), updateLen + finalLen, *pulDataLen); |
1941 | 0 | return crv2; |
1942 | 0 | } else { |
1943 | 0 | return crv; |
1944 | 0 | } |
1945 | 0 | } |
1946 | | |
1947 | 12 | rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, |
1948 | 12 | pEncryptedData, ulEncryptedDataLen); |
1949 | | /* XXX need to do MUCH better error mapping than this. */ |
1950 | 12 | crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError()); |
1951 | 12 | if (rv == SECSuccess) { |
1952 | 1 | if (context->doPad) { |
1953 | 0 | unsigned int padSize = 0; |
1954 | 0 | crv = sftk_CheckCBCPadding(pData, outlen, context->blockSize, |
1955 | 0 | &padSize); |
1956 | | /* Update pulDataLen, in constant time, if crv is OK */ |
1957 | 0 | *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulDataLen); |
1958 | 1 | } else { |
1959 | 1 | *pulDataLen = (CK_ULONG)outlen; |
1960 | 1 | } |
1961 | 1 | } |
1962 | 12 | sftk_TerminateOp(session, SFTK_DECRYPT, context); |
1963 | 12 | done: |
1964 | 12 | sftk_FreeSession(session); |
1965 | 12 | return crv; |
1966 | 12 | } |
1967 | | |
1968 | | /* |
1969 | | ************** Crypto Functions: Digest (HASH) ************************ |
1970 | | */ |
1971 | | |
1972 | | /* NSC_DigestInit initializes a message-digesting operation. */ |
1973 | | CK_RV |
1974 | | NSC_DigestInit(CK_SESSION_HANDLE hSession, |
1975 | | CK_MECHANISM_PTR pMechanism) |
1976 | 64 | { |
1977 | 64 | SFTKSession *session; |
1978 | 64 | SFTKSessionContext *context; |
1979 | 64 | CK_RV crv = CKR_OK; |
1980 | | |
1981 | 64 | CHECK_FORK(); |
1982 | | |
1983 | 64 | session = sftk_SessionFromHandle(hSession); |
1984 | 64 | if (session == NULL) |
1985 | 0 | return CKR_SESSION_HANDLE_INVALID; |
1986 | 64 | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_HASH, |
1987 | 64 | NULL, 0, NULL, 0, CKA_DIGEST); |
1988 | 64 | if (crv != CKR_OK) { |
1989 | 0 | sftk_FreeSession(session); |
1990 | 0 | return crv; |
1991 | 0 | } |
1992 | | |
1993 | 64 | #define INIT_MECH(mmm) \ |
1994 | 64 | case CKM_##mmm: { \ |
1995 | 64 | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ |
1996 | 64 | context->cipherInfo = (void *)mmm##_ctx; \ |
1997 | 64 | context->cipherInfoLen = mmm##_FlattenSize(mmm##_ctx); \ |
1998 | 64 | context->currentMech = CKM_##mmm; \ |
1999 | 64 | context->hashUpdate = SFTKHash_##mmm##_Update; \ |
2000 | 64 | context->end = SFTKHash_##mmm##_End; \ |
2001 | 64 | context->destroy = SFTKHash_##mmm##_DestroyContext; \ |
2002 | 64 | context->maxLen = mmm##_LENGTH; \ |
2003 | 64 | if (mmm##_ctx) \ |
2004 | 64 | mmm##_Begin(mmm##_ctx); \ |
2005 | 64 | else \ |
2006 | 64 | crv = CKR_HOST_MEMORY; \ |
2007 | 64 | break; \ |
2008 | 64 | } |
2009 | | |
2010 | 64 | switch (pMechanism->mechanism) { |
2011 | 0 | INIT_MECH(MD2) |
2012 | 9 | INIT_MECH(MD5) |
2013 | 11 | INIT_MECH(SHA1) |
2014 | 5 | INIT_MECH(SHA224) |
2015 | 20 | INIT_MECH(SHA256) |
2016 | 9 | INIT_MECH(SHA384) |
2017 | 10 | INIT_MECH(SHA512) |
2018 | 0 | INIT_MECH(SHA3_224) |
2019 | 0 | INIT_MECH(SHA3_256) |
2020 | 0 | INIT_MECH(SHA3_384) |
2021 | 0 | INIT_MECH(SHA3_512) |
2022 | | |
2023 | 0 | default: |
2024 | 0 | crv = CKR_MECHANISM_INVALID; |
2025 | 0 | break; |
2026 | 64 | } |
2027 | | |
2028 | 64 | if (crv != CKR_OK) { |
2029 | 0 | sftk_FreeContext(context); |
2030 | 0 | sftk_FreeSession(session); |
2031 | 0 | return crv; |
2032 | 0 | } |
2033 | 64 | sftk_SetContextByType(session, SFTK_HASH, context); |
2034 | 64 | sftk_FreeSession(session); |
2035 | 64 | return CKR_OK; |
2036 | 64 | } |
2037 | | |
2038 | | /* NSC_Digest digests data in a single part. */ |
2039 | | CK_RV |
2040 | | NSC_Digest(CK_SESSION_HANDLE hSession, |
2041 | | CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, |
2042 | | CK_ULONG_PTR pulDigestLen) |
2043 | 0 | { |
2044 | 0 | SFTKSession *session; |
2045 | 0 | SFTKSessionContext *context; |
2046 | 0 | unsigned int digestLen; |
2047 | 0 | unsigned int maxout = *pulDigestLen; |
2048 | 0 | CK_RV crv; |
2049 | |
|
2050 | 0 | CHECK_FORK(); |
2051 | | |
2052 | | /* make sure we're legal */ |
2053 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_FALSE, &session); |
2054 | 0 | if (crv != CKR_OK) |
2055 | 0 | return crv; |
2056 | | |
2057 | 0 | if (pDigest == NULL) { |
2058 | 0 | *pulDigestLen = context->maxLen; |
2059 | 0 | goto finish; |
2060 | 0 | } |
2061 | | |
2062 | 0 | #if (ULONG_MAX > UINT_MAX) |
2063 | | /* The context->hashUpdate function takes an unsigned int for its data |
2064 | | * length argument, but NSC_Digest takes an unsigned long. */ |
2065 | 0 | while (ulDataLen > UINT_MAX) { |
2066 | 0 | (*context->hashUpdate)(context->cipherInfo, pData, UINT_MAX); |
2067 | 0 | pData += UINT_MAX; |
2068 | 0 | ulDataLen -= UINT_MAX; |
2069 | 0 | } |
2070 | 0 | #endif |
2071 | 0 | (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen); |
2072 | | |
2073 | | /* NOTE: this assumes buf size is bigenough for the algorithm */ |
2074 | 0 | (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout); |
2075 | 0 | *pulDigestLen = digestLen; |
2076 | |
|
2077 | 0 | sftk_TerminateOp(session, SFTK_HASH, context); |
2078 | 0 | finish: |
2079 | 0 | sftk_FreeSession(session); |
2080 | 0 | return CKR_OK; |
2081 | 0 | } |
2082 | | |
2083 | | /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */ |
2084 | | CK_RV |
2085 | | NSC_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
2086 | | CK_ULONG ulPartLen) |
2087 | 667 | { |
2088 | 667 | SFTKSessionContext *context; |
2089 | 667 | CK_RV crv; |
2090 | | |
2091 | 667 | CHECK_FORK(); |
2092 | | |
2093 | | /* make sure we're legal */ |
2094 | 667 | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, NULL); |
2095 | 667 | if (crv != CKR_OK) |
2096 | 0 | return crv; |
2097 | | |
2098 | 667 | #if (ULONG_MAX > UINT_MAX) |
2099 | | /* The context->hashUpdate function takes an unsigned int for its data |
2100 | | * length argument, but NSC_DigestUpdate takes an unsigned long. */ |
2101 | 667 | while (ulPartLen > UINT_MAX) { |
2102 | 0 | (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX); |
2103 | 0 | pPart += UINT_MAX; |
2104 | 0 | ulPartLen -= UINT_MAX; |
2105 | 0 | } |
2106 | 667 | #endif |
2107 | 667 | (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen); |
2108 | | |
2109 | 667 | return CKR_OK; |
2110 | 667 | } |
2111 | | |
2112 | | /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */ |
2113 | | CK_RV |
2114 | | NSC_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, |
2115 | | CK_ULONG_PTR pulDigestLen) |
2116 | 64 | { |
2117 | 64 | SFTKSession *session; |
2118 | 64 | SFTKSessionContext *context; |
2119 | 64 | unsigned int maxout = *pulDigestLen; |
2120 | 64 | unsigned int digestLen; |
2121 | 64 | CK_RV crv; |
2122 | | |
2123 | 64 | CHECK_FORK(); |
2124 | | |
2125 | | /* make sure we're legal */ |
2126 | 64 | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); |
2127 | 64 | if (crv != CKR_OK) |
2128 | 0 | return crv; |
2129 | | |
2130 | 64 | if (pDigest != NULL) { |
2131 | 64 | (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout); |
2132 | 64 | *pulDigestLen = digestLen; |
2133 | 64 | sftk_TerminateOp(session, SFTK_HASH, context); |
2134 | 64 | } else { |
2135 | 0 | *pulDigestLen = context->maxLen; |
2136 | 0 | } |
2137 | | |
2138 | 64 | sftk_FreeSession(session); |
2139 | 64 | return CKR_OK; |
2140 | 64 | } |
2141 | | |
2142 | | /* |
2143 | | * these helper functions are used by Generic Macing and Signing functions |
2144 | | * that use hashes as part of their operations. |
2145 | | */ |
2146 | | #define DOSUB(mmm) \ |
2147 | | static CK_RV \ |
2148 | | sftk_doSub##mmm(SFTKSessionContext *context) \ |
2149 | 0 | { \ |
2150 | 0 | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ |
2151 | 0 | context->hashInfo = (void *)mmm##_ctx; \ |
2152 | 0 | context->hashUpdate = SFTKHash_##mmm##_Update; \ |
2153 | 0 | context->end = SFTKHash_##mmm##_End; \ |
2154 | 0 | context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \ |
2155 | 0 | if (!context->hashInfo) { \ |
2156 | 0 | return CKR_HOST_MEMORY; \ |
2157 | 0 | } \ |
2158 | 0 | mmm##_Begin(mmm##_ctx); \ |
2159 | 0 | return CKR_OK; \ |
2160 | 0 | } Unexecuted instantiation: pkcs11c.c:sftk_doSubMD5 Unexecuted instantiation: pkcs11c.c:sftk_doSubMD2 Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA1 Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA224 Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA256 Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA384 Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA512 |
2161 | | |
2162 | | DOSUB(MD2) |
2163 | | DOSUB(MD5) |
2164 | | DOSUB(SHA1) |
2165 | | DOSUB(SHA224) |
2166 | | DOSUB(SHA256) |
2167 | | DOSUB(SHA384) |
2168 | | DOSUB(SHA512) |
2169 | | |
2170 | | static SECStatus |
2171 | | sftk_SignCopy( |
2172 | | void *copyLen, |
2173 | | unsigned char *out, unsigned int *outLength, |
2174 | | unsigned int maxLength, |
2175 | | const unsigned char *hashResult, |
2176 | | unsigned int hashResultLength) |
2177 | 69 | { |
2178 | 69 | unsigned int toCopy = *(CK_ULONG *)copyLen; |
2179 | 69 | if (toCopy > maxLength) { |
2180 | 0 | toCopy = maxLength; |
2181 | 0 | } |
2182 | 69 | if (toCopy > hashResultLength) { |
2183 | 0 | toCopy = hashResultLength; |
2184 | 0 | } |
2185 | 69 | memcpy(out, hashResult, toCopy); |
2186 | 69 | if (outLength) { |
2187 | 69 | *outLength = toCopy; |
2188 | 69 | } |
2189 | 69 | return SECSuccess; |
2190 | 69 | } |
2191 | | |
2192 | | /* Verify is just a compare for HMAC */ |
2193 | | static SECStatus |
2194 | | sftk_HMACCmp(void *copyLen, const unsigned char *sig, unsigned int sigLen, |
2195 | | const unsigned char *hash, unsigned int hashLen) |
2196 | 0 | { |
2197 | 0 | if (NSS_SecureMemcmp(sig, hash, *(CK_ULONG *)copyLen) == 0) { |
2198 | 0 | return SECSuccess; |
2199 | 0 | } |
2200 | | |
2201 | 0 | PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
2202 | 0 | return SECFailure; |
2203 | 0 | } |
2204 | | |
2205 | | /* |
2206 | | * common HMAC + CMAC initialization routine |
2207 | | */ |
2208 | | static CK_RV |
2209 | | sftk_doMACInit(CK_MECHANISM_TYPE mech, SFTKSessionContext *session, |
2210 | | SFTKObject *key, CK_ULONG mac_size) |
2211 | 69 | { |
2212 | 69 | CK_RV crv; |
2213 | 69 | sftk_MACCtx *context; |
2214 | 69 | CK_ULONG *intpointer; |
2215 | 69 | PRBool isFIPS = sftk_isFIPS(key->slot->slotID); |
2216 | | |
2217 | | /* Set up the initial context. */ |
2218 | 69 | crv = sftk_MAC_Create(mech, key, &context); |
2219 | 69 | if (crv != CKR_OK) { |
2220 | 0 | return crv; |
2221 | 0 | } |
2222 | | |
2223 | 69 | session->hashInfo = context; |
2224 | 69 | session->multi = PR_TRUE; |
2225 | | |
2226 | | /* Required by FIPS 198 Section 4. Delay this check until after the MAC |
2227 | | * has been initialized to steal the output size of the MAC. */ |
2228 | 69 | if (isFIPS && (mac_size < 4 || mac_size < context->mac_size / 2)) { |
2229 | 0 | sftk_MAC_DestroyContext(context, PR_TRUE); |
2230 | 0 | return CKR_BUFFER_TOO_SMALL; |
2231 | 0 | } |
2232 | | |
2233 | | /* Configure our helper functions appropriately. Note that these casts |
2234 | | * ignore the return values. */ |
2235 | 69 | session->hashUpdate = SFTKHash_sftk_MAC_Update; |
2236 | 69 | session->end = SFTKHash_sftk_MAC_End; |
2237 | 69 | session->hashdestroy = SFTKHash_sftk_MAC_DestroyContext; |
2238 | | |
2239 | 69 | intpointer = PORT_New(CK_ULONG); |
2240 | 69 | if (intpointer == NULL) { |
2241 | 0 | sftk_MAC_DestroyContext(context, PR_TRUE); |
2242 | 0 | return CKR_HOST_MEMORY; |
2243 | 0 | } |
2244 | 69 | *intpointer = mac_size; |
2245 | 69 | session->cipherInfo = intpointer; |
2246 | | |
2247 | | /* Since we're only "hashing", copy the result from session->end to the |
2248 | | * caller using sftk_SignCopy. */ |
2249 | 69 | session->update = sftk_SignCopy; |
2250 | 69 | session->verify = sftk_HMACCmp; |
2251 | 69 | session->destroy = sftk_Space; |
2252 | | |
2253 | 69 | session->maxLen = context->mac_size; |
2254 | | |
2255 | 69 | return CKR_OK; |
2256 | 69 | } |
2257 | | |
2258 | | /* |
2259 | | * SSL Macing support. SSL Macs are inited, then update with the base |
2260 | | * hashing algorithm, then finalized in sign and verify |
2261 | | */ |
2262 | | |
2263 | | /* |
2264 | | * FROM SSL: |
2265 | | * 60 bytes is 3 times the maximum length MAC size that is supported. |
2266 | | * We probably should have one copy of this table. We still need this table |
2267 | | * in ssl to 'sign' the handshake hashes. |
2268 | | */ |
2269 | | static unsigned char ssl_pad_1[60] = { |
2270 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2271 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2272 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2273 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2274 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2275 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2276 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2277 | | 0x36, 0x36, 0x36, 0x36 |
2278 | | }; |
2279 | | static unsigned char ssl_pad_2[60] = { |
2280 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2281 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2282 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2283 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2284 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2285 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2286 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2287 | | 0x5c, 0x5c, 0x5c, 0x5c |
2288 | | }; |
2289 | | |
2290 | | static SECStatus |
2291 | | sftk_SSLMACSign(void *ctx, unsigned char *sig, unsigned int *sigLen, |
2292 | | unsigned int maxLen, const unsigned char *hash, unsigned int hashLen) |
2293 | 0 | { |
2294 | 0 | SFTKSSLMACInfo *info = ctx; |
2295 | 0 | unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; |
2296 | 0 | unsigned int out; |
2297 | |
|
2298 | 0 | info->begin(info->hashContext); |
2299 | 0 | info->update(info->hashContext, info->key, info->keySize); |
2300 | 0 | info->update(info->hashContext, ssl_pad_2, info->padSize); |
2301 | 0 | info->update(info->hashContext, hash, hashLen); |
2302 | 0 | info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH); |
2303 | 0 | PORT_Memcpy(sig, tmpBuf, info->macSize); |
2304 | 0 | PORT_Memset(tmpBuf, 0, info->macSize); |
2305 | 0 | *sigLen = info->macSize; |
2306 | 0 | return SECSuccess; |
2307 | 0 | } |
2308 | | |
2309 | | static SECStatus |
2310 | | sftk_SSLMACVerify(void *ctx, const unsigned char *sig, unsigned int sigLen, |
2311 | | const unsigned char *hash, unsigned int hashLen) |
2312 | 0 | { |
2313 | 0 | SFTKSSLMACInfo *info = ctx; |
2314 | 0 | unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; |
2315 | 0 | unsigned int out; |
2316 | 0 | int cmp; |
2317 | |
|
2318 | 0 | info->begin(info->hashContext); |
2319 | 0 | info->update(info->hashContext, info->key, info->keySize); |
2320 | 0 | info->update(info->hashContext, ssl_pad_2, info->padSize); |
2321 | 0 | info->update(info->hashContext, hash, hashLen); |
2322 | 0 | info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH); |
2323 | 0 | cmp = NSS_SecureMemcmp(sig, tmpBuf, info->macSize); |
2324 | 0 | PORT_Memset(tmpBuf, 0, info->macSize); |
2325 | 0 | return (cmp == 0) ? SECSuccess : SECFailure; |
2326 | 0 | } |
2327 | | |
2328 | | /* |
2329 | | * common HMAC initalization routine |
2330 | | */ |
2331 | | static CK_RV |
2332 | | sftk_doSSLMACInit(SFTKSessionContext *context, SECOidTag oid, |
2333 | | SFTKObject *key, CK_ULONG mac_size) |
2334 | 0 | { |
2335 | 0 | SFTKAttribute *keyval; |
2336 | 0 | SFTKBegin begin; |
2337 | 0 | int padSize; |
2338 | 0 | SFTKSSLMACInfo *sslmacinfo; |
2339 | 0 | CK_RV crv = CKR_MECHANISM_INVALID; |
2340 | |
|
2341 | 0 | if (oid == SEC_OID_SHA1) { |
2342 | 0 | crv = sftk_doSubSHA1(context); |
2343 | 0 | if (crv != CKR_OK) |
2344 | 0 | return crv; |
2345 | 0 | begin = SFTKHash_SHA1_Begin; |
2346 | 0 | padSize = 40; |
2347 | 0 | } else { |
2348 | 0 | crv = sftk_doSubMD5(context); |
2349 | 0 | if (crv != CKR_OK) |
2350 | 0 | return crv; |
2351 | 0 | begin = SFTKHash_MD5_Begin; |
2352 | 0 | padSize = 48; |
2353 | 0 | } |
2354 | 0 | context->multi = PR_TRUE; |
2355 | |
|
2356 | 0 | keyval = sftk_FindAttribute(key, CKA_VALUE); |
2357 | 0 | if (keyval == NULL) |
2358 | 0 | return CKR_KEY_SIZE_RANGE; |
2359 | | |
2360 | 0 | context->hashUpdate(context->hashInfo, keyval->attrib.pValue, |
2361 | 0 | keyval->attrib.ulValueLen); |
2362 | 0 | context->hashUpdate(context->hashInfo, ssl_pad_1, padSize); |
2363 | 0 | sslmacinfo = (SFTKSSLMACInfo *)PORT_Alloc(sizeof(SFTKSSLMACInfo)); |
2364 | 0 | if (sslmacinfo == NULL) { |
2365 | 0 | sftk_FreeAttribute(keyval); |
2366 | 0 | return CKR_HOST_MEMORY; |
2367 | 0 | } |
2368 | 0 | sslmacinfo->size = sizeof(SFTKSSLMACInfo); |
2369 | 0 | sslmacinfo->macSize = mac_size; |
2370 | 0 | sslmacinfo->hashContext = context->hashInfo; |
2371 | 0 | PORT_Memcpy(sslmacinfo->key, keyval->attrib.pValue, |
2372 | 0 | keyval->attrib.ulValueLen); |
2373 | 0 | sslmacinfo->keySize = keyval->attrib.ulValueLen; |
2374 | 0 | sslmacinfo->begin = begin; |
2375 | 0 | sslmacinfo->end = context->end; |
2376 | 0 | sslmacinfo->update = context->hashUpdate; |
2377 | 0 | sslmacinfo->padSize = padSize; |
2378 | 0 | sftk_FreeAttribute(keyval); |
2379 | 0 | context->cipherInfo = (void *)sslmacinfo; |
2380 | 0 | context->destroy = sftk_ZSpace; |
2381 | 0 | context->update = sftk_SSLMACSign; |
2382 | 0 | context->verify = sftk_SSLMACVerify; |
2383 | 0 | context->maxLen = mac_size; |
2384 | 0 | return CKR_OK; |
2385 | 0 | } |
2386 | | |
2387 | | /* |
2388 | | ************** Crypto Functions: Sign ************************ |
2389 | | */ |
2390 | | |
2391 | | /** |
2392 | | * Check if We're using CBCMacing and initialize the session context if we are. |
2393 | | * @param contextType SFTK_SIGN or SFTK_VERIFY |
2394 | | * @param keyUsage check whether key allows this usage |
2395 | | */ |
2396 | | static CK_RV |
2397 | | sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
2398 | | CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage, |
2399 | | SFTKContextType contextType) |
2400 | | |
2401 | 95 | { |
2402 | 95 | CK_MECHANISM cbc_mechanism; |
2403 | 95 | CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE; |
2404 | 95 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
2405 | 95 | CK_RC2_CBC_PARAMS rc2_params; |
2406 | 95 | #endif |
2407 | | #if NSS_SOFTOKEN_DOES_RC5 |
2408 | | CK_RC5_CBC_PARAMS rc5_params; |
2409 | | CK_RC5_MAC_GENERAL_PARAMS *rc5_mac; |
2410 | | #endif |
2411 | 95 | unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE]; |
2412 | 95 | unsigned char k2[SFTK_MAX_BLOCK_SIZE]; |
2413 | 95 | unsigned char k3[SFTK_MAX_BLOCK_SIZE]; |
2414 | 95 | SFTKSessionContext *context; |
2415 | 95 | CK_RV crv; |
2416 | 95 | unsigned int blockSize; |
2417 | 95 | PRBool isXCBC = PR_FALSE; |
2418 | | |
2419 | 95 | if (!pMechanism) { |
2420 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
2421 | 0 | } |
2422 | | |
2423 | 95 | switch (pMechanism->mechanism) { |
2424 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
2425 | 0 | case CKM_RC2_MAC_GENERAL: |
2426 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_MAC_GENERAL_PARAMS))) { |
2427 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
2428 | 0 | } |
2429 | 0 | mac_bytes = |
2430 | 0 | ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; |
2431 | | /* fall through */ |
2432 | 0 | case CKM_RC2_MAC: |
2433 | | /* this works because ulEffectiveBits is in the same place in both the |
2434 | | * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */ |
2435 | 0 | rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *) |
2436 | 0 | pMechanism->pParameter) |
2437 | 0 | ->ulEffectiveBits; |
2438 | 0 | PORT_Memset(rc2_params.iv, 0, sizeof(rc2_params.iv)); |
2439 | 0 | cbc_mechanism.mechanism = CKM_RC2_CBC; |
2440 | 0 | cbc_mechanism.pParameter = &rc2_params; |
2441 | 0 | cbc_mechanism.ulParameterLen = sizeof(rc2_params); |
2442 | 0 | blockSize = 8; |
2443 | 0 | break; |
2444 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
2445 | | |
2446 | | #if NSS_SOFTOKEN_DOES_RC5 |
2447 | | case CKM_RC5_MAC_GENERAL: |
2448 | | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) { |
2449 | | return CKR_MECHANISM_PARAM_INVALID; |
2450 | | } |
2451 | | mac_bytes = |
2452 | | ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; |
2453 | | /* fall through */ |
2454 | | case CKM_RC5_MAC: |
2455 | | /* this works because ulEffectiveBits is in the same place in both the |
2456 | | * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */ |
2457 | | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) { |
2458 | | return CKR_MECHANISM_PARAM_INVALID; |
2459 | | } |
2460 | | rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter; |
2461 | | rc5_params.ulWordsize = rc5_mac->ulWordsize; |
2462 | | rc5_params.ulRounds = rc5_mac->ulRounds; |
2463 | | rc5_params.pIv = ivBlock; |
2464 | | if ((blockSize = rc5_mac->ulWordsize * 2) > SFTK_MAX_BLOCK_SIZE) |
2465 | | return CKR_MECHANISM_PARAM_INVALID; |
2466 | | rc5_params.ulIvLen = blockSize; |
2467 | | PORT_Memset(ivBlock, 0, blockSize); |
2468 | | cbc_mechanism.mechanism = CKM_RC5_CBC; |
2469 | | cbc_mechanism.pParameter = &rc5_params; |
2470 | | cbc_mechanism.ulParameterLen = sizeof(rc5_params); |
2471 | | break; |
2472 | | #endif |
2473 | | /* add cast and idea later */ |
2474 | 0 | case CKM_DES_MAC_GENERAL: |
2475 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2476 | | /* fall through */ |
2477 | 0 | case CKM_DES_MAC: |
2478 | 0 | blockSize = 8; |
2479 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2480 | 0 | cbc_mechanism.mechanism = CKM_DES_CBC; |
2481 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2482 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2483 | 0 | break; |
2484 | 0 | case CKM_DES3_MAC_GENERAL: |
2485 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2486 | | /* fall through */ |
2487 | 0 | case CKM_DES3_MAC: |
2488 | 0 | blockSize = 8; |
2489 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2490 | 0 | cbc_mechanism.mechanism = CKM_DES3_CBC; |
2491 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2492 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2493 | 0 | break; |
2494 | 0 | case CKM_CDMF_MAC_GENERAL: |
2495 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2496 | | /* fall through */ |
2497 | 0 | case CKM_CDMF_MAC: |
2498 | 0 | blockSize = 8; |
2499 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2500 | 0 | cbc_mechanism.mechanism = CKM_CDMF_CBC; |
2501 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2502 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2503 | 0 | break; |
2504 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
2505 | 0 | case CKM_SEED_MAC_GENERAL: |
2506 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2507 | | /* fall through */ |
2508 | 0 | case CKM_SEED_MAC: |
2509 | 0 | blockSize = 16; |
2510 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2511 | 0 | cbc_mechanism.mechanism = CKM_SEED_CBC; |
2512 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2513 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2514 | 0 | break; |
2515 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
2516 | 0 | case CKM_CAMELLIA_MAC_GENERAL: |
2517 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2518 | | /* fall through */ |
2519 | 0 | case CKM_CAMELLIA_MAC: |
2520 | 0 | blockSize = 16; |
2521 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2522 | 0 | cbc_mechanism.mechanism = CKM_CAMELLIA_CBC; |
2523 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2524 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2525 | 0 | break; |
2526 | 0 | case CKM_AES_MAC_GENERAL: |
2527 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2528 | | /* fall through */ |
2529 | 0 | case CKM_AES_MAC: |
2530 | 0 | blockSize = 16; |
2531 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2532 | 0 | cbc_mechanism.mechanism = CKM_AES_CBC; |
2533 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2534 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2535 | 0 | break; |
2536 | 0 | case CKM_AES_XCBC_MAC_96: |
2537 | 0 | case CKM_AES_XCBC_MAC: |
2538 | | /* The only difference between CKM_AES_XCBC_MAC |
2539 | | * and CKM_AES_XCBC_MAC_96 is the size of the returned mac. */ |
2540 | 0 | mac_bytes = pMechanism->mechanism == CKM_AES_XCBC_MAC_96 ? 12 : 16; |
2541 | 0 | blockSize = 16; |
2542 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2543 | 0 | cbc_mechanism.mechanism = CKM_AES_CBC; |
2544 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2545 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2546 | | /* is XCBC requires extra processing at the end of the operation */ |
2547 | 0 | isXCBC = PR_TRUE; |
2548 | | /* The input key is used to generate k1, k2, and k3. k2 and k3 |
2549 | | * are used at the end in the pad step. k1 replaces the input |
2550 | | * key in the aes cbc mac */ |
2551 | 0 | crv = sftk_aes_xcbc_new_keys(hSession, hKey, &hKey, k2, k3); |
2552 | 0 | if (crv != CKR_OK) { |
2553 | 0 | return crv; |
2554 | 0 | } |
2555 | 0 | break; |
2556 | 95 | default: |
2557 | 95 | return CKR_FUNCTION_NOT_SUPPORTED; |
2558 | 95 | } |
2559 | | |
2560 | | /* if MAC size is externally supplied, it should be checked. |
2561 | | */ |
2562 | 0 | if (mac_bytes == SFTK_INVALID_MAC_SIZE) |
2563 | 0 | mac_bytes = blockSize >> 1; |
2564 | 0 | else { |
2565 | 0 | if (mac_bytes > blockSize) { |
2566 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
2567 | 0 | goto fail; |
2568 | 0 | } |
2569 | 0 | } |
2570 | | |
2571 | 0 | crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey, |
2572 | 0 | CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */ |
2573 | 0 | keyUsage, contextType, PR_TRUE); |
2574 | 0 | if (crv != CKR_OK) |
2575 | 0 | goto fail; |
2576 | 0 | crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL); |
2577 | | |
2578 | | /* this shouldn't happen! */ |
2579 | 0 | PORT_Assert(crv == CKR_OK); |
2580 | 0 | if (crv != CKR_OK) |
2581 | 0 | goto fail; |
2582 | 0 | context->blockSize = blockSize; |
2583 | 0 | context->macSize = mac_bytes; |
2584 | 0 | context->isXCBC = isXCBC; |
2585 | 0 | if (isXCBC) { |
2586 | | /* save the xcbc specific parameters */ |
2587 | 0 | PORT_Memcpy(context->k2, k2, blockSize); |
2588 | 0 | PORT_Memcpy(context->k3, k3, blockSize); |
2589 | 0 | PORT_Memset(k2, 0, blockSize); |
2590 | 0 | PORT_Memset(k3, 0, blockSize); |
2591 | | /* get rid of the temp key now that the context has been created */ |
2592 | 0 | NSC_DestroyObject(hSession, hKey); |
2593 | 0 | } |
2594 | 0 | return CKR_OK; |
2595 | 0 | fail: |
2596 | 0 | if (isXCBC) { |
2597 | 0 | PORT_Memset(k2, 0, blockSize); |
2598 | 0 | PORT_Memset(k3, 0, blockSize); |
2599 | 0 | NSC_DestroyObject(hSession, hKey); /* get rid of our temp key */ |
2600 | 0 | } |
2601 | 0 | return crv; |
2602 | 0 | } |
2603 | | |
2604 | | /* |
2605 | | * encode RSA PKCS #1 Signature data before signing... |
2606 | | */ |
2607 | | static SECStatus |
2608 | | sftk_RSAHashSign(void *ctx, unsigned char *sig, |
2609 | | unsigned int *sigLen, unsigned int maxLen, |
2610 | | const unsigned char *hash, unsigned int hashLen) |
2611 | 0 | { |
2612 | 0 | SFTKHashSignInfo *info = ctx; |
2613 | 0 | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
2614 | 0 | if (info->key->keyType != NSSLOWKEYRSAKey) { |
2615 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2616 | 0 | return SECFailure; |
2617 | 0 | } |
2618 | | |
2619 | 0 | return RSA_HashSign(info->hashOid, info->key, sig, sigLen, maxLen, |
2620 | 0 | hash, hashLen); |
2621 | 0 | } |
2622 | | |
2623 | | /* XXX Old template; want to expunge it eventually. */ |
2624 | | static DERTemplate SECAlgorithmIDTemplate[] = { |
2625 | | { DER_SEQUENCE, |
2626 | | 0, NULL, sizeof(SECAlgorithmID) }, |
2627 | | { DER_OBJECT_ID, |
2628 | | offsetof(SECAlgorithmID, algorithm) }, |
2629 | | { DER_OPTIONAL | DER_ANY, |
2630 | | offsetof(SECAlgorithmID, parameters) }, |
2631 | | { 0 } |
2632 | | }; |
2633 | | |
2634 | | /* |
2635 | | * XXX OLD Template. Once all uses have been switched over to new one, |
2636 | | * remove this. |
2637 | | */ |
2638 | | static DERTemplate SGNDigestInfoTemplate[] = { |
2639 | | { DER_SEQUENCE, |
2640 | | 0, NULL, sizeof(SGNDigestInfo) }, |
2641 | | { DER_INLINE, |
2642 | | offsetof(SGNDigestInfo, digestAlgorithm), |
2643 | | SECAlgorithmIDTemplate }, |
2644 | | { DER_OCTET_STRING, |
2645 | | offsetof(SGNDigestInfo, digest) }, |
2646 | | { 0 } |
2647 | | }; |
2648 | | |
2649 | | /* |
2650 | | * encode RSA PKCS #1 Signature data before signing... |
2651 | | */ |
2652 | | SECStatus |
2653 | | RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, |
2654 | | unsigned char *sig, unsigned int *sigLen, unsigned int maxLen, |
2655 | | const unsigned char *hash, unsigned int hashLen) |
2656 | 6 | { |
2657 | 6 | SECStatus rv = SECFailure; |
2658 | 6 | SECItem digder; |
2659 | 6 | PLArenaPool *arena = NULL; |
2660 | 6 | SGNDigestInfo *di = NULL; |
2661 | | |
2662 | 6 | digder.data = NULL; |
2663 | | |
2664 | 6 | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
2665 | 6 | if (!arena) { |
2666 | 0 | goto loser; |
2667 | 0 | } |
2668 | | |
2669 | | /* Construct digest info */ |
2670 | 6 | di = SGN_CreateDigestInfo(hashOid, hash, hashLen); |
2671 | 6 | if (!di) { |
2672 | 0 | goto loser; |
2673 | 0 | } |
2674 | | |
2675 | | /* Der encode the digest as a DigestInfo */ |
2676 | 6 | rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di); |
2677 | 6 | if (rv != SECSuccess) { |
2678 | 0 | goto loser; |
2679 | 0 | } |
2680 | | |
2681 | | /* |
2682 | | ** Encrypt signature after constructing appropriate PKCS#1 signature |
2683 | | ** block |
2684 | | */ |
2685 | 6 | rv = RSA_Sign(&key->u.rsa, sig, sigLen, maxLen, digder.data, |
2686 | 6 | digder.len); |
2687 | 6 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2688 | 0 | sftk_fatalError = PR_TRUE; |
2689 | 0 | } |
2690 | | |
2691 | 6 | loser: |
2692 | 6 | SGN_DestroyDigestInfo(di); |
2693 | 6 | if (arena != NULL) { |
2694 | 6 | PORT_FreeArena(arena, PR_TRUE); |
2695 | 6 | } |
2696 | 6 | return rv; |
2697 | 6 | } |
2698 | | |
2699 | | static SECStatus |
2700 | | sftk_RSASign(void *ctx, unsigned char *output, |
2701 | | unsigned int *outputLen, unsigned int maxOutputLen, |
2702 | | const unsigned char *input, unsigned int inputLen) |
2703 | 0 | { |
2704 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
2705 | 0 | SECStatus rv = SECFailure; |
2706 | |
|
2707 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
2708 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
2709 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2710 | 0 | return SECFailure; |
2711 | 0 | } |
2712 | | |
2713 | 0 | rv = RSA_Sign(&key->u.rsa, output, outputLen, maxOutputLen, input, |
2714 | 0 | inputLen); |
2715 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2716 | 0 | sftk_fatalError = PR_TRUE; |
2717 | 0 | } |
2718 | 0 | return rv; |
2719 | 0 | } |
2720 | | |
2721 | | static SECStatus |
2722 | | sftk_RSASignRaw(void *ctx, unsigned char *output, |
2723 | | unsigned int *outputLen, unsigned int maxOutputLen, |
2724 | | const unsigned char *input, unsigned int inputLen) |
2725 | 0 | { |
2726 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
2727 | 0 | SECStatus rv = SECFailure; |
2728 | |
|
2729 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
2730 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
2731 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2732 | 0 | return SECFailure; |
2733 | 0 | } |
2734 | | |
2735 | 0 | rv = RSA_SignRaw(&key->u.rsa, output, outputLen, maxOutputLen, input, |
2736 | 0 | inputLen); |
2737 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2738 | 0 | sftk_fatalError = PR_TRUE; |
2739 | 0 | } |
2740 | 0 | return rv; |
2741 | 0 | } |
2742 | | |
2743 | | static SECStatus |
2744 | | sftk_RSASignPSS(void *ctx, unsigned char *sig, |
2745 | | unsigned int *sigLen, unsigned int maxLen, |
2746 | | const unsigned char *hash, unsigned int hashLen) |
2747 | 0 | { |
2748 | 0 | SFTKPSSSignInfo *info = ctx; |
2749 | 0 | SECStatus rv = SECFailure; |
2750 | 0 | HASH_HashType hashAlg; |
2751 | 0 | HASH_HashType maskHashAlg; |
2752 | 0 | CK_RSA_PKCS_PSS_PARAMS *params = &info->params; |
2753 | |
|
2754 | 0 | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
2755 | 0 | if (info->key->keyType != NSSLOWKEYRSAKey) { |
2756 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2757 | 0 | return SECFailure; |
2758 | 0 | } |
2759 | | |
2760 | 0 | hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg); |
2761 | 0 | maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf); |
2762 | |
|
2763 | 0 | rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL, |
2764 | 0 | params->sLen, sig, sigLen, maxLen, hash, hashLen); |
2765 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2766 | 0 | sftk_fatalError = PR_TRUE; |
2767 | 0 | } |
2768 | 0 | return rv; |
2769 | 0 | } |
2770 | | |
2771 | | static SECStatus |
2772 | | nsc_DSA_Verify_Stub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen, |
2773 | | const unsigned char *dataBuf, unsigned int dataLen) |
2774 | 0 | { |
2775 | 0 | NSSLOWKEYPublicKey *key = ctx; |
2776 | 0 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen }; |
2777 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2778 | 0 | return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest); |
2779 | 0 | } |
2780 | | |
2781 | | static SECStatus |
2782 | | nsc_DSA_Sign_Stub(void *ctx, unsigned char *sigBuf, |
2783 | | unsigned int *sigLen, unsigned int maxSigLen, |
2784 | | const unsigned char *dataBuf, unsigned int dataLen) |
2785 | 0 | { |
2786 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
2787 | 0 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen }; |
2788 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2789 | 0 | SECStatus rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest); |
2790 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2791 | 0 | sftk_fatalError = PR_TRUE; |
2792 | 0 | } |
2793 | 0 | *sigLen = signature.len; |
2794 | 0 | return rv; |
2795 | 0 | } |
2796 | | |
2797 | | static SECStatus |
2798 | | nsc_ECDSAVerifyStub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen, |
2799 | | const unsigned char *dataBuf, unsigned int dataLen) |
2800 | 0 | { |
2801 | 0 | NSSLOWKEYPublicKey *key = ctx; |
2802 | 0 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen }; |
2803 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2804 | 0 | return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest); |
2805 | 0 | } |
2806 | | |
2807 | | static SECStatus |
2808 | | nsc_ECDSASignStub(void *ctx, unsigned char *sigBuf, |
2809 | | unsigned int *sigLen, unsigned int maxSigLen, |
2810 | | const unsigned char *dataBuf, unsigned int dataLen) |
2811 | 0 | { |
2812 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
2813 | 0 | SECItem signature = { siBuffer, sigBuf, maxSigLen }; |
2814 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2815 | |
|
2816 | 0 | SECStatus rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest); |
2817 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2818 | 0 | sftk_fatalError = PR_TRUE; |
2819 | 0 | } |
2820 | 0 | *sigLen = signature.len; |
2821 | 0 | return rv; |
2822 | 0 | } |
2823 | | |
2824 | | static SECStatus |
2825 | | nsc_EDDSAVerifyStub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen, |
2826 | | const unsigned char *dataBuf, unsigned int dataLen) |
2827 | 0 | { |
2828 | 0 | NSSLOWKEYPublicKey *key = ctx; |
2829 | 0 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen }; |
2830 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2831 | 0 | return ED_VerifyMessage(&(key->u.ec), &signature, &digest); |
2832 | 0 | } |
2833 | | |
2834 | | static SECStatus |
2835 | | nsc_EDDSASignStub(void *ctx, unsigned char *sigBuf, |
2836 | | unsigned int *sigLen, unsigned int maxSigLen, |
2837 | | const unsigned char *dataBuf, unsigned int dataLen) |
2838 | 0 | { |
2839 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
2840 | 0 | SECItem signature = { siBuffer, sigBuf, maxSigLen }; |
2841 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2842 | |
|
2843 | 0 | SECStatus rv = ED_SignMessage(&(key->u.ec), &signature, &digest); |
2844 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2845 | 0 | sftk_fatalError = PR_TRUE; |
2846 | 0 | } |
2847 | 0 | *sigLen = signature.len; |
2848 | 0 | return rv; |
2849 | 0 | } |
2850 | | |
2851 | | /* NSC_SignInit setups up the signing operations. There are three basic |
2852 | | * types of signing: |
2853 | | * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied |
2854 | | * to data in a single Sign operation (which often looks a lot like an |
2855 | | * encrypt, with data coming in and data going out). |
2856 | | * (2) Hash based signing, where we continually hash the data, then apply |
2857 | | * some sort of signature to the end. |
2858 | | * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key, |
2859 | | * and only the final block is part of the mac. |
2860 | | * |
2861 | | * For case number 3, we initialize a context much like the Encryption Context |
2862 | | * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and |
2863 | | * C_Final by the following method... if it's not multi-part, and it's doesn't |
2864 | | * have a hash context, it must be a block Encryption CBC MAC. |
2865 | | * |
2866 | | * For case number 2, we initialize a hash structure, as well as make it |
2867 | | * multi-part. Updates are simple calls to the hash update function. Final |
2868 | | * calls the hashend, then passes the result to the 'update' function (which |
2869 | | * operates as a final signature function). In some hash based MAC'ing (as |
2870 | | * opposed to hash base signatures), the update function is can be simply a |
2871 | | * copy (as is the case with HMAC). |
2872 | | */ |
2873 | | CK_RV |
2874 | | NSC_SignInit(CK_SESSION_HANDLE hSession, |
2875 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
2876 | 95 | { |
2877 | 95 | SFTKSession *session; |
2878 | 95 | SFTKObject *key; |
2879 | 95 | SFTKSessionContext *context; |
2880 | 95 | CK_KEY_TYPE key_type; |
2881 | 95 | CK_RV crv = CKR_OK; |
2882 | 95 | NSSLOWKEYPrivateKey *privKey; |
2883 | 95 | SFTKHashSignInfo *info = NULL; |
2884 | 95 | SFTKPSSSignInfo *pinfo = NULL; |
2885 | | |
2886 | 95 | CHECK_FORK(); |
2887 | | |
2888 | | /* Block Cipher MACing Algorithms use a different Context init method..*/ |
2889 | 95 | crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN); |
2890 | 95 | if (crv != CKR_FUNCTION_NOT_SUPPORTED) |
2891 | 0 | return crv; |
2892 | | |
2893 | | /* we're not using a block cipher mac */ |
2894 | 95 | session = sftk_SessionFromHandle(hSession); |
2895 | 95 | if (session == NULL) |
2896 | 0 | return CKR_SESSION_HANDLE_INVALID; |
2897 | 95 | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_SIGN, &key, |
2898 | 95 | hKey, &key_type, CKO_PRIVATE_KEY, CKA_SIGN); |
2899 | 95 | if (crv != CKR_OK) { |
2900 | 0 | sftk_FreeSession(session); |
2901 | 0 | return crv; |
2902 | 0 | } |
2903 | | |
2904 | 95 | context->multi = PR_FALSE; |
2905 | | |
2906 | 95 | #define INIT_RSA_SIGN_MECH(mmm) \ |
2907 | 95 | case CKM_##mmm##_RSA_PKCS: \ |
2908 | 0 | context->multi = PR_TRUE; \ |
2909 | 0 | crv = sftk_doSub##mmm(context); \ |
2910 | 0 | if (crv != CKR_OK) \ |
2911 | 0 | break; \ |
2912 | 0 | context->update = sftk_RSAHashSign; \ |
2913 | 0 | info = PORT_New(SFTKHashSignInfo); \ |
2914 | 0 | if (info == NULL) { \ |
2915 | 0 | crv = CKR_HOST_MEMORY; \ |
2916 | 0 | break; \ |
2917 | 0 | } \ |
2918 | 0 | info->hashOid = SEC_OID_##mmm; \ |
2919 | 0 | goto finish_rsa; |
2920 | | |
2921 | 95 | switch (pMechanism->mechanism) { |
2922 | 0 | INIT_RSA_SIGN_MECH(MD5) |
2923 | 0 | INIT_RSA_SIGN_MECH(MD2) |
2924 | 0 | INIT_RSA_SIGN_MECH(SHA1) |
2925 | 0 | INIT_RSA_SIGN_MECH(SHA224) |
2926 | 0 | INIT_RSA_SIGN_MECH(SHA256) |
2927 | 0 | INIT_RSA_SIGN_MECH(SHA384) |
2928 | 0 | INIT_RSA_SIGN_MECH(SHA512) |
2929 | | |
2930 | 0 | case CKM_RSA_PKCS: |
2931 | 0 | context->update = sftk_RSASign; |
2932 | 0 | goto finish_rsa; |
2933 | 0 | case CKM_RSA_X_509: |
2934 | 0 | context->update = sftk_RSASignRaw; |
2935 | 0 | finish_rsa: |
2936 | 0 | if (key_type != CKK_RSA) { |
2937 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
2938 | 0 | break; |
2939 | 0 | } |
2940 | 0 | context->rsa = PR_TRUE; |
2941 | 0 | privKey = sftk_GetPrivKey(key, CKK_RSA, &crv); |
2942 | 0 | if (privKey == NULL) { |
2943 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
2944 | 0 | break; |
2945 | 0 | } |
2946 | | /* OK, info is allocated only if we're doing hash and sign mechanism. |
2947 | | * It's necessary to be able to set the correct OID in the final |
2948 | | * signature. |
2949 | | */ |
2950 | 0 | if (info) { |
2951 | 0 | info->key = privKey; |
2952 | 0 | context->cipherInfo = info; |
2953 | 0 | context->destroy = sftk_Space; |
2954 | 0 | } else { |
2955 | 0 | context->cipherInfo = privKey; |
2956 | 0 | context->destroy = sftk_Null; |
2957 | 0 | } |
2958 | 0 | context->maxLen = nsslowkey_PrivateModulusLen(privKey); |
2959 | 0 | break; |
2960 | | |
2961 | 0 | #define INIT_RSA_PSS_SIG_MECH(mmm) \ |
2962 | 0 | case CKM_##mmm##_RSA_PKCS_PSS: \ |
2963 | 0 | context->multi = PR_TRUE; \ |
2964 | 0 | crv = sftk_doSub##mmm(context); \ |
2965 | 0 | if (crv != CKR_OK) \ |
2966 | 0 | break; \ |
2967 | 0 | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) { \ |
2968 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; \ |
2969 | 0 | break; \ |
2970 | 0 | } \ |
2971 | 0 | if (((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)->hashAlg != CKM_##mmm) { \ |
2972 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; \ |
2973 | 0 | break; \ |
2974 | 0 | } \ |
2975 | 0 | goto finish_rsa_pss; |
2976 | 0 | INIT_RSA_PSS_SIG_MECH(SHA1) |
2977 | 0 | INIT_RSA_PSS_SIG_MECH(SHA224) |
2978 | 0 | INIT_RSA_PSS_SIG_MECH(SHA256) |
2979 | 0 | INIT_RSA_PSS_SIG_MECH(SHA384) |
2980 | 0 | INIT_RSA_PSS_SIG_MECH(SHA512) |
2981 | 0 | case CKM_RSA_PKCS_PSS: |
2982 | 0 | finish_rsa_pss: |
2983 | 0 | if (key_type != CKK_RSA) { |
2984 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
2985 | 0 | break; |
2986 | 0 | } |
2987 | 0 | context->rsa = PR_TRUE; |
2988 | 0 | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || |
2989 | 0 | !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) { |
2990 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
2991 | 0 | break; |
2992 | 0 | } |
2993 | 0 | pinfo = PORT_New(SFTKPSSSignInfo); |
2994 | 0 | if (pinfo == NULL) { |
2995 | 0 | crv = CKR_HOST_MEMORY; |
2996 | 0 | break; |
2997 | 0 | } |
2998 | 0 | pinfo->size = sizeof(SFTKPSSSignInfo); |
2999 | 0 | pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter; |
3000 | 0 | pinfo->key = sftk_GetPrivKey(key, CKK_RSA, &crv); |
3001 | 0 | if (pinfo->key == NULL) { |
3002 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3003 | 0 | break; |
3004 | 0 | } |
3005 | 0 | context->cipherInfo = pinfo; |
3006 | 0 | context->destroy = sftk_ZSpace; |
3007 | 0 | context->update = sftk_RSASignPSS; |
3008 | 0 | context->maxLen = nsslowkey_PrivateModulusLen(pinfo->key); |
3009 | 0 | break; |
3010 | | |
3011 | 0 | #define INIT_DSA_SIG_MECH(mmm) \ |
3012 | 0 | case CKM_DSA_##mmm: \ |
3013 | 0 | context->multi = PR_TRUE; \ |
3014 | 0 | crv = sftk_doSub##mmm(context); \ |
3015 | 0 | if (crv != CKR_OK) \ |
3016 | 0 | break; \ |
3017 | 0 | goto finish_dsa; |
3018 | 0 | INIT_DSA_SIG_MECH(SHA1) |
3019 | 0 | INIT_DSA_SIG_MECH(SHA224) |
3020 | 0 | INIT_DSA_SIG_MECH(SHA256) |
3021 | 0 | INIT_DSA_SIG_MECH(SHA384) |
3022 | 0 | INIT_DSA_SIG_MECH(SHA512) |
3023 | 0 | case CKM_DSA: |
3024 | 0 | finish_dsa: |
3025 | 0 | if (key_type != CKK_DSA) { |
3026 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3027 | 0 | break; |
3028 | 0 | } |
3029 | 0 | privKey = sftk_GetPrivKey(key, CKK_DSA, &crv); |
3030 | 0 | if (privKey == NULL) { |
3031 | 0 | break; |
3032 | 0 | } |
3033 | 0 | context->cipherInfo = privKey; |
3034 | 0 | context->update = nsc_DSA_Sign_Stub; |
3035 | 0 | context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey; |
3036 | 0 | context->maxLen = DSA_MAX_SIGNATURE_LEN; |
3037 | |
|
3038 | 0 | break; |
3039 | | |
3040 | 0 | #define INIT_ECDSA_SIG_MECH(mmm) \ |
3041 | 0 | case CKM_ECDSA_##mmm: \ |
3042 | 0 | context->multi = PR_TRUE; \ |
3043 | 0 | crv = sftk_doSub##mmm(context); \ |
3044 | 0 | if (crv != CKR_OK) \ |
3045 | 0 | break; \ |
3046 | 0 | goto finish_ecdsa; |
3047 | 0 | INIT_ECDSA_SIG_MECH(SHA1) |
3048 | 0 | INIT_ECDSA_SIG_MECH(SHA224) |
3049 | 0 | INIT_ECDSA_SIG_MECH(SHA256) |
3050 | 0 | INIT_ECDSA_SIG_MECH(SHA384) |
3051 | 0 | INIT_ECDSA_SIG_MECH(SHA512) |
3052 | 0 | case CKM_ECDSA: |
3053 | 0 | finish_ecdsa: |
3054 | 0 | if (key_type != CKK_EC) { |
3055 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3056 | 0 | break; |
3057 | 0 | } |
3058 | 0 | privKey = sftk_GetPrivKey(key, CKK_EC, &crv); |
3059 | 0 | if (privKey == NULL) { |
3060 | 0 | crv = CKR_HOST_MEMORY; |
3061 | 0 | break; |
3062 | 0 | } |
3063 | 0 | context->cipherInfo = privKey; |
3064 | 0 | context->update = nsc_ECDSASignStub; |
3065 | 0 | context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey; |
3066 | 0 | context->maxLen = MAX_ECKEY_LEN * 2; |
3067 | |
|
3068 | 0 | break; |
3069 | | |
3070 | 0 | case CKM_EDDSA: |
3071 | 0 | if (key_type != CKK_EC_EDWARDS) { |
3072 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3073 | 0 | break; |
3074 | 0 | } |
3075 | | |
3076 | 0 | if (pMechanism->pParameter) { |
3077 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3078 | 0 | break; |
3079 | 0 | } |
3080 | | |
3081 | 0 | privKey = sftk_GetPrivKey(key, CKK_EC_EDWARDS, &crv); |
3082 | 0 | if (privKey == NULL) { |
3083 | 0 | crv = CKR_HOST_MEMORY; |
3084 | 0 | break; |
3085 | 0 | } |
3086 | 0 | context->cipherInfo = privKey; |
3087 | 0 | context->update = nsc_EDDSASignStub; |
3088 | 0 | context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey; |
3089 | 0 | context->maxLen = MAX_ECKEY_LEN * 2; |
3090 | |
|
3091 | 0 | break; |
3092 | | |
3093 | 0 | #define INIT_HMAC_MECH(mmm) \ |
3094 | 0 | case CKM_##mmm##_HMAC_GENERAL: \ |
3095 | 0 | PORT_Assert(pMechanism->pParameter); \ |
3096 | 0 | if (!pMechanism->pParameter) { \ |
3097 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; \ |
3098 | 0 | break; \ |
3099 | 0 | } \ |
3100 | 0 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, \ |
3101 | 0 | *(CK_ULONG *)pMechanism->pParameter); \ |
3102 | 0 | break; \ |
3103 | 68 | case CKM_##mmm##_HMAC: \ |
3104 | 68 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, \ |
3105 | 68 | mmm##_LENGTH); \ |
3106 | 68 | break; |
3107 | | |
3108 | 0 | INIT_HMAC_MECH(MD2) |
3109 | 0 | INIT_HMAC_MECH(MD5) |
3110 | 0 | INIT_HMAC_MECH(SHA1) |
3111 | 0 | INIT_HMAC_MECH(SHA224) |
3112 | 0 | INIT_HMAC_MECH(SHA256) |
3113 | 0 | INIT_HMAC_MECH(SHA384) |
3114 | 0 | INIT_HMAC_MECH(SHA512) |
3115 | 0 | INIT_HMAC_MECH(SHA3_224) |
3116 | 0 | INIT_HMAC_MECH(SHA3_256) |
3117 | 0 | INIT_HMAC_MECH(SHA3_384) |
3118 | 0 | INIT_HMAC_MECH(SHA3_512) |
3119 | | |
3120 | 0 | case CKM_AES_CMAC_GENERAL: |
3121 | 0 | PORT_Assert(pMechanism->pParameter); |
3122 | 0 | if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { |
3123 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3124 | 0 | break; |
3125 | 0 | } |
3126 | 0 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, *(CK_ULONG *)pMechanism->pParameter); |
3127 | 0 | break; |
3128 | 1 | case CKM_AES_CMAC: |
3129 | 1 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, AES_BLOCK_SIZE); |
3130 | 1 | break; |
3131 | 0 | case CKM_SSL3_MD5_MAC: |
3132 | 0 | PORT_Assert(pMechanism->pParameter); |
3133 | 0 | if (!pMechanism->pParameter) { |
3134 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3135 | 0 | break; |
3136 | 0 | } |
3137 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key, |
3138 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
3139 | 0 | break; |
3140 | 0 | case CKM_SSL3_SHA1_MAC: |
3141 | 0 | PORT_Assert(pMechanism->pParameter); |
3142 | 0 | if (!pMechanism->pParameter) { |
3143 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3144 | 0 | break; |
3145 | 0 | } |
3146 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key, |
3147 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
3148 | 0 | break; |
3149 | 0 | case CKM_TLS_PRF_GENERAL: |
3150 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); |
3151 | 0 | break; |
3152 | 0 | case CKM_TLS_MAC: { |
3153 | 0 | CK_TLS_MAC_PARAMS *tls12_mac_params; |
3154 | 0 | HASH_HashType tlsPrfHash; |
3155 | 0 | const char *label; |
3156 | |
|
3157 | 0 | if (pMechanism->ulParameterLen != sizeof(CK_TLS_MAC_PARAMS)) { |
3158 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3159 | 0 | break; |
3160 | 0 | } |
3161 | 0 | tls12_mac_params = (CK_TLS_MAC_PARAMS *)pMechanism->pParameter; |
3162 | 0 | if (tls12_mac_params->prfHashMechanism == CKM_TLS_PRF) { |
3163 | | /* The TLS 1.0 and 1.1 PRF */ |
3164 | 0 | tlsPrfHash = HASH_AlgNULL; |
3165 | 0 | if (tls12_mac_params->ulMacLength != 12) { |
3166 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3167 | 0 | break; |
3168 | 0 | } |
3169 | 0 | } else { |
3170 | | /* The hash function for the TLS 1.2 PRF */ |
3171 | 0 | tlsPrfHash = |
3172 | 0 | sftk_GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism); |
3173 | 0 | if (tlsPrfHash == HASH_AlgNULL || |
3174 | 0 | tls12_mac_params->ulMacLength < 12) { |
3175 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3176 | 0 | break; |
3177 | 0 | } |
3178 | 0 | } |
3179 | 0 | if (tls12_mac_params->ulServerOrClient == 1) { |
3180 | 0 | label = "server finished"; |
3181 | 0 | } else if (tls12_mac_params->ulServerOrClient == 2) { |
3182 | 0 | label = "client finished"; |
3183 | 0 | } else { |
3184 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3185 | 0 | break; |
3186 | 0 | } |
3187 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, tlsPrfHash, |
3188 | 0 | tls12_mac_params->ulMacLength); |
3189 | 0 | if (crv == CKR_OK) { |
3190 | 0 | context->hashUpdate(context->hashInfo, (unsigned char *)label, 15); |
3191 | 0 | } |
3192 | 0 | break; |
3193 | 0 | } |
3194 | 0 | case CKM_NSS_TLS_PRF_GENERAL_SHA256: |
3195 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); |
3196 | 0 | break; |
3197 | | |
3198 | 0 | case CKM_NSS_HMAC_CONSTANT_TIME: { |
3199 | 0 | sftk_MACConstantTimeCtx *ctx = |
3200 | 0 | sftk_HMACConstantTime_New(pMechanism, key); |
3201 | 0 | CK_ULONG *intpointer; |
3202 | |
|
3203 | 0 | if (ctx == NULL) { |
3204 | 0 | crv = CKR_ARGUMENTS_BAD; |
3205 | 0 | break; |
3206 | 0 | } |
3207 | 0 | intpointer = PORT_New(CK_ULONG); |
3208 | 0 | if (intpointer == NULL) { |
3209 | 0 | PORT_Free(ctx); |
3210 | 0 | crv = CKR_HOST_MEMORY; |
3211 | 0 | break; |
3212 | 0 | } |
3213 | 0 | *intpointer = ctx->hash->length; |
3214 | |
|
3215 | 0 | context->cipherInfo = intpointer; |
3216 | 0 | context->hashInfo = ctx; |
3217 | 0 | context->currentMech = pMechanism->mechanism; |
3218 | 0 | context->hashUpdate = sftk_HMACConstantTime_Update; |
3219 | 0 | context->hashdestroy = sftk_MACConstantTime_DestroyContext; |
3220 | 0 | context->end = sftk_MACConstantTime_EndHash; |
3221 | 0 | context->update = sftk_SignCopy; |
3222 | 0 | context->destroy = sftk_Space; |
3223 | 0 | context->maxLen = 64; |
3224 | 0 | context->multi = PR_TRUE; |
3225 | 0 | break; |
3226 | 0 | } |
3227 | | |
3228 | 0 | case CKM_NSS_SSL3_MAC_CONSTANT_TIME: { |
3229 | 0 | sftk_MACConstantTimeCtx *ctx = |
3230 | 0 | sftk_SSLv3MACConstantTime_New(pMechanism, key); |
3231 | 0 | CK_ULONG *intpointer; |
3232 | |
|
3233 | 0 | if (ctx == NULL) { |
3234 | 0 | crv = CKR_ARGUMENTS_BAD; |
3235 | 0 | break; |
3236 | 0 | } |
3237 | 0 | intpointer = PORT_New(CK_ULONG); |
3238 | 0 | if (intpointer == NULL) { |
3239 | 0 | PORT_Free(ctx); |
3240 | 0 | crv = CKR_HOST_MEMORY; |
3241 | 0 | break; |
3242 | 0 | } |
3243 | 0 | *intpointer = ctx->hash->length; |
3244 | |
|
3245 | 0 | context->cipherInfo = intpointer; |
3246 | 0 | context->hashInfo = ctx; |
3247 | 0 | context->currentMech = pMechanism->mechanism; |
3248 | 0 | context->hashUpdate = sftk_SSLv3MACConstantTime_Update; |
3249 | 0 | context->hashdestroy = sftk_MACConstantTime_DestroyContext; |
3250 | 0 | context->end = sftk_MACConstantTime_EndHash; |
3251 | 0 | context->update = sftk_SignCopy; |
3252 | 0 | context->destroy = sftk_Space; |
3253 | 0 | context->maxLen = 64; |
3254 | 0 | context->multi = PR_TRUE; |
3255 | 0 | break; |
3256 | 0 | } |
3257 | | |
3258 | 26 | default: |
3259 | 26 | crv = CKR_MECHANISM_INVALID; |
3260 | 26 | break; |
3261 | 95 | } |
3262 | | |
3263 | 95 | if (crv != CKR_OK) { |
3264 | 26 | if (info) |
3265 | 0 | PORT_Free(info); |
3266 | 26 | if (pinfo) |
3267 | 0 | PORT_ZFree(pinfo, pinfo->size); |
3268 | 26 | sftk_FreeContext(context); |
3269 | 26 | sftk_FreeSession(session); |
3270 | 26 | return crv; |
3271 | 26 | } |
3272 | 69 | sftk_SetContextByType(session, SFTK_SIGN, context); |
3273 | 69 | sftk_FreeSession(session); |
3274 | 69 | return CKR_OK; |
3275 | 95 | } |
3276 | | |
3277 | | /** MAC one block of data by block cipher |
3278 | | */ |
3279 | | static CK_RV |
3280 | | sftk_MACBlock(SFTKSessionContext *ctx, void *blk) |
3281 | 0 | { |
3282 | 0 | unsigned int outlen; |
3283 | 0 | return (SECSuccess == (ctx->update)(ctx->cipherInfo, ctx->macBuf, &outlen, |
3284 | 0 | SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize)) |
3285 | 0 | ? CKR_OK |
3286 | 0 | : sftk_MapCryptError(PORT_GetError()); |
3287 | 0 | } |
3288 | | |
3289 | | /** MAC last (incomplete) block of data by block cipher |
3290 | | * |
3291 | | * Call once, then terminate MACing operation. |
3292 | | */ |
3293 | | static CK_RV |
3294 | | sftk_MACFinal(SFTKSessionContext *ctx) |
3295 | 0 | { |
3296 | 0 | unsigned int padLen = ctx->padDataLength; |
3297 | | /* pad and proceed the residual */ |
3298 | 0 | if (ctx->isXCBC) { |
3299 | 0 | CK_RV crv = sftk_xcbc_mac_pad(ctx->padBuf, padLen, ctx->blockSize, |
3300 | 0 | ctx->k2, ctx->k3); |
3301 | 0 | if (crv != CKR_OK) |
3302 | 0 | return crv; |
3303 | 0 | return sftk_MACBlock(ctx, ctx->padBuf); |
3304 | 0 | } |
3305 | 0 | if (padLen) { |
3306 | | /* shd clr ctx->padLen to make sftk_MACFinal idempotent */ |
3307 | 0 | PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen); |
3308 | 0 | return sftk_MACBlock(ctx, ctx->padBuf); |
3309 | 0 | } else |
3310 | 0 | return CKR_OK; |
3311 | 0 | } |
3312 | | |
3313 | | /** The common implementation for {Sign,Verify}Update. (S/V only vary in their |
3314 | | * setup and final operations). |
3315 | | * |
3316 | | * A call which results in an error terminates the operation [PKCS#11,v2.11] |
3317 | | */ |
3318 | | static CK_RV |
3319 | | sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
3320 | | CK_ULONG ulPartLen, SFTKContextType type) |
3321 | 524 | { |
3322 | 524 | SFTKSession *session; |
3323 | 524 | SFTKSessionContext *context; |
3324 | 524 | CK_RV crv; |
3325 | | |
3326 | | /* make sure we're legal */ |
3327 | 524 | crv = sftk_GetContext(hSession, &context, type, PR_TRUE, &session); |
3328 | 524 | if (crv != CKR_OK) |
3329 | 0 | return crv; |
3330 | | |
3331 | 524 | if (context->hashInfo) { |
3332 | 524 | #if (ULONG_MAX > UINT_MAX) |
3333 | 524 | while (ulPartLen > UINT_MAX) { |
3334 | 0 | (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX); |
3335 | 0 | pPart += UINT_MAX; |
3336 | 0 | ulPartLen -= UINT_MAX; |
3337 | 0 | } |
3338 | 524 | #endif |
3339 | 524 | (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen); |
3340 | 524 | } else { |
3341 | | /* must be block cipher MACing */ |
3342 | |
|
3343 | 0 | unsigned int blkSize = context->blockSize; |
3344 | 0 | unsigned char *residual = /* free room in context->padBuf */ |
3345 | 0 | context->padBuf + context->padDataLength; |
3346 | 0 | unsigned int minInput = /* min input for MACing at least one block */ |
3347 | 0 | blkSize - context->padDataLength; |
3348 | | |
3349 | | /* not enough data even for one block */ |
3350 | 0 | if (ulPartLen <= minInput) { |
3351 | 0 | PORT_Memcpy(residual, pPart, ulPartLen); |
3352 | 0 | context->padDataLength += ulPartLen; |
3353 | 0 | goto cleanup; |
3354 | 0 | } |
3355 | | /* MACing residual */ |
3356 | 0 | if (context->padDataLength) { |
3357 | 0 | PORT_Memcpy(residual, pPart, minInput); |
3358 | 0 | ulPartLen -= minInput; |
3359 | 0 | pPart += minInput; |
3360 | 0 | if (CKR_OK != (crv = sftk_MACBlock(context, context->padBuf))) |
3361 | 0 | goto terminate; |
3362 | 0 | } |
3363 | | /* MACing full blocks */ |
3364 | 0 | while (ulPartLen > blkSize) { |
3365 | 0 | if (CKR_OK != (crv = sftk_MACBlock(context, pPart))) |
3366 | 0 | goto terminate; |
3367 | 0 | ulPartLen -= blkSize; |
3368 | 0 | pPart += blkSize; |
3369 | 0 | } |
3370 | | /* save the residual */ |
3371 | 0 | if ((context->padDataLength = ulPartLen)) |
3372 | 0 | PORT_Memcpy(context->padBuf, pPart, ulPartLen); |
3373 | 0 | } /* blk cipher MACing */ |
3374 | | |
3375 | 524 | goto cleanup; |
3376 | | |
3377 | 524 | terminate: |
3378 | 0 | sftk_TerminateOp(session, type, context); |
3379 | 524 | cleanup: |
3380 | 524 | sftk_FreeSession(session); |
3381 | 524 | return crv; |
3382 | 0 | } |
3383 | | |
3384 | | /* NSC_SignUpdate continues a multiple-part signature operation, |
3385 | | * where the signature is (will be) an appendix to the data, |
3386 | | * and plaintext cannot be recovered from the signature |
3387 | | * |
3388 | | * A call which results in an error terminates the operation [PKCS#11,v2.11] |
3389 | | */ |
3390 | | CK_RV |
3391 | | NSC_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
3392 | | CK_ULONG ulPartLen) |
3393 | 524 | { |
3394 | 524 | CHECK_FORK(); |
3395 | 524 | return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN); |
3396 | 524 | } |
3397 | | |
3398 | | struct SFTK_SESSION_FLAGS { |
3399 | | CK_FLAGS flag; |
3400 | | SFTKContextType type; |
3401 | | }; |
3402 | | |
3403 | | const static struct SFTK_SESSION_FLAGS sftk_session_flags[] = { |
3404 | | { CKF_ENCRYPT, SFTK_ENCRYPT }, |
3405 | | { CKF_DECRYPT, SFTK_DECRYPT }, |
3406 | | { CKF_DIGEST, SFTK_HASH }, |
3407 | | { CKF_SIGN, SFTK_SIGN }, |
3408 | | { CKF_SIGN_RECOVER, SFTK_SIGN_RECOVER }, |
3409 | | { CKF_VERIFY, SFTK_VERIFY }, |
3410 | | { CKF_VERIFY_RECOVER, SFTK_VERIFY_RECOVER }, |
3411 | | { CKF_MESSAGE_ENCRYPT, SFTK_MESSAGE_ENCRYPT }, |
3412 | | { CKF_MESSAGE_DECRYPT, SFTK_MESSAGE_DECRYPT }, |
3413 | | { CKF_MESSAGE_SIGN, SFTK_MESSAGE_SIGN }, |
3414 | | { CKF_MESSAGE_VERIFY, SFTK_MESSAGE_VERIFY }, |
3415 | | }; |
3416 | | const static int sftk_flag_count = PR_ARRAY_SIZE(sftk_session_flags); |
3417 | | |
3418 | | /* |
3419 | | * Cancel one or more operations running on the existing session. |
3420 | | */ |
3421 | | CK_RV |
3422 | | NSC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags) |
3423 | 0 | { |
3424 | 0 | SFTKSession *session; |
3425 | 0 | SFTKSessionContext *context; |
3426 | 0 | CK_RV gcrv = CKR_OK; |
3427 | 0 | CK_RV crv; |
3428 | 0 | int i; |
3429 | |
|
3430 | 0 | for (i = 0; i < sftk_flag_count; i++) { |
3431 | 0 | if (flags & sftk_session_flags[i].flag) { |
3432 | 0 | flags &= ~sftk_session_flags[i].flag; |
3433 | 0 | crv = sftk_GetContext(hSession, &context, sftk_session_flags[i].type, PR_TRUE, &session); |
3434 | 0 | if (crv != CKR_OK) { |
3435 | 0 | gcrv = CKR_OPERATION_CANCEL_FAILED; |
3436 | 0 | continue; |
3437 | 0 | } |
3438 | 0 | sftk_TerminateOp(session, sftk_session_flags[i].type, context); |
3439 | 0 | } |
3440 | 0 | } |
3441 | 0 | if (flags & CKF_FIND_OBJECTS) { |
3442 | 0 | flags &= ~CKF_FIND_OBJECTS; |
3443 | 0 | crv = NSC_FindObjectsFinal(hSession); |
3444 | 0 | if (crv != CKR_OK) { |
3445 | 0 | gcrv = CKR_OPERATION_CANCEL_FAILED; |
3446 | 0 | } |
3447 | 0 | } |
3448 | 0 | if (flags) { |
3449 | 0 | gcrv = CKR_OPERATION_CANCEL_FAILED; |
3450 | 0 | } |
3451 | 0 | return gcrv; |
3452 | 0 | } |
3453 | | |
3454 | | /* NSC_SignFinal finishes a multiple-part signature operation, |
3455 | | * returning the signature. */ |
3456 | | CK_RV |
3457 | | NSC_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, |
3458 | | CK_ULONG_PTR pulSignatureLen) |
3459 | 69 | { |
3460 | 69 | SFTKSession *session; |
3461 | 69 | SFTKSessionContext *context; |
3462 | 69 | unsigned int outlen; |
3463 | 69 | unsigned int maxoutlen = *pulSignatureLen; |
3464 | 69 | CK_RV crv; |
3465 | | |
3466 | 69 | CHECK_FORK(); |
3467 | | |
3468 | | /* make sure we're legal */ |
3469 | 69 | crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_TRUE, &session); |
3470 | 69 | if (crv != CKR_OK) |
3471 | 0 | return crv; |
3472 | | |
3473 | 69 | if (context->hashInfo) { |
3474 | 69 | unsigned int digestLen; |
3475 | 69 | unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; |
3476 | | |
3477 | 69 | if (!pSignature) { |
3478 | 0 | outlen = context->maxLen; |
3479 | 0 | goto finish; |
3480 | 0 | } |
3481 | 69 | (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); |
3482 | 69 | if (SECSuccess != (context->update)(context->cipherInfo, pSignature, |
3483 | 69 | &outlen, maxoutlen, tmpbuf, digestLen)) |
3484 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
3485 | | /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate. |
3486 | | * Keeping "too small" CK_RV intact is a standard violation, but allows |
3487 | | * application read EXACT signature length */ |
3488 | 69 | PORT_Memset(tmpbuf, 0, sizeof tmpbuf); |
3489 | 69 | } else { |
3490 | | /* must be block cipher MACing */ |
3491 | 0 | outlen = context->macSize; |
3492 | | /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/ |
3493 | 0 | if (!pSignature || maxoutlen < outlen) { |
3494 | 0 | if (pSignature) |
3495 | 0 | crv = CKR_BUFFER_TOO_SMALL; |
3496 | 0 | goto finish; |
3497 | 0 | } |
3498 | 0 | if (CKR_OK == (crv = sftk_MACFinal(context))) |
3499 | 0 | PORT_Memcpy(pSignature, context->macBuf, outlen); |
3500 | 0 | } |
3501 | | |
3502 | 69 | sftk_TerminateOp(session, SFTK_SIGN, context); |
3503 | 69 | finish: |
3504 | 69 | *pulSignatureLen = outlen; |
3505 | 69 | sftk_FreeSession(session); |
3506 | 69 | return crv; |
3507 | 69 | } |
3508 | | |
3509 | | /* NSC_Sign signs (encrypts with private key) data in a single part, |
3510 | | * where the signature is (will be) an appendix to the data, |
3511 | | * and plaintext cannot be recovered from the signature */ |
3512 | | CK_RV |
3513 | | NSC_Sign(CK_SESSION_HANDLE hSession, |
3514 | | CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, |
3515 | | CK_ULONG_PTR pulSignatureLen) |
3516 | 1 | { |
3517 | 1 | SFTKSession *session; |
3518 | 1 | SFTKSessionContext *context; |
3519 | 1 | CK_RV crv; |
3520 | | |
3521 | 1 | CHECK_FORK(); |
3522 | | |
3523 | | /* make sure we're legal */ |
3524 | 1 | crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_FALSE, &session); |
3525 | 1 | if (crv != CKR_OK) |
3526 | 0 | return crv; |
3527 | | |
3528 | 1 | if (!pSignature) { |
3529 | | /* see also how C_SignUpdate implements this */ |
3530 | 0 | *pulSignatureLen = (!context->multi || context->hashInfo) |
3531 | 0 | ? context->maxLen |
3532 | 0 | : context->macSize; /* must be block cipher MACing */ |
3533 | 0 | goto finish; |
3534 | 0 | } |
3535 | | |
3536 | | /* multi part Signing are completely implemented by SignUpdate and |
3537 | | * sign Final */ |
3538 | 1 | if (context->multi) { |
3539 | | /* SignFinal can't follow failed SignUpdate */ |
3540 | 1 | if (CKR_OK == (crv = NSC_SignUpdate(hSession, pData, ulDataLen))) |
3541 | 1 | crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen); |
3542 | 1 | } else { |
3543 | | /* single-part PKC signature (e.g. CKM_ECDSA) */ |
3544 | 0 | unsigned int outlen; |
3545 | 0 | unsigned int maxoutlen = *pulSignatureLen; |
3546 | 0 | if (SECSuccess != (*context->update)(context->cipherInfo, pSignature, |
3547 | 0 | &outlen, maxoutlen, pData, ulDataLen)) |
3548 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
3549 | 0 | *pulSignatureLen = (CK_ULONG)outlen; |
3550 | | /* "too small" here is certainly continuable */ |
3551 | 0 | if (crv != CKR_BUFFER_TOO_SMALL) |
3552 | 0 | sftk_TerminateOp(session, SFTK_SIGN, context); |
3553 | 0 | } /* single-part */ |
3554 | | |
3555 | 1 | finish: |
3556 | 1 | sftk_FreeSession(session); |
3557 | 1 | return crv; |
3558 | 1 | } |
3559 | | |
3560 | | /* |
3561 | | ************** Crypto Functions: Sign Recover ************************ |
3562 | | */ |
3563 | | /* NSC_SignRecoverInit initializes a signature operation, |
3564 | | * where the (digest) data can be recovered from the signature. |
3565 | | * E.g. encryption with the user's private key */ |
3566 | | CK_RV |
3567 | | NSC_SignRecoverInit(CK_SESSION_HANDLE hSession, |
3568 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
3569 | 0 | { |
3570 | 0 | CHECK_FORK(); |
3571 | |
|
3572 | 0 | switch (pMechanism->mechanism) { |
3573 | 0 | case CKM_RSA_PKCS: |
3574 | 0 | case CKM_RSA_X_509: |
3575 | 0 | return NSC_SignInit(hSession, pMechanism, hKey); |
3576 | 0 | default: |
3577 | 0 | break; |
3578 | 0 | } |
3579 | 0 | return CKR_MECHANISM_INVALID; |
3580 | 0 | } |
3581 | | |
3582 | | /* NSC_SignRecover signs data in a single operation |
3583 | | * where the (digest) data can be recovered from the signature. |
3584 | | * E.g. encryption with the user's private key */ |
3585 | | CK_RV |
3586 | | NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
3587 | | CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) |
3588 | 0 | { |
3589 | 0 | CHECK_FORK(); |
3590 | |
|
3591 | 0 | return NSC_Sign(hSession, pData, ulDataLen, pSignature, pulSignatureLen); |
3592 | 0 | } |
3593 | | |
3594 | | /* |
3595 | | ************** Crypto Functions: verify ************************ |
3596 | | */ |
3597 | | |
3598 | | /* Handle RSA Signature formatting */ |
3599 | | static SECStatus |
3600 | | sftk_hashCheckSign(void *ctx, const unsigned char *sig, |
3601 | | unsigned int sigLen, const unsigned char *digest, |
3602 | | unsigned int digestLen) |
3603 | 0 | { |
3604 | 0 | SFTKHashVerifyInfo *info = ctx; |
3605 | 0 | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
3606 | 0 | if (info->key->keyType != NSSLOWKEYRSAKey) { |
3607 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3608 | 0 | return SECFailure; |
3609 | 0 | } |
3610 | | |
3611 | 0 | return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, digest, |
3612 | 0 | digestLen); |
3613 | 0 | } |
3614 | | |
3615 | | SECStatus |
3616 | | RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key, |
3617 | | const unsigned char *sig, unsigned int sigLen, |
3618 | | const unsigned char *digestData, unsigned int digestLen) |
3619 | 6 | { |
3620 | 6 | unsigned char *pkcs1DigestInfoData; |
3621 | 6 | SECItem pkcs1DigestInfo; |
3622 | 6 | SECItem digest; |
3623 | 6 | unsigned int bufferSize; |
3624 | 6 | SECStatus rv; |
3625 | | |
3626 | | /* pkcs1DigestInfo.data must be less than key->u.rsa.modulus.len */ |
3627 | 6 | bufferSize = key->u.rsa.modulus.len; |
3628 | 6 | pkcs1DigestInfoData = PORT_ZAlloc(bufferSize); |
3629 | 6 | if (!pkcs1DigestInfoData) { |
3630 | 0 | PORT_SetError(SEC_ERROR_NO_MEMORY); |
3631 | 0 | return SECFailure; |
3632 | 0 | } |
3633 | | |
3634 | 6 | pkcs1DigestInfo.data = pkcs1DigestInfoData; |
3635 | 6 | pkcs1DigestInfo.len = bufferSize; |
3636 | | |
3637 | | /* decrypt the block */ |
3638 | 6 | rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data, |
3639 | 6 | &pkcs1DigestInfo.len, pkcs1DigestInfo.len, |
3640 | 6 | sig, sigLen); |
3641 | 6 | if (rv != SECSuccess) { |
3642 | 0 | PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
3643 | 6 | } else { |
3644 | 6 | digest.data = (PRUint8 *)digestData; |
3645 | 6 | digest.len = digestLen; |
3646 | 6 | rv = _SGN_VerifyPKCS1DigestInfo( |
3647 | 6 | digestOid, &digest, &pkcs1DigestInfo, |
3648 | 6 | PR_FALSE /*XXX: unsafeAllowMissingParameters*/); |
3649 | 6 | } |
3650 | | |
3651 | 6 | PORT_ZFree(pkcs1DigestInfoData, bufferSize); |
3652 | 6 | return rv; |
3653 | 6 | } |
3654 | | |
3655 | | static SECStatus |
3656 | | sftk_RSACheckSign(void *ctx, const unsigned char *sig, |
3657 | | unsigned int sigLen, const unsigned char *digest, |
3658 | | unsigned int digestLen) |
3659 | 0 | { |
3660 | 0 | NSSLOWKEYPublicKey *key = ctx; |
3661 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
3662 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
3663 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3664 | 0 | return SECFailure; |
3665 | 0 | } |
3666 | | |
3667 | 0 | return RSA_CheckSign(&key->u.rsa, sig, sigLen, digest, digestLen); |
3668 | 0 | } |
3669 | | |
3670 | | static SECStatus |
3671 | | sftk_RSACheckSignRaw(void *ctx, const unsigned char *sig, |
3672 | | unsigned int sigLen, const unsigned char *digest, |
3673 | | unsigned int digestLen) |
3674 | 0 | { |
3675 | 0 | NSSLOWKEYPublicKey *key = ctx; |
3676 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
3677 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
3678 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3679 | 0 | return SECFailure; |
3680 | 0 | } |
3681 | | |
3682 | 0 | return RSA_CheckSignRaw(&key->u.rsa, sig, sigLen, digest, digestLen); |
3683 | 0 | } |
3684 | | |
3685 | | static SECStatus |
3686 | | sftk_RSACheckSignPSS(void *ctx, const unsigned char *sig, |
3687 | | unsigned int sigLen, const unsigned char *digest, |
3688 | | unsigned int digestLen) |
3689 | 0 | { |
3690 | 0 | SFTKPSSVerifyInfo *info = ctx; |
3691 | 0 | HASH_HashType hashAlg; |
3692 | 0 | HASH_HashType maskHashAlg; |
3693 | 0 | CK_RSA_PKCS_PSS_PARAMS *params = &info->params; |
3694 | |
|
3695 | 0 | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
3696 | 0 | if (info->key->keyType != NSSLOWKEYRSAKey) { |
3697 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3698 | 0 | return SECFailure; |
3699 | 0 | } |
3700 | | |
3701 | 0 | hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg); |
3702 | 0 | maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf); |
3703 | |
|
3704 | 0 | return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, |
3705 | 0 | params->sLen, sig, sigLen, digest, digestLen); |
3706 | 0 | } |
3707 | | |
3708 | | /* NSC_VerifyInit initializes a verification operation, |
3709 | | * where the signature is an appendix to the data, |
3710 | | * and plaintext cannot be recovered from the signature (e.g. DSA) */ |
3711 | | CK_RV |
3712 | | NSC_VerifyInit(CK_SESSION_HANDLE hSession, |
3713 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
3714 | 0 | { |
3715 | 0 | SFTKSession *session; |
3716 | 0 | SFTKObject *key; |
3717 | 0 | SFTKSessionContext *context; |
3718 | 0 | CK_KEY_TYPE key_type; |
3719 | 0 | CK_RV crv = CKR_OK; |
3720 | 0 | NSSLOWKEYPublicKey *pubKey; |
3721 | 0 | SFTKHashVerifyInfo *info = NULL; |
3722 | 0 | SFTKPSSVerifyInfo *pinfo = NULL; |
3723 | |
|
3724 | 0 | CHECK_FORK(); |
3725 | | |
3726 | | /* Block Cipher MACing Algorithms use a different Context init method..*/ |
3727 | 0 | crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY); |
3728 | 0 | if (crv != CKR_FUNCTION_NOT_SUPPORTED) |
3729 | 0 | return crv; |
3730 | | |
3731 | 0 | session = sftk_SessionFromHandle(hSession); |
3732 | 0 | if (session == NULL) |
3733 | 0 | return CKR_SESSION_HANDLE_INVALID; |
3734 | 0 | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY, &key, |
3735 | 0 | hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY); |
3736 | 0 | if (crv != CKR_OK) { |
3737 | 0 | sftk_FreeSession(session); |
3738 | 0 | return crv; |
3739 | 0 | } |
3740 | | |
3741 | 0 | context->multi = PR_FALSE; |
3742 | |
|
3743 | 0 | #define INIT_RSA_VFY_MECH(mmm) \ |
3744 | 0 | case CKM_##mmm##_RSA_PKCS: \ |
3745 | 0 | context->multi = PR_TRUE; \ |
3746 | 0 | crv = sftk_doSub##mmm(context); \ |
3747 | 0 | if (crv != CKR_OK) \ |
3748 | 0 | break; \ |
3749 | 0 | context->verify = sftk_hashCheckSign; \ |
3750 | 0 | info = PORT_New(SFTKHashVerifyInfo); \ |
3751 | 0 | if (info == NULL) { \ |
3752 | 0 | crv = CKR_HOST_MEMORY; \ |
3753 | 0 | break; \ |
3754 | 0 | } \ |
3755 | 0 | info->hashOid = SEC_OID_##mmm; \ |
3756 | 0 | goto finish_rsa; |
3757 | |
|
3758 | 0 | switch (pMechanism->mechanism) { |
3759 | 0 | INIT_RSA_VFY_MECH(MD5) |
3760 | 0 | INIT_RSA_VFY_MECH(MD2) |
3761 | 0 | INIT_RSA_VFY_MECH(SHA1) |
3762 | 0 | INIT_RSA_VFY_MECH(SHA224) |
3763 | 0 | INIT_RSA_VFY_MECH(SHA256) |
3764 | 0 | INIT_RSA_VFY_MECH(SHA384) |
3765 | 0 | INIT_RSA_VFY_MECH(SHA512) |
3766 | | |
3767 | 0 | case CKM_RSA_PKCS: |
3768 | 0 | context->verify = sftk_RSACheckSign; |
3769 | 0 | goto finish_rsa; |
3770 | 0 | case CKM_RSA_X_509: |
3771 | 0 | context->verify = sftk_RSACheckSignRaw; |
3772 | 0 | finish_rsa: |
3773 | 0 | if (key_type != CKK_RSA) { |
3774 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3775 | 0 | break; |
3776 | 0 | } |
3777 | 0 | context->rsa = PR_TRUE; |
3778 | 0 | pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); |
3779 | 0 | if (pubKey == NULL) { |
3780 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3781 | 0 | break; |
3782 | 0 | } |
3783 | 0 | if (info) { |
3784 | 0 | info->key = pubKey; |
3785 | 0 | context->cipherInfo = info; |
3786 | 0 | context->destroy = sftk_Space; |
3787 | 0 | } else { |
3788 | 0 | context->cipherInfo = pubKey; |
3789 | 0 | context->destroy = sftk_Null; |
3790 | 0 | } |
3791 | 0 | break; |
3792 | | |
3793 | 0 | INIT_RSA_PSS_SIG_MECH(SHA1) |
3794 | 0 | INIT_RSA_PSS_SIG_MECH(SHA224) |
3795 | 0 | INIT_RSA_PSS_SIG_MECH(SHA256) |
3796 | 0 | INIT_RSA_PSS_SIG_MECH(SHA384) |
3797 | 0 | INIT_RSA_PSS_SIG_MECH(SHA512) |
3798 | 0 | case CKM_RSA_PKCS_PSS: |
3799 | 0 | finish_rsa_pss: |
3800 | 0 | if (key_type != CKK_RSA) { |
3801 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3802 | 0 | break; |
3803 | 0 | } |
3804 | 0 | context->rsa = PR_TRUE; |
3805 | 0 | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || |
3806 | 0 | !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) { |
3807 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3808 | 0 | break; |
3809 | 0 | } |
3810 | 0 | pinfo = PORT_New(SFTKPSSVerifyInfo); |
3811 | 0 | if (pinfo == NULL) { |
3812 | 0 | crv = CKR_HOST_MEMORY; |
3813 | 0 | break; |
3814 | 0 | } |
3815 | 0 | pinfo->size = sizeof(SFTKPSSVerifyInfo); |
3816 | 0 | pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter; |
3817 | 0 | pinfo->key = sftk_GetPubKey(key, CKK_RSA, &crv); |
3818 | 0 | if (pinfo->key == NULL) { |
3819 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3820 | 0 | break; |
3821 | 0 | } |
3822 | 0 | context->cipherInfo = pinfo; |
3823 | 0 | context->destroy = sftk_ZSpace; |
3824 | 0 | context->verify = sftk_RSACheckSignPSS; |
3825 | 0 | break; |
3826 | | |
3827 | 0 | INIT_DSA_SIG_MECH(SHA1) |
3828 | 0 | INIT_DSA_SIG_MECH(SHA224) |
3829 | 0 | INIT_DSA_SIG_MECH(SHA256) |
3830 | 0 | INIT_DSA_SIG_MECH(SHA384) |
3831 | 0 | INIT_DSA_SIG_MECH(SHA512) |
3832 | 0 | case CKM_DSA: |
3833 | 0 | finish_dsa: |
3834 | 0 | if (key_type != CKK_DSA) { |
3835 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3836 | 0 | break; |
3837 | 0 | } |
3838 | 0 | pubKey = sftk_GetPubKey(key, CKK_DSA, &crv); |
3839 | 0 | if (pubKey == NULL) { |
3840 | 0 | break; |
3841 | 0 | } |
3842 | 0 | context->cipherInfo = pubKey; |
3843 | 0 | context->verify = nsc_DSA_Verify_Stub; |
3844 | 0 | context->destroy = sftk_Null; |
3845 | 0 | break; |
3846 | | |
3847 | 0 | INIT_ECDSA_SIG_MECH(SHA1) |
3848 | 0 | INIT_ECDSA_SIG_MECH(SHA224) |
3849 | 0 | INIT_ECDSA_SIG_MECH(SHA256) |
3850 | 0 | INIT_ECDSA_SIG_MECH(SHA384) |
3851 | 0 | INIT_ECDSA_SIG_MECH(SHA512) |
3852 | 0 | case CKM_ECDSA: |
3853 | 0 | finish_ecdsa: |
3854 | 0 | if (key_type != CKK_EC) { |
3855 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3856 | 0 | break; |
3857 | 0 | } |
3858 | 0 | pubKey = sftk_GetPubKey(key, CKK_EC, &crv); |
3859 | 0 | if (pubKey == NULL) { |
3860 | 0 | crv = CKR_HOST_MEMORY; |
3861 | 0 | break; |
3862 | 0 | } |
3863 | 0 | context->cipherInfo = pubKey; |
3864 | 0 | context->verify = nsc_ECDSAVerifyStub; |
3865 | 0 | context->destroy = sftk_Null; |
3866 | 0 | break; |
3867 | | |
3868 | 0 | INIT_HMAC_MECH(MD2) |
3869 | 0 | INIT_HMAC_MECH(MD5) |
3870 | 0 | INIT_HMAC_MECH(SHA1) |
3871 | 0 | INIT_HMAC_MECH(SHA224) |
3872 | 0 | INIT_HMAC_MECH(SHA256) |
3873 | 0 | INIT_HMAC_MECH(SHA384) |
3874 | 0 | INIT_HMAC_MECH(SHA512) |
3875 | 0 | INIT_HMAC_MECH(SHA3_224) |
3876 | 0 | INIT_HMAC_MECH(SHA3_256) |
3877 | 0 | INIT_HMAC_MECH(SHA3_384) |
3878 | 0 | INIT_HMAC_MECH(SHA3_512) |
3879 | | |
3880 | 0 | case CKM_EDDSA: |
3881 | 0 | if (key_type != CKK_EC_EDWARDS) { |
3882 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3883 | 0 | break; |
3884 | 0 | } |
3885 | 0 | pubKey = sftk_GetPubKey(key, CKK_EC_EDWARDS, &crv); |
3886 | 0 | if (pubKey == NULL) { |
3887 | 0 | crv = CKR_HOST_MEMORY; |
3888 | 0 | break; |
3889 | 0 | } |
3890 | | |
3891 | 0 | if (pMechanism->pParameter) { |
3892 | 0 | crv = CKR_FUNCTION_NOT_SUPPORTED; |
3893 | 0 | break; |
3894 | 0 | } |
3895 | | |
3896 | 0 | context->cipherInfo = pubKey; |
3897 | 0 | context->verify = nsc_EDDSAVerifyStub; |
3898 | 0 | context->destroy = sftk_Null; |
3899 | 0 | break; |
3900 | | |
3901 | 0 | case CKM_SSL3_MD5_MAC: |
3902 | 0 | PORT_Assert(pMechanism->pParameter); |
3903 | 0 | if (!pMechanism->pParameter) { |
3904 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3905 | 0 | break; |
3906 | 0 | } |
3907 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key, |
3908 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
3909 | 0 | break; |
3910 | 0 | case CKM_SSL3_SHA1_MAC: |
3911 | 0 | PORT_Assert(pMechanism->pParameter); |
3912 | 0 | if (!pMechanism->pParameter) { |
3913 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3914 | 0 | break; |
3915 | 0 | } |
3916 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key, |
3917 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
3918 | 0 | break; |
3919 | 0 | case CKM_TLS_PRF_GENERAL: |
3920 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); |
3921 | 0 | break; |
3922 | 0 | case CKM_NSS_TLS_PRF_GENERAL_SHA256: |
3923 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); |
3924 | 0 | break; |
3925 | | |
3926 | 0 | default: |
3927 | 0 | crv = CKR_MECHANISM_INVALID; |
3928 | 0 | break; |
3929 | 0 | } |
3930 | | |
3931 | 0 | if (crv != CKR_OK) { |
3932 | 0 | if (info) |
3933 | 0 | PORT_Free(info); |
3934 | 0 | if (pinfo) |
3935 | 0 | PORT_ZFree(pinfo, pinfo->size); |
3936 | 0 | sftk_FreeContext(context); |
3937 | 0 | sftk_FreeSession(session); |
3938 | 0 | return crv; |
3939 | 0 | } |
3940 | 0 | sftk_SetContextByType(session, SFTK_VERIFY, context); |
3941 | 0 | sftk_FreeSession(session); |
3942 | 0 | return CKR_OK; |
3943 | 0 | } |
3944 | | |
3945 | | /* NSC_Verify verifies a signature in a single-part operation, |
3946 | | * where the signature is an appendix to the data, |
3947 | | * and plaintext cannot be recovered from the signature */ |
3948 | | CK_RV |
3949 | | NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
3950 | | CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) |
3951 | 0 | { |
3952 | 0 | SFTKSession *session; |
3953 | 0 | SFTKSessionContext *context; |
3954 | 0 | CK_RV crv; |
3955 | |
|
3956 | 0 | CHECK_FORK(); |
3957 | | |
3958 | | /* make sure we're legal */ |
3959 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session); |
3960 | 0 | if (crv != CKR_OK) |
3961 | 0 | return crv; |
3962 | | |
3963 | | /* multi part Verifying are completely implemented by VerifyUpdate and |
3964 | | * VerifyFinal */ |
3965 | 0 | if (context->multi) { |
3966 | | /* VerifyFinal can't follow failed VerifyUpdate */ |
3967 | 0 | if (CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen))) |
3968 | 0 | crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen); |
3969 | 0 | } else { |
3970 | 0 | if (SECSuccess != (*context->verify)(context->cipherInfo, pSignature, |
3971 | 0 | ulSignatureLen, pData, ulDataLen)) |
3972 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
3973 | |
|
3974 | 0 | sftk_TerminateOp(session, SFTK_VERIFY, context); |
3975 | 0 | } |
3976 | 0 | sftk_FreeSession(session); |
3977 | 0 | return crv; |
3978 | 0 | } |
3979 | | |
3980 | | /* NSC_VerifyUpdate continues a multiple-part verification operation, |
3981 | | * where the signature is an appendix to the data, |
3982 | | * and plaintext cannot be recovered from the signature |
3983 | | * |
3984 | | * A call which results in an error terminates the operation [PKCS#11,v2.11] |
3985 | | */ |
3986 | | CK_RV |
3987 | | NSC_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
3988 | | CK_ULONG ulPartLen) |
3989 | 0 | { |
3990 | 0 | CHECK_FORK(); |
3991 | 0 | return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY); |
3992 | 0 | } |
3993 | | |
3994 | | /* NSC_VerifyFinal finishes a multiple-part verification operation, |
3995 | | * checking the signature. */ |
3996 | | CK_RV |
3997 | | NSC_VerifyFinal(CK_SESSION_HANDLE hSession, |
3998 | | CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) |
3999 | 0 | { |
4000 | 0 | SFTKSession *session; |
4001 | 0 | SFTKSessionContext *context; |
4002 | 0 | CK_RV crv; |
4003 | |
|
4004 | 0 | CHECK_FORK(); |
4005 | |
|
4006 | 0 | if (!pSignature) |
4007 | 0 | return CKR_ARGUMENTS_BAD; |
4008 | | |
4009 | | /* make sure we're legal */ |
4010 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session); |
4011 | 0 | if (crv != CKR_OK) |
4012 | 0 | return crv; |
4013 | | |
4014 | 0 | if (context->hashInfo) { |
4015 | 0 | unsigned int digestLen; |
4016 | 0 | unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; |
4017 | |
|
4018 | 0 | (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); |
4019 | 0 | if (SECSuccess != (context->verify)(context->cipherInfo, pSignature, |
4020 | 0 | ulSignatureLen, tmpbuf, digestLen)) |
4021 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
4022 | 0 | PORT_Memset(tmpbuf, 0, sizeof tmpbuf); |
4023 | 0 | } else if (ulSignatureLen != context->macSize) { |
4024 | | /* must be block cipher MACing */ |
4025 | 0 | crv = CKR_SIGNATURE_LEN_RANGE; |
4026 | 0 | } else if (CKR_OK == (crv = sftk_MACFinal(context))) { |
4027 | 0 | if (NSS_SecureMemcmp(pSignature, context->macBuf, ulSignatureLen)) |
4028 | 0 | crv = CKR_SIGNATURE_INVALID; |
4029 | 0 | } |
4030 | |
|
4031 | 0 | sftk_TerminateOp(session, SFTK_VERIFY, context); |
4032 | 0 | sftk_FreeSession(session); |
4033 | 0 | return crv; |
4034 | 0 | } |
4035 | | |
4036 | | /* |
4037 | | ************** Crypto Functions: Verify Recover ************************ |
4038 | | */ |
4039 | | static SECStatus |
4040 | | sftk_RSACheckSignRecover(void *ctx, unsigned char *data, |
4041 | | unsigned int *dataLen, unsigned int maxDataLen, |
4042 | | const unsigned char *sig, unsigned int sigLen) |
4043 | 0 | { |
4044 | 0 | NSSLOWKEYPublicKey *key = ctx; |
4045 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
4046 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
4047 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
4048 | 0 | return SECFailure; |
4049 | 0 | } |
4050 | | |
4051 | 0 | return RSA_CheckSignRecover(&key->u.rsa, data, dataLen, maxDataLen, |
4052 | 0 | sig, sigLen); |
4053 | 0 | } |
4054 | | |
4055 | | static SECStatus |
4056 | | sftk_RSACheckSignRecoverRaw(void *ctx, unsigned char *data, |
4057 | | unsigned int *dataLen, unsigned int maxDataLen, |
4058 | | const unsigned char *sig, unsigned int sigLen) |
4059 | 0 | { |
4060 | 0 | NSSLOWKEYPublicKey *key = ctx; |
4061 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
4062 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
4063 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
4064 | 0 | return SECFailure; |
4065 | 0 | } |
4066 | | |
4067 | 0 | return RSA_CheckSignRecoverRaw(&key->u.rsa, data, dataLen, maxDataLen, |
4068 | 0 | sig, sigLen); |
4069 | 0 | } |
4070 | | |
4071 | | /* NSC_VerifyRecoverInit initializes a signature verification operation, |
4072 | | * where the data is recovered from the signature. |
4073 | | * E.g. Decryption with the user's public key */ |
4074 | | CK_RV |
4075 | | NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, |
4076 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
4077 | 0 | { |
4078 | 0 | SFTKSession *session; |
4079 | 0 | SFTKObject *key; |
4080 | 0 | SFTKSessionContext *context; |
4081 | 0 | CK_KEY_TYPE key_type; |
4082 | 0 | CK_RV crv = CKR_OK; |
4083 | 0 | NSSLOWKEYPublicKey *pubKey; |
4084 | |
|
4085 | 0 | CHECK_FORK(); |
4086 | |
|
4087 | 0 | session = sftk_SessionFromHandle(hSession); |
4088 | 0 | if (session == NULL) |
4089 | 0 | return CKR_SESSION_HANDLE_INVALID; |
4090 | 0 | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY_RECOVER, |
4091 | 0 | &key, hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY_RECOVER); |
4092 | 0 | if (crv != CKR_OK) { |
4093 | 0 | sftk_FreeSession(session); |
4094 | 0 | return crv; |
4095 | 0 | } |
4096 | | |
4097 | 0 | context->multi = PR_TRUE; |
4098 | |
|
4099 | 0 | switch (pMechanism->mechanism) { |
4100 | 0 | case CKM_RSA_PKCS: |
4101 | 0 | case CKM_RSA_X_509: |
4102 | 0 | if (key_type != CKK_RSA) { |
4103 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4104 | 0 | break; |
4105 | 0 | } |
4106 | 0 | context->multi = PR_FALSE; |
4107 | 0 | context->rsa = PR_TRUE; |
4108 | 0 | pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); |
4109 | 0 | if (pubKey == NULL) { |
4110 | 0 | break; |
4111 | 0 | } |
4112 | 0 | context->cipherInfo = pubKey; |
4113 | 0 | context->update = pMechanism->mechanism == CKM_RSA_X_509 |
4114 | 0 | ? sftk_RSACheckSignRecoverRaw |
4115 | 0 | : sftk_RSACheckSignRecover; |
4116 | 0 | context->destroy = sftk_Null; |
4117 | 0 | break; |
4118 | 0 | default: |
4119 | 0 | crv = CKR_MECHANISM_INVALID; |
4120 | 0 | break; |
4121 | 0 | } |
4122 | | |
4123 | 0 | if (crv != CKR_OK) { |
4124 | 0 | PORT_Free(context); |
4125 | 0 | sftk_FreeSession(session); |
4126 | 0 | return crv; |
4127 | 0 | } |
4128 | 0 | sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context); |
4129 | 0 | sftk_FreeSession(session); |
4130 | 0 | return CKR_OK; |
4131 | 0 | } |
4132 | | |
4133 | | /* NSC_VerifyRecover verifies a signature in a single-part operation, |
4134 | | * where the data is recovered from the signature. |
4135 | | * E.g. Decryption with the user's public key */ |
4136 | | CK_RV |
4137 | | NSC_VerifyRecover(CK_SESSION_HANDLE hSession, |
4138 | | CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, |
4139 | | CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) |
4140 | 0 | { |
4141 | 0 | SFTKSession *session; |
4142 | 0 | SFTKSessionContext *context; |
4143 | 0 | unsigned int outlen; |
4144 | 0 | unsigned int maxoutlen = *pulDataLen; |
4145 | 0 | CK_RV crv; |
4146 | 0 | SECStatus rv; |
4147 | |
|
4148 | 0 | CHECK_FORK(); |
4149 | | |
4150 | | /* make sure we're legal */ |
4151 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY_RECOVER, |
4152 | 0 | PR_FALSE, &session); |
4153 | 0 | if (crv != CKR_OK) |
4154 | 0 | return crv; |
4155 | 0 | if (pData == NULL) { |
4156 | | /* to return the actual size, we need to do the decrypt, just return |
4157 | | * the max size, which is the size of the input signature. */ |
4158 | 0 | *pulDataLen = ulSignatureLen; |
4159 | 0 | rv = SECSuccess; |
4160 | 0 | goto finish; |
4161 | 0 | } |
4162 | | |
4163 | 0 | rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, |
4164 | 0 | pSignature, ulSignatureLen); |
4165 | 0 | *pulDataLen = (CK_ULONG)outlen; |
4166 | |
|
4167 | 0 | sftk_TerminateOp(session, SFTK_VERIFY_RECOVER, context); |
4168 | 0 | finish: |
4169 | 0 | sftk_FreeSession(session); |
4170 | 0 | return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError()); |
4171 | 0 | } |
4172 | | |
4173 | | /* |
4174 | | **************************** Random Functions: ************************ |
4175 | | */ |
4176 | | |
4177 | | /* NSC_SeedRandom mixes additional seed material into the token's random number |
4178 | | * generator. */ |
4179 | | CK_RV |
4180 | | NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, |
4181 | | CK_ULONG ulSeedLen) |
4182 | 0 | { |
4183 | 0 | SECStatus rv; |
4184 | |
|
4185 | 0 | CHECK_FORK(); |
4186 | |
|
4187 | 0 | rv = RNG_RandomUpdate(pSeed, ulSeedLen); |
4188 | 0 | return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
4189 | 0 | } |
4190 | | |
4191 | | /* NSC_GenerateRandom generates random data. */ |
4192 | | CK_RV |
4193 | | NSC_GenerateRandom(CK_SESSION_HANDLE hSession, |
4194 | | CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) |
4195 | 62 | { |
4196 | 62 | SECStatus rv; |
4197 | | |
4198 | 62 | CHECK_FORK(); |
4199 | | |
4200 | 62 | rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen); |
4201 | | /* |
4202 | | * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't |
4203 | | * seeded with enough entropy. |
4204 | | */ |
4205 | 62 | return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
4206 | 62 | } |
4207 | | |
4208 | | /* |
4209 | | **************************** Key Functions: ************************ |
4210 | | */ |
4211 | | |
4212 | | /* |
4213 | | * generate a password based encryption key. This code uses |
4214 | | * PKCS5 to do the work. |
4215 | | */ |
4216 | | static CK_RV |
4217 | | nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism, |
4218 | | void *buf, CK_ULONG *key_length, PRBool faulty3DES) |
4219 | 56 | { |
4220 | 56 | SECItem *pbe_key = NULL, iv, pwitem; |
4221 | 56 | CK_PBE_PARAMS *pbe_params = NULL; |
4222 | 56 | CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL; |
4223 | | |
4224 | 56 | *key_length = 0; |
4225 | 56 | iv.data = NULL; |
4226 | 56 | iv.len = 0; |
4227 | | |
4228 | 56 | if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { |
4229 | 56 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PKCS5_PBKD2_PARAMS))) { |
4230 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4231 | 0 | } |
4232 | 56 | pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter; |
4233 | 56 | pwitem.data = (unsigned char *)pbkd2_params->pPassword; |
4234 | | /* was this a typo in the PKCS #11 spec? */ |
4235 | 56 | pwitem.len = *pbkd2_params->ulPasswordLen; |
4236 | 56 | } else { |
4237 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) { |
4238 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4239 | 0 | } |
4240 | 0 | pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
4241 | 0 | pwitem.data = (unsigned char *)pbe_params->pPassword; |
4242 | 0 | pwitem.len = pbe_params->ulPasswordLen; |
4243 | 0 | } |
4244 | 56 | pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES); |
4245 | 56 | if (pbe_key == NULL) { |
4246 | 0 | return CKR_HOST_MEMORY; |
4247 | 0 | } |
4248 | | |
4249 | 56 | PORT_Memcpy(buf, pbe_key->data, pbe_key->len); |
4250 | 56 | *key_length = pbe_key->len; |
4251 | 56 | SECITEM_ZfreeItem(pbe_key, PR_TRUE); |
4252 | 56 | pbe_key = NULL; |
4253 | | |
4254 | 56 | if (iv.data) { |
4255 | 0 | if (pbe_params && pbe_params->pInitVector != NULL) { |
4256 | 0 | PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len); |
4257 | 0 | } |
4258 | 0 | PORT_Free(iv.data); |
4259 | 0 | } |
4260 | | |
4261 | 56 | return CKR_OK; |
4262 | 56 | } |
4263 | | |
4264 | | /* |
4265 | | * this is coded for "full" support. These selections will be limitted to |
4266 | | * the official subset by freebl. |
4267 | | */ |
4268 | | static unsigned int |
4269 | | sftk_GetSubPrimeFromPrime(unsigned int primeBits) |
4270 | 0 | { |
4271 | 0 | if (primeBits <= 1024) { |
4272 | 0 | return 160; |
4273 | 0 | } else if (primeBits <= 2048) { |
4274 | 0 | return 224; |
4275 | 0 | } else if (primeBits <= 3072) { |
4276 | 0 | return 256; |
4277 | 0 | } else if (primeBits <= 7680) { |
4278 | 0 | return 384; |
4279 | 0 | } else { |
4280 | 0 | return 512; |
4281 | 0 | } |
4282 | 0 | } |
4283 | | |
4284 | | static CK_RV |
4285 | | nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key) |
4286 | 0 | { |
4287 | 0 | SFTKAttribute *attribute; |
4288 | 0 | CK_ULONG counter; |
4289 | 0 | unsigned int seedBits = 0; |
4290 | 0 | unsigned int subprimeBits = 0; |
4291 | 0 | unsigned int primeBits; |
4292 | 0 | unsigned int j = 8; /* default to 1024 bits */ |
4293 | 0 | CK_RV crv = CKR_OK; |
4294 | 0 | PQGParams *params = NULL; |
4295 | 0 | PQGVerify *vfy = NULL; |
4296 | 0 | SECStatus rv; |
4297 | |
|
4298 | 0 | attribute = sftk_FindAttribute(key, CKA_PRIME_BITS); |
4299 | 0 | if (attribute == NULL) { |
4300 | 0 | attribute = sftk_FindAttribute(key, CKA_PRIME); |
4301 | 0 | if (attribute == NULL) { |
4302 | 0 | return CKR_TEMPLATE_INCOMPLETE; |
4303 | 0 | } else { |
4304 | 0 | primeBits = attribute->attrib.ulValueLen; |
4305 | 0 | sftk_FreeAttribute(attribute); |
4306 | 0 | } |
4307 | 0 | } else { |
4308 | 0 | primeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; |
4309 | 0 | sftk_FreeAttribute(attribute); |
4310 | 0 | } |
4311 | 0 | if (primeBits < 1024) { |
4312 | 0 | j = PQG_PBITS_TO_INDEX(primeBits); |
4313 | 0 | if (j == (unsigned int)-1) { |
4314 | 0 | return CKR_ATTRIBUTE_VALUE_INVALID; |
4315 | 0 | } |
4316 | 0 | } |
4317 | | |
4318 | 0 | attribute = sftk_FindAttribute(key, CKA_NSS_PQG_SEED_BITS); |
4319 | 0 | if (attribute != NULL) { |
4320 | 0 | seedBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; |
4321 | 0 | sftk_FreeAttribute(attribute); |
4322 | 0 | } |
4323 | |
|
4324 | 0 | attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS); |
4325 | 0 | if (attribute != NULL) { |
4326 | 0 | subprimeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; |
4327 | 0 | sftk_FreeAttribute(attribute); |
4328 | 0 | } |
4329 | | |
4330 | | /* if P and Q are supplied, we want to generate a new G */ |
4331 | 0 | attribute = sftk_FindAttribute(key, CKA_PRIME); |
4332 | 0 | if (attribute != NULL) { |
4333 | 0 | PLArenaPool *arena; |
4334 | |
|
4335 | 0 | sftk_FreeAttribute(attribute); |
4336 | 0 | arena = PORT_NewArena(1024); |
4337 | 0 | if (arena == NULL) { |
4338 | 0 | crv = CKR_HOST_MEMORY; |
4339 | 0 | goto loser; |
4340 | 0 | } |
4341 | 0 | params = PORT_ArenaAlloc(arena, sizeof(*params)); |
4342 | 0 | if (params == NULL) { |
4343 | 0 | crv = CKR_HOST_MEMORY; |
4344 | 0 | goto loser; |
4345 | 0 | } |
4346 | 0 | params->arena = arena; |
4347 | 0 | crv = sftk_Attribute2SSecItem(arena, ¶ms->prime, key, CKA_PRIME); |
4348 | 0 | if (crv != CKR_OK) { |
4349 | 0 | goto loser; |
4350 | 0 | } |
4351 | 0 | crv = sftk_Attribute2SSecItem(arena, ¶ms->subPrime, |
4352 | 0 | key, CKA_SUBPRIME); |
4353 | 0 | if (crv != CKR_OK) { |
4354 | 0 | goto loser; |
4355 | 0 | } |
4356 | | |
4357 | 0 | arena = PORT_NewArena(1024); |
4358 | 0 | if (arena == NULL) { |
4359 | 0 | crv = CKR_HOST_MEMORY; |
4360 | 0 | goto loser; |
4361 | 0 | } |
4362 | 0 | vfy = PORT_ArenaAlloc(arena, sizeof(*vfy)); |
4363 | 0 | if (vfy == NULL) { |
4364 | 0 | crv = CKR_HOST_MEMORY; |
4365 | 0 | goto loser; |
4366 | 0 | } |
4367 | 0 | vfy->arena = arena; |
4368 | 0 | crv = sftk_Attribute2SSecItem(arena, &vfy->seed, key, CKA_NSS_PQG_SEED); |
4369 | 0 | if (crv != CKR_OK) { |
4370 | 0 | goto loser; |
4371 | 0 | } |
4372 | 0 | crv = sftk_Attribute2SSecItem(arena, &vfy->h, key, CKA_NSS_PQG_H); |
4373 | 0 | if (crv != CKR_OK) { |
4374 | 0 | goto loser; |
4375 | 0 | } |
4376 | 0 | sftk_DeleteAttributeType(key, CKA_PRIME); |
4377 | 0 | sftk_DeleteAttributeType(key, CKA_SUBPRIME); |
4378 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED); |
4379 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_PQG_H); |
4380 | 0 | } |
4381 | | |
4382 | 0 | sftk_DeleteAttributeType(key, CKA_PRIME_BITS); |
4383 | 0 | sftk_DeleteAttributeType(key, CKA_SUBPRIME_BITS); |
4384 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED_BITS); |
4385 | | |
4386 | | /* use the old PQG interface if we have old input data */ |
4387 | 0 | if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) { |
4388 | 0 | if (seedBits == 0) { |
4389 | 0 | rv = PQG_ParamGen(j, ¶ms, &vfy); |
4390 | 0 | } else { |
4391 | 0 | rv = PQG_ParamGenSeedLen(j, seedBits / 8, ¶ms, &vfy); |
4392 | 0 | } |
4393 | 0 | } else { |
4394 | 0 | if (subprimeBits == 0) { |
4395 | 0 | subprimeBits = sftk_GetSubPrimeFromPrime(primeBits); |
4396 | 0 | } |
4397 | 0 | if (seedBits == 0) { |
4398 | 0 | seedBits = primeBits; |
4399 | 0 | } |
4400 | 0 | rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits / 8, ¶ms, &vfy); |
4401 | 0 | } |
4402 | |
|
4403 | 0 | if (rv != SECSuccess) { |
4404 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
4405 | 0 | sftk_fatalError = PR_TRUE; |
4406 | 0 | } |
4407 | 0 | return sftk_MapCryptError(PORT_GetError()); |
4408 | 0 | } |
4409 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME, |
4410 | 0 | params->prime.data, params->prime.len); |
4411 | 0 | if (crv != CKR_OK) |
4412 | 0 | goto loser; |
4413 | 0 | crv = sftk_AddAttributeType(key, CKA_SUBPRIME, |
4414 | 0 | params->subPrime.data, params->subPrime.len); |
4415 | 0 | if (crv != CKR_OK) |
4416 | 0 | goto loser; |
4417 | 0 | crv = sftk_AddAttributeType(key, CKA_BASE, |
4418 | 0 | params->base.data, params->base.len); |
4419 | 0 | if (crv != CKR_OK) |
4420 | 0 | goto loser; |
4421 | 0 | counter = vfy->counter; |
4422 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_PQG_COUNTER, |
4423 | 0 | &counter, sizeof(counter)); |
4424 | 0 | if (crv != CKR_OK) |
4425 | 0 | goto loser; |
4426 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_PQG_SEED, |
4427 | 0 | vfy->seed.data, vfy->seed.len); |
4428 | 0 | if (crv != CKR_OK) |
4429 | 0 | goto loser; |
4430 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_PQG_H, |
4431 | 0 | vfy->h.data, vfy->h.len); |
4432 | 0 | if (crv != CKR_OK) |
4433 | 0 | goto loser; |
4434 | | |
4435 | 0 | loser: |
4436 | 0 | if (params) { |
4437 | 0 | PQG_DestroyParams(params); |
4438 | 0 | } |
4439 | |
|
4440 | 0 | if (vfy) { |
4441 | 0 | PQG_DestroyVerify(vfy); |
4442 | 0 | } |
4443 | 0 | return crv; |
4444 | 0 | } |
4445 | | |
4446 | | static CK_RV |
4447 | | nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type, |
4448 | | CK_ULONG *key_length) |
4449 | 0 | { |
4450 | 0 | CK_RV crv = CKR_OK; |
4451 | |
|
4452 | 0 | switch (mechanism) { |
4453 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
4454 | 0 | case CKM_RC2_KEY_GEN: |
4455 | 0 | *key_type = CKK_RC2; |
4456 | 0 | if (*key_length == 0) |
4457 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4458 | 0 | break; |
4459 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
4460 | | #if NSS_SOFTOKEN_DOES_RC5 |
4461 | | case CKM_RC5_KEY_GEN: |
4462 | | *key_type = CKK_RC5; |
4463 | | if (*key_length == 0) |
4464 | | crv = CKR_TEMPLATE_INCOMPLETE; |
4465 | | break; |
4466 | | #endif |
4467 | 0 | case CKM_RC4_KEY_GEN: |
4468 | 0 | *key_type = CKK_RC4; |
4469 | 0 | if (*key_length == 0) |
4470 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4471 | 0 | break; |
4472 | 0 | case CKM_GENERIC_SECRET_KEY_GEN: |
4473 | 0 | *key_type = CKK_GENERIC_SECRET; |
4474 | 0 | if (*key_length == 0) |
4475 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4476 | 0 | break; |
4477 | 0 | case CKM_CDMF_KEY_GEN: |
4478 | 0 | *key_type = CKK_CDMF; |
4479 | 0 | *key_length = 8; |
4480 | 0 | break; |
4481 | 0 | case CKM_DES_KEY_GEN: |
4482 | 0 | *key_type = CKK_DES; |
4483 | 0 | *key_length = 8; |
4484 | 0 | break; |
4485 | 0 | case CKM_DES2_KEY_GEN: |
4486 | 0 | *key_type = CKK_DES2; |
4487 | 0 | *key_length = 16; |
4488 | 0 | break; |
4489 | 0 | case CKM_DES3_KEY_GEN: |
4490 | 0 | *key_type = CKK_DES3; |
4491 | 0 | *key_length = 24; |
4492 | 0 | break; |
4493 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
4494 | 0 | case CKM_SEED_KEY_GEN: |
4495 | 0 | *key_type = CKK_SEED; |
4496 | 0 | *key_length = 16; |
4497 | 0 | break; |
4498 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
4499 | 0 | case CKM_CAMELLIA_KEY_GEN: |
4500 | 0 | *key_type = CKK_CAMELLIA; |
4501 | 0 | if (*key_length == 0) |
4502 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4503 | 0 | break; |
4504 | 0 | case CKM_AES_KEY_GEN: |
4505 | 0 | *key_type = CKK_AES; |
4506 | 0 | if (*key_length == 0) |
4507 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4508 | 0 | break; |
4509 | 0 | case CKM_NSS_CHACHA20_KEY_GEN: |
4510 | 0 | *key_type = CKK_NSS_CHACHA20; |
4511 | 0 | *key_length = 32; |
4512 | 0 | break; |
4513 | 0 | case CKM_CHACHA20_KEY_GEN: |
4514 | 0 | *key_type = CKK_CHACHA20; |
4515 | 0 | *key_length = 32; |
4516 | 0 | break; |
4517 | 0 | case CKM_HKDF_KEY_GEN: |
4518 | 0 | *key_type = CKK_HKDF; |
4519 | 0 | if (*key_length == 0) |
4520 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4521 | 0 | break; |
4522 | 0 | default: |
4523 | 0 | PORT_Assert(0); |
4524 | 0 | crv = CKR_MECHANISM_INVALID; |
4525 | 0 | break; |
4526 | 0 | } |
4527 | | |
4528 | 0 | return crv; |
4529 | 0 | } |
4530 | | |
4531 | | CK_RV |
4532 | | nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe) |
4533 | 0 | { |
4534 | 0 | SECItem salt; |
4535 | 0 | CK_PBE_PARAMS *pbe_params = NULL; |
4536 | 0 | NSSPKCS5PBEParameter *params; |
4537 | 0 | PLArenaPool *arena = NULL; |
4538 | 0 | SECStatus rv; |
4539 | |
|
4540 | 0 | *pbe = NULL; |
4541 | |
|
4542 | 0 | arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); |
4543 | 0 | if (arena == NULL) { |
4544 | 0 | return CKR_HOST_MEMORY; |
4545 | 0 | } |
4546 | | |
4547 | 0 | params = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena, |
4548 | 0 | sizeof(NSSPKCS5PBEParameter)); |
4549 | 0 | if (params == NULL) { |
4550 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4551 | 0 | return CKR_HOST_MEMORY; |
4552 | 0 | } |
4553 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) { |
4554 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4555 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4556 | 0 | } |
4557 | | |
4558 | 0 | params->poolp = arena; |
4559 | 0 | params->ivLen = 0; |
4560 | 0 | params->pbeType = NSSPKCS5_PKCS12_V2; |
4561 | 0 | params->hashType = HASH_AlgSHA1; |
4562 | 0 | params->encAlg = SEC_OID_SHA1; /* any invalid value */ |
4563 | 0 | params->is2KeyDES = PR_FALSE; |
4564 | 0 | params->keyID = pbeBitGenIntegrityKey; |
4565 | 0 | pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
4566 | 0 | params->iter = pbe_params->ulIteration; |
4567 | |
|
4568 | 0 | salt.data = (unsigned char *)pbe_params->pSalt; |
4569 | 0 | salt.len = (unsigned int)pbe_params->ulSaltLen; |
4570 | 0 | salt.type = siBuffer; |
4571 | 0 | rv = SECITEM_CopyItem(arena, ¶ms->salt, &salt); |
4572 | 0 | if (rv != SECSuccess) { |
4573 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4574 | 0 | return CKR_HOST_MEMORY; |
4575 | 0 | } |
4576 | 0 | switch (pMechanism->mechanism) { |
4577 | 0 | case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN: |
4578 | 0 | case CKM_PBA_SHA1_WITH_SHA1_HMAC: |
4579 | 0 | params->hashType = HASH_AlgSHA1; |
4580 | 0 | params->keyLen = 20; |
4581 | 0 | break; |
4582 | 0 | case CKM_NSS_PBE_MD5_HMAC_KEY_GEN: |
4583 | 0 | params->hashType = HASH_AlgMD5; |
4584 | 0 | params->keyLen = 16; |
4585 | 0 | break; |
4586 | 0 | case CKM_NSS_PBE_MD2_HMAC_KEY_GEN: |
4587 | 0 | params->hashType = HASH_AlgMD2; |
4588 | 0 | params->keyLen = 16; |
4589 | 0 | break; |
4590 | 0 | case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN: |
4591 | 0 | params->hashType = HASH_AlgSHA224; |
4592 | 0 | params->keyLen = 28; |
4593 | 0 | break; |
4594 | 0 | case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN: |
4595 | 0 | params->hashType = HASH_AlgSHA256; |
4596 | 0 | params->keyLen = 32; |
4597 | 0 | break; |
4598 | 0 | case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN: |
4599 | 0 | params->hashType = HASH_AlgSHA384; |
4600 | 0 | params->keyLen = 48; |
4601 | 0 | break; |
4602 | 0 | case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN: |
4603 | 0 | params->hashType = HASH_AlgSHA512; |
4604 | 0 | params->keyLen = 64; |
4605 | 0 | break; |
4606 | 0 | default: |
4607 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4608 | 0 | return CKR_MECHANISM_INVALID; |
4609 | 0 | } |
4610 | 0 | *pbe = params; |
4611 | 0 | return CKR_OK; |
4612 | 0 | } |
4613 | | |
4614 | | /* maybe this should be table driven? */ |
4615 | | static CK_RV |
4616 | | nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe, |
4617 | | CK_KEY_TYPE *key_type, CK_ULONG *key_length) |
4618 | 56 | { |
4619 | 56 | CK_RV crv = CKR_OK; |
4620 | 56 | SECOidData *oid; |
4621 | 56 | CK_PBE_PARAMS *pbe_params = NULL; |
4622 | 56 | NSSPKCS5PBEParameter *params = NULL; |
4623 | 56 | HASH_HashType hashType = HASH_AlgSHA1; |
4624 | 56 | CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL; |
4625 | 56 | SECItem salt; |
4626 | 56 | CK_ULONG iteration = 0; |
4627 | | |
4628 | 56 | *pbe = NULL; |
4629 | | |
4630 | 56 | oid = SECOID_FindOIDByMechanism(pMechanism->mechanism); |
4631 | 56 | if (oid == NULL) { |
4632 | 0 | return CKR_MECHANISM_INVALID; |
4633 | 0 | } |
4634 | | |
4635 | 56 | if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { |
4636 | 56 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PKCS5_PBKD2_PARAMS))) { |
4637 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4638 | 0 | } |
4639 | 56 | pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter; |
4640 | 56 | switch (pbkd2_params->prf) { |
4641 | 12 | case CKP_PKCS5_PBKD2_HMAC_SHA1: |
4642 | 12 | hashType = HASH_AlgSHA1; |
4643 | 12 | break; |
4644 | 12 | case CKP_PKCS5_PBKD2_HMAC_SHA224: |
4645 | 12 | hashType = HASH_AlgSHA224; |
4646 | 12 | break; |
4647 | 11 | case CKP_PKCS5_PBKD2_HMAC_SHA256: |
4648 | 11 | hashType = HASH_AlgSHA256; |
4649 | 11 | break; |
4650 | 6 | case CKP_PKCS5_PBKD2_HMAC_SHA384: |
4651 | 6 | hashType = HASH_AlgSHA384; |
4652 | 6 | break; |
4653 | 15 | case CKP_PKCS5_PBKD2_HMAC_SHA512: |
4654 | 15 | hashType = HASH_AlgSHA512; |
4655 | 15 | break; |
4656 | 0 | default: |
4657 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4658 | 56 | } |
4659 | 56 | if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) { |
4660 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4661 | 0 | } |
4662 | 56 | salt.data = (unsigned char *)pbkd2_params->pSaltSourceData; |
4663 | 56 | salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen; |
4664 | 56 | iteration = pbkd2_params->iterations; |
4665 | 56 | } else { |
4666 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) { |
4667 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4668 | 0 | } |
4669 | 0 | pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
4670 | 0 | salt.data = (unsigned char *)pbe_params->pSalt; |
4671 | 0 | salt.len = (unsigned int)pbe_params->ulSaltLen; |
4672 | 0 | iteration = pbe_params->ulIteration; |
4673 | 0 | } |
4674 | 56 | params = nsspkcs5_NewParam(oid->offset, hashType, &salt, iteration); |
4675 | 56 | if (params == NULL) { |
4676 | 0 | return CKR_MECHANISM_INVALID; |
4677 | 0 | } |
4678 | | |
4679 | 56 | switch (params->encAlg) { |
4680 | 0 | case SEC_OID_DES_CBC: |
4681 | 0 | *key_type = CKK_DES; |
4682 | 0 | *key_length = params->keyLen; |
4683 | 0 | break; |
4684 | 0 | case SEC_OID_DES_EDE3_CBC: |
4685 | 0 | *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3; |
4686 | 0 | *key_length = params->keyLen; |
4687 | 0 | break; |
4688 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
4689 | 0 | case SEC_OID_RC2_CBC: |
4690 | 0 | *key_type = CKK_RC2; |
4691 | 0 | *key_length = params->keyLen; |
4692 | 0 | break; |
4693 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
4694 | 0 | case SEC_OID_RC4: |
4695 | 0 | *key_type = CKK_RC4; |
4696 | 0 | *key_length = params->keyLen; |
4697 | 0 | break; |
4698 | 56 | case SEC_OID_PKCS5_PBKDF2: |
4699 | | /* key type must already be set */ |
4700 | 56 | if (*key_type == CKK_INVALID_KEY_TYPE) { |
4701 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4702 | 0 | break; |
4703 | 0 | } |
4704 | | /* PBKDF2 needs to calculate the key length from the other parameters |
4705 | | */ |
4706 | 56 | if (*key_length == 0) { |
4707 | 0 | *key_length = sftk_MapKeySize(*key_type); |
4708 | 0 | } |
4709 | 56 | if (*key_length == 0) { |
4710 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4711 | 0 | break; |
4712 | 0 | } |
4713 | 56 | params->keyLen = *key_length; |
4714 | 56 | break; |
4715 | 0 | default: |
4716 | 0 | crv = CKR_MECHANISM_INVALID; |
4717 | 0 | break; |
4718 | 56 | } |
4719 | 56 | if (crv == CKR_OK) { |
4720 | 56 | *pbe = params; |
4721 | 56 | } else { |
4722 | 0 | nsspkcs5_DestroyPBEParameter(params); |
4723 | 0 | } |
4724 | 56 | return crv; |
4725 | 56 | } |
4726 | | |
4727 | | /* NSC_GenerateKey generates a secret key, creating a new key object. */ |
4728 | | CK_RV |
4729 | | NSC_GenerateKey(CK_SESSION_HANDLE hSession, |
4730 | | CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, |
4731 | | CK_OBJECT_HANDLE_PTR phKey) |
4732 | 56 | { |
4733 | 56 | SFTKObject *key; |
4734 | 56 | SFTKSession *session; |
4735 | 56 | PRBool checkWeak = PR_FALSE; |
4736 | 56 | CK_ULONG key_length = 0; |
4737 | 56 | CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE; |
4738 | 56 | CK_OBJECT_CLASS objclass = CKO_SECRET_KEY; |
4739 | 56 | CK_RV crv = CKR_OK; |
4740 | 56 | CK_BBOOL cktrue = CK_TRUE; |
4741 | 56 | NSSPKCS5PBEParameter *pbe_param = NULL; |
4742 | 56 | int i; |
4743 | 56 | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
4744 | 56 | unsigned char buf[MAX_KEY_LEN]; |
4745 | 56 | enum { nsc_pbe, |
4746 | 56 | nsc_ssl, |
4747 | 56 | nsc_bulk, |
4748 | 56 | nsc_param, |
4749 | 56 | nsc_jpake } key_gen_type; |
4750 | 56 | SSL3RSAPreMasterSecret *rsa_pms; |
4751 | 56 | CK_VERSION *version; |
4752 | | /* in very old versions of NSS, there were implementation errors with key |
4753 | | * generation methods. We want to beable to read these, but not |
4754 | | * produce them any more. The affected algorithm was 3DES. |
4755 | | */ |
4756 | 56 | PRBool faultyPBE3DES = PR_FALSE; |
4757 | 56 | HASH_HashType hashType = HASH_AlgNULL; |
4758 | | |
4759 | 56 | CHECK_FORK(); |
4760 | | |
4761 | 56 | if (!slot) { |
4762 | 0 | return CKR_SESSION_HANDLE_INVALID; |
4763 | 0 | } |
4764 | | /* |
4765 | | * now lets create an object to hang the attributes off of |
4766 | | */ |
4767 | 56 | key = sftk_NewObject(slot); /* fill in the handle later */ |
4768 | 56 | if (key == NULL) { |
4769 | 0 | return CKR_HOST_MEMORY; |
4770 | 0 | } |
4771 | | |
4772 | | /* |
4773 | | * load the template values into the object |
4774 | | */ |
4775 | 448 | for (i = 0; i < (int)ulCount; i++) { |
4776 | 392 | if (pTemplate[i].type == CKA_VALUE_LEN) { |
4777 | 56 | key_length = *(CK_ULONG *)pTemplate[i].pValue; |
4778 | 56 | continue; |
4779 | 56 | } |
4780 | | /* some algorithms need keytype specified */ |
4781 | 336 | if (pTemplate[i].type == CKA_KEY_TYPE) { |
4782 | 56 | key_type = *(CK_ULONG *)pTemplate[i].pValue; |
4783 | 56 | continue; |
4784 | 56 | } |
4785 | | |
4786 | 280 | crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); |
4787 | 280 | if (crv != CKR_OK) { |
4788 | 0 | break; |
4789 | 0 | } |
4790 | 280 | } |
4791 | 56 | if (crv != CKR_OK) { |
4792 | 0 | goto loser; |
4793 | 0 | } |
4794 | | |
4795 | | /* make sure we don't have any class, key_type, or value fields */ |
4796 | 56 | sftk_DeleteAttributeType(key, CKA_CLASS); |
4797 | 56 | sftk_DeleteAttributeType(key, CKA_KEY_TYPE); |
4798 | 56 | sftk_DeleteAttributeType(key, CKA_VALUE); |
4799 | | |
4800 | | /* Now Set up the parameters to generate the key (based on mechanism) */ |
4801 | 56 | key_gen_type = nsc_bulk; /* bulk key by default */ |
4802 | 56 | switch (pMechanism->mechanism) { |
4803 | 0 | case CKM_CDMF_KEY_GEN: |
4804 | 0 | case CKM_DES_KEY_GEN: |
4805 | 0 | case CKM_DES2_KEY_GEN: |
4806 | 0 | case CKM_DES3_KEY_GEN: |
4807 | 0 | checkWeak = PR_TRUE; |
4808 | | /* fall through */ |
4809 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
4810 | 0 | case CKM_RC2_KEY_GEN: |
4811 | 0 | #endif |
4812 | 0 | case CKM_RC4_KEY_GEN: |
4813 | 0 | case CKM_GENERIC_SECRET_KEY_GEN: |
4814 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
4815 | 0 | case CKM_SEED_KEY_GEN: |
4816 | 0 | #endif |
4817 | 0 | case CKM_CAMELLIA_KEY_GEN: |
4818 | 0 | case CKM_AES_KEY_GEN: |
4819 | 0 | case CKM_NSS_CHACHA20_KEY_GEN: |
4820 | 0 | case CKM_CHACHA20_KEY_GEN: |
4821 | | #if NSS_SOFTOKEN_DOES_RC5 |
4822 | | case CKM_RC5_KEY_GEN: |
4823 | | #endif |
4824 | 0 | crv = nsc_SetupBulkKeyGen(pMechanism->mechanism, &key_type, &key_length); |
4825 | 0 | break; |
4826 | 0 | case CKM_SSL3_PRE_MASTER_KEY_GEN: |
4827 | 0 | key_type = CKK_GENERIC_SECRET; |
4828 | 0 | key_length = 48; |
4829 | 0 | key_gen_type = nsc_ssl; |
4830 | 0 | break; |
4831 | 0 | case CKM_PBA_SHA1_WITH_SHA1_HMAC: |
4832 | 0 | case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN: |
4833 | 0 | case CKM_NSS_PBE_MD5_HMAC_KEY_GEN: |
4834 | 0 | case CKM_NSS_PBE_MD2_HMAC_KEY_GEN: |
4835 | 0 | case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN: |
4836 | 0 | case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN: |
4837 | 0 | case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN: |
4838 | 0 | case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN: |
4839 | 0 | key_gen_type = nsc_pbe; |
4840 | 0 | key_type = CKK_GENERIC_SECRET; |
4841 | 0 | crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param); |
4842 | 0 | break; |
4843 | 0 | case CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC: |
4844 | 0 | faultyPBE3DES = PR_TRUE; |
4845 | | /* fall through */ |
4846 | 0 | case CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC: |
4847 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
4848 | 0 | case CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC: |
4849 | 0 | case CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC: |
4850 | 0 | case CKM_PBE_SHA1_RC2_128_CBC: |
4851 | 0 | case CKM_PBE_SHA1_RC2_40_CBC: |
4852 | 0 | #endif |
4853 | 0 | case CKM_NSS_PBE_SHA1_DES_CBC: |
4854 | 0 | case CKM_NSS_PBE_SHA1_40_BIT_RC4: |
4855 | 0 | case CKM_NSS_PBE_SHA1_128_BIT_RC4: |
4856 | 0 | case CKM_PBE_SHA1_DES3_EDE_CBC: |
4857 | 0 | case CKM_PBE_SHA1_DES2_EDE_CBC: |
4858 | 0 | case CKM_PBE_SHA1_RC4_128: |
4859 | 0 | case CKM_PBE_SHA1_RC4_40: |
4860 | 0 | case CKM_PBE_MD5_DES_CBC: |
4861 | 0 | case CKM_PBE_MD2_DES_CBC: |
4862 | 56 | case CKM_PKCS5_PBKD2: |
4863 | 56 | key_gen_type = nsc_pbe; |
4864 | 56 | crv = nsc_SetupPBEKeyGen(pMechanism, &pbe_param, &key_type, &key_length); |
4865 | 56 | break; |
4866 | 0 | case CKM_DSA_PARAMETER_GEN: |
4867 | 0 | key_gen_type = nsc_param; |
4868 | 0 | key_type = CKK_DSA; |
4869 | 0 | objclass = CKO_DOMAIN_PARAMETERS; |
4870 | 0 | crv = CKR_OK; |
4871 | 0 | break; |
4872 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA1: |
4873 | 0 | hashType = HASH_AlgSHA1; |
4874 | 0 | goto jpake1; |
4875 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA256: |
4876 | 0 | hashType = HASH_AlgSHA256; |
4877 | 0 | goto jpake1; |
4878 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA384: |
4879 | 0 | hashType = HASH_AlgSHA384; |
4880 | 0 | goto jpake1; |
4881 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA512: |
4882 | 0 | hashType = HASH_AlgSHA512; |
4883 | 0 | goto jpake1; |
4884 | 0 | jpake1: |
4885 | 0 | key_gen_type = nsc_jpake; |
4886 | 0 | key_type = CKK_NSS_JPAKE_ROUND1; |
4887 | 0 | objclass = CKO_PRIVATE_KEY; |
4888 | 0 | if (pMechanism->pParameter == NULL || |
4889 | 0 | pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) { |
4890 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
4891 | 0 | break; |
4892 | 0 | } |
4893 | 0 | if (sftk_isTrue(key, CKA_TOKEN)) { |
4894 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
4895 | 0 | break; |
4896 | 0 | } |
4897 | 0 | crv = CKR_OK; |
4898 | 0 | break; |
4899 | 0 | default: |
4900 | 0 | crv = CKR_MECHANISM_INVALID; |
4901 | 0 | break; |
4902 | 56 | } |
4903 | | |
4904 | | /* make sure we aren't going to overflow the buffer */ |
4905 | 56 | if (sizeof(buf) < key_length) { |
4906 | | /* someone is getting pretty optimistic about how big their key can |
4907 | | * be... */ |
4908 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
4909 | 0 | } |
4910 | | |
4911 | 56 | if (crv != CKR_OK) { |
4912 | 0 | if (pbe_param) { |
4913 | 0 | nsspkcs5_DestroyPBEParameter(pbe_param); |
4914 | 0 | } |
4915 | 0 | goto loser; |
4916 | 0 | } |
4917 | | |
4918 | | /* if there was no error, |
4919 | | * key_type *MUST* be set in the switch statement above */ |
4920 | 56 | PORT_Assert(key_type != CKK_INVALID_KEY_TYPE); |
4921 | | |
4922 | | /* |
4923 | | * now to the actual key gen. |
4924 | | */ |
4925 | 56 | switch (key_gen_type) { |
4926 | 56 | case nsc_pbe: |
4927 | 56 | crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length, |
4928 | 56 | faultyPBE3DES); |
4929 | 56 | nsspkcs5_DestroyPBEParameter(pbe_param); |
4930 | 56 | break; |
4931 | 0 | case nsc_ssl: |
4932 | 0 | rsa_pms = (SSL3RSAPreMasterSecret *)buf; |
4933 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_VERSION))) { |
4934 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
4935 | 0 | goto loser; |
4936 | 0 | } |
4937 | 0 | version = (CK_VERSION *)pMechanism->pParameter; |
4938 | 0 | rsa_pms->client_version[0] = version->major; |
4939 | 0 | rsa_pms->client_version[1] = version->minor; |
4940 | 0 | crv = |
4941 | 0 | NSC_GenerateRandom(0, &rsa_pms->random[0], sizeof(rsa_pms->random)); |
4942 | 0 | break; |
4943 | 0 | case nsc_bulk: |
4944 | | /* get the key, check for weak keys and repeat if found */ |
4945 | 0 | do { |
4946 | 0 | crv = NSC_GenerateRandom(0, buf, key_length); |
4947 | 0 | } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf, key_type)); |
4948 | 0 | break; |
4949 | 0 | case nsc_param: |
4950 | | /* generate parameters */ |
4951 | 0 | *buf = 0; |
4952 | 0 | crv = nsc_parameter_gen(key_type, key); |
4953 | 0 | break; |
4954 | 0 | case nsc_jpake: |
4955 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_NSS_JPAKERound1Params))) { |
4956 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
4957 | 0 | goto loser; |
4958 | 0 | } |
4959 | 0 | crv = jpake_Round1(hashType, |
4960 | 0 | (CK_NSS_JPAKERound1Params *)pMechanism->pParameter, |
4961 | 0 | key); |
4962 | 0 | break; |
4963 | 56 | } |
4964 | | |
4965 | 56 | if (crv != CKR_OK) { |
4966 | 0 | goto loser; |
4967 | 0 | } |
4968 | | |
4969 | | /* Add the class, key_type, and value */ |
4970 | 56 | crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS)); |
4971 | 56 | if (crv != CKR_OK) { |
4972 | 0 | goto loser; |
4973 | 0 | } |
4974 | 56 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE)); |
4975 | 56 | if (crv != CKR_OK) { |
4976 | 0 | goto loser; |
4977 | 0 | } |
4978 | 56 | if (key_length != 0) { |
4979 | 56 | crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length); |
4980 | 56 | if (crv != CKR_OK) { |
4981 | 0 | goto loser; |
4982 | 0 | } |
4983 | 56 | } |
4984 | | |
4985 | | /* get the session */ |
4986 | 56 | session = sftk_SessionFromHandle(hSession); |
4987 | 56 | if (session == NULL) { |
4988 | 0 | crv = CKR_SESSION_HANDLE_INVALID; |
4989 | 0 | goto loser; |
4990 | 0 | } |
4991 | | |
4992 | | /* |
4993 | | * handle the base object stuff |
4994 | | */ |
4995 | 56 | crv = sftk_handleObject(key, session); |
4996 | 56 | sftk_FreeSession(session); |
4997 | 56 | if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) { |
4998 | 0 | crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL)); |
4999 | 0 | } |
5000 | 56 | if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) { |
5001 | 0 | crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL)); |
5002 | 0 | } |
5003 | 56 | if (crv == CKR_OK) { |
5004 | 56 | *phKey = key->handle; |
5005 | 56 | } |
5006 | 56 | loser: |
5007 | 56 | PORT_Memset(buf, 0, sizeof buf); |
5008 | 56 | sftk_FreeObject(key); |
5009 | 56 | return crv; |
5010 | 56 | } |
5011 | | |
5012 | 0 | #define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */ |
5013 | 0 | #define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ |
5014 | | |
5015 | | /* |
5016 | | * FIPS 140-2 pairwise consistency check utilized to validate key pair. |
5017 | | * |
5018 | | * This function returns |
5019 | | * CKR_OK if pairwise consistency check passed |
5020 | | * CKR_GENERAL_ERROR if pairwise consistency check failed |
5021 | | * other error codes if paiswise consistency check could not be |
5022 | | * performed, for example, CKR_HOST_MEMORY. |
5023 | | */ |
5024 | | static CK_RV |
5025 | | sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, SFTKSlot *slot, |
5026 | | SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType) |
5027 | 0 | { |
5028 | | /* |
5029 | | * Key type Mechanism type |
5030 | | * -------------------------------- |
5031 | | * For encrypt/decrypt: CKK_RSA => CKM_RSA_PKCS |
5032 | | * others => CKM_INVALID_MECHANISM |
5033 | | * |
5034 | | * For sign/verify: CKK_RSA => CKM_RSA_PKCS |
5035 | | * CKK_DSA => CKM_DSA |
5036 | | * CKK_EC => CKM_ECDSA |
5037 | | * others => CKM_INVALID_MECHANISM |
5038 | | * |
5039 | | * None of these mechanisms has a parameter. |
5040 | | * |
5041 | | * For derive CKK_DH => CKM_DH_PKCS_DERIVE |
5042 | | * CKK_EC => CKM_ECDH1_DERIVE |
5043 | | * CKK_EC_MONTGOMERY => CKM_ECDH1_DERIVE |
5044 | | * others => CKM_INVALID_MECHANISM |
5045 | | * |
5046 | | * The parameters for these mechanisms is the public key. |
5047 | | */ |
5048 | 0 | CK_MECHANISM mech = { 0, NULL, 0 }; |
5049 | |
|
5050 | 0 | CK_ULONG modulusLen = 0; |
5051 | 0 | CK_ULONG subPrimeLen = 0; |
5052 | 0 | PRBool isEncryptable = PR_FALSE; |
5053 | 0 | PRBool canSignVerify = PR_FALSE; |
5054 | 0 | PRBool isDerivable = PR_FALSE; |
5055 | 0 | CK_RV crv; |
5056 | | |
5057 | | /* Variables used for Encrypt/Decrypt functions. */ |
5058 | 0 | unsigned char *known_message = (unsigned char *)"Known Crypto Message"; |
5059 | 0 | unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH]; |
5060 | 0 | CK_ULONG bytes_decrypted; |
5061 | 0 | unsigned char *ciphertext; |
5062 | 0 | unsigned char *text_compared; |
5063 | 0 | CK_ULONG bytes_encrypted; |
5064 | 0 | CK_ULONG bytes_compared; |
5065 | 0 | CK_ULONG pairwise_digest_length = PAIRWISE_DIGEST_LENGTH; |
5066 | | |
5067 | | /* Variables used for Signature/Verification functions. */ |
5068 | | /* Must be at least 256 bits for DSA2 digest */ |
5069 | 0 | unsigned char *known_digest = (unsigned char *)"Mozilla Rules the World through NSS!"; |
5070 | 0 | unsigned char *signature; |
5071 | 0 | CK_ULONG signature_length; |
5072 | |
|
5073 | 0 | if (keyType == CKK_RSA) { |
5074 | 0 | SFTKAttribute *attribute; |
5075 | | |
5076 | | /* Get modulus length of private key. */ |
5077 | 0 | attribute = sftk_FindAttribute(privateKey, CKA_MODULUS); |
5078 | 0 | if (attribute == NULL) { |
5079 | 0 | return CKR_DEVICE_ERROR; |
5080 | 0 | } |
5081 | 0 | modulusLen = attribute->attrib.ulValueLen; |
5082 | 0 | if (*(unsigned char *)attribute->attrib.pValue == 0) { |
5083 | 0 | modulusLen--; |
5084 | 0 | } |
5085 | 0 | sftk_FreeAttribute(attribute); |
5086 | 0 | } else if (keyType == CKK_DSA) { |
5087 | 0 | SFTKAttribute *attribute; |
5088 | | |
5089 | | /* Get subprime length of private key. */ |
5090 | 0 | attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME); |
5091 | 0 | if (attribute == NULL) { |
5092 | 0 | return CKR_DEVICE_ERROR; |
5093 | 0 | } |
5094 | 0 | subPrimeLen = attribute->attrib.ulValueLen; |
5095 | 0 | if (subPrimeLen > 1 && *(unsigned char *)attribute->attrib.pValue == 0) { |
5096 | 0 | subPrimeLen--; |
5097 | 0 | } |
5098 | 0 | sftk_FreeAttribute(attribute); |
5099 | 0 | } |
5100 | | |
5101 | | /**************************************************/ |
5102 | | /* Pairwise Consistency Check of Encrypt/Decrypt. */ |
5103 | | /**************************************************/ |
5104 | | |
5105 | 0 | isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT); |
5106 | | |
5107 | | /* |
5108 | | * If the decryption attribute is set, attempt to encrypt |
5109 | | * with the public key and decrypt with the private key. |
5110 | | */ |
5111 | 0 | if (isEncryptable) { |
5112 | 0 | if (keyType != CKK_RSA) { |
5113 | 0 | return CKR_DEVICE_ERROR; |
5114 | 0 | } |
5115 | 0 | bytes_encrypted = modulusLen; |
5116 | 0 | mech.mechanism = CKM_RSA_PKCS; |
5117 | | |
5118 | | /* Allocate space for ciphertext. */ |
5119 | 0 | ciphertext = (unsigned char *)PORT_ZAlloc(bytes_encrypted); |
5120 | 0 | if (ciphertext == NULL) { |
5121 | 0 | return CKR_HOST_MEMORY; |
5122 | 0 | } |
5123 | | |
5124 | | /* Prepare for encryption using the public key. */ |
5125 | 0 | crv = NSC_EncryptInit(hSession, &mech, publicKey->handle); |
5126 | 0 | if (crv != CKR_OK) { |
5127 | 0 | PORT_Free(ciphertext); |
5128 | 0 | return crv; |
5129 | 0 | } |
5130 | | |
5131 | | /* Encrypt using the public key. */ |
5132 | 0 | crv = NSC_Encrypt(hSession, |
5133 | 0 | known_message, |
5134 | 0 | PAIRWISE_MESSAGE_LENGTH, |
5135 | 0 | ciphertext, |
5136 | 0 | &bytes_encrypted); |
5137 | 0 | if (crv != CKR_OK) { |
5138 | 0 | PORT_Free(ciphertext); |
5139 | 0 | return crv; |
5140 | 0 | } |
5141 | | |
5142 | | /* Always use the smaller of these two values . . . */ |
5143 | 0 | bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH); |
5144 | | |
5145 | | /* |
5146 | | * If there was a failure, the plaintext |
5147 | | * goes at the end, therefore . . . |
5148 | | */ |
5149 | 0 | text_compared = ciphertext + bytes_encrypted - bytes_compared; |
5150 | | |
5151 | | /* |
5152 | | * Check to ensure that ciphertext does |
5153 | | * NOT EQUAL known input message text |
5154 | | * per FIPS PUB 140-2 directive. |
5155 | | */ |
5156 | 0 | if (PORT_Memcmp(text_compared, known_message, |
5157 | 0 | bytes_compared) == 0) { |
5158 | | /* Set error to Invalid PRIVATE Key. */ |
5159 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
5160 | 0 | PORT_Free(ciphertext); |
5161 | 0 | return CKR_GENERAL_ERROR; |
5162 | 0 | } |
5163 | | |
5164 | | /* Prepare for decryption using the private key. */ |
5165 | 0 | crv = NSC_DecryptInit(hSession, &mech, privateKey->handle); |
5166 | 0 | if (crv != CKR_OK) { |
5167 | 0 | PORT_Free(ciphertext); |
5168 | 0 | return crv; |
5169 | 0 | } |
5170 | | |
5171 | 0 | memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH); |
5172 | | |
5173 | | /* |
5174 | | * Initialize bytes decrypted to be the |
5175 | | * expected PAIRWISE_MESSAGE_LENGTH. |
5176 | | */ |
5177 | 0 | bytes_decrypted = PAIRWISE_MESSAGE_LENGTH; |
5178 | | |
5179 | | /* |
5180 | | * Decrypt using the private key. |
5181 | | * NOTE: No need to reset the |
5182 | | * value of bytes_encrypted. |
5183 | | */ |
5184 | 0 | crv = NSC_Decrypt(hSession, |
5185 | 0 | ciphertext, |
5186 | 0 | bytes_encrypted, |
5187 | 0 | plaintext, |
5188 | 0 | &bytes_decrypted); |
5189 | | |
5190 | | /* Finished with ciphertext; free it. */ |
5191 | 0 | PORT_Free(ciphertext); |
5192 | |
|
5193 | 0 | if (crv != CKR_OK) { |
5194 | 0 | return crv; |
5195 | 0 | } |
5196 | | |
5197 | | /* |
5198 | | * Check to ensure that the output plaintext |
5199 | | * does EQUAL known input message text. |
5200 | | */ |
5201 | 0 | if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) || |
5202 | 0 | (PORT_Memcmp(plaintext, known_message, |
5203 | 0 | PAIRWISE_MESSAGE_LENGTH) != 0)) { |
5204 | | /* Set error to Bad PUBLIC Key. */ |
5205 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); |
5206 | 0 | return CKR_GENERAL_ERROR; |
5207 | 0 | } |
5208 | 0 | } |
5209 | | |
5210 | | /**********************************************/ |
5211 | | /* Pairwise Consistency Check of Sign/Verify. */ |
5212 | | /**********************************************/ |
5213 | | |
5214 | 0 | canSignVerify = sftk_isTrue(privateKey, CKA_SIGN); |
5215 | | /* Unfortunately CKA_SIGN is always true in lg dbs. We have to check the |
5216 | | * actual curve to determine if we can do sign/verify. */ |
5217 | 0 | if (canSignVerify && keyType == CKK_EC) { |
5218 | 0 | NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(privateKey, CKK_EC, &crv); |
5219 | 0 | if (privKey && privKey->u.ec.ecParams.name == ECCurve25519) { |
5220 | 0 | canSignVerify = PR_FALSE; |
5221 | 0 | } |
5222 | 0 | } |
5223 | |
|
5224 | 0 | if (canSignVerify) { |
5225 | | /* Determine length of signature. */ |
5226 | 0 | switch (keyType) { |
5227 | 0 | case CKK_RSA: |
5228 | 0 | signature_length = modulusLen; |
5229 | 0 | mech.mechanism = CKM_RSA_PKCS; |
5230 | 0 | break; |
5231 | 0 | case CKK_DSA: |
5232 | 0 | signature_length = DSA_MAX_SIGNATURE_LEN; |
5233 | 0 | pairwise_digest_length = subPrimeLen; |
5234 | 0 | mech.mechanism = CKM_DSA; |
5235 | 0 | break; |
5236 | 0 | case CKK_EC: |
5237 | 0 | signature_length = MAX_ECKEY_LEN * 2; |
5238 | 0 | mech.mechanism = CKM_ECDSA; |
5239 | 0 | break; |
5240 | 0 | case CKK_EC_EDWARDS: |
5241 | 0 | signature_length = ED25519_SIGN_LEN; |
5242 | 0 | mech.mechanism = CKM_EDDSA; |
5243 | 0 | break; |
5244 | 0 | default: |
5245 | 0 | return CKR_DEVICE_ERROR; |
5246 | 0 | } |
5247 | | |
5248 | | /* Allocate space for signature data. */ |
5249 | 0 | signature = (unsigned char *)PORT_ZAlloc(signature_length); |
5250 | 0 | if (signature == NULL) { |
5251 | 0 | return CKR_HOST_MEMORY; |
5252 | 0 | } |
5253 | | |
5254 | | /* Sign the known hash using the private key. */ |
5255 | 0 | crv = NSC_SignInit(hSession, &mech, privateKey->handle); |
5256 | 0 | if (crv != CKR_OK) { |
5257 | 0 | PORT_Free(signature); |
5258 | 0 | return crv; |
5259 | 0 | } |
5260 | | |
5261 | 0 | crv = NSC_Sign(hSession, |
5262 | 0 | known_digest, |
5263 | 0 | pairwise_digest_length, |
5264 | 0 | signature, |
5265 | 0 | &signature_length); |
5266 | 0 | if (crv != CKR_OK) { |
5267 | 0 | PORT_Free(signature); |
5268 | 0 | return crv; |
5269 | 0 | } |
5270 | | |
5271 | | /* detect trivial signing transforms */ |
5272 | 0 | if ((signature_length >= pairwise_digest_length) && |
5273 | 0 | (PORT_Memcmp(known_digest, signature + (signature_length - pairwise_digest_length), pairwise_digest_length) == 0)) { |
5274 | 0 | PORT_Free(signature); |
5275 | 0 | return CKR_DEVICE_ERROR; |
5276 | 0 | } |
5277 | | |
5278 | | /* Verify the known hash using the public key. */ |
5279 | 0 | crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); |
5280 | 0 | if (crv != CKR_OK) { |
5281 | 0 | PORT_Free(signature); |
5282 | 0 | return crv; |
5283 | 0 | } |
5284 | | |
5285 | 0 | crv = NSC_Verify(hSession, |
5286 | 0 | known_digest, |
5287 | 0 | pairwise_digest_length, |
5288 | 0 | signature, |
5289 | 0 | signature_length); |
5290 | | |
5291 | | /* Free signature data. */ |
5292 | 0 | PORT_Free(signature); |
5293 | |
|
5294 | 0 | if ((crv == CKR_SIGNATURE_LEN_RANGE) || |
5295 | 0 | (crv == CKR_SIGNATURE_INVALID)) { |
5296 | 0 | return CKR_GENERAL_ERROR; |
5297 | 0 | } |
5298 | 0 | if (crv != CKR_OK) { |
5299 | 0 | return crv; |
5300 | 0 | } |
5301 | 0 | } |
5302 | | |
5303 | | /**********************************************/ |
5304 | | /* Pairwise Consistency Check for Derivation */ |
5305 | | /**********************************************/ |
5306 | | |
5307 | 0 | isDerivable = sftk_isTrue(privateKey, CKA_DERIVE); |
5308 | |
|
5309 | 0 | if (isDerivable) { |
5310 | 0 | SFTKAttribute *pubAttribute = NULL; |
5311 | 0 | CK_OBJECT_HANDLE newKey; |
5312 | 0 | PRBool isFIPS = sftk_isFIPS(slot->slotID); |
5313 | 0 | CK_RV crv2; |
5314 | 0 | CK_OBJECT_CLASS secret = CKO_SECRET_KEY; |
5315 | 0 | CK_KEY_TYPE generic = CKK_GENERIC_SECRET; |
5316 | 0 | CK_ULONG keyLen = 128; |
5317 | 0 | CK_BBOOL ckTrue = CK_TRUE; |
5318 | 0 | CK_ATTRIBUTE template[] = { |
5319 | 0 | { CKA_CLASS, &secret, sizeof(secret) }, |
5320 | 0 | { CKA_KEY_TYPE, &generic, sizeof(generic) }, |
5321 | 0 | { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, |
5322 | 0 | { CKA_DERIVE, &ckTrue, sizeof(ckTrue) } |
5323 | 0 | }; |
5324 | 0 | CK_ULONG templateCount = PR_ARRAY_SIZE(template); |
5325 | 0 | CK_ECDH1_DERIVE_PARAMS ecParams; |
5326 | |
|
5327 | 0 | crv = CKR_OK; /*paranoia, already get's set before we drop to the end */ |
5328 | | /* FIPS 140-2 requires we verify that the resulting key is a valid key. |
5329 | | * The easiest way to do this is to do a derive operation, which checks |
5330 | | * the validity of the key */ |
5331 | |
|
5332 | 0 | switch (keyType) { |
5333 | 0 | case CKK_DH: |
5334 | 0 | mech.mechanism = CKM_DH_PKCS_DERIVE; |
5335 | 0 | pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE); |
5336 | 0 | if (pubAttribute == NULL) { |
5337 | 0 | return CKR_DEVICE_ERROR; |
5338 | 0 | } |
5339 | 0 | mech.pParameter = pubAttribute->attrib.pValue; |
5340 | 0 | mech.ulParameterLen = pubAttribute->attrib.ulValueLen; |
5341 | 0 | break; |
5342 | 0 | case CKK_EC_MONTGOMERY: |
5343 | 0 | case CKK_EC: |
5344 | 0 | mech.mechanism = CKM_ECDH1_DERIVE; |
5345 | 0 | pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT); |
5346 | 0 | if (pubAttribute == NULL) { |
5347 | 0 | return CKR_DEVICE_ERROR; |
5348 | 0 | } |
5349 | 0 | ecParams.kdf = CKD_NULL; |
5350 | 0 | ecParams.ulSharedDataLen = 0; |
5351 | 0 | ecParams.pSharedData = NULL; |
5352 | 0 | ecParams.ulPublicDataLen = pubAttribute->attrib.ulValueLen; |
5353 | 0 | ecParams.pPublicData = pubAttribute->attrib.pValue; |
5354 | 0 | mech.pParameter = &ecParams; |
5355 | 0 | mech.ulParameterLen = sizeof(ecParams); |
5356 | 0 | break; |
5357 | 0 | default: |
5358 | 0 | return CKR_DEVICE_ERROR; |
5359 | 0 | } |
5360 | | |
5361 | 0 | crv = NSC_DeriveKey(hSession, &mech, privateKey->handle, template, templateCount, &newKey); |
5362 | 0 | if (crv != CKR_OK) { |
5363 | 0 | sftk_FreeAttribute(pubAttribute); |
5364 | 0 | return crv; |
5365 | 0 | } |
5366 | | /* FIPS requires full validation, but in fipx mode NSC_Derive |
5367 | | * only does partial validation with approved primes, now handle |
5368 | | * full validation */ |
5369 | 0 | if (isFIPS && keyType == CKK_DH) { |
5370 | 0 | SECItem pubKey; |
5371 | 0 | SECItem prime; |
5372 | 0 | SECItem subPrime; |
5373 | 0 | const SECItem *subPrimePtr = &subPrime; |
5374 | |
|
5375 | 0 | pubKey.data = pubAttribute->attrib.pValue; |
5376 | 0 | pubKey.len = pubAttribute->attrib.ulValueLen; |
5377 | 0 | prime.data = subPrime.data = NULL; |
5378 | 0 | prime.len = subPrime.len = 0; |
5379 | 0 | crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME); |
5380 | 0 | if (crv != CKR_OK) { |
5381 | 0 | goto done; |
5382 | 0 | } |
5383 | 0 | crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME); |
5384 | | /* we ignore the return code an only look at the length */ |
5385 | 0 | if (subPrime.len == 0) { |
5386 | | /* subprime not supplied, In this case look it up. |
5387 | | * This only works with approved primes, but in FIPS mode |
5388 | | * that's the only kine of prime that will get here */ |
5389 | 0 | subPrimePtr = sftk_VerifyDH_Prime(&prime, isFIPS); |
5390 | 0 | if (subPrimePtr == NULL) { |
5391 | 0 | crv = CKR_GENERAL_ERROR; |
5392 | 0 | goto done; |
5393 | 0 | } |
5394 | 0 | } |
5395 | 0 | if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) { |
5396 | 0 | crv = CKR_GENERAL_ERROR; |
5397 | 0 | } |
5398 | 0 | done: |
5399 | 0 | SECITEM_ZfreeItem(&subPrime, PR_FALSE); |
5400 | 0 | SECITEM_ZfreeItem(&prime, PR_FALSE); |
5401 | 0 | } |
5402 | | /* clean up before we return */ |
5403 | 0 | sftk_FreeAttribute(pubAttribute); |
5404 | 0 | crv2 = NSC_DestroyObject(hSession, newKey); |
5405 | 0 | if (crv != CKR_OK) { |
5406 | 0 | return crv; |
5407 | 0 | } |
5408 | 0 | if (crv2 != CKR_OK) { |
5409 | 0 | return crv2; |
5410 | 0 | } |
5411 | 0 | } |
5412 | | |
5413 | 0 | return CKR_OK; |
5414 | 0 | } |
5415 | | |
5416 | | /* NSC_GenerateKeyPair generates a public-key/private-key pair, |
5417 | | * creating new key objects. */ |
5418 | | CK_RV |
5419 | | NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession, |
5420 | | CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, |
5421 | | CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, |
5422 | | CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, |
5423 | | CK_OBJECT_HANDLE_PTR phPrivateKey) |
5424 | 0 | { |
5425 | 0 | SFTKObject *publicKey, *privateKey; |
5426 | 0 | SFTKSession *session; |
5427 | 0 | CK_KEY_TYPE key_type; |
5428 | 0 | CK_RV crv = CKR_OK; |
5429 | 0 | CK_BBOOL cktrue = CK_TRUE; |
5430 | 0 | SECStatus rv; |
5431 | 0 | CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; |
5432 | 0 | CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; |
5433 | 0 | int i; |
5434 | 0 | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
5435 | 0 | unsigned int bitSize; |
5436 | | |
5437 | | /* RSA */ |
5438 | 0 | int public_modulus_bits = 0; |
5439 | 0 | SECItem pubExp; |
5440 | 0 | RSAPrivateKey *rsaPriv; |
5441 | | |
5442 | | /* DSA */ |
5443 | 0 | PQGParams pqgParam; |
5444 | 0 | DHParams dhParam; |
5445 | 0 | DSAPrivateKey *dsaPriv; |
5446 | | |
5447 | | /* Diffie Hellman */ |
5448 | 0 | DHPrivateKey *dhPriv; |
5449 | | |
5450 | | /* Elliptic Curve Cryptography */ |
5451 | 0 | SECItem ecEncodedParams; /* DER Encoded parameters */ |
5452 | 0 | ECPrivateKey *ecPriv; |
5453 | 0 | ECParams *ecParams; |
5454 | | |
5455 | | /* Kyber */ |
5456 | 0 | CK_NSS_KEM_PARAMETER_SET_TYPE ckKyberParamSet; |
5457 | |
|
5458 | 0 | CHECK_FORK(); |
5459 | |
|
5460 | 0 | if (!slot) { |
5461 | 0 | return CKR_SESSION_HANDLE_INVALID; |
5462 | 0 | } |
5463 | | /* |
5464 | | * now lets create an object to hang the attributes off of |
5465 | | */ |
5466 | 0 | publicKey = sftk_NewObject(slot); /* fill in the handle later */ |
5467 | 0 | if (publicKey == NULL) { |
5468 | 0 | return CKR_HOST_MEMORY; |
5469 | 0 | } |
5470 | | |
5471 | | /* |
5472 | | * load the template values into the publicKey |
5473 | | */ |
5474 | 0 | for (i = 0; i < (int)ulPublicKeyAttributeCount; i++) { |
5475 | 0 | if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) { |
5476 | 0 | public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue; |
5477 | 0 | continue; |
5478 | 0 | } |
5479 | | |
5480 | 0 | if (pPublicKeyTemplate[i].type == CKA_NSS_PARAMETER_SET) { |
5481 | 0 | ckKyberParamSet = *(CK_NSS_KEM_PARAMETER_SET_TYPE *)pPublicKeyTemplate[i].pValue; |
5482 | 0 | continue; |
5483 | 0 | } |
5484 | | |
5485 | 0 | crv = sftk_AddAttributeType(publicKey, |
5486 | 0 | sftk_attr_expand(&pPublicKeyTemplate[i])); |
5487 | 0 | if (crv != CKR_OK) |
5488 | 0 | break; |
5489 | 0 | } |
5490 | |
|
5491 | 0 | if (crv != CKR_OK) { |
5492 | 0 | sftk_FreeObject(publicKey); |
5493 | 0 | return CKR_HOST_MEMORY; |
5494 | 0 | } |
5495 | | |
5496 | 0 | privateKey = sftk_NewObject(slot); /* fill in the handle later */ |
5497 | 0 | if (privateKey == NULL) { |
5498 | 0 | sftk_FreeObject(publicKey); |
5499 | 0 | return CKR_HOST_MEMORY; |
5500 | 0 | } |
5501 | | /* |
5502 | | * now load the private key template |
5503 | | */ |
5504 | 0 | for (i = 0; i < (int)ulPrivateKeyAttributeCount; i++) { |
5505 | 0 | if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) { |
5506 | 0 | continue; |
5507 | 0 | } |
5508 | | |
5509 | 0 | crv = sftk_AddAttributeType(privateKey, |
5510 | 0 | sftk_attr_expand(&pPrivateKeyTemplate[i])); |
5511 | 0 | if (crv != CKR_OK) |
5512 | 0 | break; |
5513 | 0 | } |
5514 | |
|
5515 | 0 | if (crv != CKR_OK) { |
5516 | 0 | sftk_FreeObject(publicKey); |
5517 | 0 | sftk_FreeObject(privateKey); |
5518 | 0 | return CKR_HOST_MEMORY; |
5519 | 0 | } |
5520 | 0 | sftk_DeleteAttributeType(privateKey, CKA_CLASS); |
5521 | 0 | sftk_DeleteAttributeType(privateKey, CKA_KEY_TYPE); |
5522 | 0 | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
5523 | 0 | sftk_DeleteAttributeType(publicKey, CKA_CLASS); |
5524 | 0 | sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE); |
5525 | 0 | sftk_DeleteAttributeType(publicKey, CKA_VALUE); |
5526 | | |
5527 | | /* Now Set up the parameters to generate the key (based on mechanism) */ |
5528 | 0 | switch (pMechanism->mechanism) { |
5529 | 0 | case CKM_RSA_PKCS_KEY_PAIR_GEN: |
5530 | | /* format the keys */ |
5531 | 0 | sftk_DeleteAttributeType(publicKey, CKA_MODULUS); |
5532 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
5533 | 0 | sftk_DeleteAttributeType(privateKey, CKA_MODULUS); |
5534 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIVATE_EXPONENT); |
5535 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PUBLIC_EXPONENT); |
5536 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME_1); |
5537 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME_2); |
5538 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_1); |
5539 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_2); |
5540 | 0 | sftk_DeleteAttributeType(privateKey, CKA_COEFFICIENT); |
5541 | 0 | key_type = CKK_RSA; |
5542 | 0 | if (public_modulus_bits == 0) { |
5543 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5544 | 0 | break; |
5545 | 0 | } |
5546 | 0 | if (public_modulus_bits < RSA_MIN_MODULUS_BITS) { |
5547 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5548 | 0 | break; |
5549 | 0 | } |
5550 | 0 | if (public_modulus_bits % 2 != 0) { |
5551 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5552 | 0 | break; |
5553 | 0 | } |
5554 | | |
5555 | | /* extract the exponent */ |
5556 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pubExp, publicKey, CKA_PUBLIC_EXPONENT); |
5557 | 0 | if (crv != CKR_OK) |
5558 | 0 | break; |
5559 | 0 | bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len); |
5560 | 0 | if (bitSize < 2) { |
5561 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5562 | 0 | SECITEM_ZfreeItem(&pubExp, PR_FALSE); |
5563 | 0 | break; |
5564 | 0 | } |
5565 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PUBLIC_EXPONENT, |
5566 | 0 | sftk_item_expand(&pubExp)); |
5567 | 0 | if (crv != CKR_OK) { |
5568 | 0 | SECITEM_ZfreeItem(&pubExp, PR_FALSE); |
5569 | 0 | break; |
5570 | 0 | } |
5571 | | |
5572 | 0 | rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp); |
5573 | 0 | SECITEM_ZfreeItem(&pubExp, PR_FALSE); |
5574 | 0 | if (rsaPriv == NULL) { |
5575 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
5576 | 0 | sftk_fatalError = PR_TRUE; |
5577 | 0 | } |
5578 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5579 | 0 | break; |
5580 | 0 | } |
5581 | | /* now fill in the RSA dependent paramenters in the public key */ |
5582 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_MODULUS, |
5583 | 0 | sftk_item_expand(&rsaPriv->modulus)); |
5584 | 0 | if (crv != CKR_OK) |
5585 | 0 | goto kpg_done; |
5586 | | /* now fill in the RSA dependent paramenters in the private key */ |
5587 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
5588 | 0 | sftk_item_expand(&rsaPriv->modulus)); |
5589 | 0 | if (crv != CKR_OK) |
5590 | 0 | goto kpg_done; |
5591 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_MODULUS, |
5592 | 0 | sftk_item_expand(&rsaPriv->modulus)); |
5593 | 0 | if (crv != CKR_OK) |
5594 | 0 | goto kpg_done; |
5595 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIVATE_EXPONENT, |
5596 | 0 | sftk_item_expand(&rsaPriv->privateExponent)); |
5597 | 0 | if (crv != CKR_OK) |
5598 | 0 | goto kpg_done; |
5599 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME_1, |
5600 | 0 | sftk_item_expand(&rsaPriv->prime1)); |
5601 | 0 | if (crv != CKR_OK) |
5602 | 0 | goto kpg_done; |
5603 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME_2, |
5604 | 0 | sftk_item_expand(&rsaPriv->prime2)); |
5605 | 0 | if (crv != CKR_OK) |
5606 | 0 | goto kpg_done; |
5607 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_1, |
5608 | 0 | sftk_item_expand(&rsaPriv->exponent1)); |
5609 | 0 | if (crv != CKR_OK) |
5610 | 0 | goto kpg_done; |
5611 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_2, |
5612 | 0 | sftk_item_expand(&rsaPriv->exponent2)); |
5613 | 0 | if (crv != CKR_OK) |
5614 | 0 | goto kpg_done; |
5615 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_COEFFICIENT, |
5616 | 0 | sftk_item_expand(&rsaPriv->coefficient)); |
5617 | 0 | kpg_done: |
5618 | | /* Should zeroize the contents first, since this func doesn't. */ |
5619 | 0 | PORT_FreeArena(rsaPriv->arena, PR_TRUE); |
5620 | 0 | break; |
5621 | 0 | case CKM_DSA_KEY_PAIR_GEN: |
5622 | 0 | sftk_DeleteAttributeType(publicKey, CKA_VALUE); |
5623 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
5624 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME); |
5625 | 0 | sftk_DeleteAttributeType(privateKey, CKA_SUBPRIME); |
5626 | 0 | sftk_DeleteAttributeType(privateKey, CKA_BASE); |
5627 | 0 | key_type = CKK_DSA; |
5628 | | |
5629 | | /* extract the necessary parameters and copy them to the private key */ |
5630 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pqgParam.prime, publicKey, CKA_PRIME); |
5631 | 0 | if (crv != CKR_OK) |
5632 | 0 | break; |
5633 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pqgParam.subPrime, publicKey, |
5634 | 0 | CKA_SUBPRIME); |
5635 | 0 | if (crv != CKR_OK) { |
5636 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5637 | 0 | break; |
5638 | 0 | } |
5639 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pqgParam.base, publicKey, CKA_BASE); |
5640 | 0 | if (crv != CKR_OK) { |
5641 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5642 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5643 | 0 | break; |
5644 | 0 | } |
5645 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME, |
5646 | 0 | sftk_item_expand(&pqgParam.prime)); |
5647 | 0 | if (crv != CKR_OK) { |
5648 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5649 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5650 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5651 | 0 | break; |
5652 | 0 | } |
5653 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_SUBPRIME, |
5654 | 0 | sftk_item_expand(&pqgParam.subPrime)); |
5655 | 0 | if (crv != CKR_OK) { |
5656 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5657 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5658 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5659 | 0 | break; |
5660 | 0 | } |
5661 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_BASE, |
5662 | 0 | sftk_item_expand(&pqgParam.base)); |
5663 | 0 | if (crv != CKR_OK) { |
5664 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5665 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5666 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5667 | 0 | break; |
5668 | 0 | } |
5669 | | |
5670 | | /* |
5671 | | * these are checked by DSA_NewKey |
5672 | | */ |
5673 | 0 | bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data, |
5674 | 0 | pqgParam.subPrime.len); |
5675 | 0 | if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) { |
5676 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5677 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5678 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5679 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5680 | 0 | break; |
5681 | 0 | } |
5682 | 0 | bitSize = sftk_GetLengthInBits(pqgParam.prime.data, pqgParam.prime.len); |
5683 | 0 | if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) { |
5684 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5685 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5686 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5687 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5688 | 0 | break; |
5689 | 0 | } |
5690 | 0 | bitSize = sftk_GetLengthInBits(pqgParam.base.data, pqgParam.base.len); |
5691 | 0 | if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) { |
5692 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5693 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5694 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5695 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5696 | 0 | break; |
5697 | 0 | } |
5698 | | |
5699 | | /* Generate the key */ |
5700 | 0 | rv = DSA_NewKey(&pqgParam, &dsaPriv); |
5701 | |
|
5702 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
5703 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
5704 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
5705 | |
|
5706 | 0 | if (rv != SECSuccess) { |
5707 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
5708 | 0 | sftk_fatalError = PR_TRUE; |
5709 | 0 | } |
5710 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5711 | 0 | break; |
5712 | 0 | } |
5713 | | |
5714 | | /* store the generated key into the attributes */ |
5715 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, |
5716 | 0 | sftk_item_expand(&dsaPriv->publicValue)); |
5717 | 0 | if (crv != CKR_OK) |
5718 | 0 | goto dsagn_done; |
5719 | | |
5720 | | /* now fill in the RSA dependent paramenters in the private key */ |
5721 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
5722 | 0 | sftk_item_expand(&dsaPriv->publicValue)); |
5723 | 0 | if (crv != CKR_OK) |
5724 | 0 | goto dsagn_done; |
5725 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
5726 | 0 | sftk_item_expand(&dsaPriv->privateValue)); |
5727 | |
|
5728 | 0 | dsagn_done: |
5729 | | /* should zeroize, since this function doesn't. */ |
5730 | 0 | PORT_FreeArena(dsaPriv->params.arena, PR_TRUE); |
5731 | 0 | break; |
5732 | | |
5733 | 0 | case CKM_DH_PKCS_KEY_PAIR_GEN: |
5734 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME); |
5735 | 0 | sftk_DeleteAttributeType(privateKey, CKA_BASE); |
5736 | 0 | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
5737 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
5738 | 0 | key_type = CKK_DH; |
5739 | | |
5740 | | /* extract the necessary parameters and copy them to private keys */ |
5741 | 0 | crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey, |
5742 | 0 | CKA_PRIME); |
5743 | 0 | if (crv != CKR_OK) |
5744 | 0 | break; |
5745 | 0 | crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE); |
5746 | 0 | if (crv != CKR_OK) { |
5747 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
5748 | 0 | break; |
5749 | 0 | } |
5750 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME, |
5751 | 0 | sftk_item_expand(&dhParam.prime)); |
5752 | 0 | if (crv != CKR_OK) { |
5753 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
5754 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
5755 | 0 | break; |
5756 | 0 | } |
5757 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_BASE, |
5758 | 0 | sftk_item_expand(&dhParam.base)); |
5759 | 0 | if (crv != CKR_OK) { |
5760 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
5761 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
5762 | 0 | break; |
5763 | 0 | } |
5764 | 0 | bitSize = sftk_GetLengthInBits(dhParam.prime.data, dhParam.prime.len); |
5765 | 0 | if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) { |
5766 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5767 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
5768 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
5769 | 0 | break; |
5770 | 0 | } |
5771 | 0 | bitSize = sftk_GetLengthInBits(dhParam.base.data, dhParam.base.len); |
5772 | 0 | if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) { |
5773 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5774 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
5775 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
5776 | 0 | break; |
5777 | 0 | } |
5778 | | |
5779 | 0 | rv = DH_NewKey(&dhParam, &dhPriv); |
5780 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
5781 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
5782 | 0 | if (rv != SECSuccess) { |
5783 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
5784 | 0 | sftk_fatalError = PR_TRUE; |
5785 | 0 | } |
5786 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5787 | 0 | break; |
5788 | 0 | } |
5789 | | |
5790 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, |
5791 | 0 | sftk_item_expand(&dhPriv->publicValue)); |
5792 | 0 | if (crv != CKR_OK) |
5793 | 0 | goto dhgn_done; |
5794 | | |
5795 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
5796 | 0 | sftk_item_expand(&dhPriv->publicValue)); |
5797 | 0 | if (crv != CKR_OK) |
5798 | 0 | goto dhgn_done; |
5799 | | |
5800 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
5801 | 0 | sftk_item_expand(&dhPriv->privateValue)); |
5802 | |
|
5803 | 0 | dhgn_done: |
5804 | | /* should zeroize, since this function doesn't. */ |
5805 | 0 | PORT_FreeArena(dhPriv->arena, PR_TRUE); |
5806 | 0 | break; |
5807 | | |
5808 | 0 | case CKM_EC_KEY_PAIR_GEN: |
5809 | 0 | case CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN: |
5810 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS); |
5811 | 0 | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
5812 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
5813 | 0 | key_type = CKK_EC; |
5814 | | |
5815 | | /* extract the necessary parameters and copy them to private keys */ |
5816 | 0 | crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, |
5817 | 0 | CKA_EC_PARAMS); |
5818 | 0 | if (crv != CKR_OK) |
5819 | 0 | break; |
5820 | | |
5821 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS, |
5822 | 0 | sftk_item_expand(&ecEncodedParams)); |
5823 | 0 | if (crv != CKR_OK) { |
5824 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
5825 | 0 | break; |
5826 | 0 | } |
5827 | | |
5828 | | /* Decode ec params before calling EC_NewKey */ |
5829 | 0 | rv = EC_DecodeParams(&ecEncodedParams, &ecParams); |
5830 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
5831 | 0 | if (rv != SECSuccess) { |
5832 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5833 | 0 | break; |
5834 | 0 | } |
5835 | 0 | rv = EC_NewKey(ecParams, &ecPriv); |
5836 | 0 | if (rv != SECSuccess) { |
5837 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
5838 | 0 | sftk_fatalError = PR_TRUE; |
5839 | 0 | } |
5840 | 0 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
5841 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5842 | 0 | break; |
5843 | 0 | } |
5844 | | |
5845 | 0 | if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") || |
5846 | 0 | ecParams->type != ec_params_named) { |
5847 | 0 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
5848 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
5849 | 0 | sftk_item_expand(&ecPriv->publicValue)); |
5850 | 0 | } else { |
5851 | 0 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
5852 | 0 | SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, |
5853 | 0 | &ecPriv->publicValue, |
5854 | 0 | SEC_ASN1_GET(SEC_OctetStringTemplate)); |
5855 | 0 | if (!pubValue) { |
5856 | 0 | crv = CKR_ARGUMENTS_BAD; |
5857 | 0 | goto ecgn_done; |
5858 | 0 | } |
5859 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
5860 | 0 | sftk_item_expand(pubValue)); |
5861 | 0 | SECITEM_ZfreeItem(pubValue, PR_TRUE); |
5862 | 0 | } |
5863 | 0 | if (crv != CKR_OK) |
5864 | 0 | goto ecgn_done; |
5865 | | |
5866 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
5867 | 0 | sftk_item_expand(&ecPriv->privateValue)); |
5868 | 0 | if (crv != CKR_OK) |
5869 | 0 | goto ecgn_done; |
5870 | | |
5871 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
5872 | 0 | sftk_item_expand(&ecPriv->publicValue)); |
5873 | 0 | ecgn_done: |
5874 | | /* should zeroize, since this function doesn't. */ |
5875 | 0 | PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); |
5876 | 0 | break; |
5877 | | |
5878 | 0 | case CKM_NSS_KYBER_KEY_PAIR_GEN: |
5879 | 0 | case CKM_NSS_ML_KEM_KEY_PAIR_GEN: |
5880 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
5881 | 0 | key_type = CKK_NSS_KYBER; |
5882 | |
|
5883 | 0 | SECItem privKey = { siBuffer, NULL, 0 }; |
5884 | 0 | SECItem pubKey = { siBuffer, NULL, 0 }; |
5885 | 0 | KyberParams kyberParams = sftk_kyber_PK11ParamToInternal(ckKyberParamSet); |
5886 | 0 | if (!sftk_kyber_AllocPrivKeyItem(kyberParams, &privKey)) { |
5887 | 0 | crv = CKR_HOST_MEMORY; |
5888 | 0 | goto kyber_done; |
5889 | 0 | } |
5890 | 0 | if (!sftk_kyber_AllocPubKeyItem(kyberParams, &pubKey)) { |
5891 | 0 | crv = CKR_HOST_MEMORY; |
5892 | 0 | goto kyber_done; |
5893 | 0 | } |
5894 | 0 | rv = Kyber_NewKey(kyberParams, NULL, &privKey, &pubKey); |
5895 | 0 | if (rv != SECSuccess) { |
5896 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5897 | 0 | goto kyber_done; |
5898 | 0 | } |
5899 | | |
5900 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, sftk_item_expand(&pubKey)); |
5901 | 0 | if (crv != CKR_OK) { |
5902 | 0 | goto kyber_done; |
5903 | 0 | } |
5904 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_NSS_PARAMETER_SET, |
5905 | 0 | &ckKyberParamSet, sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE)); |
5906 | 0 | if (crv != CKR_OK) { |
5907 | 0 | goto kyber_done; |
5908 | 0 | } |
5909 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
5910 | 0 | sftk_item_expand(&privKey)); |
5911 | 0 | if (crv != CKR_OK) { |
5912 | 0 | goto kyber_done; |
5913 | 0 | } |
5914 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_PARAMETER_SET, |
5915 | 0 | &ckKyberParamSet, sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE)); |
5916 | 0 | if (crv != CKR_OK) { |
5917 | 0 | goto kyber_done; |
5918 | 0 | } |
5919 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
5920 | 0 | sftk_item_expand(&pubKey)); |
5921 | 0 | kyber_done: |
5922 | 0 | SECITEM_ZfreeItem(&privKey, PR_FALSE); |
5923 | 0 | SECITEM_FreeItem(&pubKey, PR_FALSE); |
5924 | 0 | break; |
5925 | | |
5926 | 0 | case CKM_EC_MONTGOMERY_KEY_PAIR_GEN: |
5927 | 0 | case CKM_EC_EDWARDS_KEY_PAIR_GEN: |
5928 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS); |
5929 | 0 | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
5930 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
5931 | 0 | key_type = (pMechanism->mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN) ? CKK_EC_EDWARDS : CKK_EC_MONTGOMERY; |
5932 | | |
5933 | | /* extract the necessary parameters and copy them to private keys */ |
5934 | 0 | crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, |
5935 | 0 | CKA_EC_PARAMS); |
5936 | 0 | if (crv != CKR_OK) { |
5937 | 0 | break; |
5938 | 0 | } |
5939 | | |
5940 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS, |
5941 | 0 | sftk_item_expand(&ecEncodedParams)); |
5942 | 0 | if (crv != CKR_OK) { |
5943 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
5944 | 0 | break; |
5945 | 0 | } |
5946 | | |
5947 | | /* Decode ec params before calling EC_NewKey */ |
5948 | 0 | rv = EC_DecodeParams(&ecEncodedParams, &ecParams); |
5949 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
5950 | 0 | if (rv != SECSuccess) { |
5951 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5952 | 0 | break; |
5953 | 0 | } |
5954 | | |
5955 | 0 | rv = EC_NewKey(ecParams, &ecPriv); |
5956 | 0 | if (rv != SECSuccess) { |
5957 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
5958 | 0 | sftk_fatalError = PR_TRUE; |
5959 | 0 | } |
5960 | 0 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
5961 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
5962 | 0 | break; |
5963 | 0 | } |
5964 | 0 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
5965 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
5966 | 0 | sftk_item_expand(&ecPriv->publicValue)); |
5967 | 0 | if (crv != CKR_OK) |
5968 | 0 | goto edgn_done; |
5969 | | |
5970 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
5971 | 0 | sftk_item_expand(&ecPriv->privateValue)); |
5972 | 0 | if (crv != CKR_OK) |
5973 | 0 | goto edgn_done; |
5974 | | |
5975 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
5976 | 0 | sftk_item_expand(&ecPriv->publicValue)); |
5977 | 0 | edgn_done: |
5978 | | /* should zeroize, since this function doesn't. */ |
5979 | 0 | PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); |
5980 | 0 | break; |
5981 | | |
5982 | 0 | default: |
5983 | 0 | crv = CKR_MECHANISM_INVALID; |
5984 | 0 | } |
5985 | | |
5986 | 0 | if (crv != CKR_OK) { |
5987 | 0 | sftk_FreeObject(privateKey); |
5988 | 0 | sftk_FreeObject(publicKey); |
5989 | 0 | return crv; |
5990 | 0 | } |
5991 | | |
5992 | | /* Add the class, key_type The loop lets us check errors blow out |
5993 | | * on errors and clean up at the bottom */ |
5994 | 0 | session = NULL; /* make pedtantic happy... session cannot leave the*/ |
5995 | | /* loop below NULL unless an error is set... */ |
5996 | 0 | do { |
5997 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_CLASS, &privClass, |
5998 | 0 | sizeof(CK_OBJECT_CLASS)); |
5999 | 0 | if (crv != CKR_OK) |
6000 | 0 | break; |
6001 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &pubClass, |
6002 | 0 | sizeof(CK_OBJECT_CLASS)); |
6003 | 0 | if (crv != CKR_OK) |
6004 | 0 | break; |
6005 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_KEY_TYPE, &key_type, |
6006 | 0 | sizeof(CK_KEY_TYPE)); |
6007 | 0 | if (crv != CKR_OK) |
6008 | 0 | break; |
6009 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &key_type, |
6010 | 0 | sizeof(CK_KEY_TYPE)); |
6011 | 0 | if (crv != CKR_OK) |
6012 | 0 | break; |
6013 | 0 | session = sftk_SessionFromHandle(hSession); |
6014 | 0 | if (session == NULL) |
6015 | 0 | crv = CKR_SESSION_HANDLE_INVALID; |
6016 | 0 | } while (0); |
6017 | | |
6018 | 0 | if (crv != CKR_OK) { |
6019 | 0 | sftk_FreeObject(privateKey); |
6020 | 0 | sftk_FreeObject(publicKey); |
6021 | 0 | return crv; |
6022 | 0 | } |
6023 | | |
6024 | | /* |
6025 | | * handle the base object cleanup for the public Key |
6026 | | */ |
6027 | 0 | crv = sftk_handleObject(privateKey, session); |
6028 | 0 | if (crv != CKR_OK) { |
6029 | 0 | sftk_FreeSession(session); |
6030 | 0 | sftk_FreeObject(privateKey); |
6031 | 0 | sftk_FreeObject(publicKey); |
6032 | 0 | return crv; |
6033 | 0 | } |
6034 | | |
6035 | | /* |
6036 | | * handle the base object cleanup for the private Key |
6037 | | * If we have any problems, we destroy the public Key we've |
6038 | | * created and linked. |
6039 | | */ |
6040 | 0 | crv = sftk_handleObject(publicKey, session); |
6041 | 0 | sftk_FreeSession(session); |
6042 | 0 | if (crv != CKR_OK) { |
6043 | 0 | sftk_FreeObject(publicKey); |
6044 | 0 | NSC_DestroyObject(hSession, privateKey->handle); |
6045 | 0 | sftk_FreeObject(privateKey); |
6046 | 0 | return crv; |
6047 | 0 | } |
6048 | 0 | if (sftk_isTrue(privateKey, CKA_SENSITIVE)) { |
6049 | 0 | crv = sftk_forceAttribute(privateKey, CKA_ALWAYS_SENSITIVE, |
6050 | 0 | &cktrue, sizeof(CK_BBOOL)); |
6051 | 0 | } |
6052 | 0 | if (crv == CKR_OK && sftk_isTrue(publicKey, CKA_SENSITIVE)) { |
6053 | 0 | crv = sftk_forceAttribute(publicKey, CKA_ALWAYS_SENSITIVE, |
6054 | 0 | &cktrue, sizeof(CK_BBOOL)); |
6055 | 0 | } |
6056 | 0 | if (crv == CKR_OK && !sftk_isTrue(privateKey, CKA_EXTRACTABLE)) { |
6057 | 0 | crv = sftk_forceAttribute(privateKey, CKA_NEVER_EXTRACTABLE, |
6058 | 0 | &cktrue, sizeof(CK_BBOOL)); |
6059 | 0 | } |
6060 | 0 | if (crv == CKR_OK && !sftk_isTrue(publicKey, CKA_EXTRACTABLE)) { |
6061 | 0 | crv = sftk_forceAttribute(publicKey, CKA_NEVER_EXTRACTABLE, |
6062 | 0 | &cktrue, sizeof(CK_BBOOL)); |
6063 | 0 | } |
6064 | |
|
6065 | 0 | if (crv == CKR_OK && pMechanism->mechanism != CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN && key_type != CKK_NSS_KYBER) { |
6066 | | /* Perform FIPS 140-2 pairwise consistency check. */ |
6067 | 0 | crv = sftk_PairwiseConsistencyCheck(hSession, slot, |
6068 | 0 | publicKey, privateKey, key_type); |
6069 | 0 | if (crv != CKR_OK) { |
6070 | 0 | if (sftk_audit_enabled) { |
6071 | 0 | char msg[128]; |
6072 | 0 | PR_snprintf(msg, sizeof msg, |
6073 | 0 | "C_GenerateKeyPair(hSession=0x%08lX, " |
6074 | 0 | "pMechanism->mechanism=0x%08lX)=0x%08lX " |
6075 | 0 | "self-test: pair-wise consistency test failed", |
6076 | 0 | (PRUint32)hSession, (PRUint32)pMechanism->mechanism, |
6077 | 0 | (PRUint32)crv); |
6078 | 0 | sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg); |
6079 | 0 | } |
6080 | 0 | } |
6081 | 0 | } |
6082 | |
|
6083 | 0 | if (crv != CKR_OK) { |
6084 | 0 | NSC_DestroyObject(hSession, publicKey->handle); |
6085 | 0 | sftk_FreeObject(publicKey); |
6086 | 0 | NSC_DestroyObject(hSession, privateKey->handle); |
6087 | 0 | sftk_FreeObject(privateKey); |
6088 | 0 | return crv; |
6089 | 0 | } |
6090 | | |
6091 | 0 | *phPrivateKey = privateKey->handle; |
6092 | 0 | *phPublicKey = publicKey->handle; |
6093 | 0 | sftk_FreeObject(publicKey); |
6094 | 0 | sftk_FreeObject(privateKey); |
6095 | |
|
6096 | 0 | return CKR_OK; |
6097 | 0 | } |
6098 | | |
6099 | | static SECItem * |
6100 | | sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp) |
6101 | 0 | { |
6102 | 0 | NSSLOWKEYPrivateKey *lk = NULL; |
6103 | 0 | NSSLOWKEYPrivateKeyInfo *pki = NULL; |
6104 | 0 | SFTKAttribute *attribute = NULL; |
6105 | 0 | PLArenaPool *arena = NULL; |
6106 | 0 | SECOidTag algorithm = SEC_OID_UNKNOWN; |
6107 | 0 | void *dummy, *param = NULL; |
6108 | 0 | SECStatus rv = SECSuccess; |
6109 | 0 | SECItem *encodedKey = NULL; |
6110 | | #ifdef EC_DEBUG |
6111 | | SECItem *fordebug; |
6112 | | #endif |
6113 | 0 | int savelen; |
6114 | |
|
6115 | 0 | if (!key) { |
6116 | 0 | *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */ |
6117 | 0 | return NULL; |
6118 | 0 | } |
6119 | | |
6120 | 0 | attribute = sftk_FindAttribute(key, CKA_KEY_TYPE); |
6121 | 0 | if (!attribute) { |
6122 | 0 | *crvp = CKR_KEY_TYPE_INCONSISTENT; |
6123 | 0 | return NULL; |
6124 | 0 | } |
6125 | | |
6126 | 0 | lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp); |
6127 | 0 | sftk_FreeAttribute(attribute); |
6128 | 0 | if (!lk) { |
6129 | 0 | return NULL; |
6130 | 0 | } |
6131 | | |
6132 | 0 | arena = PORT_NewArena(2048); /* XXX different size? */ |
6133 | 0 | if (!arena) { |
6134 | 0 | *crvp = CKR_HOST_MEMORY; |
6135 | 0 | rv = SECFailure; |
6136 | 0 | goto loser; |
6137 | 0 | } |
6138 | | |
6139 | 0 | pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena, |
6140 | 0 | sizeof(NSSLOWKEYPrivateKeyInfo)); |
6141 | 0 | if (!pki) { |
6142 | 0 | *crvp = CKR_HOST_MEMORY; |
6143 | 0 | rv = SECFailure; |
6144 | 0 | goto loser; |
6145 | 0 | } |
6146 | 0 | pki->arena = arena; |
6147 | |
|
6148 | 0 | param = NULL; |
6149 | 0 | switch (lk->keyType) { |
6150 | 0 | case NSSLOWKEYRSAKey: |
6151 | 0 | prepare_low_rsa_priv_key_for_asn1(lk); |
6152 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6153 | 0 | nsslowkey_RSAPrivateKeyTemplate); |
6154 | | |
6155 | | /* determine RSA key type from the CKA_PUBLIC_KEY_INFO if present */ |
6156 | 0 | attribute = sftk_FindAttribute(key, CKA_PUBLIC_KEY_INFO); |
6157 | 0 | if (attribute) { |
6158 | 0 | NSSLOWKEYSubjectPublicKeyInfo *publicKeyInfo; |
6159 | 0 | SECItem spki; |
6160 | |
|
6161 | 0 | spki.data = attribute->attrib.pValue; |
6162 | 0 | spki.len = attribute->attrib.ulValueLen; |
6163 | |
|
6164 | 0 | publicKeyInfo = PORT_ArenaZAlloc(arena, |
6165 | 0 | sizeof(NSSLOWKEYSubjectPublicKeyInfo)); |
6166 | 0 | if (!publicKeyInfo) { |
6167 | 0 | sftk_FreeAttribute(attribute); |
6168 | 0 | *crvp = CKR_HOST_MEMORY; |
6169 | 0 | rv = SECFailure; |
6170 | 0 | goto loser; |
6171 | 0 | } |
6172 | 0 | rv = SEC_QuickDERDecodeItem(arena, publicKeyInfo, |
6173 | 0 | nsslowkey_SubjectPublicKeyInfoTemplate, |
6174 | 0 | &spki); |
6175 | 0 | if (rv != SECSuccess) { |
6176 | 0 | sftk_FreeAttribute(attribute); |
6177 | 0 | *crvp = CKR_KEY_TYPE_INCONSISTENT; |
6178 | 0 | goto loser; |
6179 | 0 | } |
6180 | 0 | algorithm = SECOID_GetAlgorithmTag(&publicKeyInfo->algorithm); |
6181 | 0 | if (algorithm != SEC_OID_PKCS1_RSA_ENCRYPTION && |
6182 | 0 | algorithm != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { |
6183 | 0 | sftk_FreeAttribute(attribute); |
6184 | 0 | rv = SECFailure; |
6185 | 0 | *crvp = CKR_KEY_TYPE_INCONSISTENT; |
6186 | 0 | goto loser; |
6187 | 0 | } |
6188 | 0 | param = SECITEM_DupItem(&publicKeyInfo->algorithm.parameters); |
6189 | 0 | if (!param) { |
6190 | 0 | sftk_FreeAttribute(attribute); |
6191 | 0 | rv = SECFailure; |
6192 | 0 | *crvp = CKR_HOST_MEMORY; |
6193 | 0 | goto loser; |
6194 | 0 | } |
6195 | 0 | sftk_FreeAttribute(attribute); |
6196 | 0 | } else { |
6197 | | /* default to PKCS #1 */ |
6198 | 0 | algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; |
6199 | 0 | } |
6200 | 0 | break; |
6201 | 0 | case NSSLOWKEYDSAKey: |
6202 | 0 | prepare_low_dsa_priv_key_export_for_asn1(lk); |
6203 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6204 | 0 | nsslowkey_DSAPrivateKeyExportTemplate); |
6205 | 0 | prepare_low_pqg_params_for_asn1(&lk->u.dsa.params); |
6206 | 0 | param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params), |
6207 | 0 | nsslowkey_PQGParamsTemplate); |
6208 | 0 | algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE; |
6209 | 0 | break; |
6210 | 0 | case NSSLOWKEYECKey: |
6211 | 0 | prepare_low_ec_priv_key_for_asn1(lk); |
6212 | | /* Public value is encoded as a bit string so adjust length |
6213 | | * to be in bits before ASN encoding and readjust |
6214 | | * immediately after. |
6215 | | * |
6216 | | * Since the SECG specification recommends not including the |
6217 | | * parameters as part of ECPrivateKey, we zero out the curveOID |
6218 | | * length before encoding and restore it later. |
6219 | | */ |
6220 | 0 | lk->u.ec.publicValue.len <<= 3; |
6221 | 0 | savelen = lk->u.ec.ecParams.curveOID.len; |
6222 | 0 | lk->u.ec.ecParams.curveOID.len = 0; |
6223 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6224 | 0 | nsslowkey_ECPrivateKeyTemplate); |
6225 | 0 | lk->u.ec.ecParams.curveOID.len = savelen; |
6226 | 0 | lk->u.ec.publicValue.len >>= 3; |
6227 | |
|
6228 | | #ifdef EC_DEBUG |
6229 | | fordebug = &pki->privateKey; |
6230 | | SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType, |
6231 | | fordebug); |
6232 | | #endif |
6233 | |
|
6234 | 0 | param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding); |
6235 | |
|
6236 | 0 | algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY; |
6237 | 0 | break; |
6238 | 0 | case NSSLOWKEYDHKey: |
6239 | 0 | default: |
6240 | 0 | dummy = NULL; |
6241 | 0 | break; |
6242 | 0 | } |
6243 | | |
6244 | 0 | if (!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) { |
6245 | 0 | *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
6246 | 0 | rv = SECFailure; |
6247 | 0 | goto loser; |
6248 | 0 | } |
6249 | | |
6250 | 0 | rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, |
6251 | 0 | (SECItem *)param); |
6252 | 0 | if (rv != SECSuccess) { |
6253 | 0 | *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
6254 | 0 | rv = SECFailure; |
6255 | 0 | goto loser; |
6256 | 0 | } |
6257 | | |
6258 | 0 | dummy = SEC_ASN1EncodeInteger(arena, &pki->version, |
6259 | 0 | NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); |
6260 | 0 | if (!dummy) { |
6261 | 0 | *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
6262 | 0 | rv = SECFailure; |
6263 | 0 | goto loser; |
6264 | 0 | } |
6265 | | |
6266 | 0 | encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, |
6267 | 0 | nsslowkey_PrivateKeyInfoTemplate); |
6268 | 0 | *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR; |
6269 | |
|
6270 | | #ifdef EC_DEBUG |
6271 | | fordebug = encodedKey; |
6272 | | SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType, |
6273 | | fordebug); |
6274 | | #endif |
6275 | 0 | loser: |
6276 | 0 | if (arena) { |
6277 | 0 | PORT_FreeArena(arena, PR_TRUE); |
6278 | 0 | } |
6279 | |
|
6280 | 0 | if (lk && (lk != key->objectInfo)) { |
6281 | 0 | nsslowkey_DestroyPrivateKey(lk); |
6282 | 0 | } |
6283 | |
|
6284 | 0 | if (param) { |
6285 | 0 | SECITEM_ZfreeItem((SECItem *)param, PR_TRUE); |
6286 | 0 | } |
6287 | |
|
6288 | 0 | if (rv != SECSuccess) { |
6289 | 0 | return NULL; |
6290 | 0 | } |
6291 | | |
6292 | 0 | return encodedKey; |
6293 | 0 | } |
6294 | | |
6295 | | /* it doesn't matter yet, since we colapse error conditions in the |
6296 | | * level above, but we really should map those few key error differences */ |
6297 | | static CK_RV |
6298 | | sftk_mapWrap(CK_RV crv) |
6299 | 0 | { |
6300 | 0 | switch (crv) { |
6301 | 0 | case CKR_ENCRYPTED_DATA_INVALID: |
6302 | 0 | crv = CKR_WRAPPED_KEY_INVALID; |
6303 | 0 | break; |
6304 | 0 | } |
6305 | 0 | return crv; |
6306 | 0 | } |
6307 | | |
6308 | | /* NSC_WrapKey wraps (i.e., encrypts) a key. */ |
6309 | | CK_RV |
6310 | | NSC_WrapKey(CK_SESSION_HANDLE hSession, |
6311 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, |
6312 | | CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, |
6313 | | CK_ULONG_PTR pulWrappedKeyLen) |
6314 | 0 | { |
6315 | 0 | SFTKSession *session; |
6316 | 0 | SFTKAttribute *attribute; |
6317 | 0 | SFTKObject *key; |
6318 | 0 | CK_RV crv; |
6319 | |
|
6320 | 0 | CHECK_FORK(); |
6321 | |
|
6322 | 0 | session = sftk_SessionFromHandle(hSession); |
6323 | 0 | if (session == NULL) { |
6324 | 0 | return CKR_SESSION_HANDLE_INVALID; |
6325 | 0 | } |
6326 | | |
6327 | 0 | key = sftk_ObjectFromHandle(hKey, session); |
6328 | 0 | if (key == NULL) { |
6329 | 0 | sftk_FreeSession(session); |
6330 | 0 | return CKR_KEY_HANDLE_INVALID; |
6331 | 0 | } |
6332 | | |
6333 | 0 | switch (key->objclass) { |
6334 | 0 | case CKO_SECRET_KEY: { |
6335 | 0 | SFTKSessionContext *context = NULL; |
6336 | 0 | SECItem pText; |
6337 | |
|
6338 | 0 | attribute = sftk_FindAttribute(key, CKA_VALUE); |
6339 | |
|
6340 | 0 | if (attribute == NULL) { |
6341 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
6342 | 0 | break; |
6343 | 0 | } |
6344 | 0 | crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, |
6345 | 0 | CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); |
6346 | 0 | if (crv != CKR_OK) { |
6347 | 0 | sftk_FreeAttribute(attribute); |
6348 | 0 | break; |
6349 | 0 | } |
6350 | | |
6351 | 0 | pText.type = siBuffer; |
6352 | 0 | pText.data = (unsigned char *)attribute->attrib.pValue; |
6353 | 0 | pText.len = attribute->attrib.ulValueLen; |
6354 | | |
6355 | | /* Find out if this is a block cipher. */ |
6356 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, NULL); |
6357 | 0 | if (crv != CKR_OK || !context) |
6358 | 0 | break; |
6359 | 0 | if (context->blockSize > 1) { |
6360 | 0 | unsigned int remainder = pText.len % context->blockSize; |
6361 | 0 | if (!context->doPad && remainder) { |
6362 | | /* When wrapping secret keys with unpadded block ciphers, |
6363 | | ** the keys are zero padded, if necessary, to fill out |
6364 | | ** a full block. |
6365 | | */ |
6366 | 0 | pText.len += context->blockSize - remainder; |
6367 | 0 | pText.data = PORT_ZAlloc(pText.len); |
6368 | 0 | if (pText.data) |
6369 | 0 | memcpy(pText.data, attribute->attrib.pValue, |
6370 | 0 | attribute->attrib.ulValueLen); |
6371 | 0 | else { |
6372 | 0 | crv = CKR_HOST_MEMORY; |
6373 | 0 | break; |
6374 | 0 | } |
6375 | 0 | } |
6376 | 0 | } |
6377 | | |
6378 | 0 | crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data, |
6379 | 0 | pText.len, pWrappedKey, pulWrappedKeyLen); |
6380 | | /* always force a finalize, both on errors and when |
6381 | | * we are just getting the size */ |
6382 | 0 | if (crv != CKR_OK || pWrappedKey == NULL) { |
6383 | 0 | CK_RV lcrv; |
6384 | 0 | lcrv = sftk_GetContext(hSession, &context, |
6385 | 0 | SFTK_ENCRYPT, PR_FALSE, NULL); |
6386 | 0 | sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); |
6387 | 0 | if (lcrv == CKR_OK && context) { |
6388 | 0 | sftk_FreeContext(context); |
6389 | 0 | } |
6390 | 0 | } |
6391 | |
|
6392 | 0 | if (pText.data != (unsigned char *)attribute->attrib.pValue) |
6393 | 0 | PORT_ZFree(pText.data, pText.len); |
6394 | 0 | sftk_FreeAttribute(attribute); |
6395 | 0 | break; |
6396 | 0 | } |
6397 | | |
6398 | 0 | case CKO_PRIVATE_KEY: { |
6399 | 0 | SECItem *bpki = sftk_PackagePrivateKey(key, &crv); |
6400 | 0 | SFTKSessionContext *context = NULL; |
6401 | |
|
6402 | 0 | if (!bpki) { |
6403 | 0 | break; |
6404 | 0 | } |
6405 | | |
6406 | 0 | crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, |
6407 | 0 | CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); |
6408 | 0 | if (crv != CKR_OK) { |
6409 | 0 | SECITEM_ZfreeItem(bpki, PR_TRUE); |
6410 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
6411 | 0 | break; |
6412 | 0 | } |
6413 | | |
6414 | 0 | crv = NSC_Encrypt(hSession, bpki->data, bpki->len, |
6415 | 0 | pWrappedKey, pulWrappedKeyLen); |
6416 | | /* always force a finalize */ |
6417 | 0 | if (crv != CKR_OK || pWrappedKey == NULL) { |
6418 | 0 | CK_RV lcrv; |
6419 | 0 | lcrv = sftk_GetContext(hSession, &context, |
6420 | 0 | SFTK_ENCRYPT, PR_FALSE, NULL); |
6421 | 0 | sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); |
6422 | 0 | if (lcrv == CKR_OK && context) { |
6423 | 0 | sftk_FreeContext(context); |
6424 | 0 | } |
6425 | 0 | } |
6426 | 0 | SECITEM_ZfreeItem(bpki, PR_TRUE); |
6427 | 0 | break; |
6428 | 0 | } |
6429 | | |
6430 | 0 | default: |
6431 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
6432 | 0 | break; |
6433 | 0 | } |
6434 | 0 | sftk_FreeObject(key); |
6435 | 0 | sftk_FreeSession(session); |
6436 | 0 | return sftk_mapWrap(crv); |
6437 | 0 | } |
6438 | | |
6439 | | /* |
6440 | | * import a pprivate key info into the desired slot |
6441 | | */ |
6442 | | static SECStatus |
6443 | | sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) |
6444 | 0 | { |
6445 | 0 | CK_BBOOL cktrue = CK_TRUE; |
6446 | 0 | CK_KEY_TYPE keyType = CKK_RSA; |
6447 | 0 | SECStatus rv = SECFailure; |
6448 | 0 | const SEC_ASN1Template *keyTemplate, *paramTemplate; |
6449 | 0 | void *paramDest = NULL; |
6450 | 0 | PLArenaPool *arena; |
6451 | 0 | NSSLOWKEYPrivateKey *lpk = NULL; |
6452 | 0 | NSSLOWKEYPrivateKeyInfo *pki = NULL; |
6453 | 0 | CK_RV crv = CKR_KEY_TYPE_INCONSISTENT; |
6454 | |
|
6455 | 0 | arena = PORT_NewArena(2048); |
6456 | 0 | if (!arena) { |
6457 | 0 | return SECFailure; |
6458 | 0 | } |
6459 | | |
6460 | 0 | pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena, |
6461 | 0 | sizeof(NSSLOWKEYPrivateKeyInfo)); |
6462 | 0 | if (!pki) { |
6463 | 0 | PORT_FreeArena(arena, PR_FALSE); |
6464 | 0 | return SECFailure; |
6465 | 0 | } |
6466 | | |
6467 | 0 | if (SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) != SECSuccess) { |
6468 | 0 | PORT_FreeArena(arena, PR_TRUE); |
6469 | 0 | return SECFailure; |
6470 | 0 | } |
6471 | | |
6472 | 0 | lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena, |
6473 | 0 | sizeof(NSSLOWKEYPrivateKey)); |
6474 | 0 | if (lpk == NULL) { |
6475 | 0 | goto loser; |
6476 | 0 | } |
6477 | 0 | lpk->arena = arena; |
6478 | |
|
6479 | 0 | switch (SECOID_GetAlgorithmTag(&pki->algorithm)) { |
6480 | 0 | case SEC_OID_PKCS1_RSA_ENCRYPTION: |
6481 | 0 | case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: |
6482 | 0 | keyTemplate = nsslowkey_RSAPrivateKeyTemplate; |
6483 | 0 | paramTemplate = NULL; |
6484 | 0 | paramDest = NULL; |
6485 | 0 | lpk->keyType = NSSLOWKEYRSAKey; |
6486 | 0 | prepare_low_rsa_priv_key_for_asn1(lpk); |
6487 | 0 | break; |
6488 | 0 | case SEC_OID_ANSIX9_DSA_SIGNATURE: |
6489 | 0 | keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate; |
6490 | 0 | paramTemplate = nsslowkey_PQGParamsTemplate; |
6491 | 0 | paramDest = &(lpk->u.dsa.params); |
6492 | 0 | lpk->keyType = NSSLOWKEYDSAKey; |
6493 | 0 | prepare_low_dsa_priv_key_export_for_asn1(lpk); |
6494 | 0 | prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params); |
6495 | 0 | break; |
6496 | | /* case NSSLOWKEYDHKey: */ |
6497 | 0 | case SEC_OID_ANSIX962_EC_PUBLIC_KEY: |
6498 | 0 | keyTemplate = nsslowkey_ECPrivateKeyTemplate; |
6499 | 0 | paramTemplate = NULL; |
6500 | 0 | paramDest = &(lpk->u.ec.ecParams.DEREncoding); |
6501 | 0 | lpk->keyType = NSSLOWKEYECKey; |
6502 | 0 | prepare_low_ec_priv_key_for_asn1(lpk); |
6503 | 0 | prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams); |
6504 | 0 | break; |
6505 | 0 | default: |
6506 | 0 | keyTemplate = NULL; |
6507 | 0 | paramTemplate = NULL; |
6508 | 0 | paramDest = NULL; |
6509 | 0 | break; |
6510 | 0 | } |
6511 | | |
6512 | 0 | if (!keyTemplate) { |
6513 | 0 | goto loser; |
6514 | 0 | } |
6515 | | |
6516 | | /* decode the private key and any algorithm parameters */ |
6517 | 0 | rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey); |
6518 | |
|
6519 | 0 | if (lpk->keyType == NSSLOWKEYECKey) { |
6520 | | /* convert length in bits to length in bytes */ |
6521 | 0 | lpk->u.ec.publicValue.len >>= 3; |
6522 | 0 | rv = SECITEM_CopyItem(arena, |
6523 | 0 | &(lpk->u.ec.ecParams.DEREncoding), |
6524 | 0 | &(pki->algorithm.parameters)); |
6525 | 0 | if (rv != SECSuccess) { |
6526 | 0 | goto loser; |
6527 | 0 | } |
6528 | 0 | } |
6529 | | |
6530 | 0 | if (rv != SECSuccess) { |
6531 | 0 | goto loser; |
6532 | 0 | } |
6533 | 0 | if (paramDest && paramTemplate) { |
6534 | 0 | rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate, |
6535 | 0 | &(pki->algorithm.parameters)); |
6536 | 0 | if (rv != SECSuccess) { |
6537 | 0 | goto loser; |
6538 | 0 | } |
6539 | 0 | } |
6540 | | |
6541 | 0 | rv = SECFailure; |
6542 | |
|
6543 | 0 | switch (lpk->keyType) { |
6544 | 0 | case NSSLOWKEYRSAKey: |
6545 | 0 | keyType = CKK_RSA; |
6546 | 0 | if (sftk_hasAttribute(key, CKA_NSS_DB)) { |
6547 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_DB); |
6548 | 0 | } |
6549 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
6550 | 0 | sizeof(keyType)); |
6551 | 0 | if (crv != CKR_OK) |
6552 | 0 | break; |
6553 | 0 | crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue, |
6554 | 0 | sizeof(CK_BBOOL)); |
6555 | 0 | if (crv != CKR_OK) |
6556 | 0 | break; |
6557 | 0 | crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue, |
6558 | 0 | sizeof(CK_BBOOL)); |
6559 | 0 | if (crv != CKR_OK) |
6560 | 0 | break; |
6561 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
6562 | 0 | sizeof(CK_BBOOL)); |
6563 | 0 | if (crv != CKR_OK) |
6564 | 0 | break; |
6565 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, |
6566 | 0 | sizeof(CK_BBOOL)); |
6567 | 0 | if (crv != CKR_OK) |
6568 | 0 | break; |
6569 | 0 | crv = sftk_AddAttributeType(key, CKA_MODULUS, |
6570 | 0 | sftk_item_expand(&lpk->u.rsa.modulus)); |
6571 | 0 | if (crv != CKR_OK) |
6572 | 0 | break; |
6573 | 0 | crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT, |
6574 | 0 | sftk_item_expand(&lpk->u.rsa.publicExponent)); |
6575 | 0 | if (crv != CKR_OK) |
6576 | 0 | break; |
6577 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT, |
6578 | 0 | sftk_item_expand(&lpk->u.rsa.privateExponent)); |
6579 | 0 | if (crv != CKR_OK) |
6580 | 0 | break; |
6581 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME_1, |
6582 | 0 | sftk_item_expand(&lpk->u.rsa.prime1)); |
6583 | 0 | if (crv != CKR_OK) |
6584 | 0 | break; |
6585 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME_2, |
6586 | 0 | sftk_item_expand(&lpk->u.rsa.prime2)); |
6587 | 0 | if (crv != CKR_OK) |
6588 | 0 | break; |
6589 | 0 | crv = sftk_AddAttributeType(key, CKA_EXPONENT_1, |
6590 | 0 | sftk_item_expand(&lpk->u.rsa.exponent1)); |
6591 | 0 | if (crv != CKR_OK) |
6592 | 0 | break; |
6593 | 0 | crv = sftk_AddAttributeType(key, CKA_EXPONENT_2, |
6594 | 0 | sftk_item_expand(&lpk->u.rsa.exponent2)); |
6595 | 0 | if (crv != CKR_OK) |
6596 | 0 | break; |
6597 | 0 | crv = sftk_AddAttributeType(key, CKA_COEFFICIENT, |
6598 | 0 | sftk_item_expand(&lpk->u.rsa.coefficient)); |
6599 | 0 | break; |
6600 | 0 | case NSSLOWKEYDSAKey: |
6601 | 0 | keyType = CKK_DSA; |
6602 | 0 | crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT; |
6603 | 0 | if (crv != CKR_OK) |
6604 | 0 | break; |
6605 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
6606 | 0 | sizeof(keyType)); |
6607 | 0 | if (crv != CKR_OK) |
6608 | 0 | break; |
6609 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
6610 | 0 | sizeof(CK_BBOOL)); |
6611 | 0 | if (crv != CKR_OK) |
6612 | 0 | break; |
6613 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, |
6614 | 0 | sizeof(CK_BBOOL)); |
6615 | 0 | if (crv != CKR_OK) |
6616 | 0 | break; |
6617 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME, |
6618 | 0 | sftk_item_expand(&lpk->u.dsa.params.prime)); |
6619 | 0 | if (crv != CKR_OK) |
6620 | 0 | break; |
6621 | 0 | crv = sftk_AddAttributeType(key, CKA_SUBPRIME, |
6622 | 0 | sftk_item_expand(&lpk->u.dsa.params.subPrime)); |
6623 | 0 | if (crv != CKR_OK) |
6624 | 0 | break; |
6625 | 0 | crv = sftk_AddAttributeType(key, CKA_BASE, |
6626 | 0 | sftk_item_expand(&lpk->u.dsa.params.base)); |
6627 | 0 | if (crv != CKR_OK) |
6628 | 0 | break; |
6629 | 0 | crv = sftk_AddAttributeType(key, CKA_VALUE, |
6630 | 0 | sftk_item_expand(&lpk->u.dsa.privateValue)); |
6631 | 0 | if (crv != CKR_OK) |
6632 | 0 | break; |
6633 | 0 | break; |
6634 | | #ifdef notdef |
6635 | | case NSSLOWKEYDHKey: |
6636 | | template = dhTemplate; |
6637 | | templateCount = sizeof(dhTemplate) / sizeof(CK_ATTRIBUTE); |
6638 | | keyType = CKK_DH; |
6639 | | break; |
6640 | | #endif |
6641 | | /* what about fortezza??? */ |
6642 | 0 | case NSSLOWKEYECKey: |
6643 | 0 | keyType = CKK_EC; |
6644 | 0 | crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT; |
6645 | 0 | if (crv != CKR_OK) |
6646 | 0 | break; |
6647 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
6648 | 0 | sizeof(keyType)); |
6649 | 0 | if (crv != CKR_OK) |
6650 | 0 | break; |
6651 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
6652 | 0 | sizeof(CK_BBOOL)); |
6653 | 0 | if (crv != CKR_OK) |
6654 | 0 | break; |
6655 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, |
6656 | 0 | sizeof(CK_BBOOL)); |
6657 | 0 | if (crv != CKR_OK) |
6658 | 0 | break; |
6659 | 0 | crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue, |
6660 | 0 | sizeof(CK_BBOOL)); |
6661 | 0 | if (crv != CKR_OK) |
6662 | 0 | break; |
6663 | 0 | crv = sftk_AddAttributeType(key, CKA_EC_PARAMS, |
6664 | 0 | sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding)); |
6665 | 0 | if (crv != CKR_OK) |
6666 | 0 | break; |
6667 | 0 | crv = sftk_AddAttributeType(key, CKA_VALUE, |
6668 | 0 | sftk_item_expand(&lpk->u.ec.privateValue)); |
6669 | 0 | if (crv != CKR_OK) |
6670 | 0 | break; |
6671 | | /* XXX Do we need to decode the EC Params here ?? */ |
6672 | 0 | break; |
6673 | 0 | default: |
6674 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
6675 | 0 | break; |
6676 | 0 | } |
6677 | | |
6678 | 0 | if (crv != CKR_OK) { |
6679 | 0 | goto loser; |
6680 | 0 | } |
6681 | | |
6682 | | /* For RSA-PSS, record the original algorithm parameters so |
6683 | | * they can be encrypted altoghether when wrapping */ |
6684 | 0 | if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { |
6685 | 0 | NSSLOWKEYSubjectPublicKeyInfo spki; |
6686 | 0 | NSSLOWKEYPublicKey pubk; |
6687 | 0 | SECItem *publicKeyInfo; |
6688 | |
|
6689 | 0 | memset(&spki, 0, sizeof(NSSLOWKEYSubjectPublicKeyInfo)); |
6690 | 0 | rv = SECOID_CopyAlgorithmID(arena, &spki.algorithm, &pki->algorithm); |
6691 | 0 | if (rv != SECSuccess) { |
6692 | 0 | crv = CKR_HOST_MEMORY; |
6693 | 0 | goto loser; |
6694 | 0 | } |
6695 | | |
6696 | 0 | prepare_low_rsa_pub_key_for_asn1(&pubk); |
6697 | |
|
6698 | 0 | rv = SECITEM_CopyItem(arena, &pubk.u.rsa.modulus, &lpk->u.rsa.modulus); |
6699 | 0 | if (rv != SECSuccess) { |
6700 | 0 | crv = CKR_HOST_MEMORY; |
6701 | 0 | goto loser; |
6702 | 0 | } |
6703 | 0 | rv = SECITEM_CopyItem(arena, &pubk.u.rsa.publicExponent, &lpk->u.rsa.publicExponent); |
6704 | 0 | if (rv != SECSuccess) { |
6705 | 0 | crv = CKR_HOST_MEMORY; |
6706 | 0 | goto loser; |
6707 | 0 | } |
6708 | | |
6709 | 0 | if (SEC_ASN1EncodeItem(arena, &spki.subjectPublicKey, |
6710 | 0 | &pubk, nsslowkey_RSAPublicKeyTemplate) == NULL) { |
6711 | 0 | crv = CKR_HOST_MEMORY; |
6712 | 0 | goto loser; |
6713 | 0 | } |
6714 | | |
6715 | 0 | publicKeyInfo = SEC_ASN1EncodeItem(arena, NULL, |
6716 | 0 | &spki, nsslowkey_SubjectPublicKeyInfoTemplate); |
6717 | 0 | if (!publicKeyInfo) { |
6718 | 0 | crv = CKR_HOST_MEMORY; |
6719 | 0 | goto loser; |
6720 | 0 | } |
6721 | 0 | crv = sftk_AddAttributeType(key, CKA_PUBLIC_KEY_INFO, |
6722 | 0 | sftk_item_expand(publicKeyInfo)); |
6723 | 0 | } |
6724 | | |
6725 | 0 | loser: |
6726 | 0 | if (lpk) { |
6727 | 0 | nsslowkey_DestroyPrivateKey(lpk); |
6728 | 0 | } |
6729 | |
|
6730 | 0 | if (crv != CKR_OK) { |
6731 | 0 | return SECFailure; |
6732 | 0 | } |
6733 | | |
6734 | 0 | return SECSuccess; |
6735 | 0 | } |
6736 | | |
6737 | | /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */ |
6738 | | CK_RV |
6739 | | NSC_UnwrapKey(CK_SESSION_HANDLE hSession, |
6740 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, |
6741 | | CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, |
6742 | | CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, |
6743 | | CK_OBJECT_HANDLE_PTR phKey) |
6744 | 0 | { |
6745 | 0 | SFTKObject *key = NULL; |
6746 | 0 | SFTKSession *session; |
6747 | 0 | CK_ULONG key_length = 0; |
6748 | 0 | unsigned char *buf = NULL; |
6749 | 0 | CK_RV crv = CKR_OK; |
6750 | 0 | int i; |
6751 | 0 | CK_ULONG bsize = ulWrappedKeyLen; |
6752 | 0 | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
6753 | 0 | SECItem bpki; |
6754 | 0 | CK_OBJECT_CLASS target_type = CKO_SECRET_KEY; |
6755 | |
|
6756 | 0 | CHECK_FORK(); |
6757 | |
|
6758 | 0 | if (!slot) { |
6759 | 0 | return CKR_SESSION_HANDLE_INVALID; |
6760 | 0 | } |
6761 | | /* |
6762 | | * now lets create an object to hang the attributes off of |
6763 | | */ |
6764 | 0 | key = sftk_NewObject(slot); /* fill in the handle later */ |
6765 | 0 | if (key == NULL) { |
6766 | 0 | return CKR_HOST_MEMORY; |
6767 | 0 | } |
6768 | | |
6769 | | /* |
6770 | | * load the template values into the object |
6771 | | */ |
6772 | 0 | for (i = 0; i < (int)ulAttributeCount; i++) { |
6773 | 0 | if (pTemplate[i].type == CKA_VALUE_LEN) { |
6774 | 0 | key_length = *(CK_ULONG *)pTemplate[i].pValue; |
6775 | 0 | continue; |
6776 | 0 | } |
6777 | 0 | if (pTemplate[i].type == CKA_CLASS) { |
6778 | 0 | target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; |
6779 | 0 | } |
6780 | 0 | crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); |
6781 | 0 | if (crv != CKR_OK) |
6782 | 0 | break; |
6783 | 0 | } |
6784 | 0 | if (crv != CKR_OK) { |
6785 | 0 | sftk_FreeObject(key); |
6786 | 0 | return crv; |
6787 | 0 | } |
6788 | | |
6789 | 0 | crv = sftk_CryptInit(hSession, pMechanism, hUnwrappingKey, CKA_UNWRAP, |
6790 | 0 | CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE); |
6791 | 0 | if (crv != CKR_OK) { |
6792 | 0 | sftk_FreeObject(key); |
6793 | 0 | return sftk_mapWrap(crv); |
6794 | 0 | } |
6795 | | |
6796 | | /* allocate the buffer to decrypt into |
6797 | | * this assumes the unwrapped key is never larger than the |
6798 | | * wrapped key. For all the mechanisms we support this is true */ |
6799 | 0 | buf = (unsigned char *)PORT_Alloc(ulWrappedKeyLen); |
6800 | 0 | bsize = ulWrappedKeyLen; |
6801 | |
|
6802 | 0 | crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize); |
6803 | 0 | if (crv != CKR_OK) { |
6804 | 0 | sftk_FreeObject(key); |
6805 | 0 | PORT_Free(buf); |
6806 | 0 | return sftk_mapWrap(crv); |
6807 | 0 | } |
6808 | | |
6809 | 0 | switch (target_type) { |
6810 | 0 | case CKO_SECRET_KEY: |
6811 | 0 | if (!sftk_hasAttribute(key, CKA_KEY_TYPE)) { |
6812 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6813 | 0 | break; |
6814 | 0 | } |
6815 | | |
6816 | 0 | if (key_length == 0 || key_length > bsize) { |
6817 | 0 | key_length = bsize; |
6818 | 0 | } |
6819 | 0 | if (key_length > MAX_KEY_LEN) { |
6820 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
6821 | 0 | break; |
6822 | 0 | } |
6823 | | |
6824 | | /* add the value */ |
6825 | 0 | crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length); |
6826 | 0 | break; |
6827 | 0 | case CKO_PRIVATE_KEY: |
6828 | 0 | bpki.data = (unsigned char *)buf; |
6829 | 0 | bpki.len = bsize; |
6830 | 0 | crv = CKR_OK; |
6831 | 0 | if (sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) { |
6832 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6833 | 0 | } |
6834 | 0 | break; |
6835 | 0 | default: |
6836 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
6837 | 0 | break; |
6838 | 0 | } |
6839 | | |
6840 | 0 | PORT_ZFree(buf, bsize); |
6841 | 0 | if (crv != CKR_OK) { |
6842 | 0 | sftk_FreeObject(key); |
6843 | 0 | return crv; |
6844 | 0 | } |
6845 | | |
6846 | | /* get the session */ |
6847 | 0 | session = sftk_SessionFromHandle(hSession); |
6848 | 0 | if (session == NULL) { |
6849 | 0 | sftk_FreeObject(key); |
6850 | 0 | return CKR_SESSION_HANDLE_INVALID; |
6851 | 0 | } |
6852 | | |
6853 | | /* mark the key as FIPS if the previous operation was all FIPS */ |
6854 | 0 | key->isFIPS = session->lastOpWasFIPS; |
6855 | | |
6856 | | /* |
6857 | | * handle the base object stuff |
6858 | | */ |
6859 | 0 | crv = sftk_handleObject(key, session); |
6860 | 0 | *phKey = key->handle; |
6861 | 0 | sftk_FreeSession(session); |
6862 | 0 | sftk_FreeObject(key); |
6863 | |
|
6864 | 0 | return crv; |
6865 | 0 | } |
6866 | | |
6867 | | /* |
6868 | | * The SSL key gen mechanism create's lots of keys. This function handles the |
6869 | | * details of each of these key creation. |
6870 | | */ |
6871 | | static CK_RV |
6872 | | sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey, |
6873 | | PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize, |
6874 | | CK_OBJECT_HANDLE *keyHandle) |
6875 | 0 | { |
6876 | 0 | SFTKObject *key; |
6877 | 0 | SFTKSession *session; |
6878 | 0 | CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
6879 | 0 | CK_BBOOL cktrue = CK_TRUE; |
6880 | 0 | CK_BBOOL ckfalse = CK_FALSE; |
6881 | 0 | CK_RV crv = CKR_HOST_MEMORY; |
6882 | | |
6883 | | /* |
6884 | | * now lets create an object to hang the attributes off of |
6885 | | */ |
6886 | 0 | *keyHandle = CK_INVALID_HANDLE; |
6887 | 0 | key = sftk_NewObject(baseKey->slot); |
6888 | 0 | if (key == NULL) |
6889 | 0 | return CKR_HOST_MEMORY; |
6890 | 0 | sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE; |
6891 | |
|
6892 | 0 | crv = sftk_CopyObject(key, baseKey); |
6893 | 0 | if (crv != CKR_OK) |
6894 | 0 | goto loser; |
6895 | 0 | if (isMacKey) { |
6896 | 0 | crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType)); |
6897 | 0 | if (crv != CKR_OK) |
6898 | 0 | goto loser; |
6899 | 0 | crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); |
6900 | 0 | if (crv != CKR_OK) |
6901 | 0 | goto loser; |
6902 | 0 | crv = sftk_forceAttribute(key, CKA_ENCRYPT, &ckfalse, sizeof(CK_BBOOL)); |
6903 | 0 | if (crv != CKR_OK) |
6904 | 0 | goto loser; |
6905 | 0 | crv = sftk_forceAttribute(key, CKA_DECRYPT, &ckfalse, sizeof(CK_BBOOL)); |
6906 | 0 | if (crv != CKR_OK) |
6907 | 0 | goto loser; |
6908 | 0 | crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); |
6909 | 0 | if (crv != CKR_OK) |
6910 | 0 | goto loser; |
6911 | 0 | crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); |
6912 | 0 | if (crv != CKR_OK) |
6913 | 0 | goto loser; |
6914 | 0 | crv = sftk_forceAttribute(key, CKA_WRAP, &ckfalse, sizeof(CK_BBOOL)); |
6915 | 0 | if (crv != CKR_OK) |
6916 | 0 | goto loser; |
6917 | 0 | crv = sftk_forceAttribute(key, CKA_UNWRAP, &ckfalse, sizeof(CK_BBOOL)); |
6918 | 0 | if (crv != CKR_OK) |
6919 | 0 | goto loser; |
6920 | 0 | } |
6921 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, keyBlock, keySize); |
6922 | 0 | if (crv != CKR_OK) |
6923 | 0 | goto loser; |
6924 | | |
6925 | | /* get the session */ |
6926 | 0 | crv = CKR_HOST_MEMORY; |
6927 | 0 | session = sftk_SessionFromHandle(hSession); |
6928 | 0 | if (session == NULL) { |
6929 | 0 | goto loser; |
6930 | 0 | } |
6931 | | |
6932 | 0 | crv = sftk_handleObject(key, session); |
6933 | 0 | sftk_FreeSession(session); |
6934 | 0 | *keyHandle = key->handle; |
6935 | 0 | loser: |
6936 | 0 | if (key) |
6937 | 0 | sftk_FreeObject(key); |
6938 | 0 | return crv; |
6939 | 0 | } |
6940 | | |
6941 | | /* |
6942 | | * if there is an error, we need to free the keys we already created in SSL |
6943 | | * This is the routine that will do it.. |
6944 | | */ |
6945 | | static void |
6946 | | sftk_freeSSLKeys(CK_SESSION_HANDLE session, |
6947 | | CK_SSL3_KEY_MAT_OUT *returnedMaterial) |
6948 | 0 | { |
6949 | 0 | if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) { |
6950 | 0 | NSC_DestroyObject(session, returnedMaterial->hClientMacSecret); |
6951 | 0 | } |
6952 | 0 | if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) { |
6953 | 0 | NSC_DestroyObject(session, returnedMaterial->hServerMacSecret); |
6954 | 0 | } |
6955 | 0 | if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) { |
6956 | 0 | NSC_DestroyObject(session, returnedMaterial->hClientKey); |
6957 | 0 | } |
6958 | 0 | if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) { |
6959 | 0 | NSC_DestroyObject(session, returnedMaterial->hServerKey); |
6960 | 0 | } |
6961 | 0 | } |
6962 | | |
6963 | | /* |
6964 | | * when deriving from sensitive and extractable keys, we need to preserve some |
6965 | | * of the semantics in the derived key. This helper routine maintains these |
6966 | | * semantics. |
6967 | | */ |
6968 | | static CK_RV |
6969 | | sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey, |
6970 | | PRBool canBeData) |
6971 | 43 | { |
6972 | 43 | PRBool hasSensitive; |
6973 | 43 | PRBool sensitive = PR_FALSE; |
6974 | 43 | CK_BBOOL bFalse = CK_FALSE; |
6975 | 43 | PRBool hasExtractable; |
6976 | 43 | PRBool extractable = PR_TRUE; |
6977 | 43 | CK_BBOOL bTrue = CK_TRUE; |
6978 | 43 | CK_RV crv = CKR_OK; |
6979 | 43 | SFTKAttribute *att; |
6980 | 43 | PRBool isData = PR_TRUE; |
6981 | | |
6982 | 43 | if (canBeData) { |
6983 | 0 | CK_OBJECT_CLASS objClass; |
6984 | | |
6985 | | /* if the target key is actually data, don't set the unexpected |
6986 | | * attributes */ |
6987 | 0 | crv = sftk_GetULongAttribute(destKey, CKA_CLASS, &objClass); |
6988 | 0 | if (crv != CKR_OK) { |
6989 | 0 | return crv; |
6990 | 0 | } |
6991 | 0 | if (objClass == CKO_DATA) { |
6992 | 0 | return CKR_OK; |
6993 | 0 | } |
6994 | | |
6995 | | /* if the base key is data, it doesn't have sensitive attributes, |
6996 | | * allow the destKey to get it's own */ |
6997 | 0 | crv = sftk_GetULongAttribute(baseKey, CKA_CLASS, &objClass); |
6998 | 0 | if (crv != CKR_OK) { |
6999 | 0 | return crv; |
7000 | 0 | } |
7001 | 0 | if (objClass == CKO_DATA) { |
7002 | 0 | isData = PR_TRUE; |
7003 | 0 | } |
7004 | 0 | } |
7005 | | |
7006 | 43 | hasSensitive = PR_FALSE; |
7007 | 43 | att = sftk_FindAttribute(destKey, CKA_SENSITIVE); |
7008 | 43 | if (att) { |
7009 | 0 | hasSensitive = PR_TRUE; |
7010 | 0 | sensitive = (PRBool) * (CK_BBOOL *)att->attrib.pValue; |
7011 | 0 | sftk_FreeAttribute(att); |
7012 | 0 | } |
7013 | | |
7014 | 43 | hasExtractable = PR_FALSE; |
7015 | 43 | att = sftk_FindAttribute(destKey, CKA_EXTRACTABLE); |
7016 | 43 | if (att) { |
7017 | 0 | hasExtractable = PR_TRUE; |
7018 | 0 | extractable = (PRBool) * (CK_BBOOL *)att->attrib.pValue; |
7019 | 0 | sftk_FreeAttribute(att); |
7020 | 0 | } |
7021 | | |
7022 | | /* don't make a key more accessible */ |
7023 | 43 | if (sftk_isTrue(baseKey, CKA_SENSITIVE) && hasSensitive && |
7024 | 43 | (sensitive == PR_FALSE)) { |
7025 | 0 | return CKR_KEY_FUNCTION_NOT_PERMITTED; |
7026 | 0 | } |
7027 | 43 | if (!sftk_isTrue(baseKey, CKA_EXTRACTABLE) && hasExtractable && |
7028 | 43 | (extractable == PR_TRUE)) { |
7029 | 0 | return CKR_KEY_FUNCTION_NOT_PERMITTED; |
7030 | 0 | } |
7031 | | |
7032 | | /* inherit parent's sensitivity */ |
7033 | 43 | if (!hasSensitive) { |
7034 | 43 | att = sftk_FindAttribute(baseKey, CKA_SENSITIVE); |
7035 | 43 | if (att != NULL) { |
7036 | 43 | crv = sftk_defaultAttribute(destKey, |
7037 | 43 | sftk_attr_expand(&att->attrib)); |
7038 | 43 | sftk_FreeAttribute(att); |
7039 | 43 | } else if (isData) { |
7040 | 0 | crv = sftk_defaultAttribute(destKey, CKA_SENSITIVE, |
7041 | 0 | &bFalse, sizeof(bFalse)); |
7042 | 0 | } else { |
7043 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
7044 | 0 | } |
7045 | 43 | if (crv != CKR_OK) |
7046 | 0 | return crv; |
7047 | 43 | } |
7048 | 43 | if (!hasExtractable) { |
7049 | 43 | att = sftk_FindAttribute(baseKey, CKA_EXTRACTABLE); |
7050 | 43 | if (att != NULL) { |
7051 | 43 | crv = sftk_defaultAttribute(destKey, |
7052 | 43 | sftk_attr_expand(&att->attrib)); |
7053 | 43 | sftk_FreeAttribute(att); |
7054 | 43 | } else if (isData) { |
7055 | 0 | crv = sftk_defaultAttribute(destKey, CKA_EXTRACTABLE, |
7056 | 0 | &bTrue, sizeof(bTrue)); |
7057 | 0 | } else { |
7058 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
7059 | 0 | } |
7060 | 43 | if (crv != CKR_OK) |
7061 | 0 | return crv; |
7062 | 43 | } |
7063 | | |
7064 | | /* we should inherit the parent's always extractable/ never sensitive info, |
7065 | | * but handleObject always forces this attributes, so we would need to do |
7066 | | * something special. */ |
7067 | 43 | return CKR_OK; |
7068 | 43 | } |
7069 | | |
7070 | | /* |
7071 | | * make known fixed PKCS #11 key types to their sizes in bytes |
7072 | | */ |
7073 | | unsigned long |
7074 | | sftk_MapKeySize(CK_KEY_TYPE keyType) |
7075 | 9 | { |
7076 | 9 | switch (keyType) { |
7077 | 0 | case CKK_CDMF: |
7078 | 0 | return 8; |
7079 | 9 | case CKK_DES: |
7080 | 9 | return 8; |
7081 | 0 | case CKK_DES2: |
7082 | 0 | return 16; |
7083 | 0 | case CKK_DES3: |
7084 | 0 | return 24; |
7085 | | /* IDEA and CAST need to be added */ |
7086 | 0 | default: |
7087 | 0 | break; |
7088 | 9 | } |
7089 | 0 | return 0; |
7090 | 9 | } |
7091 | | |
7092 | | /* Inputs: |
7093 | | * key_len: Length of derived key to be generated. |
7094 | | * SharedSecret: a shared secret that is the output of a key agreement primitive. |
7095 | | * SharedInfo: (Optional) some data shared by the entities computing the secret key. |
7096 | | * SharedInfoLen: the length in octets of SharedInfo |
7097 | | * Hash: The hash function to be used in the KDF |
7098 | | * HashLen: the length in octets of the output of Hash |
7099 | | * Output: |
7100 | | * key: Pointer to a buffer containing derived key, if return value is SECSuccess. |
7101 | | */ |
7102 | | static CK_RV |
7103 | | sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret, |
7104 | | CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, |
7105 | | SECStatus Hash(unsigned char *, const unsigned char *, PRUint32), |
7106 | | CK_ULONG HashLen) |
7107 | 0 | { |
7108 | 0 | unsigned char *buffer = NULL, *output_buffer = NULL; |
7109 | 0 | PRUint32 buffer_len, max_counter, i; |
7110 | 0 | SECStatus rv; |
7111 | 0 | CK_RV crv; |
7112 | | |
7113 | | /* Check that key_len isn't too long. The maximum key length could be |
7114 | | * greatly increased if the code below did not limit the 4-byte counter |
7115 | | * to a maximum value of 255. */ |
7116 | 0 | if (key_len > 254 * HashLen) |
7117 | 0 | return CKR_ARGUMENTS_BAD; |
7118 | | |
7119 | 0 | if (SharedInfo == NULL) |
7120 | 0 | SharedInfoLen = 0; |
7121 | |
|
7122 | 0 | buffer_len = SharedSecret->len + 4 + SharedInfoLen; |
7123 | 0 | buffer = (CK_BYTE *)PORT_Alloc(buffer_len); |
7124 | 0 | if (buffer == NULL) { |
7125 | 0 | crv = CKR_HOST_MEMORY; |
7126 | 0 | goto loser; |
7127 | 0 | } |
7128 | | |
7129 | 0 | max_counter = key_len / HashLen; |
7130 | 0 | if (key_len > max_counter * HashLen) |
7131 | 0 | max_counter++; |
7132 | |
|
7133 | 0 | output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen); |
7134 | 0 | if (output_buffer == NULL) { |
7135 | 0 | crv = CKR_HOST_MEMORY; |
7136 | 0 | goto loser; |
7137 | 0 | } |
7138 | | |
7139 | | /* Populate buffer with SharedSecret || Counter || [SharedInfo] |
7140 | | * where Counter is 0x00000001 */ |
7141 | 0 | PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len); |
7142 | 0 | buffer[SharedSecret->len] = 0; |
7143 | 0 | buffer[SharedSecret->len + 1] = 0; |
7144 | 0 | buffer[SharedSecret->len + 2] = 0; |
7145 | 0 | buffer[SharedSecret->len + 3] = 1; |
7146 | 0 | if (SharedInfo) { |
7147 | 0 | PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen); |
7148 | 0 | } |
7149 | |
|
7150 | 0 | for (i = 0; i < max_counter; i++) { |
7151 | 0 | rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len); |
7152 | 0 | if (rv != SECSuccess) { |
7153 | | /* 'Hash' should not fail. */ |
7154 | 0 | crv = CKR_FUNCTION_FAILED; |
7155 | 0 | goto loser; |
7156 | 0 | } |
7157 | | |
7158 | | /* Increment counter (assumes max_counter < 255) */ |
7159 | 0 | buffer[SharedSecret->len + 3]++; |
7160 | 0 | } |
7161 | | |
7162 | 0 | PORT_ZFree(buffer, buffer_len); |
7163 | 0 | if (key_len < max_counter * HashLen) { |
7164 | 0 | PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len); |
7165 | 0 | } |
7166 | 0 | *key = output_buffer; |
7167 | |
|
7168 | 0 | return CKR_OK; |
7169 | | |
7170 | 0 | loser: |
7171 | 0 | if (buffer) { |
7172 | 0 | PORT_ZFree(buffer, buffer_len); |
7173 | 0 | } |
7174 | 0 | if (output_buffer) { |
7175 | 0 | PORT_ZFree(output_buffer, max_counter * HashLen); |
7176 | 0 | } |
7177 | 0 | return crv; |
7178 | 0 | } |
7179 | | |
7180 | | static CK_RV |
7181 | | sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, |
7182 | | SECItem *SharedSecret, |
7183 | | CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, |
7184 | | CK_EC_KDF_TYPE kdf) |
7185 | 0 | { |
7186 | 0 | if (kdf == CKD_SHA1_KDF) |
7187 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7188 | 0 | SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH); |
7189 | 0 | else if (kdf == CKD_SHA224_KDF) |
7190 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7191 | 0 | SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH); |
7192 | 0 | else if (kdf == CKD_SHA256_KDF) |
7193 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7194 | 0 | SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH); |
7195 | 0 | else if (kdf == CKD_SHA384_KDF) |
7196 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7197 | 0 | SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH); |
7198 | 0 | else if (kdf == CKD_SHA512_KDF) |
7199 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7200 | 0 | SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH); |
7201 | 0 | else |
7202 | 0 | return CKR_MECHANISM_INVALID; |
7203 | 0 | } |
7204 | | |
7205 | | /* |
7206 | | * Handle the derive from a block encryption cipher |
7207 | | */ |
7208 | | CK_RV |
7209 | | sftk_DeriveEncrypt(SFTKCipher encrypt, void *cipherInfo, |
7210 | | int blockSize, SFTKObject *key, CK_ULONG keySize, |
7211 | | unsigned char *data, CK_ULONG len) |
7212 | 0 | { |
7213 | | /* large enough for a 512-bit key */ |
7214 | 0 | unsigned char tmpdata[SFTK_MAX_DERIVE_KEY_SIZE]; |
7215 | 0 | SECStatus rv; |
7216 | 0 | unsigned int outLen; |
7217 | 0 | CK_RV crv; |
7218 | |
|
7219 | 0 | if ((len % blockSize) != 0) { |
7220 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7221 | 0 | } |
7222 | 0 | if (len > SFTK_MAX_DERIVE_KEY_SIZE) { |
7223 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7224 | 0 | } |
7225 | 0 | if (keySize && (len < keySize)) { |
7226 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7227 | 0 | } |
7228 | 0 | if (keySize == 0) { |
7229 | 0 | keySize = len; |
7230 | 0 | } |
7231 | |
|
7232 | 0 | rv = (*encrypt)(cipherInfo, (unsigned char *)&tmpdata, &outLen, len, data, len); |
7233 | 0 | if (rv != SECSuccess) { |
7234 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
7235 | 0 | return crv; |
7236 | 0 | } |
7237 | | |
7238 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize); |
7239 | 0 | PORT_Memset(tmpdata, 0, sizeof tmpdata); |
7240 | 0 | return crv; |
7241 | 0 | } |
7242 | | |
7243 | | CK_RV |
7244 | | sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession, |
7245 | | SFTKObject *sourceKey, const unsigned char *sourceKeyBytes, |
7246 | | int sourceKeyLen, SFTKObject *key, unsigned char *outKeyBytes, |
7247 | | int keySize, PRBool canBeData, PRBool isFIPS) |
7248 | 52 | { |
7249 | 52 | SFTKSession *session; |
7250 | 52 | SFTKAttribute *saltKey_att = NULL; |
7251 | 52 | const SECHashObject *rawHash; |
7252 | 52 | unsigned hashLen; |
7253 | 52 | unsigned genLen = 0; |
7254 | 52 | unsigned char hashbuf[HASH_LENGTH_MAX]; |
7255 | 52 | unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH]; |
7256 | 52 | unsigned char *keyBlockAlloc = NULL; /* allocated keyBlock */ |
7257 | 52 | unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */ |
7258 | 52 | const unsigned char *prk; /* psuedo-random key */ |
7259 | 52 | CK_ULONG prkLen; |
7260 | 52 | const unsigned char *okm; /* output keying material */ |
7261 | 52 | HASH_HashType hashType = sftk_GetHashTypeFromMechanism(params->prfHashMechanism); |
7262 | 52 | SFTKObject *saltKey = NULL; |
7263 | 52 | CK_RV crv = CKR_OK; |
7264 | | |
7265 | | /* Spec says it should be the base hash, but also accept the HMAC */ |
7266 | 52 | if (hashType == HASH_AlgNULL) { |
7267 | 0 | hashType = sftk_HMACMechanismToHash(params->prfHashMechanism); |
7268 | 0 | } |
7269 | 52 | rawHash = HASH_GetRawHashObject(hashType); |
7270 | 52 | if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) { |
7271 | 0 | return CKR_MECHANISM_INVALID; |
7272 | 0 | } |
7273 | 52 | hashLen = rawHash->length; |
7274 | | |
7275 | 52 | if ((!params->bExpand && !params->bExtract) || |
7276 | 52 | (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) || |
7277 | 52 | (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) { |
7278 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7279 | 0 | } |
7280 | 52 | if ((params->bExpand && keySize == 0) || |
7281 | 52 | (!params->bExpand && keySize > hashLen) || |
7282 | 52 | (params->bExpand && keySize > 255 * hashLen)) { |
7283 | 9 | return CKR_TEMPLATE_INCONSISTENT; |
7284 | 9 | } |
7285 | | |
7286 | | /* sourceKey is NULL if we are called from the POST, skip the |
7287 | | * sensitiveCheck */ |
7288 | 43 | if (sourceKey != NULL) { |
7289 | 43 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData); |
7290 | 43 | if (crv != CKR_OK) |
7291 | 0 | return crv; |
7292 | 43 | } |
7293 | | |
7294 | | /* HKDF-Extract(salt, base key value) */ |
7295 | 43 | if (params->bExtract) { |
7296 | 43 | CK_BYTE *salt; |
7297 | 43 | CK_ULONG saltLen; |
7298 | 43 | HMACContext *hmac; |
7299 | 43 | unsigned int bufLen; |
7300 | | |
7301 | 43 | switch (params->ulSaltType) { |
7302 | 5 | case CKF_HKDF_SALT_NULL: |
7303 | 5 | saltLen = hashLen; |
7304 | 5 | salt = hashbuf; |
7305 | 5 | memset(salt, 0, saltLen); |
7306 | 5 | break; |
7307 | 38 | case CKF_HKDF_SALT_DATA: |
7308 | 38 | salt = params->pSalt; |
7309 | 38 | saltLen = params->ulSaltLen; |
7310 | 38 | if ((salt == NULL) || (params->ulSaltLen == 0)) { |
7311 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7312 | 0 | } |
7313 | 38 | break; |
7314 | 38 | case CKF_HKDF_SALT_KEY: |
7315 | | /* lookup key */ |
7316 | 0 | session = sftk_SessionFromHandle(hSession); |
7317 | 0 | if (session == NULL) { |
7318 | 0 | return CKR_SESSION_HANDLE_INVALID; |
7319 | 0 | } |
7320 | | |
7321 | 0 | saltKey = sftk_ObjectFromHandle(params->hSaltKey, session); |
7322 | 0 | sftk_FreeSession(session); |
7323 | 0 | if (saltKey == NULL) { |
7324 | 0 | return CKR_KEY_HANDLE_INVALID; |
7325 | 0 | } |
7326 | | /* if the base key is not fips, but the salt key is, the |
7327 | | * resulting key can be fips */ |
7328 | 0 | if (isFIPS && (key->isFIPS == 0) && (saltKey->isFIPS == 1)) { |
7329 | 0 | CK_MECHANISM mech; |
7330 | 0 | mech.mechanism = CKM_HKDF_DERIVE; |
7331 | 0 | mech.pParameter = params; |
7332 | 0 | mech.ulParameterLen = sizeof(*params); |
7333 | 0 | key->isFIPS = sftk_operationIsFIPS(saltKey->slot, &mech, |
7334 | 0 | CKA_DERIVE, saltKey); |
7335 | 0 | } |
7336 | 0 | saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE); |
7337 | 0 | if (saltKey_att == NULL) { |
7338 | 0 | sftk_FreeObject(saltKey); |
7339 | 0 | return CKR_KEY_HANDLE_INVALID; |
7340 | 0 | } |
7341 | | /* save the resulting salt */ |
7342 | 0 | salt = saltKey_att->attrib.pValue; |
7343 | 0 | saltLen = saltKey_att->attrib.ulValueLen; |
7344 | 0 | break; |
7345 | 0 | default: |
7346 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7347 | 0 | break; |
7348 | 43 | } |
7349 | | |
7350 | 43 | hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS); |
7351 | 43 | if (saltKey_att) { |
7352 | 0 | sftk_FreeAttribute(saltKey_att); |
7353 | 0 | } |
7354 | 43 | if (saltKey) { |
7355 | 0 | sftk_FreeObject(saltKey); |
7356 | 0 | } |
7357 | 43 | if (!hmac) { |
7358 | 0 | return CKR_HOST_MEMORY; |
7359 | 0 | } |
7360 | 43 | HMAC_Begin(hmac); |
7361 | 43 | HMAC_Update(hmac, sourceKeyBytes, sourceKeyLen); |
7362 | 43 | HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf)); |
7363 | 43 | HMAC_Destroy(hmac, PR_TRUE); |
7364 | 43 | PORT_Assert(bufLen == rawHash->length); |
7365 | 43 | prk = hashbuf; |
7366 | 43 | prkLen = bufLen; |
7367 | 43 | } else { |
7368 | | /* PRK = base key value */ |
7369 | 0 | prk = sourceKeyBytes; |
7370 | 0 | prkLen = sourceKeyLen; |
7371 | 0 | } |
7372 | | |
7373 | | /* HKDF-Expand */ |
7374 | 43 | if (!params->bExpand) { |
7375 | 0 | okm = prk; |
7376 | 0 | keySize = genLen = hashLen; |
7377 | 43 | } else { |
7378 | | /* T(1) = HMAC-Hash(prk, "" | info | 0x01) |
7379 | | * T(n) = HMAC-Hash(prk, T(n-1) | info | n |
7380 | | * key material = T(1) | ... | T(n) |
7381 | | */ |
7382 | 43 | HMACContext *hmac; |
7383 | 43 | CK_BYTE bi; |
7384 | 43 | unsigned iterations; |
7385 | | |
7386 | 43 | genLen = PR_ROUNDUP(keySize, hashLen); |
7387 | 43 | iterations = genLen / hashLen; |
7388 | | |
7389 | 43 | if (genLen > sizeof(keyBlock)) { |
7390 | 40 | keyBlockAlloc = PORT_Alloc(genLen); |
7391 | 40 | if (keyBlockAlloc == NULL) { |
7392 | 0 | return CKR_HOST_MEMORY; |
7393 | 0 | } |
7394 | 40 | keyBlockData = keyBlockAlloc; |
7395 | 40 | } |
7396 | 43 | hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS); |
7397 | 43 | if (hmac == NULL) { |
7398 | 0 | PORT_Free(keyBlockAlloc); |
7399 | 0 | return CKR_HOST_MEMORY; |
7400 | 0 | } |
7401 | 5.54k | for (bi = 1; bi <= iterations && bi > 0; ++bi) { |
7402 | 5.50k | unsigned len; |
7403 | 5.50k | HMAC_Begin(hmac); |
7404 | 5.50k | if (bi > 1) { |
7405 | 5.46k | HMAC_Update(hmac, &keyBlockData[(bi - 2) * hashLen], hashLen); |
7406 | 5.46k | } |
7407 | 5.50k | if (params->ulInfoLen != 0) { |
7408 | 5.50k | HMAC_Update(hmac, params->pInfo, params->ulInfoLen); |
7409 | 5.50k | } |
7410 | 5.50k | HMAC_Update(hmac, &bi, 1); |
7411 | 5.50k | HMAC_Finish(hmac, &keyBlockData[(bi - 1) * hashLen], &len, |
7412 | 5.50k | hashLen); |
7413 | 5.50k | PORT_Assert(len == hashLen); |
7414 | 5.50k | } |
7415 | 43 | HMAC_Destroy(hmac, PR_TRUE); |
7416 | 43 | okm = &keyBlockData[0]; |
7417 | 43 | } |
7418 | | /* key material = okm */ |
7419 | 43 | crv = CKR_OK; |
7420 | 43 | if (key) { |
7421 | 43 | crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize); |
7422 | 43 | } else { |
7423 | 0 | PORT_Assert(outKeyBytes != NULL); |
7424 | 0 | PORT_Memcpy(outKeyBytes, okm, keySize); |
7425 | 0 | } |
7426 | 43 | PORT_Memset(keyBlockData, 0, genLen); |
7427 | 43 | PORT_Memset(hashbuf, 0, sizeof(hashbuf)); |
7428 | 43 | PORT_Free(keyBlockAlloc); |
7429 | 43 | return crv; |
7430 | 43 | } |
7431 | | |
7432 | | /* |
7433 | | * SSL Key generation given pre master secret |
7434 | | */ |
7435 | 0 | #define NUM_MIXERS 9 |
7436 | | static const char *const mixers[NUM_MIXERS] = { |
7437 | | "A", |
7438 | | "BB", |
7439 | | "CCC", |
7440 | | "DDDD", |
7441 | | "EEEEE", |
7442 | | "FFFFFF", |
7443 | | "GGGGGGG", |
7444 | | "HHHHHHHH", |
7445 | | "IIIIIIIII" |
7446 | | }; |
7447 | 0 | #define SSL3_PMS_LENGTH 48 |
7448 | 0 | #define SSL3_MASTER_SECRET_LENGTH 48 |
7449 | 0 | #define SSL3_RANDOM_LENGTH 32 |
7450 | | |
7451 | | /* NSC_DeriveKey derives a key from a base key, creating a new key object. */ |
7452 | | CK_RV |
7453 | | NSC_DeriveKey(CK_SESSION_HANDLE hSession, |
7454 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, |
7455 | | CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, |
7456 | | CK_OBJECT_HANDLE_PTR phKey) |
7457 | 52 | { |
7458 | 52 | SFTKSession *session; |
7459 | 52 | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
7460 | 52 | SFTKObject *key; |
7461 | 52 | SFTKObject *sourceKey; |
7462 | 52 | SFTKAttribute *att = NULL; |
7463 | 52 | SFTKAttribute *att2 = NULL; |
7464 | 52 | unsigned char *buf; |
7465 | 52 | SHA1Context *sha; |
7466 | 52 | MD5Context *md5; |
7467 | 52 | MD2Context *md2; |
7468 | 52 | CK_ULONG macSize; |
7469 | 52 | CK_ULONG tmpKeySize; |
7470 | 52 | CK_ULONG IVSize; |
7471 | 52 | CK_ULONG keySize = 0; |
7472 | 52 | CK_RV crv = CKR_OK; |
7473 | 52 | CK_BBOOL cktrue = CK_TRUE; |
7474 | 52 | CK_BBOOL ckfalse = CK_FALSE; |
7475 | 52 | CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
7476 | 52 | CK_OBJECT_CLASS classType = CKO_SECRET_KEY; |
7477 | 52 | CK_KEY_DERIVATION_STRING_DATA *stringPtr; |
7478 | 52 | PRBool isTLS = PR_FALSE; |
7479 | 52 | PRBool isDH = PR_FALSE; |
7480 | 52 | HASH_HashType tlsPrfHash = HASH_AlgNULL; |
7481 | 52 | SECStatus rv; |
7482 | 52 | int i; |
7483 | 52 | unsigned int outLen; |
7484 | 52 | unsigned char sha_out[SHA1_LENGTH]; |
7485 | 52 | unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH]; |
7486 | 52 | PRBool isFIPS; |
7487 | 52 | HASH_HashType hashType; |
7488 | 52 | CK_MECHANISM_TYPE hashMech; |
7489 | 52 | PRBool extractValue = PR_TRUE; |
7490 | 52 | CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS ikeAppB; |
7491 | 52 | CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *pIkeAppB; |
7492 | | |
7493 | 52 | CHECK_FORK(); |
7494 | | |
7495 | 52 | if (!slot) { |
7496 | 0 | return CKR_SESSION_HANDLE_INVALID; |
7497 | 0 | } |
7498 | 52 | if (!pMechanism) { |
7499 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
7500 | 0 | } |
7501 | 52 | CK_MECHANISM_TYPE mechanism = pMechanism->mechanism; |
7502 | | |
7503 | | /* |
7504 | | * now lets create an object to hang the attributes off of |
7505 | | */ |
7506 | 52 | if (phKey) { |
7507 | 52 | *phKey = CK_INVALID_HANDLE; |
7508 | 52 | } |
7509 | | |
7510 | 52 | key = sftk_NewObject(slot); /* fill in the handle later */ |
7511 | 52 | if (key == NULL) { |
7512 | 0 | return CKR_HOST_MEMORY; |
7513 | 0 | } |
7514 | 52 | isFIPS = sftk_isFIPS(slot->slotID); |
7515 | | |
7516 | | /* |
7517 | | * load the template values into the object |
7518 | | */ |
7519 | 260 | for (i = 0; i < (int)ulAttributeCount; i++) { |
7520 | 208 | crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); |
7521 | 208 | if (crv != CKR_OK) |
7522 | 0 | break; |
7523 | | |
7524 | 208 | if (pTemplate[i].type == CKA_KEY_TYPE) { |
7525 | 52 | keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue; |
7526 | 52 | } |
7527 | 208 | if (pTemplate[i].type == CKA_VALUE_LEN) { |
7528 | 52 | keySize = *(CK_ULONG *)pTemplate[i].pValue; |
7529 | 52 | } |
7530 | 208 | } |
7531 | 52 | if (crv != CKR_OK) { |
7532 | 0 | sftk_FreeObject(key); |
7533 | 0 | return crv; |
7534 | 0 | } |
7535 | | |
7536 | 52 | if (keySize == 0) { |
7537 | 0 | keySize = sftk_MapKeySize(keyType); |
7538 | 0 | } |
7539 | | |
7540 | 52 | switch (mechanism) { |
7541 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */ |
7542 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */ |
7543 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */ |
7544 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA512: |
7545 | 0 | extractValue = PR_FALSE; |
7546 | 0 | classType = CKO_PRIVATE_KEY; |
7547 | 0 | break; |
7548 | 0 | case CKM_NSS_PUB_FROM_PRIV: |
7549 | 0 | extractValue = PR_FALSE; |
7550 | 0 | classType = CKO_PUBLIC_KEY; |
7551 | 0 | break; |
7552 | 0 | case CKM_HKDF_DATA: /* fall through */ |
7553 | 0 | case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */ |
7554 | 0 | case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */ |
7555 | 0 | case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: |
7556 | 0 | classType = CKO_DATA; |
7557 | 0 | break; |
7558 | 0 | case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */ |
7559 | 0 | case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */ |
7560 | 0 | case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */ |
7561 | 0 | case CKM_NSS_JPAKE_FINAL_SHA512: |
7562 | 0 | extractValue = PR_FALSE; |
7563 | | /* fall through */ |
7564 | 52 | default: |
7565 | 52 | classType = CKO_SECRET_KEY; |
7566 | 52 | } |
7567 | | |
7568 | 52 | crv = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType)); |
7569 | 52 | if (crv != CKR_OK) { |
7570 | 0 | sftk_FreeObject(key); |
7571 | 0 | return crv; |
7572 | 0 | } |
7573 | | |
7574 | | /* look up the base key we're deriving with */ |
7575 | 52 | session = sftk_SessionFromHandle(hSession); |
7576 | 52 | if (session == NULL) { |
7577 | 0 | sftk_FreeObject(key); |
7578 | 0 | return CKR_SESSION_HANDLE_INVALID; |
7579 | 0 | } |
7580 | | |
7581 | 52 | sourceKey = sftk_ObjectFromHandle(hBaseKey, session); |
7582 | 52 | sftk_FreeSession(session); |
7583 | | /* is this eventually succeeds, lastOpWasFIPS will be set the resulting key's |
7584 | | * FIPS state below. */ |
7585 | 52 | session->lastOpWasFIPS = PR_FALSE; |
7586 | 52 | if (sourceKey == NULL) { |
7587 | 0 | sftk_FreeObject(key); |
7588 | 0 | return CKR_KEY_HANDLE_INVALID; |
7589 | 0 | } |
7590 | | |
7591 | 52 | if (extractValue) { |
7592 | | /* get the value of the base key */ |
7593 | 52 | att = sftk_FindAttribute(sourceKey, CKA_VALUE); |
7594 | 52 | if (att == NULL) { |
7595 | 0 | sftk_FreeObject(key); |
7596 | 0 | sftk_FreeObject(sourceKey); |
7597 | 0 | return CKR_KEY_HANDLE_INVALID; |
7598 | 0 | } |
7599 | 52 | } |
7600 | 52 | key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DERIVE, sourceKey); |
7601 | | |
7602 | 52 | switch (mechanism) { |
7603 | | /* get a public key from a private key. nsslowkey_ConvertToPublickey() |
7604 | | * will generate the public portion if it doesn't already exist. */ |
7605 | 0 | case CKM_NSS_PUB_FROM_PRIV: { |
7606 | 0 | NSSLOWKEYPrivateKey *privKey; |
7607 | 0 | NSSLOWKEYPublicKey *pubKey; |
7608 | 0 | int error; |
7609 | |
|
7610 | 0 | crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType); |
7611 | 0 | if (crv != CKR_OK) { |
7612 | 0 | break; |
7613 | 0 | } |
7614 | | |
7615 | | /* privKey is stored in sourceKey and will be destroyed when |
7616 | | * the sourceKey is freed. */ |
7617 | 0 | privKey = sftk_GetPrivKey(sourceKey, keyType, &crv); |
7618 | 0 | if (privKey == NULL) { |
7619 | 0 | break; |
7620 | 0 | } |
7621 | 0 | pubKey = nsslowkey_ConvertToPublicKey(privKey); |
7622 | 0 | if (pubKey == NULL) { |
7623 | 0 | error = PORT_GetError(); |
7624 | 0 | crv = sftk_MapCryptError(error); |
7625 | 0 | break; |
7626 | 0 | } |
7627 | 0 | crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey); |
7628 | 0 | nsslowkey_DestroyPublicKey(pubKey); |
7629 | 0 | break; |
7630 | 0 | } |
7631 | 0 | case CKM_NSS_IKE_PRF_DERIVE: |
7632 | 0 | if (pMechanism->ulParameterLen != |
7633 | 0 | sizeof(CK_NSS_IKE_PRF_DERIVE_PARAMS)) { |
7634 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7635 | 0 | break; |
7636 | 0 | } |
7637 | 0 | crv = sftk_ike_prf(hSession, att, |
7638 | 0 | (CK_NSS_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key); |
7639 | 0 | break; |
7640 | 0 | case CKM_NSS_IKE1_PRF_DERIVE: |
7641 | 0 | if (pMechanism->ulParameterLen != |
7642 | 0 | sizeof(CK_NSS_IKE1_PRF_DERIVE_PARAMS)) { |
7643 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7644 | 0 | break; |
7645 | 0 | } |
7646 | 0 | crv = sftk_ike1_prf(hSession, att, |
7647 | 0 | (CK_NSS_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter, |
7648 | 0 | key, keySize); |
7649 | 0 | break; |
7650 | 0 | case CKM_NSS_IKE1_APP_B_PRF_DERIVE: |
7651 | 0 | pIkeAppB = (CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS *)pMechanism->pParameter; |
7652 | 0 | if (pMechanism->ulParameterLen == |
7653 | 0 | sizeof(CK_MECHANISM_TYPE)) { |
7654 | 0 | ikeAppB.prfMechanism = *(CK_MECHANISM_TYPE *)pMechanism->pParameter; |
7655 | 0 | ikeAppB.bHasKeygxy = PR_FALSE; |
7656 | 0 | ikeAppB.hKeygxy = CK_INVALID_HANDLE; |
7657 | 0 | ikeAppB.pExtraData = NULL; |
7658 | 0 | ikeAppB.ulExtraDataLen = 0; |
7659 | 0 | pIkeAppB = &ikeAppB; |
7660 | 0 | } else if (pMechanism->ulParameterLen != |
7661 | 0 | sizeof(CK_NSS_IKE1_APP_B_PRF_DERIVE_PARAMS)) { |
7662 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7663 | 0 | break; |
7664 | 0 | } |
7665 | 0 | crv = sftk_ike1_appendix_b_prf(hSession, att, pIkeAppB, key, |
7666 | 0 | keySize); |
7667 | 0 | break; |
7668 | 0 | case CKM_NSS_IKE_PRF_PLUS_DERIVE: |
7669 | 0 | if (pMechanism->ulParameterLen != |
7670 | 0 | sizeof(CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS)) { |
7671 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7672 | 0 | break; |
7673 | 0 | } |
7674 | 0 | crv = sftk_ike_prf_plus(hSession, att, |
7675 | 0 | (CK_NSS_IKE_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter, |
7676 | 0 | key, keySize); |
7677 | 0 | break; |
7678 | | /* |
7679 | | * generate the master secret |
7680 | | */ |
7681 | 0 | case CKM_TLS12_MASTER_KEY_DERIVE: |
7682 | 0 | case CKM_TLS12_MASTER_KEY_DERIVE_DH: |
7683 | 0 | case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256: |
7684 | 0 | case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256: |
7685 | 0 | case CKM_TLS_MASTER_KEY_DERIVE: |
7686 | 0 | case CKM_TLS_MASTER_KEY_DERIVE_DH: |
7687 | 0 | case CKM_SSL3_MASTER_KEY_DERIVE: |
7688 | 0 | case CKM_SSL3_MASTER_KEY_DERIVE_DH: { |
7689 | 0 | CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master; |
7690 | 0 | SSL3RSAPreMasterSecret *rsa_pms; |
7691 | 0 | unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; |
7692 | |
|
7693 | 0 | if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) || |
7694 | 0 | (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { |
7695 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) { |
7696 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7697 | 0 | break; |
7698 | 0 | } |
7699 | 0 | CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master = |
7700 | 0 | (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter; |
7701 | 0 | tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_master->prfHashMechanism); |
7702 | 0 | if (tlsPrfHash == HASH_AlgNULL) { |
7703 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7704 | 0 | break; |
7705 | 0 | } |
7706 | 0 | } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) || |
7707 | 0 | (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) { |
7708 | 0 | tlsPrfHash = HASH_AlgSHA256; |
7709 | 0 | } |
7710 | | |
7711 | 0 | if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) && |
7712 | 0 | (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) { |
7713 | 0 | isTLS = PR_TRUE; |
7714 | 0 | } |
7715 | 0 | if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) || |
7716 | 0 | (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) || |
7717 | 0 | (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) || |
7718 | 0 | (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { |
7719 | 0 | isDH = PR_TRUE; |
7720 | 0 | } |
7721 | | |
7722 | | /* first do the consistency checks */ |
7723 | 0 | if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { |
7724 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7725 | 0 | break; |
7726 | 0 | } |
7727 | 0 | att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); |
7728 | 0 | if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != |
7729 | 0 | CKK_GENERIC_SECRET)) { |
7730 | 0 | if (att2) |
7731 | 0 | sftk_FreeAttribute(att2); |
7732 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7733 | 0 | break; |
7734 | 0 | } |
7735 | 0 | sftk_FreeAttribute(att2); |
7736 | 0 | if (keyType != CKK_GENERIC_SECRET) { |
7737 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7738 | 0 | break; |
7739 | 0 | } |
7740 | 0 | if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { |
7741 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7742 | 0 | break; |
7743 | 0 | } |
7744 | | |
7745 | | /* finally do the key gen */ |
7746 | 0 | ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) |
7747 | 0 | pMechanism->pParameter; |
7748 | |
|
7749 | 0 | if (ssl3_master->pVersion) { |
7750 | 0 | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
7751 | 0 | rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue; |
7752 | | /* don't leak more key material then necessary for SSL to work */ |
7753 | 0 | if ((sessKey == NULL) || sessKey->wasDerived) { |
7754 | 0 | ssl3_master->pVersion->major = 0xff; |
7755 | 0 | ssl3_master->pVersion->minor = 0xff; |
7756 | 0 | } else { |
7757 | 0 | ssl3_master->pVersion->major = rsa_pms->client_version[0]; |
7758 | 0 | ssl3_master->pVersion->minor = rsa_pms->client_version[1]; |
7759 | 0 | } |
7760 | 0 | } |
7761 | 0 | if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) { |
7762 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7763 | 0 | break; |
7764 | 0 | } |
7765 | 0 | if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) { |
7766 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7767 | 0 | break; |
7768 | 0 | } |
7769 | 0 | PORT_Memcpy(crsrdata, |
7770 | 0 | ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); |
7771 | 0 | PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, |
7772 | 0 | ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); |
7773 | |
|
7774 | 0 | if (isTLS) { |
7775 | 0 | SECStatus status; |
7776 | 0 | SECItem crsr = { siBuffer, NULL, 0 }; |
7777 | 0 | SECItem master = { siBuffer, NULL, 0 }; |
7778 | 0 | SECItem pms = { siBuffer, NULL, 0 }; |
7779 | |
|
7780 | 0 | crsr.data = crsrdata; |
7781 | 0 | crsr.len = sizeof crsrdata; |
7782 | 0 | master.data = key_block; |
7783 | 0 | master.len = SSL3_MASTER_SECRET_LENGTH; |
7784 | 0 | pms.data = (unsigned char *)att->attrib.pValue; |
7785 | 0 | pms.len = att->attrib.ulValueLen; |
7786 | |
|
7787 | 0 | if (tlsPrfHash != HASH_AlgNULL) { |
7788 | 0 | status = TLS_P_hash(tlsPrfHash, &pms, "master secret", |
7789 | 0 | &crsr, &master, isFIPS); |
7790 | 0 | } else { |
7791 | 0 | status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS); |
7792 | 0 | } |
7793 | 0 | if (status != SECSuccess) { |
7794 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
7795 | 0 | crv = CKR_FUNCTION_FAILED; |
7796 | 0 | break; |
7797 | 0 | } |
7798 | 0 | } else { |
7799 | | /* now allocate the hash contexts */ |
7800 | 0 | md5 = MD5_NewContext(); |
7801 | 0 | if (md5 == NULL) { |
7802 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
7803 | 0 | crv = CKR_HOST_MEMORY; |
7804 | 0 | break; |
7805 | 0 | } |
7806 | 0 | sha = SHA1_NewContext(); |
7807 | 0 | if (sha == NULL) { |
7808 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
7809 | 0 | PORT_Free(md5); |
7810 | 0 | crv = CKR_HOST_MEMORY; |
7811 | 0 | break; |
7812 | 0 | } |
7813 | 0 | for (i = 0; i < 3; i++) { |
7814 | 0 | SHA1_Begin(sha); |
7815 | 0 | SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i])); |
7816 | 0 | SHA1_Update(sha, (const unsigned char *)att->attrib.pValue, |
7817 | 0 | att->attrib.ulValueLen); |
7818 | 0 | SHA1_Update(sha, crsrdata, sizeof crsrdata); |
7819 | 0 | SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); |
7820 | 0 | PORT_Assert(outLen == SHA1_LENGTH); |
7821 | |
|
7822 | 0 | MD5_Begin(md5); |
7823 | 0 | MD5_Update(md5, (const unsigned char *)att->attrib.pValue, |
7824 | 0 | att->attrib.ulValueLen); |
7825 | 0 | MD5_Update(md5, sha_out, outLen); |
7826 | 0 | MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH); |
7827 | 0 | PORT_Assert(outLen == MD5_LENGTH); |
7828 | 0 | } |
7829 | 0 | PORT_Free(md5); |
7830 | 0 | PORT_Free(sha); |
7831 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
7832 | 0 | PORT_Memset(sha_out, 0, sizeof sha_out); |
7833 | 0 | } |
7834 | | |
7835 | | /* store the results */ |
7836 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, SSL3_MASTER_SECRET_LENGTH); |
7837 | 0 | PORT_Memset(key_block, 0, sizeof key_block); |
7838 | 0 | if (crv != CKR_OK) |
7839 | 0 | break; |
7840 | 0 | keyType = CKK_GENERIC_SECRET; |
7841 | 0 | crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType)); |
7842 | 0 | if (isTLS) { |
7843 | | /* TLS's master secret is used to "sign" finished msgs with PRF. */ |
7844 | | /* XXX This seems like a hack. But SFTK_Derive only accepts |
7845 | | * one "operation" argument. */ |
7846 | 0 | crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); |
7847 | 0 | if (crv != CKR_OK) |
7848 | 0 | break; |
7849 | 0 | crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); |
7850 | 0 | if (crv != CKR_OK) |
7851 | 0 | break; |
7852 | | /* While we're here, we might as well force this, too. */ |
7853 | 0 | crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); |
7854 | 0 | if (crv != CKR_OK) |
7855 | 0 | break; |
7856 | 0 | } |
7857 | 0 | break; |
7858 | 0 | } |
7859 | | |
7860 | | /* Extended master key derivation [draft-ietf-tls-session-hash] */ |
7861 | 0 | case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE: |
7862 | 0 | case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: { |
7863 | 0 | CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params; |
7864 | 0 | SSL3RSAPreMasterSecret *rsa_pms; |
7865 | 0 | SECStatus status; |
7866 | 0 | SECItem pms = { siBuffer, NULL, 0 }; |
7867 | 0 | SECItem seed = { siBuffer, NULL, 0 }; |
7868 | 0 | SECItem master = { siBuffer, NULL, 0 }; |
7869 | |
|
7870 | 0 | ems_params = (CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *) |
7871 | 0 | pMechanism->pParameter; |
7872 | | |
7873 | | /* First do the consistency checks */ |
7874 | 0 | if ((mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE) && |
7875 | 0 | (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { |
7876 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7877 | 0 | break; |
7878 | 0 | } |
7879 | 0 | att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); |
7880 | 0 | if ((att2 == NULL) || |
7881 | 0 | (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) { |
7882 | 0 | if (att2) |
7883 | 0 | sftk_FreeAttribute(att2); |
7884 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7885 | 0 | break; |
7886 | 0 | } |
7887 | 0 | sftk_FreeAttribute(att2); |
7888 | 0 | if (keyType != CKK_GENERIC_SECRET) { |
7889 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7890 | 0 | break; |
7891 | 0 | } |
7892 | 0 | if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { |
7893 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7894 | 0 | break; |
7895 | 0 | } |
7896 | | |
7897 | | /* Do the key derivation */ |
7898 | 0 | pms.data = (unsigned char *)att->attrib.pValue; |
7899 | 0 | pms.len = att->attrib.ulValueLen; |
7900 | 0 | seed.data = ems_params->pSessionHash; |
7901 | 0 | seed.len = ems_params->ulSessionHashLen; |
7902 | 0 | master.data = key_block; |
7903 | 0 | master.len = SSL3_MASTER_SECRET_LENGTH; |
7904 | 0 | if (ems_params->prfHashMechanism == CKM_TLS_PRF) { |
7905 | | /* |
7906 | | * In this case, the session hash is the concatenation of SHA-1 |
7907 | | * and MD5, so it should be 36 bytes long. |
7908 | | */ |
7909 | 0 | if (seed.len != MD5_LENGTH + SHA1_LENGTH) { |
7910 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
7911 | 0 | break; |
7912 | 0 | } |
7913 | | |
7914 | 0 | status = TLS_PRF(&pms, "extended master secret", |
7915 | 0 | &seed, &master, isFIPS); |
7916 | 0 | } else { |
7917 | 0 | const SECHashObject *hashObj; |
7918 | |
|
7919 | 0 | tlsPrfHash = sftk_GetHashTypeFromMechanism(ems_params->prfHashMechanism); |
7920 | 0 | if (tlsPrfHash == HASH_AlgNULL) { |
7921 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7922 | 0 | break; |
7923 | 0 | } |
7924 | | |
7925 | 0 | hashObj = HASH_GetRawHashObject(tlsPrfHash); |
7926 | 0 | if (seed.len != hashObj->length) { |
7927 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
7928 | 0 | break; |
7929 | 0 | } |
7930 | | |
7931 | 0 | status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret", |
7932 | 0 | &seed, &master, isFIPS); |
7933 | 0 | } |
7934 | 0 | if (status != SECSuccess) { |
7935 | 0 | crv = CKR_FUNCTION_FAILED; |
7936 | 0 | break; |
7937 | 0 | } |
7938 | | |
7939 | | /* Reflect the version if required */ |
7940 | 0 | if (ems_params->pVersion) { |
7941 | 0 | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
7942 | 0 | rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue; |
7943 | | /* don't leak more key material than necessary for SSL to work */ |
7944 | 0 | if ((sessKey == NULL) || sessKey->wasDerived) { |
7945 | 0 | ems_params->pVersion->major = 0xff; |
7946 | 0 | ems_params->pVersion->minor = 0xff; |
7947 | 0 | } else { |
7948 | 0 | ems_params->pVersion->major = rsa_pms->client_version[0]; |
7949 | 0 | ems_params->pVersion->minor = rsa_pms->client_version[1]; |
7950 | 0 | } |
7951 | 0 | } |
7952 | | |
7953 | | /* Store the results */ |
7954 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, |
7955 | 0 | SSL3_MASTER_SECRET_LENGTH); |
7956 | 0 | PORT_Memset(key_block, 0, sizeof key_block); |
7957 | 0 | break; |
7958 | 0 | } |
7959 | | |
7960 | 0 | case CKM_TLS12_KEY_AND_MAC_DERIVE: |
7961 | 0 | case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: |
7962 | 0 | case CKM_TLS_KEY_AND_MAC_DERIVE: |
7963 | 0 | case CKM_SSL3_KEY_AND_MAC_DERIVE: { |
7964 | 0 | CK_SSL3_KEY_MAT_PARAMS *ssl3_keys; |
7965 | 0 | CK_SSL3_KEY_MAT_OUT *ssl3_keys_out; |
7966 | 0 | CK_ULONG effKeySize; |
7967 | 0 | unsigned int block_needed; |
7968 | 0 | unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; |
7969 | |
|
7970 | 0 | if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) { |
7971 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) { |
7972 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7973 | 0 | break; |
7974 | 0 | } |
7975 | 0 | CK_TLS12_KEY_MAT_PARAMS *tls12_keys = |
7976 | 0 | (CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter; |
7977 | 0 | tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_keys->prfHashMechanism); |
7978 | 0 | if (tlsPrfHash == HASH_AlgNULL) { |
7979 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
7980 | 0 | break; |
7981 | 0 | } |
7982 | 0 | } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) { |
7983 | 0 | tlsPrfHash = HASH_AlgSHA256; |
7984 | 0 | } |
7985 | | |
7986 | 0 | if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) { |
7987 | 0 | isTLS = PR_TRUE; |
7988 | 0 | } |
7989 | |
|
7990 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
7991 | 0 | if (crv != CKR_OK) |
7992 | 0 | break; |
7993 | | |
7994 | 0 | if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) { |
7995 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
7996 | 0 | break; |
7997 | 0 | } |
7998 | 0 | att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); |
7999 | 0 | if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != |
8000 | 0 | CKK_GENERIC_SECRET)) { |
8001 | 0 | if (att2) |
8002 | 0 | sftk_FreeAttribute(att2); |
8003 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
8004 | 0 | break; |
8005 | 0 | } |
8006 | 0 | sftk_FreeAttribute(att2); |
8007 | 0 | md5 = MD5_NewContext(); |
8008 | 0 | if (md5 == NULL) { |
8009 | 0 | crv = CKR_HOST_MEMORY; |
8010 | 0 | break; |
8011 | 0 | } |
8012 | 0 | sha = SHA1_NewContext(); |
8013 | 0 | if (sha == NULL) { |
8014 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
8015 | 0 | crv = CKR_HOST_MEMORY; |
8016 | 0 | break; |
8017 | 0 | } |
8018 | | |
8019 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_SSL3_KEY_MAT_PARAMS))) { |
8020 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
8021 | 0 | SHA1_DestroyContext(sha, PR_TRUE); |
8022 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8023 | 0 | break; |
8024 | 0 | } |
8025 | 0 | ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter; |
8026 | |
|
8027 | 0 | PORT_Memcpy(srcrdata, |
8028 | 0 | ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); |
8029 | 0 | PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, |
8030 | 0 | ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); |
8031 | | |
8032 | | /* |
8033 | | * clear out our returned keys so we can recover on failure |
8034 | | */ |
8035 | 0 | ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial; |
8036 | 0 | ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE; |
8037 | 0 | ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE; |
8038 | 0 | ssl3_keys_out->hClientKey = CK_INVALID_HANDLE; |
8039 | 0 | ssl3_keys_out->hServerKey = CK_INVALID_HANDLE; |
8040 | | |
8041 | | /* |
8042 | | * How much key material do we need? |
8043 | | */ |
8044 | 0 | macSize = ssl3_keys->ulMacSizeInBits / 8; |
8045 | 0 | effKeySize = ssl3_keys->ulKeySizeInBits / 8; |
8046 | 0 | IVSize = ssl3_keys->ulIVSizeInBits / 8; |
8047 | 0 | if (keySize == 0) { |
8048 | 0 | effKeySize = keySize; |
8049 | 0 | } |
8050 | | |
8051 | | /* bIsExport must be false. */ |
8052 | 0 | if (ssl3_keys->bIsExport) { |
8053 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
8054 | 0 | SHA1_DestroyContext(sha, PR_TRUE); |
8055 | 0 | PORT_Memset(srcrdata, 0, sizeof srcrdata); |
8056 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8057 | 0 | break; |
8058 | 0 | } |
8059 | | |
8060 | 0 | block_needed = 2 * (macSize + effKeySize + IVSize); |
8061 | 0 | PORT_Assert(block_needed <= sizeof key_block); |
8062 | 0 | if (block_needed > sizeof key_block) |
8063 | 0 | block_needed = sizeof key_block; |
8064 | | |
8065 | | /* |
8066 | | * generate the key material: This looks amazingly similar to the |
8067 | | * PMS code, and is clearly crying out for a function to provide it. |
8068 | | */ |
8069 | 0 | if (isTLS) { |
8070 | 0 | SECStatus status; |
8071 | 0 | SECItem srcr = { siBuffer, NULL, 0 }; |
8072 | 0 | SECItem keyblk = { siBuffer, NULL, 0 }; |
8073 | 0 | SECItem master = { siBuffer, NULL, 0 }; |
8074 | |
|
8075 | 0 | srcr.data = srcrdata; |
8076 | 0 | srcr.len = sizeof srcrdata; |
8077 | 0 | keyblk.data = key_block; |
8078 | 0 | keyblk.len = block_needed; |
8079 | 0 | master.data = (unsigned char *)att->attrib.pValue; |
8080 | 0 | master.len = att->attrib.ulValueLen; |
8081 | |
|
8082 | 0 | if (tlsPrfHash != HASH_AlgNULL) { |
8083 | 0 | status = TLS_P_hash(tlsPrfHash, &master, "key expansion", |
8084 | 0 | &srcr, &keyblk, isFIPS); |
8085 | 0 | } else { |
8086 | 0 | status = TLS_PRF(&master, "key expansion", &srcr, &keyblk, |
8087 | 0 | isFIPS); |
8088 | 0 | } |
8089 | 0 | if (status != SECSuccess) { |
8090 | 0 | goto key_and_mac_derive_fail; |
8091 | 0 | } |
8092 | 0 | } else { |
8093 | 0 | unsigned int block_bytes = 0; |
8094 | | /* key_block = |
8095 | | * MD5(master_secret + SHA('A' + master_secret + |
8096 | | * ServerHello.random + ClientHello.random)) + |
8097 | | * MD5(master_secret + SHA('BB' + master_secret + |
8098 | | * ServerHello.random + ClientHello.random)) + |
8099 | | * MD5(master_secret + SHA('CCC' + master_secret + |
8100 | | * ServerHello.random + ClientHello.random)) + |
8101 | | * [...]; |
8102 | | */ |
8103 | 0 | for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) { |
8104 | 0 | SHA1_Begin(sha); |
8105 | 0 | SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i])); |
8106 | 0 | SHA1_Update(sha, (const unsigned char *)att->attrib.pValue, |
8107 | 0 | att->attrib.ulValueLen); |
8108 | 0 | SHA1_Update(sha, srcrdata, sizeof srcrdata); |
8109 | 0 | SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); |
8110 | 0 | PORT_Assert(outLen == SHA1_LENGTH); |
8111 | 0 | MD5_Begin(md5); |
8112 | 0 | MD5_Update(md5, (const unsigned char *)att->attrib.pValue, |
8113 | 0 | att->attrib.ulValueLen); |
8114 | 0 | MD5_Update(md5, sha_out, outLen); |
8115 | 0 | MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH); |
8116 | 0 | PORT_Assert(outLen == MD5_LENGTH); |
8117 | 0 | block_bytes += outLen; |
8118 | 0 | } |
8119 | 0 | PORT_Memset(sha_out, 0, sizeof sha_out); |
8120 | 0 | } |
8121 | | |
8122 | | /* |
8123 | | * Put the key material where it goes. |
8124 | | */ |
8125 | 0 | i = 0; /* now shows how much consumed */ |
8126 | | |
8127 | | /* |
8128 | | * The key_block is partitioned as follows: |
8129 | | * client_write_MAC_secret[CipherSpec.hash_size] |
8130 | | */ |
8131 | 0 | crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize, |
8132 | 0 | &ssl3_keys_out->hClientMacSecret); |
8133 | 0 | if (crv != CKR_OK) |
8134 | 0 | goto key_and_mac_derive_fail; |
8135 | | |
8136 | 0 | i += macSize; |
8137 | | |
8138 | | /* |
8139 | | * server_write_MAC_secret[CipherSpec.hash_size] |
8140 | | */ |
8141 | 0 | crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize, |
8142 | 0 | &ssl3_keys_out->hServerMacSecret); |
8143 | 0 | if (crv != CKR_OK) { |
8144 | 0 | goto key_and_mac_derive_fail; |
8145 | 0 | } |
8146 | 0 | i += macSize; |
8147 | |
|
8148 | 0 | if (keySize) { |
8149 | | /* |
8150 | | ** Generate Domestic write keys and IVs. |
8151 | | ** client_write_key[CipherSpec.key_material] |
8152 | | */ |
8153 | 0 | crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i], |
8154 | 0 | keySize, &ssl3_keys_out->hClientKey); |
8155 | 0 | if (crv != CKR_OK) { |
8156 | 0 | goto key_and_mac_derive_fail; |
8157 | 0 | } |
8158 | 0 | i += keySize; |
8159 | | |
8160 | | /* |
8161 | | ** server_write_key[CipherSpec.key_material] |
8162 | | */ |
8163 | 0 | crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i], |
8164 | 0 | keySize, &ssl3_keys_out->hServerKey); |
8165 | 0 | if (crv != CKR_OK) { |
8166 | 0 | goto key_and_mac_derive_fail; |
8167 | 0 | } |
8168 | 0 | i += keySize; |
8169 | | |
8170 | | /* |
8171 | | ** client_write_IV[CipherSpec.IV_size] |
8172 | | */ |
8173 | 0 | if (IVSize > 0) { |
8174 | 0 | PORT_Memcpy(ssl3_keys_out->pIVClient, |
8175 | 0 | &key_block[i], IVSize); |
8176 | 0 | i += IVSize; |
8177 | 0 | } |
8178 | | |
8179 | | /* |
8180 | | ** server_write_IV[CipherSpec.IV_size] |
8181 | | */ |
8182 | 0 | if (IVSize > 0) { |
8183 | 0 | PORT_Memcpy(ssl3_keys_out->pIVServer, |
8184 | 0 | &key_block[i], IVSize); |
8185 | 0 | i += IVSize; |
8186 | 0 | } |
8187 | 0 | PORT_Assert(i <= sizeof key_block); |
8188 | 0 | } |
8189 | | |
8190 | 0 | crv = CKR_OK; |
8191 | |
|
8192 | 0 | if (0) { |
8193 | 0 | key_and_mac_derive_fail: |
8194 | 0 | if (crv == CKR_OK) |
8195 | 0 | crv = CKR_FUNCTION_FAILED; |
8196 | 0 | sftk_freeSSLKeys(hSession, ssl3_keys_out); |
8197 | 0 | } |
8198 | 0 | PORT_Memset(srcrdata, 0, sizeof srcrdata); |
8199 | 0 | PORT_Memset(key_block, 0, sizeof key_block); |
8200 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
8201 | 0 | SHA1_DestroyContext(sha, PR_TRUE); |
8202 | 0 | sftk_FreeObject(key); |
8203 | 0 | key = NULL; |
8204 | 0 | break; |
8205 | 0 | } |
8206 | | |
8207 | 0 | case CKM_DES3_ECB_ENCRYPT_DATA: |
8208 | 0 | case CKM_DES3_CBC_ENCRYPT_DATA: { |
8209 | 0 | void *cipherInfo; |
8210 | 0 | unsigned char des3key[MAX_DES3_KEY_SIZE]; |
8211 | 0 | CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr; |
8212 | 0 | int mode; |
8213 | 0 | unsigned char *iv; |
8214 | 0 | unsigned char *data; |
8215 | 0 | CK_ULONG len; |
8216 | |
|
8217 | 0 | if (mechanism == CKM_DES3_ECB_ENCRYPT_DATA) { |
8218 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8219 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8220 | 0 | break; |
8221 | 0 | } |
8222 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) |
8223 | 0 | pMechanism->pParameter; |
8224 | 0 | mode = NSS_DES_EDE3; |
8225 | 0 | iv = NULL; |
8226 | 0 | data = stringPtr->pData; |
8227 | 0 | len = stringPtr->ulLen; |
8228 | 0 | } else { |
8229 | 0 | mode = NSS_DES_EDE3_CBC; |
8230 | 0 | desEncryptPtr = |
8231 | 0 | (CK_DES_CBC_ENCRYPT_DATA_PARAMS *) |
8232 | 0 | pMechanism->pParameter; |
8233 | 0 | iv = desEncryptPtr->iv; |
8234 | 0 | data = desEncryptPtr->pData; |
8235 | 0 | len = desEncryptPtr->length; |
8236 | 0 | } |
8237 | 0 | if (att->attrib.ulValueLen == 16) { |
8238 | 0 | PORT_Memcpy(des3key, att->attrib.pValue, 16); |
8239 | 0 | PORT_Memcpy(des3key + 16, des3key, 8); |
8240 | 0 | } else if (att->attrib.ulValueLen == 24) { |
8241 | 0 | PORT_Memcpy(des3key, att->attrib.pValue, 24); |
8242 | 0 | } else { |
8243 | 0 | crv = CKR_KEY_SIZE_RANGE; |
8244 | 0 | break; |
8245 | 0 | } |
8246 | 0 | cipherInfo = DES_CreateContext(des3key, iv, mode, PR_TRUE); |
8247 | 0 | PORT_Memset(des3key, 0, 24); |
8248 | 0 | if (cipherInfo == NULL) { |
8249 | 0 | crv = CKR_HOST_MEMORY; |
8250 | 0 | break; |
8251 | 0 | } |
8252 | 0 | crv = sftk_DeriveEncrypt(SFTKCipher_DES_Encrypt, |
8253 | 0 | cipherInfo, 8, key, keySize, |
8254 | 0 | data, len); |
8255 | 0 | DES_DestroyContext(cipherInfo, PR_TRUE); |
8256 | 0 | break; |
8257 | 0 | } |
8258 | | |
8259 | 0 | case CKM_AES_ECB_ENCRYPT_DATA: |
8260 | 0 | case CKM_AES_CBC_ENCRYPT_DATA: { |
8261 | 0 | void *cipherInfo; |
8262 | 0 | CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; |
8263 | 0 | int mode; |
8264 | 0 | unsigned char *iv; |
8265 | 0 | unsigned char *data; |
8266 | 0 | CK_ULONG len; |
8267 | |
|
8268 | 0 | if (mechanism == CKM_AES_ECB_ENCRYPT_DATA) { |
8269 | 0 | mode = NSS_AES; |
8270 | 0 | iv = NULL; |
8271 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8272 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8273 | 0 | break; |
8274 | 0 | } |
8275 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
8276 | 0 | data = stringPtr->pData; |
8277 | 0 | len = stringPtr->ulLen; |
8278 | 0 | } else { |
8279 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) { |
8280 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8281 | 0 | break; |
8282 | 0 | } |
8283 | 0 | aesEncryptPtr = |
8284 | 0 | (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)pMechanism->pParameter; |
8285 | 0 | mode = NSS_AES_CBC; |
8286 | 0 | iv = aesEncryptPtr->iv; |
8287 | 0 | data = aesEncryptPtr->pData; |
8288 | 0 | len = aesEncryptPtr->length; |
8289 | 0 | } |
8290 | | |
8291 | 0 | cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue, |
8292 | 0 | iv, mode, PR_TRUE, |
8293 | 0 | att->attrib.ulValueLen, 16); |
8294 | 0 | if (cipherInfo == NULL) { |
8295 | 0 | crv = CKR_HOST_MEMORY; |
8296 | 0 | break; |
8297 | 0 | } |
8298 | 0 | crv = sftk_DeriveEncrypt(SFTKCipher_AES_Encrypt, |
8299 | 0 | cipherInfo, 16, key, keySize, |
8300 | 0 | data, len); |
8301 | 0 | AES_DestroyContext(cipherInfo, PR_TRUE); |
8302 | 0 | break; |
8303 | 0 | } |
8304 | | |
8305 | 0 | case CKM_CAMELLIA_ECB_ENCRYPT_DATA: |
8306 | 0 | case CKM_CAMELLIA_CBC_ENCRYPT_DATA: { |
8307 | 0 | void *cipherInfo; |
8308 | 0 | CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; |
8309 | 0 | int mode; |
8310 | 0 | unsigned char *iv; |
8311 | 0 | unsigned char *data; |
8312 | 0 | CK_ULONG len; |
8313 | |
|
8314 | 0 | if (mechanism == CKM_CAMELLIA_ECB_ENCRYPT_DATA) { |
8315 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8316 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8317 | 0 | break; |
8318 | 0 | } |
8319 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) |
8320 | 0 | pMechanism->pParameter; |
8321 | 0 | aesEncryptPtr = NULL; |
8322 | 0 | mode = NSS_CAMELLIA; |
8323 | 0 | data = stringPtr->pData; |
8324 | 0 | len = stringPtr->ulLen; |
8325 | 0 | iv = NULL; |
8326 | 0 | } else { |
8327 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) { |
8328 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8329 | 0 | break; |
8330 | 0 | } |
8331 | 0 | stringPtr = NULL; |
8332 | 0 | aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *) |
8333 | 0 | pMechanism->pParameter; |
8334 | 0 | mode = NSS_CAMELLIA_CBC; |
8335 | 0 | iv = aesEncryptPtr->iv; |
8336 | 0 | data = aesEncryptPtr->pData; |
8337 | 0 | len = aesEncryptPtr->length; |
8338 | 0 | } |
8339 | | |
8340 | 0 | cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue, |
8341 | 0 | iv, mode, PR_TRUE, |
8342 | 0 | att->attrib.ulValueLen); |
8343 | 0 | if (cipherInfo == NULL) { |
8344 | 0 | crv = CKR_HOST_MEMORY; |
8345 | 0 | break; |
8346 | 0 | } |
8347 | 0 | crv = sftk_DeriveEncrypt(SFTKCipher_Camellia_Encrypt, |
8348 | 0 | cipherInfo, 16, key, keySize, |
8349 | 0 | data, len); |
8350 | 0 | Camellia_DestroyContext(cipherInfo, PR_TRUE); |
8351 | 0 | break; |
8352 | 0 | } |
8353 | | |
8354 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
8355 | 0 | case CKM_SEED_ECB_ENCRYPT_DATA: |
8356 | 0 | case CKM_SEED_CBC_ENCRYPT_DATA: { |
8357 | 0 | void *cipherInfo; |
8358 | 0 | CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; |
8359 | 0 | int mode; |
8360 | 0 | unsigned char *iv; |
8361 | 0 | unsigned char *data; |
8362 | 0 | CK_ULONG len; |
8363 | |
|
8364 | 0 | if (mechanism == CKM_SEED_ECB_ENCRYPT_DATA) { |
8365 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8366 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8367 | 0 | break; |
8368 | 0 | } |
8369 | 0 | mode = NSS_SEED; |
8370 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) |
8371 | 0 | pMechanism->pParameter; |
8372 | 0 | aesEncryptPtr = NULL; |
8373 | 0 | data = stringPtr->pData; |
8374 | 0 | len = stringPtr->ulLen; |
8375 | 0 | iv = NULL; |
8376 | 0 | } else { |
8377 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) { |
8378 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8379 | 0 | break; |
8380 | 0 | } |
8381 | 0 | mode = NSS_SEED_CBC; |
8382 | 0 | aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *) |
8383 | 0 | pMechanism->pParameter; |
8384 | 0 | iv = aesEncryptPtr->iv; |
8385 | 0 | data = aesEncryptPtr->pData; |
8386 | 0 | len = aesEncryptPtr->length; |
8387 | 0 | } |
8388 | | |
8389 | 0 | cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue, |
8390 | 0 | iv, mode, PR_TRUE); |
8391 | 0 | if (cipherInfo == NULL) { |
8392 | 0 | crv = CKR_HOST_MEMORY; |
8393 | 0 | break; |
8394 | 0 | } |
8395 | 0 | crv = sftk_DeriveEncrypt(SFTKCipher_SEED_Encrypt, |
8396 | 0 | cipherInfo, 16, key, keySize, |
8397 | 0 | data, len); |
8398 | 0 | SEED_DestroyContext(cipherInfo, PR_TRUE); |
8399 | 0 | break; |
8400 | 0 | } |
8401 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
8402 | | |
8403 | 0 | case CKM_CONCATENATE_BASE_AND_KEY: { |
8404 | 0 | SFTKObject *paramKey; |
8405 | |
|
8406 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8407 | 0 | if (crv != CKR_OK) |
8408 | 0 | break; |
8409 | | |
8410 | 0 | session = sftk_SessionFromHandle(hSession); |
8411 | 0 | if (session == NULL) { |
8412 | 0 | crv = CKR_SESSION_HANDLE_INVALID; |
8413 | 0 | break; |
8414 | 0 | } |
8415 | | |
8416 | 0 | paramKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *) |
8417 | 0 | pMechanism->pParameter, |
8418 | 0 | session); |
8419 | 0 | sftk_FreeSession(session); |
8420 | 0 | if (paramKey == NULL) { |
8421 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
8422 | 0 | break; |
8423 | 0 | } |
8424 | | |
8425 | 0 | if (sftk_isTrue(paramKey, CKA_SENSITIVE)) { |
8426 | 0 | crv = sftk_forceAttribute(key, CKA_SENSITIVE, &cktrue, |
8427 | 0 | sizeof(CK_BBOOL)); |
8428 | 0 | if (crv != CKR_OK) { |
8429 | 0 | sftk_FreeObject(paramKey); |
8430 | 0 | break; |
8431 | 0 | } |
8432 | 0 | } |
8433 | | |
8434 | 0 | if (sftk_hasAttribute(paramKey, CKA_EXTRACTABLE) && !sftk_isTrue(paramKey, CKA_EXTRACTABLE)) { |
8435 | 0 | crv = sftk_forceAttribute(key, CKA_EXTRACTABLE, &ckfalse, sizeof(CK_BBOOL)); |
8436 | 0 | if (crv != CKR_OK) { |
8437 | 0 | sftk_FreeObject(paramKey); |
8438 | 0 | break; |
8439 | 0 | } |
8440 | 0 | } |
8441 | | |
8442 | 0 | att2 = sftk_FindAttribute(paramKey, CKA_VALUE); |
8443 | 0 | if (att2 == NULL) { |
8444 | 0 | sftk_FreeObject(paramKey); |
8445 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
8446 | 0 | break; |
8447 | 0 | } |
8448 | 0 | tmpKeySize = att->attrib.ulValueLen + att2->attrib.ulValueLen; |
8449 | 0 | if (keySize == 0) |
8450 | 0 | keySize = tmpKeySize; |
8451 | 0 | if (keySize > tmpKeySize) { |
8452 | 0 | sftk_FreeObject(paramKey); |
8453 | 0 | sftk_FreeAttribute(att2); |
8454 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8455 | 0 | break; |
8456 | 0 | } |
8457 | 0 | buf = (unsigned char *)PORT_Alloc(tmpKeySize); |
8458 | 0 | if (buf == NULL) { |
8459 | 0 | sftk_FreeAttribute(att2); |
8460 | 0 | sftk_FreeObject(paramKey); |
8461 | 0 | crv = CKR_HOST_MEMORY; |
8462 | 0 | break; |
8463 | 0 | } |
8464 | | |
8465 | 0 | PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen); |
8466 | 0 | PORT_Memcpy(buf + att->attrib.ulValueLen, |
8467 | 0 | att2->attrib.pValue, att2->attrib.ulValueLen); |
8468 | |
|
8469 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
8470 | 0 | PORT_ZFree(buf, tmpKeySize); |
8471 | 0 | sftk_FreeAttribute(att2); |
8472 | 0 | sftk_FreeObject(paramKey); |
8473 | 0 | break; |
8474 | 0 | } |
8475 | | |
8476 | 0 | case CKM_CONCATENATE_BASE_AND_DATA: |
8477 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8478 | 0 | if (crv != CKR_OK) |
8479 | 0 | break; |
8480 | | |
8481 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8482 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8483 | 0 | break; |
8484 | 0 | } |
8485 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
8486 | 0 | tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen; |
8487 | 0 | if (keySize == 0) |
8488 | 0 | keySize = tmpKeySize; |
8489 | 0 | if (keySize > tmpKeySize) { |
8490 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8491 | 0 | break; |
8492 | 0 | } |
8493 | 0 | buf = (unsigned char *)PORT_Alloc(tmpKeySize); |
8494 | 0 | if (buf == NULL) { |
8495 | 0 | crv = CKR_HOST_MEMORY; |
8496 | 0 | break; |
8497 | 0 | } |
8498 | | |
8499 | 0 | PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen); |
8500 | 0 | PORT_Memcpy(buf + att->attrib.ulValueLen, stringPtr->pData, |
8501 | 0 | stringPtr->ulLen); |
8502 | |
|
8503 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
8504 | 0 | PORT_ZFree(buf, tmpKeySize); |
8505 | 0 | break; |
8506 | 0 | case CKM_CONCATENATE_DATA_AND_BASE: |
8507 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8508 | 0 | if (crv != CKR_OK) |
8509 | 0 | break; |
8510 | | |
8511 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8512 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8513 | 0 | break; |
8514 | 0 | } |
8515 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
8516 | 0 | tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen; |
8517 | 0 | if (keySize == 0) |
8518 | 0 | keySize = tmpKeySize; |
8519 | 0 | if (keySize > tmpKeySize) { |
8520 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8521 | 0 | break; |
8522 | 0 | } |
8523 | 0 | buf = (unsigned char *)PORT_Alloc(tmpKeySize); |
8524 | 0 | if (buf == NULL) { |
8525 | 0 | crv = CKR_HOST_MEMORY; |
8526 | 0 | break; |
8527 | 0 | } |
8528 | | |
8529 | 0 | PORT_Memcpy(buf, stringPtr->pData, stringPtr->ulLen); |
8530 | 0 | PORT_Memcpy(buf + stringPtr->ulLen, att->attrib.pValue, |
8531 | 0 | att->attrib.ulValueLen); |
8532 | |
|
8533 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
8534 | 0 | PORT_ZFree(buf, tmpKeySize); |
8535 | 0 | break; |
8536 | 0 | case CKM_XOR_BASE_AND_DATA: |
8537 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8538 | 0 | if (crv != CKR_OK) |
8539 | 0 | break; |
8540 | | |
8541 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
8542 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8543 | 0 | break; |
8544 | 0 | } |
8545 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
8546 | 0 | tmpKeySize = PR_MIN(att->attrib.ulValueLen, stringPtr->ulLen); |
8547 | 0 | if (keySize == 0) |
8548 | 0 | keySize = tmpKeySize; |
8549 | 0 | if (keySize > tmpKeySize) { |
8550 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8551 | 0 | break; |
8552 | 0 | } |
8553 | 0 | buf = (unsigned char *)PORT_Alloc(keySize); |
8554 | 0 | if (buf == NULL) { |
8555 | 0 | crv = CKR_HOST_MEMORY; |
8556 | 0 | break; |
8557 | 0 | } |
8558 | | |
8559 | 0 | PORT_Memcpy(buf, att->attrib.pValue, keySize); |
8560 | 0 | for (i = 0; i < (int)keySize; i++) { |
8561 | 0 | buf[i] ^= stringPtr->pData[i]; |
8562 | 0 | } |
8563 | |
|
8564 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
8565 | 0 | PORT_ZFree(buf, keySize); |
8566 | 0 | break; |
8567 | | |
8568 | 0 | case CKM_EXTRACT_KEY_FROM_KEY: { |
8569 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_EXTRACT_PARAMS))) { |
8570 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8571 | 0 | break; |
8572 | 0 | } |
8573 | | /* the following assumes 8 bits per byte */ |
8574 | 0 | CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter; |
8575 | 0 | CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */ |
8576 | 0 | CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */ |
8577 | |
|
8578 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8579 | 0 | if (crv != CKR_OK) |
8580 | 0 | break; |
8581 | | |
8582 | 0 | if (keySize == 0) { |
8583 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
8584 | 0 | break; |
8585 | 0 | } |
8586 | | /* make sure we have enough bits in the original key */ |
8587 | 0 | if (att->attrib.ulValueLen < |
8588 | 0 | (offset + keySize + ((shift != 0) ? 1 : 0))) { |
8589 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8590 | 0 | break; |
8591 | 0 | } |
8592 | 0 | buf = (unsigned char *)PORT_Alloc(keySize); |
8593 | 0 | if (buf == NULL) { |
8594 | 0 | crv = CKR_HOST_MEMORY; |
8595 | 0 | break; |
8596 | 0 | } |
8597 | | |
8598 | | /* copy the bits we need into the new key */ |
8599 | 0 | for (i = 0; i < (int)keySize; i++) { |
8600 | 0 | unsigned char *value = |
8601 | 0 | ((unsigned char *)att->attrib.pValue) + offset + i; |
8602 | 0 | if (shift) { |
8603 | 0 | buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift)); |
8604 | 0 | } else { |
8605 | 0 | buf[i] = value[0]; |
8606 | 0 | } |
8607 | 0 | } |
8608 | |
|
8609 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
8610 | 0 | PORT_ZFree(buf, keySize); |
8611 | 0 | break; |
8612 | 0 | } |
8613 | 0 | case CKM_MD2_KEY_DERIVATION: |
8614 | 0 | if (keySize == 0) |
8615 | 0 | keySize = MD2_LENGTH; |
8616 | 0 | if (keySize > MD2_LENGTH) { |
8617 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8618 | 0 | break; |
8619 | 0 | } |
8620 | | /* now allocate the hash contexts */ |
8621 | 0 | md2 = MD2_NewContext(); |
8622 | 0 | if (md2 == NULL) { |
8623 | 0 | crv = CKR_HOST_MEMORY; |
8624 | 0 | break; |
8625 | 0 | } |
8626 | 0 | MD2_Begin(md2); |
8627 | 0 | MD2_Update(md2, (const unsigned char *)att->attrib.pValue, |
8628 | 0 | att->attrib.ulValueLen); |
8629 | 0 | MD2_End(md2, key_block, &outLen, MD2_LENGTH); |
8630 | 0 | MD2_DestroyContext(md2, PR_TRUE); |
8631 | |
|
8632 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); |
8633 | 0 | PORT_Memset(key_block, 0, MD2_LENGTH); |
8634 | 0 | break; |
8635 | 0 | #define DERIVE_KEY_HASH(hash) \ |
8636 | 0 | case CKM_##hash##_KEY_DERIVATION: \ |
8637 | 0 | if (keySize == 0) \ |
8638 | 0 | keySize = hash##_LENGTH; \ |
8639 | 0 | if (keySize > hash##_LENGTH) { \ |
8640 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; \ |
8641 | 0 | break; \ |
8642 | 0 | } \ |
8643 | 0 | hash##_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, \ |
8644 | 0 | att->attrib.ulValueLen); \ |
8645 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); \ |
8646 | 0 | PORT_Memset(key_block, 0, hash##_LENGTH); \ |
8647 | 0 | break; |
8648 | 0 | DERIVE_KEY_HASH(MD5) |
8649 | 0 | DERIVE_KEY_HASH(SHA1) |
8650 | 0 | DERIVE_KEY_HASH(SHA224) |
8651 | 0 | DERIVE_KEY_HASH(SHA256) |
8652 | 0 | DERIVE_KEY_HASH(SHA384) |
8653 | 0 | DERIVE_KEY_HASH(SHA512) |
8654 | 0 | DERIVE_KEY_HASH(SHA3_224) |
8655 | 0 | DERIVE_KEY_HASH(SHA3_256) |
8656 | 0 | DERIVE_KEY_HASH(SHA3_384) |
8657 | 0 | DERIVE_KEY_HASH(SHA3_512) |
8658 | | |
8659 | 0 | case CKM_DH_PKCS_DERIVE: { |
8660 | 0 | SECItem derived, dhPublic; |
8661 | 0 | SECItem dhPrime, dhValue; |
8662 | 0 | const SECItem *subPrime; |
8663 | | /* sourceKey - values for the local existing low key */ |
8664 | | /* get prime and value attributes */ |
8665 | 0 | crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME); |
8666 | 0 | if (crv != CKR_OK) |
8667 | 0 | break; |
8668 | | |
8669 | 0 | dhPublic.data = pMechanism->pParameter; |
8670 | 0 | dhPublic.len = pMechanism->ulParameterLen; |
8671 | | |
8672 | | /* if the prime is an approved prime, we can skip all the other |
8673 | | * checks. */ |
8674 | 0 | subPrime = sftk_VerifyDH_Prime(&dhPrime, isFIPS); |
8675 | 0 | if (subPrime == NULL) { |
8676 | 0 | SECItem dhSubPrime; |
8677 | | /* If the caller set the subprime value, it means that |
8678 | | * either the caller knows the subprime value and wants us |
8679 | | * to validate the key against the subprime, or that the |
8680 | | * caller wants us to verify that the prime is a safe prime |
8681 | | * by passing in subprime = (prime-1)/2 */ |
8682 | 0 | dhSubPrime.data = NULL; |
8683 | 0 | dhSubPrime.len = 0; |
8684 | 0 | crv = sftk_Attribute2SecItem(NULL, &dhSubPrime, |
8685 | 0 | sourceKey, CKA_SUBPRIME); |
8686 | | /* we ignore the value of crv here, We treat a valid |
8687 | | * return of len = 0 and a failure to find a subrime the same |
8688 | | * NOTE: we free the subprime in both cases depending on |
8689 | | * PORT_Free of NULL to be a noop */ |
8690 | 0 | if (dhSubPrime.len != 0) { |
8691 | 0 | PRBool isSafe = PR_FALSE; |
8692 | | |
8693 | | /* Callers can set dhSubPrime to q=(p-1)/2 to force |
8694 | | * checks for safe primes. If so we only need to check |
8695 | | * q and p for primality and skip the group test. */ |
8696 | 0 | rv = sftk_IsSafePrime(&dhPrime, &dhSubPrime, &isSafe); |
8697 | 0 | if (rv != SECSuccess) { |
8698 | | /* either p or q was even and therefore not prime, |
8699 | | * we can stop processing here and fail now */ |
8700 | 0 | crv = CKR_ARGUMENTS_BAD; |
8701 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8702 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
8703 | 0 | break; |
8704 | 0 | } |
8705 | | |
8706 | | /* first make sure the primes are really prime */ |
8707 | 0 | if (!KEA_PrimeCheck(&dhPrime)) { |
8708 | 0 | crv = CKR_ARGUMENTS_BAD; |
8709 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8710 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
8711 | 0 | break; |
8712 | 0 | } |
8713 | 0 | if (!KEA_PrimeCheck(&dhSubPrime)) { |
8714 | 0 | crv = CKR_ARGUMENTS_BAD; |
8715 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8716 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
8717 | 0 | break; |
8718 | 0 | } |
8719 | 0 | if (isFIPS || !isSafe) { |
8720 | | /* With safe primes, there is only one other small |
8721 | | * subgroup. As long as y isn't 0, 1, or -1 mod p, |
8722 | | * any other y is safe. Only do the full check for |
8723 | | * non-safe primes, except in FIPS mode we need |
8724 | | * to do this check on all primes in which |
8725 | | * we receive the subprime value */ |
8726 | 0 | if (!KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime)) { |
8727 | 0 | crv = CKR_ARGUMENTS_BAD; |
8728 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8729 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
8730 | 0 | break; |
8731 | 0 | } |
8732 | 0 | } |
8733 | 0 | } else if (isFIPS) { |
8734 | | /* In FIPS mode we only accept approved primes, or |
8735 | | * primes with the full subprime value */ |
8736 | 0 | crv = CKR_ARGUMENTS_BAD; |
8737 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8738 | 0 | break; |
8739 | 0 | } |
8740 | | /* checks are complete, no need for the subPrime any longer */ |
8741 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
8742 | 0 | } |
8743 | | |
8744 | | /* now that the prime is validated, get the private value */ |
8745 | 0 | crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE); |
8746 | 0 | if (crv != CKR_OK) { |
8747 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8748 | 0 | break; |
8749 | 0 | } |
8750 | | |
8751 | | /* calculate private value - oct */ |
8752 | 0 | rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); |
8753 | |
|
8754 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
8755 | 0 | SECITEM_ZfreeItem(&dhValue, PR_FALSE); |
8756 | |
|
8757 | 0 | if (rv == SECSuccess) { |
8758 | 0 | sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len); |
8759 | 0 | SECITEM_ZfreeItem(&derived, PR_FALSE); |
8760 | 0 | crv = CKR_OK; |
8761 | 0 | } else |
8762 | 0 | crv = CKR_HOST_MEMORY; |
8763 | |
|
8764 | 0 | break; |
8765 | 0 | } |
8766 | | |
8767 | 0 | case CKM_ECDH1_DERIVE: |
8768 | 0 | case CKM_ECDH1_COFACTOR_DERIVE: { |
8769 | 0 | SECItem ecScalar, ecPoint; |
8770 | 0 | SECItem tmp; |
8771 | 0 | PRBool withCofactor = PR_FALSE; |
8772 | 0 | unsigned char *secret; |
8773 | 0 | unsigned char *keyData = NULL; |
8774 | 0 | unsigned int secretlen, pubKeyLen; |
8775 | 0 | CK_ECDH1_DERIVE_PARAMS *mechParams; |
8776 | 0 | NSSLOWKEYPrivateKey *privKey; |
8777 | 0 | PLArenaPool *arena = NULL; |
8778 | | |
8779 | | /* Check mechanism parameters */ |
8780 | 0 | mechParams = (CK_ECDH1_DERIVE_PARAMS *)pMechanism->pParameter; |
8781 | 0 | if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) || |
8782 | 0 | ((mechParams->kdf == CKD_NULL) && |
8783 | 0 | ((mechParams->ulSharedDataLen != 0) || |
8784 | 0 | (mechParams->pSharedData != NULL)))) { |
8785 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8786 | 0 | break; |
8787 | 0 | } |
8788 | | |
8789 | 0 | privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv); |
8790 | 0 | if (privKey == NULL) { |
8791 | 0 | break; |
8792 | 0 | } |
8793 | | |
8794 | | /* Now we are working with a non-NULL private key */ |
8795 | 0 | SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue); |
8796 | |
|
8797 | 0 | ecPoint.data = mechParams->pPublicData; |
8798 | 0 | ecPoint.len = mechParams->ulPublicDataLen; |
8799 | |
|
8800 | 0 | pubKeyLen = EC_GetPointSize(&privKey->u.ec.ecParams); |
8801 | | |
8802 | | /* if the len is too large, might be an encoded point */ |
8803 | 0 | if (ecPoint.len > pubKeyLen) { |
8804 | 0 | SECItem newPoint; |
8805 | |
|
8806 | 0 | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
8807 | 0 | if (arena == NULL) { |
8808 | 0 | goto ec_loser; |
8809 | 0 | } |
8810 | | |
8811 | 0 | rv = SEC_QuickDERDecodeItem(arena, &newPoint, |
8812 | 0 | SEC_ASN1_GET(SEC_OctetStringTemplate), |
8813 | 0 | &ecPoint); |
8814 | 0 | if (rv != SECSuccess) { |
8815 | 0 | goto ec_loser; |
8816 | 0 | } |
8817 | 0 | ecPoint = newPoint; |
8818 | 0 | } |
8819 | | |
8820 | 0 | if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) { |
8821 | 0 | withCofactor = PR_TRUE; |
8822 | 0 | } |
8823 | |
|
8824 | 0 | rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar, |
8825 | 0 | withCofactor, &tmp); |
8826 | 0 | SECITEM_ZfreeItem(&ecScalar, PR_FALSE); |
8827 | 0 | ecScalar.data = NULL; |
8828 | 0 | if (privKey != sourceKey->objectInfo) { |
8829 | 0 | nsslowkey_DestroyPrivateKey(privKey); |
8830 | 0 | privKey = NULL; |
8831 | 0 | } |
8832 | 0 | if (arena) { |
8833 | 0 | PORT_FreeArena(arena, PR_FALSE); |
8834 | 0 | arena = NULL; |
8835 | 0 | } |
8836 | |
|
8837 | 0 | if (rv != SECSuccess) { |
8838 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
8839 | 0 | break; |
8840 | 0 | } |
8841 | | |
8842 | | /* |
8843 | | * apply the kdf function. |
8844 | | */ |
8845 | 0 | if (mechParams->kdf == CKD_NULL) { |
8846 | | /* |
8847 | | * tmp is the raw data created by ECDH_Derive, |
8848 | | * secret and secretlen are the values we will |
8849 | | * eventually pass as our generated key. |
8850 | | */ |
8851 | 0 | secret = tmp.data; |
8852 | 0 | secretlen = tmp.len; |
8853 | 0 | } else { |
8854 | 0 | secretlen = keySize; |
8855 | 0 | crv = sftk_ANSI_X9_63_kdf(&secret, keySize, |
8856 | 0 | &tmp, mechParams->pSharedData, |
8857 | 0 | mechParams->ulSharedDataLen, mechParams->kdf); |
8858 | 0 | PORT_ZFree(tmp.data, tmp.len); |
8859 | 0 | if (crv != CKR_OK) { |
8860 | 0 | break; |
8861 | 0 | } |
8862 | 0 | tmp.data = secret; |
8863 | 0 | tmp.len = secretlen; |
8864 | 0 | } |
8865 | | |
8866 | | /* |
8867 | | * if keySize is supplied, then we are generating a key of a specific |
8868 | | * length. This is done by taking the least significant 'keySize' |
8869 | | * bytes from the unsigned value calculated by ECDH. Note: this may |
8870 | | * mean padding temp with extra leading zeros from what ECDH_Derive |
8871 | | * already returned (which itself may contain leading zeros). |
8872 | | */ |
8873 | 0 | if (keySize) { |
8874 | 0 | if (secretlen < keySize) { |
8875 | 0 | keyData = PORT_ZAlloc(keySize); |
8876 | 0 | if (!keyData) { |
8877 | 0 | PORT_ZFree(tmp.data, tmp.len); |
8878 | 0 | crv = CKR_HOST_MEMORY; |
8879 | 0 | break; |
8880 | 0 | } |
8881 | 0 | PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen); |
8882 | 0 | secret = keyData; |
8883 | 0 | } else { |
8884 | 0 | secret += (secretlen - keySize); |
8885 | 0 | } |
8886 | 0 | secretlen = keySize; |
8887 | 0 | } |
8888 | | |
8889 | 0 | sftk_forceAttribute(key, CKA_VALUE, secret, secretlen); |
8890 | 0 | PORT_ZFree(tmp.data, tmp.len); |
8891 | 0 | if (keyData) { |
8892 | 0 | PORT_ZFree(keyData, keySize); |
8893 | 0 | } |
8894 | 0 | break; |
8895 | | |
8896 | 0 | ec_loser: |
8897 | 0 | crv = CKR_ARGUMENTS_BAD; |
8898 | 0 | SECITEM_ZfreeItem(&ecScalar, PR_FALSE); |
8899 | 0 | if (privKey != sourceKey->objectInfo) |
8900 | 0 | nsslowkey_DestroyPrivateKey(privKey); |
8901 | 0 | if (arena) { |
8902 | 0 | PORT_FreeArena(arena, PR_TRUE); |
8903 | 0 | } |
8904 | 0 | break; |
8905 | 0 | } |
8906 | | /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */ |
8907 | 17 | case CKM_NSS_HKDF_SHA1: |
8908 | 17 | hashMech = CKM_SHA_1; |
8909 | 17 | goto hkdf; |
8910 | 9 | case CKM_NSS_HKDF_SHA256: |
8911 | 9 | hashMech = CKM_SHA256; |
8912 | 9 | goto hkdf; |
8913 | 15 | case CKM_NSS_HKDF_SHA384: |
8914 | 15 | hashMech = CKM_SHA384; |
8915 | 15 | goto hkdf; |
8916 | 11 | case CKM_NSS_HKDF_SHA512: |
8917 | 11 | hashMech = CKM_SHA512; |
8918 | 11 | goto hkdf; |
8919 | 52 | hkdf : { |
8920 | 52 | const CK_NSS_HKDFParams *params = |
8921 | 52 | (const CK_NSS_HKDFParams *)pMechanism->pParameter; |
8922 | 52 | CK_HKDF_PARAMS hkdfParams; |
8923 | | |
8924 | 52 | if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams)) { |
8925 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8926 | 0 | break; |
8927 | 0 | } |
8928 | 52 | hkdfParams.bExtract = params->bExtract; |
8929 | 52 | hkdfParams.bExpand = params->bExpand; |
8930 | 52 | if (params->pSalt) { |
8931 | 47 | hkdfParams.ulSaltType = CKF_HKDF_SALT_DATA; |
8932 | 47 | } else { |
8933 | 5 | hkdfParams.ulSaltType = CKF_HKDF_SALT_NULL; |
8934 | 5 | } |
8935 | 52 | hkdfParams.pSalt = params->pSalt; |
8936 | 52 | hkdfParams.ulSaltLen = params->ulSaltLen; |
8937 | 52 | hkdfParams.hSaltKey = CK_INVALID_HANDLE; |
8938 | 52 | hkdfParams.pInfo = params->pInfo; |
8939 | 52 | hkdfParams.ulInfoLen = params->ulInfoLen; |
8940 | 52 | hkdfParams.prfHashMechanism = hashMech; |
8941 | | |
8942 | 52 | crv = sftk_HKDF(&hkdfParams, hSession, sourceKey, |
8943 | 52 | att->attrib.pValue, att->attrib.ulValueLen, |
8944 | 52 | key, NULL, keySize, PR_FALSE, isFIPS); |
8945 | 52 | } break; |
8946 | 0 | case CKM_HKDF_DERIVE: |
8947 | 0 | case CKM_HKDF_DATA: /* only difference is the class of key */ |
8948 | 0 | if ((pMechanism->pParameter == NULL) || |
8949 | 0 | (pMechanism->ulParameterLen != sizeof(CK_HKDF_PARAMS))) { |
8950 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8951 | 0 | break; |
8952 | 0 | } |
8953 | 0 | crv = sftk_HKDF((CK_HKDF_PARAMS_PTR)pMechanism->pParameter, |
8954 | 0 | hSession, sourceKey, att->attrib.pValue, |
8955 | 0 | att->attrib.ulValueLen, key, NULL, keySize, PR_TRUE, |
8956 | 0 | isFIPS); |
8957 | 0 | break; |
8958 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA1: |
8959 | 0 | hashType = HASH_AlgSHA1; |
8960 | 0 | goto jpake2; |
8961 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA256: |
8962 | 0 | hashType = HASH_AlgSHA256; |
8963 | 0 | goto jpake2; |
8964 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA384: |
8965 | 0 | hashType = HASH_AlgSHA384; |
8966 | 0 | goto jpake2; |
8967 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA512: |
8968 | 0 | hashType = HASH_AlgSHA512; |
8969 | 0 | goto jpake2; |
8970 | 0 | jpake2: |
8971 | 0 | if (pMechanism->pParameter == NULL || |
8972 | 0 | pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params)) |
8973 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8974 | 0 | if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN)) |
8975 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8976 | 0 | if (crv == CKR_OK) |
8977 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8978 | 0 | if (crv == CKR_OK) |
8979 | 0 | crv = jpake_Round2(hashType, |
8980 | 0 | (CK_NSS_JPAKERound2Params *)pMechanism->pParameter, |
8981 | 0 | sourceKey, key); |
8982 | 0 | break; |
8983 | | |
8984 | 0 | case CKM_NSS_JPAKE_FINAL_SHA1: |
8985 | 0 | hashType = HASH_AlgSHA1; |
8986 | 0 | goto jpakeFinal; |
8987 | 0 | case CKM_NSS_JPAKE_FINAL_SHA256: |
8988 | 0 | hashType = HASH_AlgSHA256; |
8989 | 0 | goto jpakeFinal; |
8990 | 0 | case CKM_NSS_JPAKE_FINAL_SHA384: |
8991 | 0 | hashType = HASH_AlgSHA384; |
8992 | 0 | goto jpakeFinal; |
8993 | 0 | case CKM_NSS_JPAKE_FINAL_SHA512: |
8994 | 0 | hashType = HASH_AlgSHA512; |
8995 | 0 | goto jpakeFinal; |
8996 | 0 | jpakeFinal: |
8997 | 0 | if (pMechanism->pParameter == NULL || |
8998 | 0 | pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams)) |
8999 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9000 | | /* We purposely do not do the derive sensitivity check; we want to be |
9001 | | able to derive non-sensitive keys while allowing the ROUND1 and |
9002 | | ROUND2 keys to be sensitive (which they always are, since they are |
9003 | | in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE |
9004 | | in the template in order for the resultant keyblock key to be |
9005 | | sensitive. |
9006 | | */ |
9007 | 0 | if (crv == CKR_OK) |
9008 | 0 | crv = jpake_Final(hashType, |
9009 | 0 | (CK_NSS_JPAKEFinalParams *)pMechanism->pParameter, |
9010 | 0 | sourceKey, key); |
9011 | 0 | break; |
9012 | | |
9013 | 0 | case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */ |
9014 | 0 | case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */ |
9015 | 0 | case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */ |
9016 | 0 | case CKM_SP800_108_COUNTER_KDF: /* fall through */ |
9017 | 0 | case CKM_SP800_108_FEEDBACK_KDF: /* fall through */ |
9018 | 0 | case CKM_SP800_108_DOUBLE_PIPELINE_KDF: |
9019 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9020 | 0 | if (crv != CKR_OK) { |
9021 | 0 | break; |
9022 | 0 | } |
9023 | | |
9024 | 0 | crv = kbkdf_Dispatch(mechanism, hSession, pMechanism, sourceKey, key, keySize); |
9025 | 0 | break; |
9026 | 0 | default: |
9027 | 0 | crv = CKR_MECHANISM_INVALID; |
9028 | 52 | } |
9029 | 52 | if (att) { |
9030 | 52 | sftk_FreeAttribute(att); |
9031 | 52 | } |
9032 | 52 | sftk_FreeObject(sourceKey); |
9033 | 52 | if (crv != CKR_OK) { |
9034 | 9 | if (key) |
9035 | 9 | sftk_FreeObject(key); |
9036 | 9 | return crv; |
9037 | 9 | } |
9038 | | |
9039 | | /* link the key object into the list */ |
9040 | 43 | if (key) { |
9041 | 43 | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
9042 | 43 | PORT_Assert(sessKey); |
9043 | | /* get the session */ |
9044 | 43 | sessKey->wasDerived = PR_TRUE; |
9045 | 43 | session = sftk_SessionFromHandle(hSession); |
9046 | 43 | if (session == NULL) { |
9047 | 0 | sftk_FreeObject(key); |
9048 | 0 | return CKR_HOST_MEMORY; |
9049 | 0 | } |
9050 | | |
9051 | 43 | crv = sftk_handleObject(key, session); |
9052 | 43 | session->lastOpWasFIPS = key->isFIPS; |
9053 | 43 | sftk_FreeSession(session); |
9054 | 43 | if (phKey) { |
9055 | 43 | *phKey = key->handle; |
9056 | 43 | } |
9057 | 43 | sftk_FreeObject(key); |
9058 | 43 | } |
9059 | 43 | return crv; |
9060 | 43 | } |
9061 | | |
9062 | | /* NSC_GetFunctionStatus obtains an updated status of a function running |
9063 | | * in parallel with an application. */ |
9064 | | CK_RV |
9065 | | NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession) |
9066 | 0 | { |
9067 | 0 | CHECK_FORK(); |
9068 | |
|
9069 | 0 | return CKR_FUNCTION_NOT_PARALLEL; |
9070 | 0 | } |
9071 | | |
9072 | | /* NSC_CancelFunction cancels a function running in parallel */ |
9073 | | CK_RV |
9074 | | NSC_CancelFunction(CK_SESSION_HANDLE hSession) |
9075 | 0 | { |
9076 | 0 | CHECK_FORK(); |
9077 | |
|
9078 | 0 | return CKR_FUNCTION_NOT_PARALLEL; |
9079 | 0 | } |
9080 | | |
9081 | | /* NSC_GetOperationState saves the state of the cryptographic |
9082 | | * operation in a session. |
9083 | | * NOTE: This code only works for digest functions for now. eventually need |
9084 | | * to add full flatten/resurect to our state stuff so that all types of state |
9085 | | * can be saved */ |
9086 | | CK_RV |
9087 | | NSC_GetOperationState(CK_SESSION_HANDLE hSession, |
9088 | | CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) |
9089 | 0 | { |
9090 | 0 | SFTKSessionContext *context; |
9091 | 0 | SFTKSession *session; |
9092 | 0 | CK_RV crv; |
9093 | 0 | CK_ULONG pOSLen = *pulOperationStateLen; |
9094 | |
|
9095 | 0 | CHECK_FORK(); |
9096 | | |
9097 | | /* make sure we're legal */ |
9098 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); |
9099 | 0 | if (crv != CKR_OK) |
9100 | 0 | return crv; |
9101 | | |
9102 | | /* a zero cipherInfoLen signals that this context cannot be serialized */ |
9103 | 0 | if (context->cipherInfoLen == 0) { |
9104 | 0 | return CKR_STATE_UNSAVEABLE; |
9105 | 0 | } |
9106 | | |
9107 | 0 | *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) + sizeof(SFTKContextType); |
9108 | 0 | if (pOperationState == NULL) { |
9109 | 0 | sftk_FreeSession(session); |
9110 | 0 | return CKR_OK; |
9111 | 0 | } else { |
9112 | 0 | if (pOSLen < *pulOperationStateLen) { |
9113 | 0 | return CKR_BUFFER_TOO_SMALL; |
9114 | 0 | } |
9115 | 0 | } |
9116 | 0 | PORT_Memcpy(pOperationState, &context->type, sizeof(SFTKContextType)); |
9117 | 0 | pOperationState += sizeof(SFTKContextType); |
9118 | 0 | PORT_Memcpy(pOperationState, &context->currentMech, |
9119 | 0 | sizeof(CK_MECHANISM_TYPE)); |
9120 | 0 | pOperationState += sizeof(CK_MECHANISM_TYPE); |
9121 | 0 | PORT_Memcpy(pOperationState, context->cipherInfo, context->cipherInfoLen); |
9122 | 0 | sftk_FreeSession(session); |
9123 | 0 | return CKR_OK; |
9124 | 0 | } |
9125 | | |
9126 | | #define sftk_Decrement(stateSize, len) \ |
9127 | 0 | stateSize = ((stateSize) > (CK_ULONG)(len)) ? ((stateSize) - (CK_ULONG)(len)) : 0; |
9128 | | |
9129 | | /* NSC_SetOperationState restores the state of the cryptographic |
9130 | | * operation in a session. This is coded like it can restore lots of |
9131 | | * states, but it only works for truly flat cipher structures. */ |
9132 | | CK_RV |
9133 | | NSC_SetOperationState(CK_SESSION_HANDLE hSession, |
9134 | | CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, |
9135 | | CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) |
9136 | 0 | { |
9137 | 0 | SFTKSessionContext *context; |
9138 | 0 | SFTKSession *session; |
9139 | 0 | SFTKContextType type; |
9140 | 0 | CK_MECHANISM mech; |
9141 | 0 | CK_RV crv = CKR_OK; |
9142 | |
|
9143 | 0 | CHECK_FORK(); |
9144 | |
|
9145 | 0 | while (ulOperationStateLen != 0) { |
9146 | | /* get what type of state we're dealing with... */ |
9147 | 0 | PORT_Memcpy(&type, pOperationState, sizeof(SFTKContextType)); |
9148 | | |
9149 | | /* fix up session contexts based on type */ |
9150 | 0 | session = sftk_SessionFromHandle(hSession); |
9151 | 0 | if (session == NULL) |
9152 | 0 | return CKR_SESSION_HANDLE_INVALID; |
9153 | 0 | context = sftk_ReturnContextByType(session, type); |
9154 | 0 | sftk_SetContextByType(session, type, NULL); |
9155 | 0 | if (context) { |
9156 | 0 | sftk_FreeContext(context); |
9157 | 0 | } |
9158 | 0 | pOperationState += sizeof(SFTKContextType); |
9159 | 0 | sftk_Decrement(ulOperationStateLen, sizeof(SFTKContextType)); |
9160 | | |
9161 | | /* get the mechanism structure */ |
9162 | 0 | PORT_Memcpy(&mech.mechanism, pOperationState, sizeof(CK_MECHANISM_TYPE)); |
9163 | 0 | pOperationState += sizeof(CK_MECHANISM_TYPE); |
9164 | 0 | sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE)); |
9165 | | /* should be filled in... but not necessary for hash */ |
9166 | 0 | mech.pParameter = NULL; |
9167 | 0 | mech.ulParameterLen = 0; |
9168 | 0 | switch (type) { |
9169 | 0 | case SFTK_HASH: |
9170 | 0 | crv = NSC_DigestInit(hSession, &mech); |
9171 | 0 | if (crv != CKR_OK) |
9172 | 0 | break; |
9173 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, |
9174 | 0 | NULL); |
9175 | 0 | if (crv != CKR_OK) |
9176 | 0 | break; |
9177 | 0 | if (context->cipherInfoLen == 0) { |
9178 | 0 | crv = CKR_SAVED_STATE_INVALID; |
9179 | 0 | break; |
9180 | 0 | } |
9181 | 0 | PORT_Memcpy(context->cipherInfo, pOperationState, |
9182 | 0 | context->cipherInfoLen); |
9183 | 0 | pOperationState += context->cipherInfoLen; |
9184 | 0 | sftk_Decrement(ulOperationStateLen, context->cipherInfoLen); |
9185 | 0 | break; |
9186 | 0 | default: |
9187 | | /* do sign/encrypt/decrypt later */ |
9188 | 0 | crv = CKR_SAVED_STATE_INVALID; |
9189 | 0 | } |
9190 | 0 | sftk_FreeSession(session); |
9191 | 0 | if (crv != CKR_OK) |
9192 | 0 | break; |
9193 | 0 | } |
9194 | 0 | return crv; |
9195 | 0 | } |
9196 | | |
9197 | | /* Dual-function cryptographic operations */ |
9198 | | |
9199 | | /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption |
9200 | | * operation. */ |
9201 | | CK_RV |
9202 | | NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
9203 | | CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
9204 | | CK_ULONG_PTR pulEncryptedPartLen) |
9205 | 0 | { |
9206 | 0 | CK_RV crv; |
9207 | |
|
9208 | 0 | CHECK_FORK(); |
9209 | |
|
9210 | 0 | crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, |
9211 | 0 | pulEncryptedPartLen); |
9212 | 0 | if (crv != CKR_OK) |
9213 | 0 | return crv; |
9214 | 0 | crv = NSC_DigestUpdate(hSession, pPart, ulPartLen); |
9215 | |
|
9216 | 0 | return crv; |
9217 | 0 | } |
9218 | | |
9219 | | /* NSC_DecryptDigestUpdate continues a multiple-part decryption and |
9220 | | * digesting operation. */ |
9221 | | CK_RV |
9222 | | NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, |
9223 | | CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, |
9224 | | CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) |
9225 | 0 | { |
9226 | 0 | CK_RV crv; |
9227 | |
|
9228 | 0 | CHECK_FORK(); |
9229 | |
|
9230 | 0 | crv = NSC_DecryptUpdate(hSession, pEncryptedPart, ulEncryptedPartLen, |
9231 | 0 | pPart, pulPartLen); |
9232 | 0 | if (crv != CKR_OK) |
9233 | 0 | return crv; |
9234 | 0 | crv = NSC_DigestUpdate(hSession, pPart, *pulPartLen); |
9235 | |
|
9236 | 0 | return crv; |
9237 | 0 | } |
9238 | | |
9239 | | /* NSC_SignEncryptUpdate continues a multiple-part signing and |
9240 | | * encryption operation. */ |
9241 | | CK_RV |
9242 | | NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
9243 | | CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
9244 | | CK_ULONG_PTR pulEncryptedPartLen) |
9245 | 0 | { |
9246 | 0 | CK_RV crv; |
9247 | |
|
9248 | 0 | CHECK_FORK(); |
9249 | |
|
9250 | 0 | crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, |
9251 | 0 | pulEncryptedPartLen); |
9252 | 0 | if (crv != CKR_OK) |
9253 | 0 | return crv; |
9254 | 0 | crv = NSC_SignUpdate(hSession, pPart, ulPartLen); |
9255 | |
|
9256 | 0 | return crv; |
9257 | 0 | } |
9258 | | |
9259 | | /* NSC_DecryptVerifyUpdate continues a multiple-part decryption |
9260 | | * and verify operation. */ |
9261 | | CK_RV |
9262 | | NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, |
9263 | | CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, |
9264 | | CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) |
9265 | 0 | { |
9266 | 0 | CK_RV crv; |
9267 | |
|
9268 | 0 | CHECK_FORK(); |
9269 | |
|
9270 | 0 | crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, |
9271 | 0 | pData, pulDataLen); |
9272 | 0 | if (crv != CKR_OK) |
9273 | 0 | return crv; |
9274 | 0 | crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen); |
9275 | |
|
9276 | 0 | return crv; |
9277 | 0 | } |
9278 | | |
9279 | | /* NSC_DigestKey continues a multi-part message-digesting operation, |
9280 | | * by digesting the value of a secret key as part of the data already digested. |
9281 | | */ |
9282 | | CK_RV |
9283 | | NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) |
9284 | 0 | { |
9285 | 0 | SFTKSession *session = NULL; |
9286 | 0 | SFTKObject *key = NULL; |
9287 | 0 | SFTKAttribute *att; |
9288 | 0 | CK_RV crv; |
9289 | |
|
9290 | 0 | CHECK_FORK(); |
9291 | |
|
9292 | 0 | session = sftk_SessionFromHandle(hSession); |
9293 | 0 | if (session == NULL) |
9294 | 0 | return CKR_SESSION_HANDLE_INVALID; |
9295 | | |
9296 | 0 | key = sftk_ObjectFromHandle(hKey, session); |
9297 | 0 | sftk_FreeSession(session); |
9298 | 0 | if (key == NULL) |
9299 | 0 | return CKR_KEY_HANDLE_INVALID; |
9300 | | |
9301 | | /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */ |
9302 | | |
9303 | | /* make sure it's a valid key for this operation */ |
9304 | 0 | if (key->objclass != CKO_SECRET_KEY) { |
9305 | 0 | sftk_FreeObject(key); |
9306 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
9307 | 0 | } |
9308 | | /* get the key value */ |
9309 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
9310 | 0 | sftk_FreeObject(key); |
9311 | 0 | if (!att) { |
9312 | 0 | return CKR_KEY_HANDLE_INVALID; |
9313 | 0 | } |
9314 | 0 | crv = NSC_DigestUpdate(hSession, (CK_BYTE_PTR)att->attrib.pValue, |
9315 | 0 | att->attrib.ulValueLen); |
9316 | 0 | sftk_FreeAttribute(att); |
9317 | 0 | return crv; |
9318 | 0 | } |