Coverage Report

Created: 2026-10-13 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}