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