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