/src/nss-nspr/nss/lib/softoken/sftkmessage.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 | | * Implement the PKCS #11 v3.0 Message interfaces |
8 | | */ |
9 | | #include "seccomon.h" |
10 | | #include "pkcs11.h" |
11 | | #include "pkcs11i.h" |
12 | | #include "blapi.h" |
13 | | #include "prenv.h" |
14 | | #include "softoken.h" |
15 | | |
16 | | static SECStatus |
17 | | sftk_ChaCha20_Poly1305_Message_Encrypt(void *vctx, |
18 | | void *cipherText, unsigned int *cipherTextLen, |
19 | | unsigned int maxOutLen, void *plainText, |
20 | | unsigned int plainTextLen, |
21 | | void *vparams, |
22 | | unsigned int paramsLen, void *aad, |
23 | | unsigned int aadLen) |
24 | 0 | { |
25 | 0 | ChaCha20Poly1305Context *ctx = vctx; |
26 | 0 | CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS *params = vparams; |
27 | 0 | return ChaCha20Poly1305_Encrypt(ctx, cipherText, cipherTextLen, maxOutLen, |
28 | 0 | plainText, plainTextLen, params->pNonce, params->ulNonceLen, |
29 | 0 | aad, aadLen, params->pTag); |
30 | 0 | } |
31 | | |
32 | | static SECStatus |
33 | | sftk_ChaCha20_Poly1305_Message_Decrypt(void *vctx, |
34 | | void *plainText, unsigned int *plainTextLen, |
35 | | unsigned int maxOutLen, void *cipherText, |
36 | | unsigned int cipherTextLen, |
37 | | void *vparams, |
38 | | unsigned int paramsLen, void *aad, |
39 | | unsigned int aadLen) |
40 | 0 | { |
41 | 0 | ChaCha20Poly1305Context *ctx = vctx; |
42 | 0 | CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS *params = vparams; |
43 | 0 | return ChaCha20Poly1305_Decrypt(ctx, plainText, plainTextLen, maxOutLen, |
44 | 0 | cipherText, cipherTextLen, params->pNonce, params->ulNonceLen, |
45 | 0 | aad, aadLen, params->pTag); |
46 | 0 | } |
47 | | |
48 | | void |
49 | | sftk_ChaCha20Poly1305_DestroyContext(void *vctx, PRBool freeit) |
50 | 0 | { |
51 | 0 | ChaCha20Poly1305Context *ctx = vctx; |
52 | 0 | ChaCha20Poly1305_DestroyContext(ctx, freeit); |
53 | 0 | } |
54 | | |
55 | | static SECStatus |
56 | | sftk_AES_AEAD(void *vctx, |
57 | | void *plainText, unsigned int *plainTextLen, |
58 | | unsigned int maxOutLen, void *cipherText, |
59 | | unsigned int cipherTextLen, |
60 | | void *params, |
61 | | unsigned int paramsLen, void *aad, |
62 | | unsigned int aadLen) |
63 | 0 | { |
64 | 0 | AESContext *ctx = vctx; |
65 | 0 | return AES_AEAD(ctx, plainText, plainTextLen, maxOutLen, cipherText, cipherTextLen, params, paramsLen, aad, aadLen); |
66 | 0 | } |
67 | | |
68 | | void |
69 | | sftk_AES_DestroyContext(void *ctx, PRBool freeit) |
70 | 0 | { |
71 | 0 | AESContext *actx = ctx; |
72 | 0 | AES_DestroyContext(actx, freeit); |
73 | 0 | } |
74 | | |
75 | | /* |
76 | | * Handle AEAD Encryption operation |
77 | | * |
78 | | * The setup is similiar to sftk_CryptInit except we set the aeadUpdate |
79 | | * function instead of the normal update function. This function handles |
80 | | * both the Encrypt case and the Decrypt case. |
81 | | */ |
82 | | static CK_RV |
83 | | sftk_MessageCryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
84 | | CK_OBJECT_HANDLE hKey, SFTKContextType contextType, |
85 | | CK_ATTRIBUTE_TYPE operation, PRBool encrypt) |
86 | 0 | { |
87 | 0 | SFTKSession *session; |
88 | 0 | SFTKObject *key; |
89 | 0 | SFTKSessionContext *context; |
90 | 0 | SFTKAttribute *att; |
91 | 0 | CK_KEY_TYPE key_type; |
92 | 0 | CK_RV crv = CKR_OK; |
93 | |
|
94 | 0 | if (!pMechanism) { |
95 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
96 | 0 | } |
97 | | |
98 | 0 | crv = sftk_MechAllowsOperation(pMechanism->mechanism, |
99 | 0 | CKA_NSS_MESSAGE | operation); |
100 | 0 | if (crv != CKR_OK) |
101 | 0 | return crv; |
102 | | |
103 | 0 | session = sftk_SessionFromHandle(hSession); |
104 | 0 | if (session == NULL) |
105 | 0 | return CKR_SESSION_HANDLE_INVALID; |
106 | | |
107 | 0 | crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key, |
108 | 0 | hKey, &key_type, CKO_SECRET_KEY, operation); |
109 | 0 | if (crv != CKR_OK) { |
110 | 0 | sftk_FreeSession(session); |
111 | 0 | return crv; |
112 | 0 | } |
113 | | |
114 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
115 | 0 | if (att == NULL) { |
116 | 0 | sftk_FreeSession(session); |
117 | 0 | sftk_FreeContext(context); |
118 | 0 | return CKR_KEY_HANDLE_INVALID; |
119 | 0 | } |
120 | | |
121 | 0 | context->doPad = PR_FALSE; |
122 | 0 | context->multi = PR_TRUE; /* All message are 'multi' operations */ |
123 | |
|
124 | 0 | switch (pMechanism->mechanism) { |
125 | 0 | case CKM_AES_GCM: |
126 | 0 | context->cipherInfo = AES_CreateContext( |
127 | 0 | (unsigned char *)att->attrib.pValue, |
128 | 0 | NULL, NSS_AES_GCM, encrypt, att->attrib.ulValueLen, |
129 | 0 | AES_BLOCK_SIZE); |
130 | 0 | context->aeadUpdate = sftk_AES_AEAD; |
131 | 0 | context->destroy = sftk_AES_DestroyContext; |
132 | 0 | break; |
133 | 0 | case CKM_CHACHA20_POLY1305: |
134 | 0 | context->cipherInfo = ChaCha20Poly1305_CreateContext( |
135 | 0 | (unsigned char *)att->attrib.pValue, att->attrib.ulValueLen, |
136 | 0 | 16); |
137 | 0 | context->aeadUpdate = (encrypt ? sftk_ChaCha20_Poly1305_Message_Encrypt : sftk_ChaCha20_Poly1305_Message_Decrypt); |
138 | 0 | context->destroy = sftk_ChaCha20Poly1305_DestroyContext; |
139 | 0 | break; |
140 | 0 | default: |
141 | 0 | crv = CKR_MECHANISM_INVALID; |
142 | 0 | break; |
143 | 0 | } |
144 | 0 | if (context->cipherInfo == NULL) { |
145 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
146 | 0 | if (crv == CKR_OK) { |
147 | 0 | crv = CKR_GENERAL_ERROR; |
148 | 0 | } |
149 | 0 | } |
150 | 0 | if (crv != CKR_OK) { |
151 | 0 | sftk_FreeContext(context); |
152 | 0 | sftk_FreeSession(session); |
153 | 0 | return crv; |
154 | 0 | } |
155 | 0 | sftk_SetContextByType(session, contextType, context); |
156 | 0 | sftk_FreeSession(session); |
157 | 0 | return CKR_OK; |
158 | 0 | } |
159 | | |
160 | | /* |
161 | | * Generic handler for the actual encryption/decryption. Each call handles |
162 | | * The authentication data for the entire block. Multiple calls using |
163 | | * BeginMessage and NextMessage are not supported and CKF_MESSSAGE_MULTI is |
164 | | * not set on the supported algorithms |
165 | | */ |
166 | | static CK_RV |
167 | | sftk_CryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
168 | | CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData, |
169 | | CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pIntext, |
170 | | CK_ULONG ulIntextLen, CK_BYTE_PTR pOuttext, |
171 | | CK_ULONG_PTR pulOuttextLen, SFTKContextType contextType) |
172 | 0 | { |
173 | 0 | SFTKSessionContext *context; |
174 | 0 | unsigned int outlen; |
175 | 0 | unsigned int maxout = *pulOuttextLen; |
176 | 0 | CK_RV crv; |
177 | 0 | SECStatus rv; |
178 | |
|
179 | 0 | CHECK_FORK(); |
180 | | |
181 | | /* make sure we're legal */ |
182 | 0 | crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL); |
183 | 0 | if (crv != CKR_OK) |
184 | 0 | return crv; |
185 | | |
186 | 0 | if (!pOuttext) { |
187 | 0 | *pulOuttextLen = ulIntextLen; |
188 | 0 | return CKR_OK; |
189 | 0 | } |
190 | 0 | rv = (*context->aeadUpdate)(context->cipherInfo, pOuttext, &outlen, |
191 | 0 | maxout, pIntext, ulIntextLen, |
192 | 0 | pParameter, ulParameterLen, |
193 | 0 | pAssociatedData, ulAssociatedDataLen); |
194 | |
|
195 | 0 | if (rv != SECSuccess) { |
196 | 0 | if (contextType == SFTK_MESSAGE_ENCRYPT) { |
197 | 0 | return sftk_MapCryptError(PORT_GetError()); |
198 | 0 | } else { |
199 | 0 | return sftk_MapDecryptError(PORT_GetError()); |
200 | 0 | } |
201 | 0 | } |
202 | 0 | *pulOuttextLen = (CK_ULONG)(outlen); |
203 | 0 | return CKR_OK; |
204 | 0 | } |
205 | | |
206 | | /* |
207 | | * Common message cleanup rountine |
208 | | */ |
209 | | static CK_RV |
210 | | sftk_MessageCryptFinal(CK_SESSION_HANDLE hSession, |
211 | | SFTKContextType contextType) |
212 | 0 | { |
213 | 0 | SFTKSession *session; |
214 | 0 | SFTKSessionContext *context; |
215 | 0 | CK_RV crv; |
216 | |
|
217 | 0 | CHECK_FORK(); |
218 | | |
219 | | /* make sure we're legal */ |
220 | 0 | crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, &session); |
221 | 0 | if (crv != CKR_OK) |
222 | 0 | return crv; |
223 | 0 | sftk_TerminateOp(session, contextType, context); |
224 | 0 | sftk_FreeSession(session); |
225 | 0 | return CKR_OK; |
226 | 0 | } |
227 | | |
228 | | /* MessageEncrypt and EncryptMessage functions just use the helper functions |
229 | | * above */ |
230 | | CK_RV |
231 | | NSC_MessageEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
232 | | CK_OBJECT_HANDLE hKey) |
233 | 0 | { |
234 | 0 | return sftk_MessageCryptInit(hSession, pMechanism, hKey, |
235 | 0 | SFTK_MESSAGE_ENCRYPT, CKA_ENCRYPT, PR_TRUE); |
236 | 0 | } |
237 | | |
238 | | CK_RV |
239 | | NSC_EncryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
240 | | CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData, |
241 | | CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pPlaintext, |
242 | | CK_ULONG ulPlaintextLen, CK_BYTE_PTR pCiphertext, |
243 | | CK_ULONG_PTR pulCiphertextLen) |
244 | 0 | { |
245 | 0 | return sftk_CryptMessage(hSession, pParameter, ulParameterLen, |
246 | 0 | pAssociatedData, ulAssociatedDataLen, pPlaintext, |
247 | 0 | ulPlaintextLen, pCiphertext, pulCiphertextLen, |
248 | 0 | SFTK_MESSAGE_ENCRYPT); |
249 | 0 | } |
250 | | |
251 | | /* |
252 | | * We only support the single shot function. The Begin/Next version can be |
253 | | * dealt with if we need to support S/MIME or something. It would probably |
254 | | * just buffer rather then returning intermediate results. |
255 | | */ |
256 | | CK_RV |
257 | | NSC_EncryptMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
258 | | CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData, |
259 | | CK_ULONG ulAssociatedDataLen) |
260 | 0 | { |
261 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
262 | 0 | } |
263 | | |
264 | | CK_RV |
265 | | NSC_EncryptMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
266 | | CK_ULONG ulParameterLen, CK_BYTE_PTR pPlaintextPart, |
267 | | CK_ULONG ulPlaintextPartLen, CK_BYTE_PTR pCiphertextPart, |
268 | | CK_ULONG_PTR pulCiphertextPartLen, CK_FLAGS flags) |
269 | 0 | { |
270 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
271 | 0 | } |
272 | | |
273 | | CK_RV |
274 | | NSC_MessageEncryptFinal(CK_SESSION_HANDLE hSession) |
275 | 0 | { |
276 | 0 | return sftk_MessageCryptFinal(hSession, SFTK_MESSAGE_ENCRYPT); |
277 | 0 | } |
278 | | |
279 | | /* MessageDecrypt and DecryptMessage functions just use the helper functions |
280 | | * above */ |
281 | | CK_RV |
282 | | NSC_MessageDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
283 | | CK_OBJECT_HANDLE hKey) |
284 | 0 | { |
285 | 0 | return sftk_MessageCryptInit(hSession, pMechanism, hKey, |
286 | 0 | SFTK_MESSAGE_DECRYPT, CKA_DECRYPT, PR_FALSE); |
287 | 0 | } |
288 | | |
289 | | CK_RV |
290 | | NSC_DecryptMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
291 | | CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData, |
292 | | CK_ULONG ulAssociatedDataLen, CK_BYTE_PTR pCiphertext, |
293 | | CK_ULONG ulCiphertextLen, CK_BYTE_PTR pPlaintext, |
294 | | CK_ULONG_PTR pulPlaintextLen) |
295 | 0 | { |
296 | 0 | return sftk_CryptMessage(hSession, pParameter, ulParameterLen, |
297 | 0 | pAssociatedData, ulAssociatedDataLen, pCiphertext, |
298 | 0 | ulCiphertextLen, pPlaintext, pulPlaintextLen, |
299 | 0 | SFTK_MESSAGE_DECRYPT); |
300 | 0 | } |
301 | | |
302 | | /* |
303 | | * We only support the single shot function. The Begin/Next version can be |
304 | | * dealt with if we need to support S/MIME or something. It would probably |
305 | | * just buffer rather then returning intermediate results. This is expecially |
306 | | * true for decrypt, which isn't supposed to return any data unless it's been |
307 | | * authenticated (which can't happen until the last block is processed). |
308 | | */ |
309 | | CK_RV |
310 | | NSC_DecryptMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
311 | | CK_ULONG ulParameterLen, CK_BYTE_PTR pAssociatedData, |
312 | | CK_ULONG ulAssociatedDataLen) |
313 | 0 | { |
314 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
315 | 0 | } |
316 | | |
317 | | CK_RV |
318 | | NSC_DecryptMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
319 | | CK_ULONG ulParameterLen, CK_BYTE_PTR pCiphertextPart, |
320 | | CK_ULONG ulCiphertextPartLen, CK_BYTE_PTR pPlaintextPart, |
321 | | CK_ULONG_PTR pulPlaintextPartLen, CK_FLAGS flags) |
322 | 0 | { |
323 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
324 | 0 | } |
325 | | |
326 | | CK_RV |
327 | | NSC_MessageDecryptFinal(CK_SESSION_HANDLE hSession) |
328 | 0 | { |
329 | 0 | return sftk_MessageCryptFinal(hSession, SFTK_MESSAGE_DECRYPT); |
330 | 0 | } |
331 | | |
332 | | /* |
333 | | * There are no mechanisms defined to use the MessageSign and MessageVerify |
334 | | * interfaces yet, so we don't need to implement anything. |
335 | | */ |
336 | | CK_RV |
337 | | NSC_MessageSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
338 | | CK_OBJECT_HANDLE hKey) |
339 | 0 | { |
340 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
341 | 0 | } |
342 | | |
343 | | CK_RV |
344 | | NSC_SignMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
345 | | CK_ULONG ulParameterLen, CK_BYTE_PTR pData, CK_ULONG ulDataLen, |
346 | | CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) |
347 | 0 | { |
348 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
349 | 0 | } |
350 | | |
351 | | CK_RV |
352 | | NSC_SignMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
353 | | CK_ULONG ulParameterLen) |
354 | 0 | { |
355 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
356 | 0 | } |
357 | | |
358 | | CK_RV |
359 | | NSC_SignMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
360 | | CK_ULONG ulParameterLen, CK_BYTE_PTR pData, |
361 | | CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, |
362 | | CK_ULONG_PTR pulSignatureLen) |
363 | 0 | { |
364 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
365 | 0 | } |
366 | | |
367 | | CK_RV |
368 | | NSC_MessageSignFinal(CK_SESSION_HANDLE hSession) |
369 | 0 | { |
370 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
371 | 0 | } |
372 | | |
373 | | CK_RV |
374 | | NSC_MessageVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
375 | | CK_OBJECT_HANDLE hKey) |
376 | 0 | { |
377 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
378 | 0 | } |
379 | | |
380 | | CK_RV |
381 | | NSC_VerifyMessage(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
382 | | CK_ULONG ulParameterLen, CK_BYTE_PTR pData, |
383 | | CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, |
384 | | CK_ULONG ulSignatureLen) |
385 | 0 | { |
386 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
387 | 0 | } |
388 | | |
389 | | CK_RV |
390 | | NSC_VerifyMessageBegin(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
391 | | CK_ULONG ulParameterLen) |
392 | 0 | { |
393 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
394 | 0 | } |
395 | | |
396 | | CK_RV |
397 | | NSC_VerifyMessageNext(CK_SESSION_HANDLE hSession, CK_VOID_PTR pParameter, |
398 | | CK_ULONG ulParameterLen, CK_BYTE_PTR pData, |
399 | | CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, |
400 | | CK_ULONG ulSignatureLen) |
401 | 0 | { |
402 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
403 | 0 | } |
404 | | |
405 | | CK_RV |
406 | | NSC_MessageVerifyFinal(CK_SESSION_HANDLE hSession) |
407 | 0 | { |
408 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
409 | 0 | } |