Coverage Report

Created: 2024-11-21 07:03

/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
}