Coverage Report

Created: 2026-08-18 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nss/lib/softoken/pkcs11c.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
 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
8
 *   This implementation has two slots:
9
 *      slot 1 is our generic crypto support. It does not require login.
10
 *   It supports Public Key ops, and all they bulk ciphers and hashes.
11
 *   It can also support Private Key ops for imported Private keys. It does
12
 *   not have any token storage.
13
 *      slot 2 is our private key support. It requires a login before use. It
14
 *   can store Private Keys and Certs as token objects. Currently only private
15
 *   keys and their associated Certificates are saved on the token.
16
 *
17
 *   In this implementation, session objects are only visible to the session
18
 *   that created or generated them.
19
 */
20
21
#include <limits.h> /* for UINT_MAX and ULONG_MAX */
22
23
#include "lowkeyti.h"
24
#include "seccomon.h"
25
#include "secitem.h"
26
#include "secport.h"
27
#include "blapi.h"
28
/* we need to use the deprecated mechanisms values for backward compatibility */
29
#include "pkcs11.h"
30
#include "pkcs11i.h"
31
#include "pkcs1sig.h"
32
#include "lowkeyi.h"
33
#include "secder.h"
34
#include "secdig.h"
35
#include "lowpbe.h" /* We do PBE below */
36
#include "pkcs11t.h"
37
#include "secoid.h"
38
#include "cmac.h"
39
#include "alghmac.h"
40
#include "softoken.h"
41
#include "secasn1.h"
42
#include "secerr.h"
43
#include "kem.h"
44
#include "kyber.h"
45
46
#include "prprf.h"
47
#include "prenv.h"
48
#include "prerror.h"
49
50
#define __PASTE(x, y) x##y
51
448k
#define BAD_PARAM_CAST(pMech, typeSize) (!pMech->pParameter || pMech->ulParameterLen < typeSize)
52
/*
53
 * we renamed all our internal functions, get the correct
54
 * definitions for them...
55
 */
56
#undef CK_PKCS11_FUNCTION_INFO
57
#undef CK_NEED_ARG_LIST
58
59
#define CK_PKCS11_3_0 1
60
61
#define CK_EXTERN extern
62
#define CK_PKCS11_FUNCTION_INFO(func) \
63
    CK_RV __PASTE(NS, func)
64
#define CK_NEED_ARG_LIST 1
65
66
#include "pkcs11f.h"
67
68
/* create a definition of SHA1 that's consistent
69
 * with the rest of the CKM_SHAxxx hashes*/
70
656k
#define CKM_SHA1 CKM_SHA_1
71
164k
#define CKM_SHA1_HMAC CKM_SHA_1_HMAC
72
0
#define CKM_SHA1_HMAC_GENERAL CKM_SHA_1_HMAC_GENERAL
73
74
typedef struct {
75
    PRUint8 client_version[2];
76
    PRUint8 random[46];
77
} SSL3RSAPreMasterSecret;
78
79
static void
80
sftk_Null(void *data, PRBool freeit)
81
148k
{
82
148k
    return;
83
148k
}
84
85
/* fake hash end, the hashed data is already in the signature context,
86
 * return a NULL hash, which will be passed to the sign final and ignored */
87
void
88
sftk_NullHashEnd(void *info, unsigned char *data, unsigned int *lenp,
89
                 unsigned int maxlen)
90
0
{
91
0
    *lenp = 0;
92
0
}
93
94
#ifdef EC_DEBUG
95
#define SEC_PRINT(str1, str2, num, sitem)             \
96
    printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
97
           str1, str2, num, sitem->len);              \
98
    for (i = 0; i < sitem->len; i++) {                \
99
        printf("%02x:", sitem->data[i]);              \
100
    }                                                 \
101
    printf("\n")
102
#else
103
#undef EC_DEBUG
104
#define SEC_PRINT(a, b, c, d)
105
#endif
106
107
/* Wrappers to avoid undefined behavior calling functions through a pointer of incorrect type. */
108
#define SFTKHashWrap(ctxtype, mmm)                                                        \
109
    static void                                                                           \
110
        SFTKHash_##mmm##_Update(void *vctx, const unsigned char *input, unsigned int len) \
111
16.4M
    {                                                                                     \
112
16.4M
        ctxtype *ctx = vctx;                                                              \
113
16.4M
        mmm##_Update(ctx, input, len);                                                    \
114
16.4M
    }                                                                                     \
pkcs11c.c:SFTKHash_MD2_Update
Line
Count
Source
111
1.20k
    {                                                                                     \
112
1.20k
        ctxtype *ctx = vctx;                                                              \
113
1.20k
        mmm##_Update(ctx, input, len);                                                    \
114
1.20k
    }                                                                                     \
pkcs11c.c:SFTKHash_MD5_Update
Line
Count
Source
111
920k
    {                                                                                     \
112
920k
        ctxtype *ctx = vctx;                                                              \
113
920k
        mmm##_Update(ctx, input, len);                                                    \
114
920k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA1_Update
Line
Count
Source
111
828k
    {                                                                                     \
112
828k
        ctxtype *ctx = vctx;                                                              \
113
828k
        mmm##_Update(ctx, input, len);                                                    \
114
828k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA224_Update
Line
Count
Source
111
1.62M
    {                                                                                     \
112
1.62M
        ctxtype *ctx = vctx;                                                              \
113
1.62M
        mmm##_Update(ctx, input, len);                                                    \
114
1.62M
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA256_Update
Line
Count
Source
111
1.03M
    {                                                                                     \
112
1.03M
        ctxtype *ctx = vctx;                                                              \
113
1.03M
        mmm##_Update(ctx, input, len);                                                    \
114
1.03M
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA384_Update
Line
Count
Source
111
2.84M
    {                                                                                     \
112
2.84M
        ctxtype *ctx = vctx;                                                              \
113
2.84M
        mmm##_Update(ctx, input, len);                                                    \
114
2.84M
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA512_Update
Line
Count
Source
111
4.10M
    {                                                                                     \
112
4.10M
        ctxtype *ctx = vctx;                                                              \
113
4.10M
        mmm##_Update(ctx, input, len);                                                    \
114
4.10M
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA3_224_Update
Line
Count
Source
111
47.2k
    {                                                                                     \
112
47.2k
        ctxtype *ctx = vctx;                                                              \
113
47.2k
        mmm##_Update(ctx, input, len);                                                    \
114
47.2k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA3_256_Update
Line
Count
Source
111
3.53M
    {                                                                                     \
112
3.53M
        ctxtype *ctx = vctx;                                                              \
113
3.53M
        mmm##_Update(ctx, input, len);                                                    \
114
3.53M
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA3_384_Update
Line
Count
Source
111
879k
    {                                                                                     \
112
879k
        ctxtype *ctx = vctx;                                                              \
113
879k
        mmm##_Update(ctx, input, len);                                                    \
114
879k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA3_512_Update
Line
Count
Source
111
559k
    {                                                                                     \
112
559k
        ctxtype *ctx = vctx;                                                              \
113
559k
        mmm##_Update(ctx, input, len);                                                    \
114
559k
    }                                                                                     \
pkcs11c.c:SFTKHash_sftk_MAC_Update
Line
Count
Source
111
78.7k
    {                                                                                     \
112
78.7k
        ctxtype *ctx = vctx;                                                              \
113
78.7k
        mmm##_Update(ctx, input, len);                                                    \
114
78.7k
    }                                                                                     \
115
    static void                                                                           \
116
        SFTKHash_##mmm##_End(void *vctx, unsigned char *digest,                           \
117
                             unsigned int *len, unsigned int maxLen)                      \
118
687k
    {                                                                                     \
119
687k
        ctxtype *ctx = vctx;                                                              \
120
687k
        mmm##_End(ctx, digest, len, maxLen);                                              \
121
687k
    }                                                                                     \
Unexecuted instantiation: pkcs11c.c:SFTKHash_MD2_End
pkcs11c.c:SFTKHash_MD5_End
Line
Count
Source
118
75.2k
    {                                                                                     \
119
75.2k
        ctxtype *ctx = vctx;                                                              \
120
75.2k
        mmm##_End(ctx, digest, len, maxLen);                                              \
121
75.2k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA1_End
Line
Count
Source
118
283k
    {                                                                                     \
119
283k
        ctxtype *ctx = vctx;                                                              \
120
283k
        mmm##_End(ctx, digest, len, maxLen);                                              \
121
283k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA224_End
Line
Count
Source
118
3.62k
    {                                                                                     \
119
3.62k
        ctxtype *ctx = vctx;                                                              \
120
3.62k
        mmm##_End(ctx, digest, len, maxLen);                                              \
121
3.62k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA256_End
Line
Count
Source
118
151k
    {                                                                                     \
119
151k
        ctxtype *ctx = vctx;                                                              \
120
151k
        mmm##_End(ctx, digest, len, maxLen);                                              \
121
151k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA384_End
Line
Count
Source
118
59.6k
    {                                                                                     \
119
59.6k
        ctxtype *ctx = vctx;                                                              \
120
59.6k
        mmm##_End(ctx, digest, len, maxLen);                                              \
121
59.6k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA512_End
Line
Count
Source
118
16.8k
    {                                                                                     \
119
16.8k
        ctxtype *ctx = vctx;                                                              \
120
16.8k
        mmm##_End(ctx, digest, len, maxLen);                                              \
121
16.8k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA3_224_End
Line
Count
Source
118
2.49k
    {                                                                                     \
119
2.49k
        ctxtype *ctx = vctx;                                                              \
120
2.49k
        mmm##_End(ctx, digest, len, maxLen);                                              \
121
2.49k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA3_256_End
Line
Count
Source
118
40.8k
    {                                                                                     \
119
40.8k
        ctxtype *ctx = vctx;                                                              \
120
40.8k
        mmm##_End(ctx, digest, len, maxLen);                                              \
121
40.8k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA3_384_End
Line
Count
Source
118
1.01k
    {                                                                                     \
119
1.01k
        ctxtype *ctx = vctx;                                                              \
120
1.01k
        mmm##_End(ctx, digest, len, maxLen);                                              \
121
1.01k
    }                                                                                     \
pkcs11c.c:SFTKHash_SHA3_512_End
Line
Count
Source
118
309
    {                                                                                     \
119
309
        ctxtype *ctx = vctx;                                                              \
120
309
        mmm##_End(ctx, digest, len, maxLen);                                              \
121
309
    }                                                                                     \
pkcs11c.c:SFTKHash_sftk_MAC_End
Line
Count
Source
118
52.0k
    {                                                                                     \
119
52.0k
        ctxtype *ctx = vctx;                                                              \
120
52.0k
        mmm##_End(ctx, digest, len, maxLen);                                              \
121
52.0k
    }                                                                                     \
122
    static void                                                                           \
123
        SFTKHash_##mmm##_DestroyContext(void *vctx, PRBool freeit)                        \
124
1.23M
    {                                                                                     \
125
1.23M
        ctxtype *ctx = vctx;                                                              \
126
1.23M
        mmm##_DestroyContext(ctx, freeit);                                                \
127
1.23M
    }
pkcs11c.c:SFTKHash_MD2_DestroyContext
Line
Count
Source
124
50
    {                                                                                     \
125
50
        ctxtype *ctx = vctx;                                                              \
126
50
        mmm##_DestroyContext(ctx, freeit);                                                \
127
50
    }
pkcs11c.c:SFTKHash_MD5_DestroyContext
Line
Count
Source
124
117k
    {                                                                                     \
125
117k
        ctxtype *ctx = vctx;                                                              \
126
117k
        mmm##_DestroyContext(ctx, freeit);                                                \
127
117k
    }
pkcs11c.c:SFTKHash_SHA1_DestroyContext
Line
Count
Source
124
328k
    {                                                                                     \
125
328k
        ctxtype *ctx = vctx;                                                              \
126
328k
        mmm##_DestroyContext(ctx, freeit);                                                \
127
328k
    }
pkcs11c.c:SFTKHash_SHA224_DestroyContext
Line
Count
Source
124
162k
    {                                                                                     \
125
162k
        ctxtype *ctx = vctx;                                                              \
126
162k
        mmm##_DestroyContext(ctx, freeit);                                                \
127
162k
    }
pkcs11c.c:SFTKHash_SHA256_DestroyContext
Line
Count
Source
124
180k
    {                                                                                     \
125
180k
        ctxtype *ctx = vctx;                                                              \
126
180k
        mmm##_DestroyContext(ctx, freeit);                                                \
127
180k
    }
pkcs11c.c:SFTKHash_SHA384_DestroyContext
Line
Count
Source
124
72.4k
    {                                                                                     \
125
72.4k
        ctxtype *ctx = vctx;                                                              \
126
72.4k
        mmm##_DestroyContext(ctx, freeit);                                                \
127
72.4k
    }
pkcs11c.c:SFTKHash_SHA512_DestroyContext
Line
Count
Source
124
59.4k
    {                                                                                     \
125
59.4k
        ctxtype *ctx = vctx;                                                              \
126
59.4k
        mmm##_DestroyContext(ctx, freeit);                                                \
127
59.4k
    }
pkcs11c.c:SFTKHash_SHA3_224_DestroyContext
Line
Count
Source
124
7.64k
    {                                                                                     \
125
7.64k
        ctxtype *ctx = vctx;                                                              \
126
7.64k
        mmm##_DestroyContext(ctx, freeit);                                                \
127
7.64k
    }
pkcs11c.c:SFTKHash_SHA3_256_DestroyContext
Line
Count
Source
124
49.9k
    {                                                                                     \
125
49.9k
        ctxtype *ctx = vctx;                                                              \
126
49.9k
        mmm##_DestroyContext(ctx, freeit);                                                \
127
49.9k
    }
pkcs11c.c:SFTKHash_SHA3_384_DestroyContext
Line
Count
Source
124
5.66k
    {                                                                                     \
125
5.66k
        ctxtype *ctx = vctx;                                                              \
126
5.66k
        mmm##_DestroyContext(ctx, freeit);                                                \
127
5.66k
    }
pkcs11c.c:SFTKHash_SHA3_512_DestroyContext
Line
Count
Source
124
1.44k
    {                                                                                     \
125
1.44k
        ctxtype *ctx = vctx;                                                              \
126
1.44k
        mmm##_DestroyContext(ctx, freeit);                                                \
127
1.44k
    }
pkcs11c.c:SFTKHash_sftk_MAC_DestroyContext
Line
Count
Source
124
253k
    {                                                                                     \
125
253k
        ctxtype *ctx = vctx;                                                              \
126
253k
        mmm##_DestroyContext(ctx, freeit);                                                \
127
253k
    }
128
129
SFTKHashWrap(MD2Context, MD2);
130
SFTKHashWrap(MD5Context, MD5);
131
SFTKHashWrap(SHA1Context, SHA1);
132
SFTKHashWrap(SHA224Context, SHA224);
133
SFTKHashWrap(SHA256Context, SHA256);
134
SFTKHashWrap(SHA384Context, SHA384);
135
SFTKHashWrap(SHA512Context, SHA512);
136
SFTKHashWrap(SHA3_224Context, SHA3_224);
137
SFTKHashWrap(SHA3_256Context, SHA3_256);
138
SFTKHashWrap(SHA3_384Context, SHA3_384);
139
SFTKHashWrap(SHA3_512Context, SHA3_512);
140
SFTKHashWrap(sftk_MACCtx, sftk_MAC);
141
142
static void
143
SFTKHash_SHA1_Begin(void *vctx)
144
0
{
145
0
    SHA1Context *ctx = vctx;
146
0
    SHA1_Begin(ctx);
147
0
}
148
149
static void
150
SFTKHash_MD5_Begin(void *vctx)
151
0
{
152
0
    MD5Context *ctx = vctx;
153
0
    MD5_Begin(ctx);
154
0
}
155
156
#define SFTKCipherWrap(ctxtype, mmm)                                         \
157
    static SECStatus                                                         \
158
        SFTKCipher_##mmm(void *vctx, unsigned char *output,                  \
159
                         unsigned int *outputLen, unsigned int maxOutputLen, \
160
                         const unsigned char *input, unsigned int inputLen)  \
161
130k
    {                                                                        \
162
130k
        ctxtype *ctx = vctx;                                                 \
163
130k
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
164
130k
                   input, inputLen);                                         \
165
130k
    }
Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC2_Encrypt
pkcs11c.c:SFTKCipher_RC2_Decrypt
Line
Count
Source
161
52
    {                                                                        \
162
52
        ctxtype *ctx = vctx;                                                 \
163
52
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
164
52
                   input, inputLen);                                         \
165
52
    }
pkcs11c.c:SFTKCipher_RC4_Encrypt
Line
Count
Source
161
69
    {                                                                        \
162
69
        ctxtype *ctx = vctx;                                                 \
163
69
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
164
69
                   input, inputLen);                                         \
165
69
    }
pkcs11c.c:SFTKCipher_RC4_Decrypt
Line
Count
Source
161
48
    {                                                                        \
162
48
        ctxtype *ctx = vctx;                                                 \
163
48
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
164
48
                   input, inputLen);                                         \
165
48
    }
pkcs11c.c:SFTKCipher_DES_Encrypt
Line
Count
Source
161
56.8k
    {                                                                        \
162
56.8k
        ctxtype *ctx = vctx;                                                 \
163
56.8k
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
164
56.8k
                   input, inputLen);                                         \
165
56.8k
    }
pkcs11c.c:SFTKCipher_DES_Decrypt
Line
Count
Source
161
28.7k
    {                                                                        \
162
28.7k
        ctxtype *ctx = vctx;                                                 \
163
28.7k
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
164
28.7k
                   input, inputLen);                                         \
165
28.7k
    }
pkcs11c.c:SFTKCipher_SEED_Encrypt
Line
Count
Source
161
583
    {                                                                        \
162
583
        ctxtype *ctx = vctx;                                                 \
163
583
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
164
583
                   input, inputLen);                                         \
165
583
    }
pkcs11c.c:SFTKCipher_SEED_Decrypt
Line
Count
Source
161
1.71k
    {                                                                        \
162
1.71k
        ctxtype *ctx = vctx;                                                 \
163
1.71k
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
164
1.71k
                   input, inputLen);                                         \
165
1.71k
    }
pkcs11c.c:SFTKCipher_Camellia_Encrypt
Line
Count
Source
161
711
    {                                                                        \
162
711
        ctxtype *ctx = vctx;                                                 \
163
711
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
164
711
                   input, inputLen);                                         \
165
711
    }
pkcs11c.c:SFTKCipher_Camellia_Decrypt
Line
Count
Source
161
6.66k
    {                                                                        \
162
6.66k
        ctxtype *ctx = vctx;                                                 \
163
6.66k
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
164
6.66k
                   input, inputLen);                                         \
165
6.66k
    }
pkcs11c.c:SFTKCipher_AES_Encrypt
Line
Count
Source
161
23.4k
    {                                                                        \
162
23.4k
        ctxtype *ctx = vctx;                                                 \
163
23.4k
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
164
23.4k
                   input, inputLen);                                         \
165
23.4k
    }
pkcs11c.c:SFTKCipher_AES_Decrypt
Line
Count
Source
161
11.2k
    {                                                                        \
162
11.2k
        ctxtype *ctx = vctx;                                                 \
163
11.2k
        return mmm(ctx, output, outputLen, maxOutputLen,                     \
164
11.2k
                   input, inputLen);                                         \
165
11.2k
    }
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_Encrypt
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_Decrypt
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_EncryptKWP
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_DecryptKWP
166
167
SFTKCipherWrap(AESKeyWrapContext, AESKeyWrap_EncryptKWP);
168
SFTKCipherWrap(AESKeyWrapContext, AESKeyWrap_DecryptKWP);
169
170
#define SFTKCipherWrap2(ctxtype, mmm)                                        \
171
    SFTKCipherWrap(ctxtype, mmm##_Encrypt);                                  \
172
    SFTKCipherWrap(ctxtype, mmm##_Decrypt);                                  \
173
    static void SFTKCipher_##mmm##_DestroyContext(void *vctx, PRBool freeit) \
174
254k
    {                                                                        \
175
254k
        ctxtype *ctx = vctx;                                                 \
176
254k
        mmm##_DestroyContext(ctx, freeit);                                   \
177
254k
    }
pkcs11c.c:SFTKCipher_RC2_DestroyContext
Line
Count
Source
174
26
    {                                                                        \
175
26
        ctxtype *ctx = vctx;                                                 \
176
26
        mmm##_DestroyContext(ctx, freeit);                                   \
177
26
    }
pkcs11c.c:SFTKCipher_RC4_DestroyContext
Line
Count
Source
174
5.97k
    {                                                                        \
175
5.97k
        ctxtype *ctx = vctx;                                                 \
176
5.97k
        mmm##_DestroyContext(ctx, freeit);                                   \
177
5.97k
    }
pkcs11c.c:SFTKCipher_DES_DestroyContext
Line
Count
Source
174
90.2k
    {                                                                        \
175
90.2k
        ctxtype *ctx = vctx;                                                 \
176
90.2k
        mmm##_DestroyContext(ctx, freeit);                                   \
177
90.2k
    }
pkcs11c.c:SFTKCipher_SEED_DestroyContext
Line
Count
Source
174
12.6k
    {                                                                        \
175
12.6k
        ctxtype *ctx = vctx;                                                 \
176
12.6k
        mmm##_DestroyContext(ctx, freeit);                                   \
177
12.6k
    }
pkcs11c.c:SFTKCipher_Camellia_DestroyContext
Line
Count
Source
174
34.0k
    {                                                                        \
175
34.0k
        ctxtype *ctx = vctx;                                                 \
176
34.0k
        mmm##_DestroyContext(ctx, freeit);                                   \
177
34.0k
    }
pkcs11c.c:SFTKCipher_AES_DestroyContext
Line
Count
Source
174
111k
    {                                                                        \
175
111k
        ctxtype *ctx = vctx;                                                 \
176
111k
        mmm##_DestroyContext(ctx, freeit);                                   \
177
111k
    }
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_DestroyContext
178
179
#ifndef NSS_DISABLE_DEPRECATED_RC2
180
SFTKCipherWrap2(RC2Context, RC2);
181
#endif
182
SFTKCipherWrap2(RC4Context, RC4);
183
SFTKCipherWrap2(DESContext, DES);
184
#ifndef NSS_DISABLE_DEPRECATED_SEED
185
SFTKCipherWrap2(SEEDContext, SEED);
186
#endif
187
SFTKCipherWrap2(CamelliaContext, Camellia);
188
SFTKCipherWrap2(AESContext, AES);
189
SFTKCipherWrap2(AESKeyWrapContext, AESKeyWrap);
190
191
#if NSS_SOFTOKEN_DOES_RC5
192
SFTKCipherWrap2(RC5Context, RC5);
193
#endif
194
195
/*
196
 * free routines.... Free local type  allocated data, and convert
197
 * other free routines to the destroy signature.
198
 */
199
static void
200
sftk_FreePrivKey(void *vkey, PRBool freeit)
201
0
{
202
0
    NSSLOWKEYPrivateKey *key = vkey;
203
0
    nsslowkey_DestroyPrivateKey(key);
204
0
}
205
206
static void
207
sftk_Space(void *data, PRBool freeit)
208
279k
{
209
279k
    PORT_Free(data);
210
279k
}
211
212
static void
213
sftk_ZSpace(void *data, PRBool freeit)
214
5.58k
{
215
5.58k
    size_t len = *(size_t *)data;
216
5.58k
    PORT_ZFree(data, len);
217
5.58k
}
218
219
/*
220
 * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
221
 * Deprecating a full des key to 40 bit key strenth.
222
 */
223
static CK_RV
224
sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey)
225
3
{
226
3
    unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae };
227
3
    unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 };
228
3
    unsigned char enc_src[8];
229
3
    unsigned char enc_dest[8];
230
3
    unsigned int leng, i;
231
3
    DESContext *descx;
232
3
    SECStatus rv;
233
3
    CK_RV crv = CKR_OK;
234
235
    /* zero the parity bits */
236
27
    for (i = 0; i < 8; i++) {
237
24
        enc_src[i] = cdmfkey[i] & 0xfe;
238
24
    }
239
240
    /* encrypt with key 1 */
241
3
    descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE);
242
3
    if (descx == NULL) {
243
0
        crv = CKR_HOST_MEMORY;
244
0
        goto done;
245
0
    }
246
3
    rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8);
247
3
    DES_DestroyContext(descx, PR_TRUE);
248
3
    if (rv != SECSuccess) {
249
0
        crv = sftk_MapCryptError(PORT_GetError());
250
0
        goto done;
251
0
    }
252
253
    /* xor source with des, zero the parity bits and deprecate the key*/
254
27
    for (i = 0; i < 8; i++) {
255
24
        if (i & 1) {
256
12
            enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe;
257
12
        } else {
258
12
            enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e;
259
12
        }
260
24
    }
261
262
    /* encrypt with key 2 */
263
3
    descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE);
264
3
    if (descx == NULL) {
265
0
        crv = CKR_HOST_MEMORY;
266
0
        goto done;
267
0
    }
268
3
    rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8);
269
3
    DES_DestroyContext(descx, PR_TRUE);
270
3
    if (rv != SECSuccess) {
271
0
        crv = sftk_MapCryptError(PORT_GetError());
272
0
        goto done;
273
0
    }
274
275
    /* set the corret parity on our new des key */
276
3
    sftk_FormatDESKey(deskey, 8);
277
3
done:
278
3
    PORT_Memset(enc_src, 0, sizeof enc_src);
279
3
    PORT_Memset(enc_dest, 0, sizeof enc_dest);
280
3
    return crv;
281
3
}
282
283
/* NSC_DestroyObject destroys an object. */
284
CK_RV
285
NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
286
1.46M
{
287
1.46M
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
288
1.46M
    SFTKSession *session;
289
1.46M
    SFTKObject *object;
290
1.46M
    SFTKFreeStatus status;
291
292
1.46M
    CHECK_FORK();
293
294
1.46M
    if (slot == NULL) {
295
0
        return CKR_SESSION_HANDLE_INVALID;
296
0
    }
297
    /*
298
     * This whole block just makes sure we really can destroy the
299
     * requested object.
300
     */
301
1.46M
    session = sftk_SessionFromHandle(hSession);
302
1.46M
    if (session == NULL) {
303
0
        return CKR_SESSION_HANDLE_INVALID;
304
0
    }
305
306
1.46M
    object = sftk_ObjectFromHandle(hObject, session);
307
1.46M
    if (object == NULL) {
308
489
        sftk_FreeSession(session);
309
489
        return CKR_OBJECT_HANDLE_INVALID;
310
489
    }
311
312
    /* don't destroy a private object if we aren't logged in */
313
1.46M
    PR_Lock(slot->slotLock);
314
1.46M
    PRBool wouldNeedToLogIn = !slot->isLoggedIn && slot->needLogin;
315
1.46M
    PR_Unlock(slot->slotLock);
316
1.46M
    if (wouldNeedToLogIn && sftk_isTrue(object, CKA_PRIVATE)) {
317
0
        sftk_FreeSession(session);
318
0
        sftk_FreeObject(object);
319
0
        return CKR_USER_NOT_LOGGED_IN;
320
0
    }
321
322
    /* don't destroy a token object if we aren't in a rw session */
323
324
1.46M
    if (((session->info.flags & CKF_RW_SESSION) == 0) &&
325
1.46M
        (sftk_isTrue(object, CKA_TOKEN))) {
326
0
        sftk_FreeSession(session);
327
0
        sftk_FreeObject(object);
328
0
        return CKR_SESSION_READ_ONLY;
329
0
    }
330
331
1.46M
    sftk_DeleteObject(session, object);
332
333
1.46M
    sftk_FreeSession(session);
334
335
    /*
336
     * get some indication if the object is destroyed. Note: this is not
337
     * 100%. Someone may have an object reference outstanding (though that
338
     * should not be the case by here. Also note that the object is "half"
339
     * destroyed. Our internal representation is destroyed, but it may still
340
     * be in the data base.
341
     */
342
1.46M
    status = sftk_FreeObject(object);
343
344
1.46M
    return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;
345
1.46M
}
346
347
/*
348
 * Returns true if "params" contains a valid set of PSS parameters
349
 */
350
static PRBool
351
sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params)
352
5.58k
{
353
5.58k
    if (!params) {
354
0
        return PR_FALSE;
355
0
    }
356
5.58k
    if (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL ||
357
5.58k
        sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) {
358
2
        return PR_FALSE;
359
2
    }
360
5.58k
    return PR_TRUE;
361
5.58k
}
362
363
/*
364
 * Returns true if "params" contains a valid set of OAEP parameters
365
 */
366
static PRBool
367
sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS *params)
368
0
{
369
0
    if (!params) {
370
0
        return PR_FALSE;
371
0
    }
372
    /* The requirements of ulSourceLen/pSourceData come from PKCS #11, which
373
     * state:
374
     *   If the parameter is empty, pSourceData must be NULL and
375
     *   ulSourceDataLen must be zero.
376
     */
377
0
    if (params->source != CKZ_DATA_SPECIFIED ||
378
0
        (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) ||
379
0
        (sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) ||
380
0
        (params->ulSourceDataLen == 0 && params->pSourceData != NULL) ||
381
0
        (params->ulSourceDataLen != 0 && params->pSourceData == NULL)) {
382
0
        return PR_FALSE;
383
0
    }
384
0
    return PR_TRUE;
385
0
}
386
387
/*
388
 * return a context based on the SFTKContext type.
389
 */
390
SFTKSessionContext *
391
sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type)
392
23.9M
{
393
23.9M
    switch (type) {
394
690k
        case SFTK_ENCRYPT:
395
1.24M
        case SFTK_DECRYPT:
396
1.34M
        case SFTK_MESSAGE_ENCRYPT:
397
1.58M
        case SFTK_MESSAGE_DECRYPT:
398
1.58M
            return session->enc_context;
399
20.2M
        case SFTK_HASH:
400
20.2M
            return session->hash_context;
401
1.97M
        case SFTK_SIGN:
402
1.97M
        case SFTK_SIGN_RECOVER:
403
2.05M
        case SFTK_VERIFY:
404
2.12M
        case SFTK_VERIFY_RECOVER:
405
2.12M
        case SFTK_MESSAGE_SIGN:
406
2.12M
        case SFTK_MESSAGE_VERIFY:
407
2.12M
            return session->hash_context;
408
23.9M
    }
409
0
    return NULL;
410
23.9M
}
411
412
/*
413
 * change a context based on the SFTKContext type.
414
 */
415
void
416
sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
417
                      SFTKSessionContext *context)
418
3.34M
{
419
3.34M
    switch (type) {
420
307k
        case SFTK_ENCRYPT:
421
563k
        case SFTK_DECRYPT:
422
597k
        case SFTK_MESSAGE_ENCRYPT:
423
708k
        case SFTK_MESSAGE_DECRYPT:
424
708k
            session->enc_context = context;
425
708k
            break;
426
1.77M
        case SFTK_HASH:
427
1.77M
            session->hash_context = context;
428
1.77M
            break;
429
805k
        case SFTK_SIGN:
430
805k
        case SFTK_SIGN_RECOVER:
431
828k
        case SFTK_VERIFY:
432
863k
        case SFTK_VERIFY_RECOVER:
433
863k
        case SFTK_MESSAGE_SIGN:
434
863k
        case SFTK_MESSAGE_VERIFY:
435
863k
            session->hash_context = context;
436
863k
            break;
437
3.34M
    }
438
3.34M
    return;
439
3.34M
}
440
441
/*
442
 * Atomically install a freshly-initialized context onto a session, used
443
 * by every C_...Init function. The bucket lock makes the "is the slot
444
 * empty?" check and the assignment a single critical section, closing
445
 * the race where two threads concurrently entering an Init each pass
446
 * the unlocked check in sftk_InitGeneric, allocate a context, and then
447
 * one overwrites the other's pointer (leaking the loser's context).
448
 *
449
 * On CKR_OPERATION_ACTIVE the caller retains ownership of `context` and
450
 * must free it (typically via sftk_FreeContext).
451
 */
452
CK_RV
453
sftk_InstallContext(SFTKSession *session, SFTKContextType type,
454
                    SFTKSessionContext *context)
455
2.02M
{
456
2.02M
    SFTKSlot *slot = sftk_SlotFromSession(session);
457
2.02M
    PRLock *lock = SFTK_SESSION_LOCK(slot, session->handle);
458
2.02M
    CK_RV crv;
459
460
2.02M
    PR_Lock(lock);
461
2.02M
    if (sftk_ReturnContextByType(session, type) != NULL) {
462
0
        crv = CKR_OPERATION_ACTIVE;
463
2.02M
    } else {
464
2.02M
        sftk_SetContextByType(session, type, context);
465
2.02M
        crv = CKR_OK;
466
2.02M
    }
467
2.02M
    PR_Unlock(lock);
468
2.02M
    return crv;
469
2.02M
}
470
471
/* Pair to sftk_InstallContext. Atomically detach whatever context is
472
 * stored on the session for `type` and free it. Holding the session
473
 * bucket lock for the detach ensures that a concurrent
474
 * sftk_InstallContext sees either the old context still in place
475
 * (yielding CKR_OPERATION_ACTIVE) or the slot already NULL (allowing
476
 * its install to succeed), never a transient stale pointer. */
477
void
478
sftk_UninstallContext(SFTKSession *session, SFTKContextType type)
479
1.32M
{
480
1.32M
    SFTKSlot *slot = sftk_SlotFromSession(session);
481
1.32M
    PRLock *lock = SFTK_SESSION_LOCK(slot, session->handle);
482
1.32M
    SFTKSessionContext *context;
483
484
1.32M
    PR_Lock(lock);
485
1.32M
    context = sftk_ReturnContextByType(session, type);
486
1.32M
    sftk_SetContextByType(session, type, NULL);
487
    /* Read isFIPS while still under the lock so the write to
488
     * session->lastOpWasFIPS reflects the context being torn down,
489
     * not one a concurrent installer might race in afterwards. */
490
1.32M
    if (context) {
491
1.17M
        session->lastOpWasFIPS = context->isFIPS;
492
1.17M
    }
493
1.32M
    PR_Unlock(lock);
494
1.32M
    if (context) {
495
1.17M
        sftk_FreeContext(context);
496
1.17M
    }
497
1.32M
}
498
499
/*
500
 * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal,
501
 * and C_XXX function. The function takes a session handle, the context
502
 * type, and whether or not the session needs to be multipart. It
503
 * returns the context and the session pointer; the caller is
504
 * responsible for freeing the session. If the caller doesn't need
505
 * a context lookup (e.g. it already holds a session reference), it
506
 * should call sftk_ReturnContextByType directly.
507
 */
508
CK_RV
509
sftk_GetContext(CK_SESSION_HANDLE handle, SFTKSessionContext **contextPtr,
510
                SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr)
511
18.3M
{
512
18.3M
    SFTKSession *session;
513
18.3M
    SFTKSessionContext *context;
514
515
18.3M
    PORT_Assert(sessionPtr != NULL);
516
18.3M
    session = sftk_SessionFromHandle(handle);
517
18.3M
    if (session == NULL)
518
0
        return CKR_SESSION_HANDLE_INVALID;
519
18.3M
    context = sftk_ReturnContextByType(session, type);
520
    /* make sure the context is valid */
521
18.3M
    if ((context == NULL) || (context->type != type) || (needMulti && !(context->multi))) {
522
181k
        sftk_FreeSession(session);
523
181k
        return CKR_OPERATION_NOT_INITIALIZED;
524
181k
    }
525
18.1M
    *contextPtr = context;
526
18.1M
    *sessionPtr = session;
527
18.1M
    return CKR_OK;
528
18.3M
}
529
530
/* Terminate operation (in the PKCS#11 spec sense). Thin wrapper over
531
 * sftk_UninstallContext: the install/uninstall pair takes the slot
532
 * lock, frees whatever is currently installed for `ctype`, and reads
533
 * context->isFIPS into session->lastOpWasFIPS under the lock. */
534
void
535
sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype)
536
1.15M
{
537
1.15M
    sftk_UninstallContext(session, ctype);
538
1.15M
}
539
540
/*
541
 ************** Crypto Functions:     Encrypt ************************
542
 */
543
544
/*
545
 * All the NSC_InitXXX functions have a set of common checks and processing they
546
 * all need to do at the beginning. This is done here.
547
 */
548
CK_RV
549
sftk_InitGeneric(SFTKSession *session, CK_MECHANISM *pMechanism,
550
                 SFTKSessionContext **contextPtr,
551
                 SFTKContextType ctype, SFTKObject **keyPtr,
552
                 CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
553
                 CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation)
554
2.02M
{
555
2.02M
    SFTKObject *key = NULL;
556
2.02M
    SFTKAttribute *att;
557
2.02M
    SFTKSessionContext *context;
558
559
    /* We can only init if there is not current context active */
560
2.02M
    if (sftk_ReturnContextByType(session, ctype) != NULL) {
561
0
        return CKR_OPERATION_ACTIVE;
562
0
    }
563
564
    /* find the key */
565
2.02M
    if (keyPtr) {
566
1.04M
        key = sftk_ObjectFromHandle(hKey, session);
567
1.04M
        if (key == NULL) {
568
0
            return CKR_KEY_HANDLE_INVALID;
569
0
        }
570
571
        /* make sure it's a valid  key for this operation */
572
1.04M
        if (((key->objclass != CKO_SECRET_KEY) &&
573
156k
             (key->objclass != pubKeyType)) ||
574
1.04M
            !sftk_isTrue(key, operation)) {
575
0
            sftk_FreeObject(key);
576
0
            return CKR_KEY_TYPE_INCONSISTENT;
577
0
        }
578
        /* get the key type */
579
1.04M
        att = sftk_FindAttribute(key, CKA_KEY_TYPE);
580
1.04M
        if (att == NULL) {
581
0
            sftk_FreeObject(key);
582
0
            return CKR_KEY_TYPE_INCONSISTENT;
583
0
        }
584
1.04M
        PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE));
585
1.04M
        if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) {
586
0
            sftk_FreeAttribute(att);
587
0
            sftk_FreeObject(key);
588
0
            return CKR_ATTRIBUTE_VALUE_INVALID;
589
0
        }
590
1.04M
        PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE));
591
1.04M
        sftk_FreeAttribute(att);
592
1.04M
        *keyPtr = key;
593
1.04M
    }
594
595
    /* allocate the context structure */
596
2.02M
    context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext));
597
2.02M
    if (context == NULL) {
598
0
        if (key)
599
0
            sftk_FreeObject(key);
600
0
        return CKR_HOST_MEMORY;
601
0
    }
602
2.02M
    context->type = ctype;
603
2.02M
    context->multi = PR_TRUE;
604
2.02M
    context->rsa = PR_FALSE;
605
2.02M
    context->cipherInfo = NULL;
606
2.02M
    context->hashInfo = NULL;
607
2.02M
    context->doPad = PR_FALSE;
608
2.02M
    context->padDataLength = 0;
609
2.02M
    context->key = key;
610
2.02M
    context->blockSize = 0;
611
2.02M
    context->maxLen = 0;
612
2.02M
    context->signature = NULL;
613
2.02M
    context->isFIPS = sftk_operationIsFIPS(session->slot, pMechanism,
614
2.02M
                                           operation, key, 0);
615
2.02M
    *contextPtr = context;
616
2.02M
    return CKR_OK;
617
2.02M
}
618
619
static int
620
sftk_aes_mode(CK_MECHANISM_TYPE mechanism)
621
111k
{
622
111k
    switch (mechanism) {
623
473
        case CKM_AES_CBC_PAD:
624
89.7k
        case CKM_AES_CBC:
625
89.7k
            return NSS_AES_CBC;
626
20.7k
        case CKM_AES_ECB:
627
20.7k
            return NSS_AES;
628
0
        case CKM_AES_CTS:
629
0
            return NSS_AES_CTS;
630
450
        case CKM_AES_CTR:
631
450
            return NSS_AES_CTR;
632
657
        case CKM_AES_GCM:
633
657
            return NSS_AES_GCM;
634
111k
    }
635
0
    return -1;
636
111k
}
637
638
static SECStatus
639
sftk_RSAEncryptRaw(void *ctx, unsigned char *output,
640
                   unsigned int *outputLen, unsigned int maxLen,
641
                   const unsigned char *input, unsigned int inputLen)
642
0
{
643
0
    NSSLOWKEYPublicKey *key = ctx;
644
0
    SECStatus rv = SECFailure;
645
646
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
647
0
    if (key->keyType != NSSLOWKEYRSAKey) {
648
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
649
0
        return SECFailure;
650
0
    }
651
652
0
    rv = RSA_EncryptRaw(&key->u.rsa, output, outputLen, maxLen, input,
653
0
                        inputLen);
654
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
655
0
        sftk_fatalError = PR_TRUE;
656
0
    }
657
658
0
    return rv;
659
0
}
660
661
static SECStatus
662
sftk_RSADecryptRaw(void *ctx, unsigned char *output,
663
                   unsigned int *outputLen, unsigned int maxLen,
664
                   const unsigned char *input, unsigned int inputLen)
665
0
{
666
0
    NSSLOWKEYPrivateKey *key = ctx;
667
0
    SECStatus rv = SECFailure;
668
669
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
670
0
    if (key->keyType != NSSLOWKEYRSAKey) {
671
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
672
0
        return SECFailure;
673
0
    }
674
675
0
    rv = RSA_DecryptRaw(&key->u.rsa, output, outputLen, maxLen, input,
676
0
                        inputLen);
677
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
678
0
        sftk_fatalError = PR_TRUE;
679
0
    }
680
681
0
    return rv;
682
0
}
683
684
static SECStatus
685
sftk_RSAEncrypt(void *ctx, unsigned char *output,
686
                unsigned int *outputLen, unsigned int maxLen,
687
                const unsigned char *input, unsigned int inputLen)
688
15.5k
{
689
15.5k
    NSSLOWKEYPublicKey *key = ctx;
690
15.5k
    SECStatus rv = SECFailure;
691
692
15.5k
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
693
15.5k
    if (key->keyType != NSSLOWKEYRSAKey) {
694
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
695
0
        return SECFailure;
696
0
    }
697
698
15.5k
    rv = RSA_EncryptBlock(&key->u.rsa, output, outputLen, maxLen, input,
699
15.5k
                          inputLen);
700
15.5k
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
701
0
        sftk_fatalError = PR_TRUE;
702
0
    }
703
704
15.5k
    return rv;
705
15.5k
}
706
707
static SECStatus
708
sftk_RSADecrypt(void *ctx, unsigned char *output,
709
                unsigned int *outputLen, unsigned int maxLen,
710
                const unsigned char *input, unsigned int inputLen)
711
82.6k
{
712
82.6k
    NSSLOWKEYPrivateKey *key = ctx;
713
82.6k
    SECStatus rv = SECFailure;
714
715
82.6k
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
716
82.6k
    if (key->keyType != NSSLOWKEYRSAKey) {
717
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
718
0
        return SECFailure;
719
0
    }
720
721
82.6k
    rv = RSA_DecryptBlock(&key->u.rsa, output, outputLen, maxLen, input,
722
82.6k
                          inputLen);
723
82.6k
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
724
0
        sftk_fatalError = PR_TRUE;
725
0
    }
726
727
82.6k
    return rv;
728
82.6k
}
729
730
static void
731
sftk_freeRSAOAEPInfo(void *ctx, PRBool freeit)
732
0
{
733
0
    SFTKOAEPInfo *info = ctx;
734
0
    PORT_ZFree(info->params.pSourceData, info->params.ulSourceDataLen);
735
0
    PORT_ZFree(info, sizeof(SFTKOAEPInfo));
736
0
}
737
738
static SECStatus
739
sftk_RSAEncryptOAEP(void *ctx, unsigned char *output,
740
                    unsigned int *outputLen, unsigned int maxLen,
741
                    const unsigned char *input, unsigned int inputLen)
742
0
{
743
0
    SFTKOAEPInfo *info = ctx;
744
0
    HASH_HashType hashAlg;
745
0
    HASH_HashType maskHashAlg;
746
747
0
    PORT_Assert(info->key.pub->keyType == NSSLOWKEYRSAKey);
748
0
    if (info->key.pub->keyType != NSSLOWKEYRSAKey) {
749
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
750
0
        return SECFailure;
751
0
    }
752
753
0
    hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg);
754
0
    maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf);
755
756
0
    return RSA_EncryptOAEP(&info->key.pub->u.rsa, hashAlg, maskHashAlg,
757
0
                           (const unsigned char *)info->params.pSourceData,
758
0
                           info->params.ulSourceDataLen, NULL, 0,
759
0
                           output, outputLen, maxLen, input, inputLen);
760
0
}
761
762
static SECStatus
763
sftk_RSADecryptOAEP(void *ctx, unsigned char *output,
764
                    unsigned int *outputLen, unsigned int maxLen,
765
                    const unsigned char *input, unsigned int inputLen)
766
0
{
767
0
    SFTKOAEPInfo *info = ctx;
768
0
    SECStatus rv = SECFailure;
769
0
    HASH_HashType hashAlg;
770
0
    HASH_HashType maskHashAlg;
771
772
0
    PORT_Assert(info->key.priv->keyType == NSSLOWKEYRSAKey);
773
0
    if (info->key.priv->keyType != NSSLOWKEYRSAKey) {
774
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
775
0
        return SECFailure;
776
0
    }
777
778
0
    hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg);
779
0
    maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf);
780
781
0
    rv = RSA_DecryptOAEP(&info->key.priv->u.rsa, hashAlg, maskHashAlg,
782
0
                         (const unsigned char *)info->params.pSourceData,
783
0
                         info->params.ulSourceDataLen,
784
0
                         output, outputLen, maxLen, input, inputLen);
785
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
786
0
        sftk_fatalError = PR_TRUE;
787
0
    }
788
0
    return rv;
789
0
}
790
791
static SFTKChaCha20Poly1305Info *
792
sftk_ChaCha20Poly1305_CreateContext(const unsigned char *key,
793
                                    unsigned int keyLen,
794
                                    const CK_NSS_AEAD_PARAMS *params)
795
392
{
796
392
    SFTKChaCha20Poly1305Info *ctx;
797
798
392
    if (params->ulNonceLen != sizeof(ctx->nonce)) {
799
52
        PORT_SetError(SEC_ERROR_INPUT_LEN);
800
52
        return NULL;
801
52
    }
802
803
340
    ctx = PORT_New(SFTKChaCha20Poly1305Info);
804
340
    if (ctx == NULL) {
805
0
        return NULL;
806
0
    }
807
808
340
    if (ChaCha20Poly1305_InitContext(&ctx->freeblCtx, key, keyLen,
809
340
                                     params->ulTagLen) != SECSuccess) {
810
96
        PORT_Free(ctx);
811
96
        return NULL;
812
96
    }
813
814
244
    PORT_Memcpy(ctx->nonce, params->pNonce, sizeof(ctx->nonce));
815
816
    /* AAD data and length must both be null, or both non-null. */
817
244
    PORT_Assert((params->pAAD == NULL) == (params->ulAADLen == 0));
818
819
244
    if (params->ulAADLen > sizeof(ctx->ad)) {
820
        /* Need to allocate an overflow buffer for the additional data. */
821
0
        ctx->adOverflow = (unsigned char *)PORT_Alloc(params->ulAADLen);
822
0
        if (!ctx->adOverflow) {
823
0
            PORT_Free(ctx);
824
0
            return NULL;
825
0
        }
826
0
        PORT_Memcpy(ctx->adOverflow, params->pAAD, params->ulAADLen);
827
244
    } else {
828
244
        ctx->adOverflow = NULL;
829
244
        if (params->pAAD) {
830
0
            PORT_Memcpy(ctx->ad, params->pAAD, params->ulAADLen);
831
0
        }
832
244
    }
833
244
    ctx->adLen = params->ulAADLen;
834
835
244
    return ctx;
836
244
}
837
838
static void
839
sftk_ChaCha20Poly1305_DestroyContext(void *vctx,
840
                                     PRBool freeit)
841
244
{
842
244
    SFTKChaCha20Poly1305Info *ctx = vctx;
843
244
    ChaCha20Poly1305_DestroyContext(&ctx->freeblCtx, PR_FALSE);
844
244
    if (ctx->adOverflow != NULL) {
845
0
        PORT_ZFree(ctx->adOverflow, ctx->adLen);
846
0
        ctx->adOverflow = NULL;
847
244
    } else {
848
244
        PORT_Memset(ctx->ad, 0, ctx->adLen);
849
244
    }
850
244
    ctx->adLen = 0;
851
244
    if (freeit) {
852
244
        PORT_Free(ctx);
853
244
    }
854
244
}
855
856
static SECStatus
857
sftk_ChaCha20Poly1305_Encrypt(void *vctx,
858
                              unsigned char *output, unsigned int *outputLen,
859
                              unsigned int maxOutputLen,
860
                              const unsigned char *input, unsigned int inputLen)
861
113
{
862
113
    const SFTKChaCha20Poly1305Info *ctx = vctx;
863
113
    const unsigned char *ad = ctx->adOverflow;
864
865
113
    if (ad == NULL) {
866
113
        ad = ctx->ad;
867
113
    }
868
869
113
    return ChaCha20Poly1305_Seal(&ctx->freeblCtx, output, outputLen,
870
113
                                 maxOutputLen, input, inputLen, ctx->nonce,
871
113
                                 sizeof(ctx->nonce), ad, ctx->adLen);
872
113
}
873
874
static SECStatus
875
sftk_ChaCha20Poly1305_Decrypt(void *vctx,
876
                              unsigned char *output, unsigned int *outputLen,
877
                              unsigned int maxOutputLen,
878
                              const unsigned char *input, unsigned int inputLen)
879
131
{
880
131
    const SFTKChaCha20Poly1305Info *ctx = vctx;
881
131
    const unsigned char *ad = ctx->adOverflow;
882
883
131
    if (ad == NULL) {
884
131
        ad = ctx->ad;
885
131
    }
886
887
131
    return ChaCha20Poly1305_Open(&ctx->freeblCtx, output, outputLen,
888
131
                                 maxOutputLen, input, inputLen, ctx->nonce,
889
131
                                 sizeof(ctx->nonce), ad, ctx->adLen);
890
131
}
891
892
static SECStatus
893
sftk_ChaCha20Ctr(void *vctx,
894
                 unsigned char *output, unsigned int *outputLen,
895
                 unsigned int maxOutputLen,
896
                 const unsigned char *input, unsigned int inputLen)
897
16.6k
{
898
16.6k
    if (maxOutputLen < inputLen) {
899
0
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
900
0
        return SECFailure;
901
0
    }
902
16.6k
    SFTKChaCha20CtrInfo *ctx = vctx;
903
16.6k
    ChaCha20_Xor(output, input, inputLen, ctx->key,
904
16.6k
                 ctx->nonce, ctx->counter);
905
16.6k
    *outputLen = inputLen;
906
16.6k
    return SECSuccess;
907
16.6k
}
908
909
static void
910
sftk_ChaCha20Ctr_DestroyContext(void *vctx,
911
                                PRBool freeit)
912
16.6k
{
913
16.6k
    SFTKChaCha20CtrInfo *ctx = vctx;
914
16.6k
    memset(ctx, 0, sizeof(SFTKChaCha20CtrInfo));
915
16.6k
    if (freeit) {
916
16.6k
        PORT_Free(ctx);
917
16.6k
    }
918
16.6k
}
919
920
/** NSC_CryptInit initializes an encryption/Decryption operation.
921
 *
922
 * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey.
923
 * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block
924
 *  ciphers MAC'ing.
925
 */
926
CK_RV
927
sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
928
               CK_OBJECT_HANDLE hKey,
929
               CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage,
930
               SFTKContextType contextType, PRBool isEncrypt)
931
370k
{
932
370k
    SFTKSession *session;
933
370k
    SFTKObject *key;
934
370k
    SFTKSessionContext *context;
935
370k
    SFTKAttribute *att;
936
370k
#ifndef NSS_DISABLE_DEPRECATED_RC2
937
370k
    CK_RC2_CBC_PARAMS *rc2_param;
938
370k
    unsigned effectiveKeyLength;
939
370k
#endif
940
#if NSS_SOFTOKEN_DOES_RC5
941
    CK_RC5_CBC_PARAMS *rc5_param;
942
    SECItem rc5Key;
943
#endif
944
370k
    CK_NSS_GCM_PARAMS nss_gcm_param;
945
370k
    void *aes_param;
946
370k
    CK_NSS_AEAD_PARAMS nss_aead_params;
947
370k
    CK_NSS_AEAD_PARAMS *nss_aead_params_ptr = NULL;
948
370k
    CK_KEY_TYPE key_type;
949
370k
    CK_RV crv = CKR_OK;
950
370k
    unsigned char newdeskey[24];
951
370k
    PRBool useNewKey = PR_FALSE;
952
370k
    int t;
953
954
370k
    if (!pMechanism) {
955
0
        return CKR_MECHANISM_PARAM_INVALID;
956
0
    }
957
958
370k
    crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage);
959
370k
    if (crv != CKR_OK)
960
655
        return crv;
961
962
369k
    session = sftk_SessionFromHandle(hSession);
963
369k
    if (session == NULL)
964
0
        return CKR_SESSION_HANDLE_INVALID;
965
966
369k
    crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key,
967
369k
                           hKey, &key_type,
968
369k
                           isEncrypt ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY,
969
369k
                           keyUsage);
970
971
369k
    if (crv != CKR_OK) {
972
0
        sftk_FreeSession(session);
973
0
        return crv;
974
0
    }
975
976
369k
    context->doPad = PR_FALSE;
977
369k
    switch (pMechanism->mechanism) {
978
98.1k
        case CKM_RSA_PKCS:
979
98.1k
        case CKM_RSA_X_509:
980
98.1k
            if (key_type != CKK_RSA) {
981
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
982
0
                break;
983
0
            }
984
98.1k
            context->multi = PR_FALSE;
985
98.1k
            context->rsa = PR_TRUE;
986
98.1k
            if (isEncrypt) {
987
15.5k
                NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
988
15.5k
                if (pubKey == NULL) {
989
0
                    crv = CKR_KEY_HANDLE_INVALID;
990
0
                    break;
991
0
                }
992
15.5k
                context->maxLen = nsslowkey_PublicModulusLen(pubKey);
993
15.5k
                context->cipherInfo = (void *)pubKey;
994
15.5k
                context->update = pMechanism->mechanism == CKM_RSA_X_509
995
15.5k
                                      ? sftk_RSAEncryptRaw
996
15.5k
                                      : sftk_RSAEncrypt;
997
82.6k
            } else {
998
82.6k
                NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key, CKK_RSA, &crv);
999
82.6k
                if (privKey == NULL) {
1000
0
                    crv = CKR_KEY_HANDLE_INVALID;
1001
0
                    break;
1002
0
                }
1003
82.6k
                context->maxLen = nsslowkey_PrivateModulusLen(privKey);
1004
82.6k
                context->cipherInfo = (void *)privKey;
1005
82.6k
                context->update = pMechanism->mechanism == CKM_RSA_X_509
1006
82.6k
                                      ? sftk_RSADecryptRaw
1007
82.6k
                                      : sftk_RSADecrypt;
1008
82.6k
            }
1009
98.1k
            context->destroy = sftk_Null;
1010
98.1k
            break;
1011
0
        case CKM_RSA_PKCS_OAEP:
1012
0
            if (key_type != CKK_RSA) {
1013
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1014
0
                break;
1015
0
            }
1016
0
            if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) ||
1017
0
                !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter)) {
1018
0
                crv = CKR_MECHANISM_PARAM_INVALID;
1019
0
                break;
1020
0
            }
1021
0
            context->multi = PR_FALSE;
1022
0
            context->rsa = PR_TRUE;
1023
0
            {
1024
0
                SFTKOAEPInfo *info;
1025
0
                CK_RSA_PKCS_OAEP_PARAMS *params =
1026
0
                    (CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter;
1027
                /* make a copy of the source data value for future
1028
                 * use (once the user has reclaimed his data in pParameter)*/
1029
0
                void *newSource = NULL;
1030
0
                if (params->pSourceData) {
1031
0
                    newSource = PORT_Alloc(params->ulSourceDataLen);
1032
0
                    if (newSource == NULL) {
1033
0
                        crv = CKR_HOST_MEMORY;
1034
0
                        break;
1035
0
                    }
1036
0
                    PORT_Memcpy(newSource, params->pSourceData, params->ulSourceDataLen);
1037
0
                }
1038
0
                info = PORT_New(SFTKOAEPInfo);
1039
0
                if (info == NULL) {
1040
0
                    PORT_ZFree(newSource, params->ulSourceDataLen);
1041
0
                    crv = CKR_HOST_MEMORY;
1042
0
                    break;
1043
0
                }
1044
0
                info->params = *params;
1045
0
                info->params.pSourceData = newSource;
1046
0
                info->isEncrypt = isEncrypt;
1047
1048
                /* now setup encryption and decryption contexts */
1049
0
                if (isEncrypt) {
1050
0
                    info->key.pub = sftk_GetPubKey(key, CKK_RSA, &crv);
1051
0
                    if (info->key.pub == NULL) {
1052
0
                        sftk_freeRSAOAEPInfo(info, PR_TRUE);
1053
0
                        crv = CKR_KEY_HANDLE_INVALID;
1054
0
                        break;
1055
0
                    }
1056
0
                    context->update = sftk_RSAEncryptOAEP;
1057
0
                    context->maxLen = nsslowkey_PublicModulusLen(info->key.pub);
1058
0
                } else {
1059
0
                    info->key.priv = sftk_GetPrivKey(key, CKK_RSA, &crv);
1060
0
                    if (info->key.priv == NULL) {
1061
0
                        sftk_freeRSAOAEPInfo(info, PR_TRUE);
1062
0
                        crv = CKR_KEY_HANDLE_INVALID;
1063
0
                        break;
1064
0
                    }
1065
0
                    context->update = sftk_RSADecryptOAEP;
1066
0
                    context->maxLen = nsslowkey_PrivateModulusLen(info->key.priv);
1067
0
                }
1068
0
                context->cipherInfo = info;
1069
0
            }
1070
0
            context->destroy = sftk_freeRSAOAEPInfo;
1071
0
            break;
1072
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
1073
0
        case CKM_RC2_CBC_PAD:
1074
0
            context->doPad = PR_TRUE;
1075
        /* fall thru */
1076
0
        case CKM_RC2_ECB:
1077
26
        case CKM_RC2_CBC:
1078
26
            context->blockSize = 8;
1079
26
            if (key_type != CKK_RC2) {
1080
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1081
0
                break;
1082
0
            }
1083
26
            att = sftk_FindAttribute(key, CKA_VALUE);
1084
26
            if (att == NULL) {
1085
0
                crv = CKR_KEY_HANDLE_INVALID;
1086
0
                break;
1087
0
            }
1088
1089
26
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_CBC_PARAMS))) {
1090
0
                sftk_FreeAttribute(att);
1091
0
                crv = CKR_MECHANISM_PARAM_INVALID;
1092
0
                break;
1093
0
            }
1094
26
            rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
1095
26
            effectiveKeyLength = (rc2_param->ulEffectiveBits + 7) / 8;
1096
26
            context->cipherInfo =
1097
26
                RC2_CreateContext((unsigned char *)att->attrib.pValue,
1098
26
                                  att->attrib.ulValueLen, rc2_param->iv,
1099
26
                                  pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : NSS_RC2_CBC, effectiveKeyLength);
1100
26
            sftk_FreeAttribute(att);
1101
26
            if (context->cipherInfo == NULL) {
1102
0
                crv = CKR_HOST_MEMORY;
1103
0
                break;
1104
0
            }
1105
26
            context->update = isEncrypt ? SFTKCipher_RC2_Encrypt : SFTKCipher_RC2_Decrypt;
1106
26
            context->destroy = SFTKCipher_RC2_DestroyContext;
1107
26
            break;
1108
0
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
1109
1110
#if NSS_SOFTOKEN_DOES_RC5
1111
        case CKM_RC5_CBC_PAD:
1112
            context->doPad = PR_TRUE;
1113
        /* fall thru */
1114
        case CKM_RC5_ECB:
1115
        case CKM_RC5_CBC:
1116
            if (key_type != CKK_RC5) {
1117
                crv = CKR_KEY_TYPE_INCONSISTENT;
1118
                break;
1119
            }
1120
            att = sftk_FindAttribute(key, CKA_VALUE);
1121
            if (att == NULL) {
1122
                crv = CKR_KEY_HANDLE_INVALID;
1123
                break;
1124
            }
1125
1126
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_CBC_PARAMS))) {
1127
                sftk_FreeAttribute(att);
1128
                crv = CKR_MECHANISM_PARAM_INVALID;
1129
                break;
1130
            }
1131
            rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
1132
            context->blockSize = rc5_param->ulWordsize * 2;
1133
            rc5Key.data = (unsigned char *)att->attrib.pValue;
1134
            rc5Key.len = att->attrib.ulValueLen;
1135
            context->cipherInfo = RC5_CreateContext(&rc5Key, rc5_param->ulRounds,
1136
                                                    rc5_param->ulWordsize, rc5_param->pIv,
1137
                                                    pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);
1138
            sftk_FreeAttribute(att);
1139
            if (context->cipherInfo == NULL) {
1140
                crv = CKR_HOST_MEMORY;
1141
                break;
1142
            }
1143
            context->update = isEncrypt ? SFTKCipher_RC5_Encrypt : SFTKCipher_RC5_Decrypt;
1144
            context->destroy = SFTKCipher_RC5_DestroyContext;
1145
            break;
1146
#endif
1147
5.97k
        case CKM_RC4:
1148
5.97k
            if (key_type != CKK_RC4) {
1149
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1150
0
                break;
1151
0
            }
1152
5.97k
            att = sftk_FindAttribute(key, CKA_VALUE);
1153
5.97k
            if (att == NULL) {
1154
0
                crv = CKR_KEY_HANDLE_INVALID;
1155
0
                break;
1156
0
            }
1157
5.97k
            context->cipherInfo =
1158
5.97k
                RC4_CreateContext((unsigned char *)att->attrib.pValue,
1159
5.97k
                                  att->attrib.ulValueLen);
1160
5.97k
            sftk_FreeAttribute(att);
1161
5.97k
            if (context->cipherInfo == NULL) {
1162
0
                crv = CKR_HOST_MEMORY; /* WRONG !!! */
1163
0
                break;
1164
0
            }
1165
5.97k
            context->update = isEncrypt ? SFTKCipher_RC4_Encrypt : SFTKCipher_RC4_Decrypt;
1166
5.97k
            context->destroy = SFTKCipher_RC4_DestroyContext;
1167
5.97k
            break;
1168
0
        case CKM_CDMF_CBC_PAD:
1169
0
            context->doPad = PR_TRUE;
1170
        /* fall thru */
1171
0
        case CKM_CDMF_ECB:
1172
3
        case CKM_CDMF_CBC:
1173
3
            if (key_type != CKK_CDMF) {
1174
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1175
0
                break;
1176
0
            }
1177
3
            t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;
1178
3
            goto finish_des;
1179
160
        case CKM_DES_ECB:
1180
160
            if (key_type != CKK_DES) {
1181
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1182
0
                break;
1183
0
            }
1184
160
            t = NSS_DES;
1185
160
            goto finish_des;
1186
0
        case CKM_DES_CBC_PAD:
1187
0
            context->doPad = PR_TRUE;
1188
        /* fall thru */
1189
11.8k
        case CKM_DES_CBC:
1190
11.8k
            if (key_type != CKK_DES) {
1191
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1192
0
                break;
1193
0
            }
1194
11.8k
            t = NSS_DES_CBC;
1195
11.8k
            goto finish_des;
1196
55.4k
        case CKM_DES3_ECB:
1197
55.4k
            if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
1198
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1199
0
                break;
1200
0
            }
1201
55.4k
            t = NSS_DES_EDE3;
1202
55.4k
            goto finish_des;
1203
0
        case CKM_DES3_CBC_PAD:
1204
0
            context->doPad = PR_TRUE;
1205
        /* fall thru */
1206
22.7k
        case CKM_DES3_CBC:
1207
22.7k
            if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
1208
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1209
0
                break;
1210
0
            }
1211
22.7k
            t = NSS_DES_EDE3_CBC;
1212
90.2k
        finish_des:
1213
90.2k
            if ((t != NSS_DES && t != NSS_DES_EDE3) && (pMechanism->pParameter == NULL ||
1214
34.6k
                                                        pMechanism->ulParameterLen < 8)) {
1215
10
                crv = CKR_DOMAIN_PARAMS_INVALID;
1216
10
                break;
1217
10
            }
1218
90.2k
            context->blockSize = 8;
1219
90.2k
            att = sftk_FindAttribute(key, CKA_VALUE);
1220
90.2k
            if (att == NULL) {
1221
0
                crv = CKR_KEY_HANDLE_INVALID;
1222
0
                break;
1223
0
            }
1224
90.2k
            if (key_type == CKK_DES2 &&
1225
0
                (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) {
1226
                /* extend DES2 key to DES3 key. */
1227
0
                memcpy(newdeskey, att->attrib.pValue, 16);
1228
0
                memcpy(newdeskey + 16, newdeskey, 8);
1229
0
                useNewKey = PR_TRUE;
1230
90.2k
            } else if (key_type == CKK_CDMF) {
1231
3
                crv = sftk_cdmf2des((unsigned char *)att->attrib.pValue, newdeskey);
1232
3
                if (crv != CKR_OK) {
1233
0
                    sftk_FreeAttribute(att);
1234
0
                    break;
1235
0
                }
1236
3
                useNewKey = PR_TRUE;
1237
3
            }
1238
90.2k
            context->cipherInfo = DES_CreateContext(
1239
90.2k
                useNewKey ? newdeskey : (unsigned char *)att->attrib.pValue,
1240
90.2k
                (unsigned char *)pMechanism->pParameter, t, isEncrypt);
1241
90.2k
            if (useNewKey)
1242
3
                memset(newdeskey, 0, sizeof newdeskey);
1243
90.2k
            sftk_FreeAttribute(att);
1244
90.2k
            if (context->cipherInfo == NULL) {
1245
0
                crv = CKR_HOST_MEMORY;
1246
0
                break;
1247
0
            }
1248
90.2k
            context->update = isEncrypt ? SFTKCipher_DES_Encrypt : SFTKCipher_DES_Decrypt;
1249
90.2k
            context->destroy = SFTKCipher_DES_DestroyContext;
1250
90.2k
            break;
1251
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
1252
0
        case CKM_SEED_CBC_PAD:
1253
0
            context->doPad = PR_TRUE;
1254
        /* fall thru */
1255
12.4k
        case CKM_SEED_CBC:
1256
12.4k
            if (!pMechanism->pParameter ||
1257
12.4k
                pMechanism->ulParameterLen != 16) {
1258
10
                crv = CKR_MECHANISM_PARAM_INVALID;
1259
10
                break;
1260
10
            }
1261
        /* fall thru */
1262
12.6k
        case CKM_SEED_ECB:
1263
12.6k
            context->blockSize = 16;
1264
12.6k
            if (key_type != CKK_SEED) {
1265
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1266
0
                break;
1267
0
            }
1268
12.6k
            att = sftk_FindAttribute(key, CKA_VALUE);
1269
12.6k
            if (att == NULL) {
1270
0
                crv = CKR_KEY_HANDLE_INVALID;
1271
0
                break;
1272
0
            }
1273
12.6k
            context->cipherInfo = SEED_CreateContext(
1274
12.6k
                (unsigned char *)att->attrib.pValue,
1275
12.6k
                (unsigned char *)pMechanism->pParameter,
1276
12.6k
                pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC,
1277
12.6k
                isEncrypt);
1278
12.6k
            sftk_FreeAttribute(att);
1279
12.6k
            if (context->cipherInfo == NULL) {
1280
0
                crv = CKR_HOST_MEMORY;
1281
0
                break;
1282
0
            }
1283
12.6k
            context->update = isEncrypt ? SFTKCipher_SEED_Encrypt : SFTKCipher_SEED_Decrypt;
1284
12.6k
            context->destroy = SFTKCipher_SEED_DestroyContext;
1285
12.6k
            break;
1286
0
#endif /* NSS_DISABLE_DEPRECATED_SEED */
1287
0
        case CKM_CAMELLIA_CBC_PAD:
1288
0
            context->doPad = PR_TRUE;
1289
        /* fall thru */
1290
33.6k
        case CKM_CAMELLIA_CBC:
1291
33.6k
            if (!pMechanism->pParameter ||
1292
33.6k
                pMechanism->ulParameterLen != 16) {
1293
6
                crv = CKR_MECHANISM_PARAM_INVALID;
1294
6
                break;
1295
6
            }
1296
        /* fall thru */
1297
34.0k
        case CKM_CAMELLIA_ECB:
1298
34.0k
            context->blockSize = 16;
1299
34.0k
            if (key_type != CKK_CAMELLIA) {
1300
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1301
0
                break;
1302
0
            }
1303
34.0k
            att = sftk_FindAttribute(key, CKA_VALUE);
1304
34.0k
            if (att == NULL) {
1305
0
                crv = CKR_KEY_HANDLE_INVALID;
1306
0
                break;
1307
0
            }
1308
34.0k
            context->cipherInfo = Camellia_CreateContext(
1309
34.0k
                (unsigned char *)att->attrib.pValue,
1310
34.0k
                (unsigned char *)pMechanism->pParameter,
1311
34.0k
                pMechanism->mechanism ==
1312
34.0k
                        CKM_CAMELLIA_ECB
1313
34.0k
                    ? NSS_CAMELLIA
1314
34.0k
                    : NSS_CAMELLIA_CBC,
1315
34.0k
                isEncrypt, att->attrib.ulValueLen);
1316
34.0k
            sftk_FreeAttribute(att);
1317
34.0k
            if (context->cipherInfo == NULL) {
1318
7
                crv = CKR_HOST_MEMORY;
1319
7
                break;
1320
7
            }
1321
34.0k
            context->update = isEncrypt ? SFTKCipher_Camellia_Encrypt : SFTKCipher_Camellia_Decrypt;
1322
34.0k
            context->destroy = SFTKCipher_Camellia_DestroyContext;
1323
34.0k
            break;
1324
1325
473
        case CKM_AES_CBC_PAD:
1326
473
            context->doPad = PR_TRUE;
1327
        /* fall thru */
1328
21.2k
        case CKM_AES_ECB:
1329
110k
        case CKM_AES_CBC:
1330
110k
            context->blockSize = 16;
1331
110k
        case CKM_AES_CTS:
1332
110k
        case CKM_AES_CTR:
1333
111k
        case CKM_AES_GCM:
1334
111k
            aes_param = pMechanism->pParameter;
1335
            /*
1336
             *  Due to a mismatch between the documentation and the header
1337
             *  file, two different definitions for CK_GCM_PARAMS exist.
1338
             *  The header file is normative according to Oasis, but NSS used
1339
             *  the documentation. In PKCS #11 v3.0, this was reconciled in
1340
             *  favor of the header file definition. To maintain binary
1341
             *  compatibility, NSS now defines CK_GCM_PARAMS_V3 as the official
1342
             *  version v3 (V2.4 header file) and CK_NSS_GCM_PARAMS as the
1343
             *  legacy (V2.4 documentation, NSS version). CK_GCM_PARAMS
1344
             *  is defined as CK_GCM_PARAMS_V3 if NSS_PKCS11_2_0_COMPAT is not
1345
             *  defined and CK_NSS_GCM_PARAMS if it is. Internally
1346
             *  softoken continues to use the legacy version. The code below
1347
             *  automatically detects which parameter was passed in and
1348
             *  converts CK_GCM_PARAMS_V3 to the CK_NSS_GCM_PARAMS (legacy
1349
             *  version) on the fly. NSS proper will eventually start
1350
             *  using the CK_GCM_PARAMS_V3 version and fall back to the
1351
             *  CK_NSS_GCM_PARAMS if the CK_GCM_PARAMS_V3 version fails with
1352
             *  CKR_MECHANISM_PARAM_INVALID.
1353
             */
1354
111k
            if (pMechanism->mechanism == CKM_AES_GCM) {
1355
657
                if (!aes_param) {
1356
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1357
0
                    break;
1358
0
                }
1359
657
                if (pMechanism->ulParameterLen == sizeof(CK_GCM_PARAMS_V3)) {
1360
                    /* convert the true V3 parameters into the old NSS parameters */
1361
0
                    CK_GCM_PARAMS_V3 *gcm_params = (CK_GCM_PARAMS_V3 *)aes_param;
1362
0
                    if (gcm_params->ulIvLen * 8 != gcm_params->ulIvBits) {
1363
                        /* only support byte aligned IV lengths */
1364
0
                        crv = CKR_MECHANISM_PARAM_INVALID;
1365
0
                        break;
1366
0
                    }
1367
0
                    aes_param = (void *)&nss_gcm_param;
1368
0
                    nss_gcm_param.pIv = gcm_params->pIv;
1369
0
                    nss_gcm_param.ulIvLen = gcm_params->ulIvLen;
1370
0
                    nss_gcm_param.pAAD = gcm_params->pAAD;
1371
0
                    nss_gcm_param.ulAADLen = gcm_params->ulAADLen;
1372
0
                    nss_gcm_param.ulTagBits = gcm_params->ulTagBits;
1373
657
                } else if (pMechanism->ulParameterLen != sizeof(CK_NSS_GCM_PARAMS)) {
1374
                    /* neither old nor new style params, must be invalid */
1375
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1376
0
                    break;
1377
0
                }
1378
110k
            } else if ((pMechanism->mechanism == CKM_AES_CTR && BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CTR_PARAMS))) ||
1379
110k
                       ((pMechanism->mechanism == CKM_AES_CBC ||
1380
21.6k
                         pMechanism->mechanism == CKM_AES_CBC_PAD ||
1381
21.2k
                         pMechanism->mechanism == CKM_AES_CTS) &&
1382
89.7k
                        BAD_PARAM_CAST(pMechanism, AES_BLOCK_SIZE))) {
1383
10
                crv = CKR_MECHANISM_PARAM_INVALID;
1384
10
                break;
1385
10
            }
1386
1387
111k
            if (pMechanism->mechanism == CKM_AES_GCM) {
1388
657
                context->multi = PR_FALSE;
1389
657
            }
1390
111k
            if (key_type != CKK_AES) {
1391
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1392
0
                break;
1393
0
            }
1394
111k
            att = sftk_FindAttribute(key, CKA_VALUE);
1395
111k
            if (att == NULL) {
1396
0
                crv = CKR_KEY_HANDLE_INVALID;
1397
0
                break;
1398
0
            }
1399
111k
            context->cipherInfo = AES_CreateContext(
1400
111k
                (unsigned char *)att->attrib.pValue,
1401
111k
                (unsigned char *)aes_param,
1402
111k
                sftk_aes_mode(pMechanism->mechanism),
1403
111k
                isEncrypt, att->attrib.ulValueLen, 16);
1404
111k
            sftk_FreeAttribute(att);
1405
111k
            if (context->cipherInfo == NULL) {
1406
130
                crv = CKR_HOST_MEMORY;
1407
130
                break;
1408
130
            }
1409
111k
            context->update = isEncrypt ? SFTKCipher_AES_Encrypt : SFTKCipher_AES_Decrypt;
1410
111k
            context->destroy = SFTKCipher_AES_DestroyContext;
1411
111k
            break;
1412
1413
392
        case CKM_NSS_CHACHA20_POLY1305:
1414
392
        case CKM_CHACHA20_POLY1305:
1415
392
            if (pMechanism->mechanism == CKM_NSS_CHACHA20_POLY1305) {
1416
392
                if (key_type != CKK_NSS_CHACHA20) {
1417
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
1418
0
                    break;
1419
0
                }
1420
392
                if ((pMechanism->pParameter == NULL) ||
1421
392
                    (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS))) {
1422
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1423
0
                    break;
1424
0
                }
1425
392
                nss_aead_params_ptr = (CK_NSS_AEAD_PARAMS *)pMechanism->pParameter;
1426
392
            } else {
1427
0
                CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR chacha_poly_params;
1428
0
                if (key_type != CKK_CHACHA20) {
1429
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
1430
0
                    break;
1431
0
                }
1432
0
                if ((pMechanism->pParameter == NULL) ||
1433
0
                    (pMechanism->ulParameterLen !=
1434
0
                     sizeof(CK_SALSA20_CHACHA20_POLY1305_PARAMS))) {
1435
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1436
0
                    break;
1437
0
                }
1438
0
                chacha_poly_params = (CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR)
1439
0
                                         pMechanism->pParameter;
1440
0
                nss_aead_params_ptr = &nss_aead_params;
1441
0
                nss_aead_params.pNonce = chacha_poly_params->pNonce;
1442
0
                nss_aead_params.ulNonceLen = chacha_poly_params->ulNonceLen;
1443
0
                nss_aead_params.pAAD = chacha_poly_params->pAAD;
1444
0
                nss_aead_params.ulAADLen = chacha_poly_params->ulAADLen;
1445
0
                nss_aead_params.ulTagLen = 16; /* Poly1305 is always 16 */
1446
0
            }
1447
1448
392
            context->multi = PR_FALSE;
1449
392
            att = sftk_FindAttribute(key, CKA_VALUE);
1450
392
            if (att == NULL) {
1451
0
                crv = CKR_KEY_HANDLE_INVALID;
1452
0
                break;
1453
0
            }
1454
392
            context->cipherInfo = sftk_ChaCha20Poly1305_CreateContext(
1455
392
                (unsigned char *)att->attrib.pValue, att->attrib.ulValueLen,
1456
392
                nss_aead_params_ptr);
1457
392
            sftk_FreeAttribute(att);
1458
392
            if (context->cipherInfo == NULL) {
1459
148
                crv = sftk_MapCryptError(PORT_GetError());
1460
148
                break;
1461
148
            }
1462
244
            context->update = isEncrypt ? sftk_ChaCha20Poly1305_Encrypt : sftk_ChaCha20Poly1305_Decrypt;
1463
244
            context->destroy = sftk_ChaCha20Poly1305_DestroyContext;
1464
244
            break;
1465
1466
16.6k
        case CKM_NSS_CHACHA20_CTR: /* old NSS private version */
1467
16.6k
        case CKM_CHACHA20:         /* PKCS #11 v3 version */
1468
16.6k
        {
1469
16.6k
            unsigned char *counter;
1470
16.6k
            unsigned char *nonce;
1471
16.6k
            unsigned long counter_len;
1472
16.6k
            unsigned long nonce_len;
1473
16.6k
            context->multi = PR_FALSE;
1474
16.6k
            if (pMechanism->mechanism == CKM_NSS_CHACHA20_CTR) {
1475
16.6k
                if (key_type != CKK_NSS_CHACHA20) {
1476
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
1477
0
                    break;
1478
0
                }
1479
16.6k
                if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) {
1480
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1481
0
                    break;
1482
0
                }
1483
16.6k
                counter_len = 4;
1484
16.6k
                counter = pMechanism->pParameter;
1485
16.6k
                nonce = counter + 4;
1486
16.6k
                nonce_len = 12;
1487
16.6k
            } else {
1488
0
                CK_CHACHA20_PARAMS_PTR chacha20_param_ptr;
1489
0
                if (key_type != CKK_CHACHA20) {
1490
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
1491
0
                    break;
1492
0
                }
1493
0
                if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != sizeof(CK_CHACHA20_PARAMS)) {
1494
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1495
0
                    break;
1496
0
                }
1497
0
                chacha20_param_ptr = (CK_CHACHA20_PARAMS_PTR)pMechanism->pParameter;
1498
0
                if ((chacha20_param_ptr->blockCounterBits != 32) &&
1499
0
                    (chacha20_param_ptr->blockCounterBits != 64)) {
1500
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
1501
0
                    break;
1502
0
                }
1503
0
                counter_len = chacha20_param_ptr->blockCounterBits / PR_BITS_PER_BYTE;
1504
0
                counter = chacha20_param_ptr->pBlockCounter;
1505
0
                nonce = chacha20_param_ptr->pNonce;
1506
0
                nonce_len = chacha20_param_ptr->ulNonceBits / PR_BITS_PER_BYTE;
1507
0
            }
1508
1509
16.6k
            att = sftk_FindAttribute(key, CKA_VALUE);
1510
16.6k
            if (att == NULL) {
1511
0
                crv = CKR_KEY_HANDLE_INVALID;
1512
0
                break;
1513
0
            }
1514
16.6k
            SFTKChaCha20CtrInfo *ctx = PORT_ZNew(SFTKChaCha20CtrInfo);
1515
16.6k
            if (!ctx) {
1516
0
                sftk_FreeAttribute(att);
1517
0
                crv = CKR_HOST_MEMORY;
1518
0
                break;
1519
0
            }
1520
16.6k
            if (att->attrib.ulValueLen != sizeof(ctx->key)) {
1521
0
                sftk_FreeAttribute(att);
1522
0
                PORT_Free(ctx);
1523
0
                crv = CKR_KEY_HANDLE_INVALID;
1524
0
                break;
1525
0
            }
1526
16.6k
            memcpy(ctx->key, att->attrib.pValue, att->attrib.ulValueLen);
1527
16.6k
            sftk_FreeAttribute(att);
1528
1529
            /* make sure we don't overflow our parameters */
1530
16.6k
            if ((sizeof(ctx->counter) < counter_len) ||
1531
16.6k
                (sizeof(ctx->nonce) < nonce_len)) {
1532
0
                PORT_Free(ctx);
1533
0
                crv = CKR_MECHANISM_PARAM_INVALID;
1534
0
                break;
1535
0
            }
1536
1537
            /* The counter is little endian. */
1538
16.6k
            int i = 0;
1539
83.2k
            for (; i < counter_len; ++i) {
1540
66.5k
                ctx->counter |= (PRUint32)counter[i] << (i * 8);
1541
66.5k
            }
1542
16.6k
            memcpy(ctx->nonce, nonce, nonce_len);
1543
16.6k
            context->cipherInfo = ctx;
1544
16.6k
            context->update = sftk_ChaCha20Ctr;
1545
16.6k
            context->destroy = sftk_ChaCha20Ctr_DestroyContext;
1546
16.6k
            break;
1547
16.6k
        }
1548
1549
0
        case CKM_NSS_AES_KEY_WRAP_PAD:
1550
0
        case CKM_AES_KEY_WRAP_PAD:
1551
0
            context->doPad = PR_TRUE;
1552
        /* fall thru */
1553
0
        case CKM_NSS_AES_KEY_WRAP:
1554
0
        case CKM_AES_KEY_WRAP:
1555
0
            context->blockSize = 8;
1556
0
            context->multi = PR_FALSE;
1557
0
            if (key_type != CKK_AES) {
1558
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1559
0
                break;
1560
0
            }
1561
            /* pParameter is an optional custom IV; if provided it must be
1562
             * exactly AES_KEY_WRAP_IV_BYTES long to avoid an over-read in
1563
             * AESKeyWrap_InitContext. */
1564
0
            if (pMechanism->pParameter != NULL &&
1565
0
                pMechanism->ulParameterLen != AES_KEY_WRAP_IV_BYTES) {
1566
0
                crv = CKR_MECHANISM_PARAM_INVALID;
1567
0
                break;
1568
0
            }
1569
0
            att = sftk_FindAttribute(key, CKA_VALUE);
1570
0
            if (att == NULL) {
1571
0
                crv = CKR_KEY_HANDLE_INVALID;
1572
0
                break;
1573
0
            }
1574
0
            context->cipherInfo = AESKeyWrap_CreateContext(
1575
0
                (unsigned char *)att->attrib.pValue,
1576
0
                (unsigned char *)pMechanism->pParameter,
1577
0
                isEncrypt, att->attrib.ulValueLen);
1578
0
            sftk_FreeAttribute(att);
1579
0
            if (context->cipherInfo == NULL) {
1580
0
                crv = CKR_HOST_MEMORY;
1581
0
                break;
1582
0
            }
1583
0
            context->update = isEncrypt ? SFTKCipher_AESKeyWrap_Encrypt
1584
0
                                        : SFTKCipher_AESKeyWrap_Decrypt;
1585
0
            context->destroy = SFTKCipher_AESKeyWrap_DestroyContext;
1586
0
            break;
1587
1588
0
        case CKM_AES_KEY_WRAP_KWP:
1589
            /* KWP (RFC 5649) uses a fixed built-in AIV; no user-supplied IV
1590
             * is accepted. */
1591
0
            if (pMechanism->pParameter != NULL || pMechanism->ulParameterLen != 0) {
1592
0
                crv = CKR_MECHANISM_PARAM_INVALID;
1593
0
                break;
1594
0
            }
1595
0
            context->multi = PR_FALSE;
1596
0
            if (key_type != CKK_AES) {
1597
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
1598
0
                break;
1599
0
            }
1600
0
            att = sftk_FindAttribute(key, CKA_VALUE);
1601
0
            if (att == NULL) {
1602
0
                crv = CKR_KEY_HANDLE_INVALID;
1603
0
                break;
1604
0
            }
1605
0
            context->cipherInfo = AESKeyWrap_CreateContext(
1606
0
                (unsigned char *)att->attrib.pValue,
1607
0
                NULL, /* always use built-in AIV for KWP */
1608
0
                isEncrypt, (unsigned int)att->attrib.ulValueLen);
1609
0
            sftk_FreeAttribute(att);
1610
0
            if (context->cipherInfo == NULL) {
1611
0
                crv = CKR_HOST_MEMORY;
1612
0
                break;
1613
0
            }
1614
0
            context->update = isEncrypt ? SFTKCipher_AESKeyWrap_EncryptKWP
1615
0
                                        : SFTKCipher_AESKeyWrap_DecryptKWP;
1616
0
            context->destroy = SFTKCipher_AESKeyWrap_DestroyContext;
1617
0
            break;
1618
1619
0
        default:
1620
0
            crv = CKR_MECHANISM_INVALID;
1621
0
            break;
1622
369k
    }
1623
1624
369k
    if (crv != CKR_OK) {
1625
321
        sftk_FreeContext(context);
1626
321
        sftk_FreeSession(session);
1627
321
        return crv;
1628
321
    }
1629
369k
    crv = sftk_InstallContext(session, contextType, context);
1630
369k
    if (crv != CKR_OK) {
1631
0
        sftk_FreeContext(context);
1632
0
    }
1633
369k
    sftk_FreeSession(session);
1634
369k
    return crv;
1635
369k
}
1636
1637
/* NSC_EncryptInit initializes an encryption operation. */
1638
CK_RV
1639
NSC_EncryptInit(CK_SESSION_HANDLE hSession,
1640
                CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1641
127k
{
1642
127k
    CHECK_FORK();
1643
127k
    return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT,
1644
127k
                          SFTK_ENCRYPT, PR_TRUE);
1645
127k
}
1646
1647
/* NSC_EncryptUpdate continues a multiple-part encryption operation. */
1648
CK_RV
1649
NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,
1650
                  CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
1651
                  CK_ULONG_PTR pulEncryptedPartLen)
1652
4.36k
{
1653
4.36k
    SFTKSession *session;
1654
4.36k
    SFTKSessionContext *context;
1655
4.36k
    unsigned int outlen, i;
1656
4.36k
    unsigned int padoutlen = 0;
1657
4.36k
    unsigned int maxout = *pulEncryptedPartLen;
1658
4.36k
    CK_RV crv;
1659
4.36k
    SECStatus rv;
1660
1661
4.36k
    CHECK_FORK();
1662
1663
    /* Hold the session reference for the duration of the context deref;
1664
     * see comment on NSC_DigestUpdate. */
1665
4.36k
    crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, &session);
1666
4.36k
    if (crv != CKR_OK)
1667
0
        return crv;
1668
1669
4.36k
    if (!pEncryptedPart) {
1670
0
        if (context->doPad) {
1671
0
            CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength;
1672
0
            CK_ULONG blocksToSend = totalDataAvailable / context->blockSize;
1673
1674
0
            *pulEncryptedPartLen = blocksToSend * context->blockSize;
1675
0
            goto finish;
1676
0
        }
1677
0
        *pulEncryptedPartLen = ulPartLen;
1678
0
        goto finish;
1679
0
    }
1680
1681
    /* do padding */
1682
4.36k
    if (context->doPad) {
1683
        /* deal with previous buffered data */
1684
473
        if (context->padDataLength != 0) {
1685
            /* fill in the padded to a full block size */
1686
0
            for (i = context->padDataLength;
1687
0
                 (ulPartLen != 0) && i < context->blockSize; i++) {
1688
0
                context->padBuf[i] = *pPart++;
1689
0
                ulPartLen--;
1690
0
                context->padDataLength++;
1691
0
            }
1692
1693
            /* not enough data to encrypt yet? then return */
1694
0
            if (context->padDataLength != context->blockSize) {
1695
0
                *pulEncryptedPartLen = 0;
1696
0
                goto finish;
1697
0
            }
1698
            /* encrypt the current padded data */
1699
0
            rv = (*context->update)(context->cipherInfo, pEncryptedPart,
1700
0
                                    &padoutlen, maxout, context->padBuf,
1701
0
                                    context->blockSize);
1702
0
            if (rv != SECSuccess) {
1703
0
                crv = sftk_MapCryptError(PORT_GetError());
1704
0
                goto finish;
1705
0
            }
1706
0
            pEncryptedPart += padoutlen;
1707
0
            maxout -= padoutlen;
1708
0
        }
1709
        /* save the residual */
1710
473
        context->padDataLength = ulPartLen % context->blockSize;
1711
473
        if (context->padDataLength) {
1712
473
            PORT_Memcpy(context->padBuf,
1713
473
                        &pPart[ulPartLen - context->padDataLength],
1714
473
                        context->padDataLength);
1715
473
            ulPartLen -= context->padDataLength;
1716
473
        }
1717
        /* if we've exhausted our new buffer, we're done */
1718
473
        if (ulPartLen == 0) {
1719
0
            *pulEncryptedPartLen = padoutlen;
1720
0
            goto finish;
1721
0
        }
1722
473
    }
1723
1724
    /* do it: NOTE: this assumes buf size in is >= buf size out! */
1725
4.36k
    rv = (*context->update)(context->cipherInfo, pEncryptedPart,
1726
4.36k
                            &outlen, maxout, pPart, ulPartLen);
1727
4.36k
    if (rv != SECSuccess) {
1728
107
        crv = sftk_MapCryptError(PORT_GetError());
1729
107
        goto finish;
1730
107
    }
1731
4.25k
    *pulEncryptedPartLen = (CK_ULONG)(outlen + padoutlen);
1732
4.36k
finish:
1733
4.36k
    sftk_FreeSession(session);
1734
4.36k
    return crv;
1735
4.25k
}
1736
1737
/* NSC_EncryptFinal finishes a multiple-part encryption operation. */
1738
CK_RV
1739
NSC_EncryptFinal(CK_SESSION_HANDLE hSession,
1740
                 CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
1741
617
{
1742
617
    SFTKSession *session;
1743
617
    SFTKSessionContext *context;
1744
617
    unsigned int outlen, i;
1745
617
    unsigned int maxout = *pulLastEncryptedPartLen;
1746
617
    CK_RV crv;
1747
617
    SECStatus rv = SECSuccess;
1748
617
    PRBool contextFinished = PR_TRUE;
1749
1750
617
    CHECK_FORK();
1751
1752
    /* make sure we're legal */
1753
617
    crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, &session);
1754
617
    if (crv != CKR_OK)
1755
0
        return crv;
1756
1757
617
    *pulLastEncryptedPartLen = 0;
1758
617
    if (!pLastEncryptedPart) {
1759
        /* caller is checking the amount of remaining data */
1760
0
        if (context->blockSize > 0 && context->doPad) {
1761
0
            *pulLastEncryptedPartLen = context->blockSize;
1762
0
            contextFinished = PR_FALSE; /* still have padding to go */
1763
0
        }
1764
0
        goto finish;
1765
0
    }
1766
1767
    /* do padding */
1768
617
    if (context->doPad) {
1769
473
        unsigned char padbyte = (unsigned char)(context->blockSize - context->padDataLength);
1770
        /* fill out rest of pad buffer with pad magic*/
1771
4.27k
        for (i = context->padDataLength; i < context->blockSize; i++) {
1772
3.80k
            context->padBuf[i] = padbyte;
1773
3.80k
        }
1774
473
        rv = (*context->update)(context->cipherInfo, pLastEncryptedPart,
1775
473
                                &outlen, maxout, context->padBuf, context->blockSize);
1776
473
        if (rv == SECSuccess)
1777
473
            *pulLastEncryptedPartLen = (CK_ULONG)outlen;
1778
473
    }
1779
1780
617
finish:
1781
617
    if (contextFinished)
1782
617
        sftk_TerminateOp(session, SFTK_ENCRYPT);
1783
617
    sftk_FreeSession(session);
1784
617
    return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
1785
617
}
1786
1787
/* NSC_Encrypt encrypts single-part data. */
1788
CK_RV
1789
NSC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
1790
            CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
1791
            CK_ULONG_PTR pulEncryptedDataLen)
1792
109k
{
1793
109k
    SFTKSession *session;
1794
109k
    SFTKSessionContext *context;
1795
109k
    unsigned int outlen;
1796
109k
    unsigned int maxoutlen = *pulEncryptedDataLen;
1797
109k
    CK_RV crv;
1798
109k
    CK_RV crv2;
1799
109k
    SECStatus rv = SECSuccess;
1800
109k
    SECItem pText;
1801
1802
109k
    pText.type = siBuffer;
1803
109k
    pText.data = pData;
1804
109k
    pText.len = ulDataLen;
1805
1806
109k
    CHECK_FORK();
1807
1808
    /* make sure we're legal */
1809
109k
    crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, &session);
1810
109k
    if (crv != CKR_OK)
1811
0
        return crv;
1812
1813
109k
    if (!pEncryptedData) {
1814
0
        outlen = context->rsa ? context->maxLen : ulDataLen + 2 * context->blockSize;
1815
0
        goto done;
1816
0
    }
1817
1818
109k
    if (context->doPad) {
1819
473
        if (context->multi) {
1820
473
            CK_ULONG updateLen = maxoutlen;
1821
473
            CK_ULONG finalLen;
1822
            /* padding is fairly complicated, have the update and final
1823
             * code deal with it */
1824
473
            sftk_FreeSession(session);
1825
473
            crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData,
1826
473
                                    &updateLen);
1827
473
            if (crv != CKR_OK) {
1828
0
                updateLen = 0;
1829
0
            }
1830
473
            maxoutlen -= updateLen;
1831
473
            pEncryptedData += updateLen;
1832
473
            finalLen = maxoutlen;
1833
473
            crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen);
1834
473
            if (crv == CKR_OK && crv2 == CKR_OK) {
1835
473
                *pulEncryptedDataLen = updateLen + finalLen;
1836
473
            }
1837
473
            return crv == CKR_OK ? crv2 : crv;
1838
473
        }
1839
        /* doPad without multi means that padding must be done on the first
1840
        ** and only update.  There will be no final.
1841
        */
1842
0
        PORT_Assert(context->blockSize > 1);
1843
0
        if (context->blockSize > 1) {
1844
0
            CK_ULONG remainder = ulDataLen % context->blockSize;
1845
0
            CK_ULONG padding = context->blockSize - remainder;
1846
0
            pText.len += padding;
1847
0
            pText.data = PORT_ZAlloc(pText.len);
1848
0
            if (pText.data) {
1849
0
                memcpy(pText.data, pData, ulDataLen);
1850
0
                memset(pText.data + ulDataLen, padding, padding);
1851
0
            } else {
1852
0
                crv = CKR_HOST_MEMORY;
1853
0
                goto fail;
1854
0
            }
1855
0
        }
1856
0
    }
1857
1858
    /* do it: NOTE: this assumes buf size is big enough. */
1859
109k
    rv = (*context->update)(context->cipherInfo, pEncryptedData,
1860
109k
                            &outlen, maxoutlen, pText.data, pText.len);
1861
109k
    crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
1862
109k
    if (pText.data != pData)
1863
0
        PORT_ZFree(pText.data, pText.len);
1864
109k
fail:
1865
109k
    sftk_TerminateOp(session, SFTK_ENCRYPT);
1866
109k
done:
1867
109k
    sftk_FreeSession(session);
1868
109k
    if (crv == CKR_OK) {
1869
108k
        *pulEncryptedDataLen = (CK_ULONG)outlen;
1870
108k
    }
1871
109k
    return crv;
1872
109k
}
1873
1874
/*
1875
 ************** Crypto Functions:     Decrypt ************************
1876
 */
1877
1878
/* NSC_DecryptInit initializes a decryption operation. */
1879
CK_RV
1880
NSC_DecryptInit(CK_SESSION_HANDLE hSession,
1881
                CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1882
128k
{
1883
128k
    CHECK_FORK();
1884
128k
    return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT,
1885
128k
                          SFTK_DECRYPT, PR_FALSE);
1886
128k
}
1887
1888
/* NSC_DecryptUpdate continues a multiple-part decryption operation. */
1889
CK_RV
1890
NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
1891
                  CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
1892
                  CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
1893
47.4k
{
1894
47.4k
    SFTKSession *session;
1895
47.4k
    SFTKSessionContext *context;
1896
47.4k
    unsigned int padoutlen = 0;
1897
47.4k
    unsigned int outlen;
1898
47.4k
    unsigned int maxout = *pulPartLen;
1899
47.4k
    CK_RV crv;
1900
47.4k
    SECStatus rv;
1901
1902
47.4k
    CHECK_FORK();
1903
1904
    /* Hold the session reference for the duration of the context deref;
1905
     * see comment on NSC_DigestUpdate. */
1906
47.4k
    crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, &session);
1907
47.4k
    if (crv != CKR_OK)
1908
0
        return crv;
1909
1910
    /* this can only happen on an NSS programming error */
1911
47.4k
    PORT_Assert((context->padDataLength == 0) || context->padDataLength == context->blockSize);
1912
1913
47.4k
    if (context->doPad) {
1914
        /* Check the data length for block ciphers. If we are padding,
1915
         * then we must be using a block cipher. In the non-padding case
1916
         * the error will be returned by the underlying decryption
1917
         * function when we do the actual decrypt. We need to do the
1918
         * check here to avoid returning a negative length to the caller
1919
         * or reading before the beginning of the pEncryptedPart buffer.
1920
         */
1921
0
        if ((ulEncryptedPartLen == 0) ||
1922
0
            (ulEncryptedPartLen % context->blockSize) != 0) {
1923
0
            crv = CKR_ENCRYPTED_DATA_LEN_RANGE;
1924
0
            goto finish;
1925
0
        }
1926
0
    }
1927
1928
47.4k
    if (!pPart) {
1929
0
        if (context->doPad) {
1930
0
            *pulPartLen =
1931
0
                ulEncryptedPartLen + context->padDataLength - context->blockSize;
1932
0
            goto finish;
1933
0
        }
1934
        /* for stream ciphers there is are no constraints on ulEncryptedPartLen.
1935
         * for block ciphers, it must be a multiple of blockSize. The error is
1936
         * detected when this function is called again do decrypt the output.
1937
         */
1938
0
        *pulPartLen = ulEncryptedPartLen;
1939
0
        goto finish;
1940
0
    }
1941
1942
47.4k
    if (context->doPad) {
1943
        /* first decrypt our saved buffer */
1944
0
        if (context->padDataLength != 0) {
1945
0
            rv = (*context->update)(context->cipherInfo, pPart, &padoutlen,
1946
0
                                    maxout, context->padBuf, context->blockSize);
1947
0
            if (rv != SECSuccess) {
1948
0
                crv = sftk_MapDecryptError(PORT_GetError());
1949
0
                goto finish;
1950
0
            }
1951
0
            pPart += padoutlen;
1952
0
            maxout -= padoutlen;
1953
0
        }
1954
        /* now save the final block for the next decrypt or the final */
1955
0
        PORT_Memcpy(context->padBuf, &pEncryptedPart[ulEncryptedPartLen - context->blockSize],
1956
0
                    context->blockSize);
1957
0
        context->padDataLength = context->blockSize;
1958
0
        ulEncryptedPartLen -= context->padDataLength;
1959
0
    }
1960
1961
    /* do it: NOTE: this assumes buf size in is >= buf size out! */
1962
47.4k
    rv = (*context->update)(context->cipherInfo, pPart, &outlen,
1963
47.4k
                            maxout, pEncryptedPart, ulEncryptedPartLen);
1964
47.4k
    if (rv != SECSuccess) {
1965
82
        crv = sftk_MapDecryptError(PORT_GetError());
1966
82
        goto finish;
1967
82
    }
1968
47.3k
    *pulPartLen = (CK_ULONG)(outlen + padoutlen);
1969
47.4k
finish:
1970
47.4k
    sftk_FreeSession(session);
1971
47.4k
    return crv;
1972
47.3k
}
1973
1974
/* NSC_DecryptFinal finishes a multiple-part decryption operation. */
1975
CK_RV
1976
NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
1977
                 CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen)
1978
36
{
1979
36
    SFTKSession *session;
1980
36
    SFTKSessionContext *context;
1981
36
    unsigned int outlen;
1982
36
    unsigned int maxout = *pulLastPartLen;
1983
36
    CK_RV crv;
1984
36
    SECStatus rv = SECSuccess;
1985
1986
36
    CHECK_FORK();
1987
1988
    /* make sure we're legal */
1989
36
    crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, &session);
1990
36
    if (crv != CKR_OK)
1991
0
        return crv;
1992
1993
36
    *pulLastPartLen = 0;
1994
36
    if (!pLastPart) {
1995
        /* caller is checking the amount of remaining data */
1996
0
        if (context->padDataLength > 0) {
1997
0
            *pulLastPartLen = context->padDataLength;
1998
0
        }
1999
0
        goto finish;
2000
0
    }
2001
2002
36
    if (context->doPad) {
2003
        /* decrypt our saved buffer */
2004
0
        if (context->padDataLength != 0) {
2005
            /* this assumes that pLastPart is big enough to hold the *whole*
2006
             * buffer!!! */
2007
0
            rv = (*context->update)(context->cipherInfo, pLastPart, &outlen,
2008
0
                                    maxout, context->padBuf, context->blockSize);
2009
0
            if (rv != SECSuccess) {
2010
0
                crv = sftk_MapDecryptError(PORT_GetError());
2011
0
            } else {
2012
0
                unsigned int padSize = 0;
2013
0
                crv = sftk_CheckCBCPadding(pLastPart, outlen,
2014
0
                                           context->blockSize, &padSize);
2015
                /* Update pulLastPartLen, in constant time, if crv is OK */
2016
0
                *pulLastPartLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulLastPartLen);
2017
0
            }
2018
0
        }
2019
0
    }
2020
2021
36
    sftk_TerminateOp(session, SFTK_DECRYPT);
2022
36
finish:
2023
36
    sftk_FreeSession(session);
2024
36
    return crv;
2025
36
}
2026
2027
/* NSC_Decrypt decrypts encrypted data in a single part. */
2028
CK_RV
2029
NSC_Decrypt(CK_SESSION_HANDLE hSession,
2030
            CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
2031
            CK_ULONG_PTR pulDataLen)
2032
83.8k
{
2033
83.8k
    SFTKSession *session;
2034
83.8k
    SFTKSessionContext *context;
2035
83.8k
    unsigned int outlen;
2036
83.8k
    unsigned int maxoutlen = *pulDataLen;
2037
83.8k
    CK_RV crv;
2038
83.8k
    CK_RV crv2;
2039
83.8k
    SECStatus rv = SECSuccess;
2040
2041
83.8k
    CHECK_FORK();
2042
2043
    /* make sure we're legal */
2044
83.8k
    crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_FALSE, &session);
2045
83.8k
    if (crv != CKR_OK)
2046
0
        return crv;
2047
2048
83.8k
    if (!pData) {
2049
0
        *pulDataLen = (CK_ULONG)(ulEncryptedDataLen + context->blockSize);
2050
0
        goto done;
2051
0
    }
2052
2053
83.8k
    if (context->doPad && context->multi) {
2054
0
        CK_ULONG updateLen = maxoutlen;
2055
0
        CK_ULONG finalLen;
2056
        /* padding is fairly complicated, have the update and final
2057
         * code deal with it */
2058
0
        sftk_FreeSession(session);
2059
0
        crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
2060
0
                                pData, &updateLen);
2061
0
        if (crv == CKR_OK) {
2062
0
            maxoutlen -= updateLen;
2063
0
            pData += updateLen;
2064
0
        }
2065
0
        finalLen = maxoutlen;
2066
0
        crv2 = NSC_DecryptFinal(hSession, pData, &finalLen);
2067
0
        if (crv == CKR_OK) {
2068
0
            *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv2), updateLen + finalLen, *pulDataLen);
2069
0
            return crv2;
2070
0
        } else {
2071
0
            return crv;
2072
0
        }
2073
0
    }
2074
2075
83.8k
    rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
2076
83.8k
                            pEncryptedData, ulEncryptedDataLen);
2077
    /* XXX need to do MUCH better error mapping than this. */
2078
83.8k
    crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
2079
83.8k
    if (rv == SECSuccess) {
2080
4.98k
        if (context->doPad) {
2081
0
            unsigned int padSize = 0;
2082
0
            crv = sftk_CheckCBCPadding(pData, outlen, context->blockSize,
2083
0
                                       &padSize);
2084
            /* Update pulDataLen, in constant time, if crv is OK */
2085
0
            *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulDataLen);
2086
4.98k
        } else {
2087
4.98k
            *pulDataLen = (CK_ULONG)outlen;
2088
4.98k
        }
2089
4.98k
    }
2090
83.8k
    sftk_TerminateOp(session, SFTK_DECRYPT);
2091
83.8k
done:
2092
83.8k
    sftk_FreeSession(session);
2093
83.8k
    return crv;
2094
83.8k
}
2095
2096
/*
2097
 ************** Crypto Functions:     Digest (HASH)  ************************
2098
 */
2099
2100
/* NSC_DigestInit initializes a message-digesting operation. */
2101
CK_RV
2102
NSC_DigestInit(CK_SESSION_HANDLE hSession,
2103
               CK_MECHANISM_PTR pMechanism)
2104
978k
{
2105
978k
    SFTKSession *session;
2106
978k
    SFTKSessionContext *context;
2107
978k
    CK_RV crv = CKR_OK;
2108
2109
978k
    CHECK_FORK();
2110
2111
978k
    session = sftk_SessionFromHandle(hSession);
2112
978k
    if (session == NULL)
2113
0
        return CKR_SESSION_HANDLE_INVALID;
2114
978k
    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_HASH,
2115
978k
                           NULL, 0, NULL, 0, CKA_DIGEST);
2116
978k
    if (crv != CKR_OK) {
2117
0
        sftk_FreeSession(session);
2118
0
        return crv;
2119
0
    }
2120
2121
978k
#define INIT_MECH(mmm)                                         \
2122
978k
    case CKM_##mmm: {                                          \
2123
978k
        mmm##Context *mmm##_ctx = mmm##_NewContext();          \
2124
978k
        context->cipherInfo = (void *)mmm##_ctx;               \
2125
978k
        context->cipherInfoLen = mmm##_FlattenSize(mmm##_ctx); \
2126
978k
        context->currentMech = CKM_##mmm;                      \
2127
978k
        context->hashUpdate = SFTKHash_##mmm##_Update;         \
2128
978k
        context->end = SFTKHash_##mmm##_End;                   \
2129
978k
        context->destroy = SFTKHash_##mmm##_DestroyContext;    \
2130
978k
        context->maxLen = mmm##_LENGTH;                        \
2131
978k
        if (mmm##_ctx)                                         \
2132
978k
            mmm##_Begin(mmm##_ctx);                            \
2133
978k
        else                                                   \
2134
978k
            crv = CKR_HOST_MEMORY;                             \
2135
978k
        break;                                                 \
2136
978k
    }
2137
2138
978k
    switch (pMechanism->mechanism) {
2139
50
        INIT_MECH(MD2)
2140
117k
        INIT_MECH(MD5)
2141
328k
        INIT_MECH(SHA1)
2142
162k
        INIT_MECH(SHA224)
2143
175k
        INIT_MECH(SHA256)
2144
71.8k
        INIT_MECH(SHA384)
2145
58.9k
        INIT_MECH(SHA512)
2146
7.64k
        INIT_MECH(SHA3_224)
2147
49.9k
        INIT_MECH(SHA3_256)
2148
5.66k
        INIT_MECH(SHA3_384)
2149
1.44k
        INIT_MECH(SHA3_512)
2150
2151
0
        default:
2152
0
            crv = CKR_MECHANISM_INVALID;
2153
0
            break;
2154
978k
    }
2155
2156
978k
    if (crv != CKR_OK) {
2157
0
        sftk_FreeContext(context);
2158
0
        sftk_FreeSession(session);
2159
0
        return crv;
2160
0
    }
2161
978k
    crv = sftk_InstallContext(session, SFTK_HASH, context);
2162
978k
    if (crv != CKR_OK) {
2163
0
        sftk_FreeContext(context);
2164
0
    }
2165
978k
    sftk_FreeSession(session);
2166
978k
    return crv;
2167
978k
}
2168
2169
/* NSC_Digest digests data in a single part. */
2170
CK_RV
2171
NSC_Digest(CK_SESSION_HANDLE hSession,
2172
           CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,
2173
           CK_ULONG_PTR pulDigestLen)
2174
0
{
2175
0
    SFTKSession *session;
2176
0
    SFTKSessionContext *context;
2177
0
    unsigned int digestLen;
2178
0
    unsigned int maxout = *pulDigestLen;
2179
0
    CK_RV crv;
2180
2181
0
    CHECK_FORK();
2182
2183
    /* make sure we're legal */
2184
0
    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_FALSE, &session);
2185
0
    if (crv != CKR_OK)
2186
0
        return crv;
2187
2188
0
    if (pDigest == NULL) {
2189
0
        *pulDigestLen = context->maxLen;
2190
0
        goto finish;
2191
0
    }
2192
2193
0
#if (ULONG_MAX > UINT_MAX)
2194
    /* The context->hashUpdate function takes an unsigned int for its data
2195
     * length argument, but NSC_Digest takes an unsigned long. */
2196
0
    while (ulDataLen > UINT_MAX) {
2197
0
        (*context->hashUpdate)(context->cipherInfo, pData, UINT_MAX);
2198
0
        pData += UINT_MAX;
2199
0
        ulDataLen -= UINT_MAX;
2200
0
    }
2201
0
#endif
2202
0
    (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen);
2203
2204
    /*  NOTE: this assumes buf size is bigenough for the algorithm */
2205
0
    (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
2206
0
    *pulDigestLen = digestLen;
2207
2208
0
    sftk_TerminateOp(session, SFTK_HASH);
2209
0
finish:
2210
0
    sftk_FreeSession(session);
2211
0
    return CKR_OK;
2212
0
}
2213
2214
/* NSC_DigestUpdate continues a multiple-part message-digesting operation. */
2215
CK_RV
2216
NSC_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
2217
                 CK_ULONG ulPartLen)
2218
16.3M
{
2219
16.3M
    SFTKSession *session;
2220
16.3M
    SFTKSessionContext *context;
2221
16.3M
    CK_RV crv;
2222
2223
16.3M
    CHECK_FORK();
2224
2225
    /* Hold the session reference for the duration of the context deref:
2226
     * without it, a concurrent NSC_CloseSession could drive refCount to 0
2227
     * inside sftk_GetContext, destroying the session (and freeing the
2228
     * context) before we touch context->hashUpdate. */
2229
16.3M
    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
2230
16.3M
    if (crv != CKR_OK)
2231
0
        return crv;
2232
2233
16.3M
#if (ULONG_MAX > UINT_MAX)
2234
    /* The context->hashUpdate function takes an unsigned int for its data
2235
     * length argument, but NSC_DigestUpdate takes an unsigned long. */
2236
16.3M
    while (ulPartLen > UINT_MAX) {
2237
0
        (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX);
2238
0
        pPart += UINT_MAX;
2239
0
        ulPartLen -= UINT_MAX;
2240
0
    }
2241
16.3M
#endif
2242
16.3M
    (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen);
2243
2244
16.3M
    sftk_FreeSession(session);
2245
16.3M
    return CKR_OK;
2246
16.3M
}
2247
2248
/* NSC_DigestFinal finishes a multiple-part message-digesting operation. */
2249
CK_RV
2250
NSC_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
2251
                CK_ULONG_PTR pulDigestLen)
2252
773k
{
2253
773k
    SFTKSession *session;
2254
773k
    SFTKSessionContext *context;
2255
773k
    unsigned int maxout = *pulDigestLen;
2256
773k
    unsigned int digestLen;
2257
773k
    CK_RV crv;
2258
2259
773k
    CHECK_FORK();
2260
2261
    /* make sure we're legal */
2262
773k
    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
2263
773k
    if (crv != CKR_OK)
2264
144k
        return crv;
2265
2266
628k
    if (pDigest != NULL) {
2267
628k
        (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
2268
628k
        *pulDigestLen = digestLen;
2269
628k
        sftk_TerminateOp(session, SFTK_HASH);
2270
628k
    } else {
2271
0
        *pulDigestLen = context->maxLen;
2272
0
    }
2273
2274
628k
    sftk_FreeSession(session);
2275
628k
    return CKR_OK;
2276
773k
}
2277
2278
/*
2279
 * these helper functions are used by Generic Macing and Signing functions
2280
 * that use hashes as part of their operations.
2281
 */
2282
#define DOSUB(mmm)                                              \
2283
    static CK_RV                                                \
2284
        sftk_doSub##mmm(SFTKSessionContext *context)            \
2285
6.85k
    {                                                           \
2286
6.85k
        mmm##Context *mmm##_ctx = mmm##_NewContext();           \
2287
6.85k
        context->hashInfo = (void *)mmm##_ctx;                  \
2288
6.85k
        context->hashUpdate = SFTKHash_##mmm##_Update;          \
2289
6.85k
        context->end = SFTKHash_##mmm##_End;                    \
2290
6.85k
        context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \
2291
6.85k
        if (!context->hashInfo) {                               \
2292
0
            return CKR_HOST_MEMORY;                             \
2293
0
        }                                                       \
2294
6.85k
        mmm##_Begin(mmm##_ctx);                                 \
2295
6.85k
        return CKR_OK;                                          \
2296
6.85k
    }
Unexecuted instantiation: pkcs11c.c:sftk_doSubMD5
Unexecuted instantiation: pkcs11c.c:sftk_doSubMD2
pkcs11c.c:sftk_doSubSHA1
Line
Count
Source
2285
418
    {                                                           \
2286
418
        mmm##Context *mmm##_ctx = mmm##_NewContext();           \
2287
418
        context->hashInfo = (void *)mmm##_ctx;                  \
2288
418
        context->hashUpdate = SFTKHash_##mmm##_Update;          \
2289
418
        context->end = SFTKHash_##mmm##_End;                    \
2290
418
        context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \
2291
418
        if (!context->hashInfo) {                               \
2292
0
            return CKR_HOST_MEMORY;                             \
2293
0
        }                                                       \
2294
418
        mmm##_Begin(mmm##_ctx);                                 \
2295
418
        return CKR_OK;                                          \
2296
418
    }
pkcs11c.c:sftk_doSubSHA224
Line
Count
Source
2285
11
    {                                                           \
2286
11
        mmm##Context *mmm##_ctx = mmm##_NewContext();           \
2287
11
        context->hashInfo = (void *)mmm##_ctx;                  \
2288
11
        context->hashUpdate = SFTKHash_##mmm##_Update;          \
2289
11
        context->end = SFTKHash_##mmm##_End;                    \
2290
11
        context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \
2291
11
        if (!context->hashInfo) {                               \
2292
0
            return CKR_HOST_MEMORY;                             \
2293
0
        }                                                       \
2294
11
        mmm##_Begin(mmm##_ctx);                                 \
2295
11
        return CKR_OK;                                          \
2296
11
    }
pkcs11c.c:sftk_doSubSHA256
Line
Count
Source
2285
5.34k
    {                                                           \
2286
5.34k
        mmm##Context *mmm##_ctx = mmm##_NewContext();           \
2287
5.34k
        context->hashInfo = (void *)mmm##_ctx;                  \
2288
5.34k
        context->hashUpdate = SFTKHash_##mmm##_Update;          \
2289
5.34k
        context->end = SFTKHash_##mmm##_End;                    \
2290
5.34k
        context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \
2291
5.34k
        if (!context->hashInfo) {                               \
2292
0
            return CKR_HOST_MEMORY;                             \
2293
0
        }                                                       \
2294
5.34k
        mmm##_Begin(mmm##_ctx);                                 \
2295
5.34k
        return CKR_OK;                                          \
2296
5.34k
    }
pkcs11c.c:sftk_doSubSHA384
Line
Count
Source
2285
586
    {                                                           \
2286
586
        mmm##Context *mmm##_ctx = mmm##_NewContext();           \
2287
586
        context->hashInfo = (void *)mmm##_ctx;                  \
2288
586
        context->hashUpdate = SFTKHash_##mmm##_Update;          \
2289
586
        context->end = SFTKHash_##mmm##_End;                    \
2290
586
        context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \
2291
586
        if (!context->hashInfo) {                               \
2292
0
            return CKR_HOST_MEMORY;                             \
2293
0
        }                                                       \
2294
586
        mmm##_Begin(mmm##_ctx);                                 \
2295
586
        return CKR_OK;                                          \
2296
586
    }
pkcs11c.c:sftk_doSubSHA512
Line
Count
Source
2285
490
    {                                                           \
2286
490
        mmm##Context *mmm##_ctx = mmm##_NewContext();           \
2287
490
        context->hashInfo = (void *)mmm##_ctx;                  \
2288
490
        context->hashUpdate = SFTKHash_##mmm##_Update;          \
2289
490
        context->end = SFTKHash_##mmm##_End;                    \
2290
490
        context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \
2291
490
        if (!context->hashInfo) {                               \
2292
0
            return CKR_HOST_MEMORY;                             \
2293
0
        }                                                       \
2294
490
        mmm##_Begin(mmm##_ctx);                                 \
2295
490
        return CKR_OK;                                          \
2296
490
    }
2297
2298
DOSUB(MD2)
2299
DOSUB(MD5)
2300
DOSUB(SHA1)
2301
DOSUB(SHA224)
2302
DOSUB(SHA256)
2303
DOSUB(SHA384)
2304
DOSUB(SHA512)
2305
2306
static SECStatus
2307
sftk_SignCopy(
2308
    void *copyLen,
2309
    unsigned char *out, unsigned int *outLength,
2310
    unsigned int maxLength,
2311
    const unsigned char *hashResult,
2312
    unsigned int hashResultLength)
2313
75.3k
{
2314
75.3k
    unsigned int toCopy = *(CK_ULONG *)copyLen;
2315
75.3k
    if (toCopy > maxLength) {
2316
0
        toCopy = maxLength;
2317
0
    }
2318
75.3k
    if (toCopy > hashResultLength) {
2319
0
        toCopy = hashResultLength;
2320
0
    }
2321
75.3k
    memcpy(out, hashResult, toCopy);
2322
75.3k
    if (outLength) {
2323
75.3k
        *outLength = toCopy;
2324
75.3k
    }
2325
75.3k
    return SECSuccess;
2326
75.3k
}
2327
2328
/* Verify is just a compare for HMAC */
2329
static SECStatus
2330
sftk_HMACCmp(void *ctx, const unsigned char *sig, unsigned int sigLen,
2331
             const unsigned char *hash, unsigned int hashLen)
2332
0
{
2333
0
    CK_ULONG compareLen = *(CK_ULONG *)ctx;
2334
0
    PORT_Assert(compareLen == hashLen);
2335
0
    if (compareLen != hashLen) {
2336
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
2337
0
        return SECFailure;
2338
0
    }
2339
2340
    // Handle MAC truncation. NB: should the caller not wish to support
2341
    // truncation, it is their responsibility to ensure that the MAC has not
2342
    // been truncated.
2343
0
    if (compareLen > sigLen) {
2344
0
        compareLen = sigLen;
2345
0
    }
2346
0
    if (NSS_SecureMemcmp(sig, hash, compareLen) == 0) {
2347
0
        return SECSuccess;
2348
0
    }
2349
2350
0
    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
2351
0
    return SECFailure;
2352
0
}
2353
2354
/*
2355
 * common HMAC + CMAC initialization routine
2356
 */
2357
static CK_RV
2358
sftk_doMACInit(CK_MECHANISM_TYPE mech, SFTKSessionContext *session,
2359
               SFTKObject *key, CK_ULONG mac_size)
2360
253k
{
2361
253k
    CK_RV crv;
2362
253k
    sftk_MACCtx *context;
2363
253k
    CK_ULONG *intpointer;
2364
253k
    PRBool isFIPS = sftk_isFIPS(key->slot->slotID);
2365
2366
    /* Set up the initial context. */
2367
253k
    crv = sftk_MAC_Create(mech, key, &context);
2368
253k
    if (crv != CKR_OK) {
2369
0
        return crv;
2370
0
    }
2371
2372
253k
    session->hashInfo = context;
2373
253k
    session->multi = PR_TRUE;
2374
2375
    /* Required by FIPS 198 Section 4. Delay this check until after the MAC
2376
     * has been initialized to steal the output size of the MAC. */
2377
253k
    if (isFIPS && (mac_size < 4 || mac_size < context->mac_size / 2)) {
2378
0
        sftk_MAC_DestroyContext(context, PR_TRUE);
2379
0
        return CKR_BUFFER_TOO_SMALL;
2380
0
    }
2381
2382
    /* Configure our helper functions appropriately. Note that these casts
2383
     * ignore the return values. */
2384
253k
    session->hashUpdate = SFTKHash_sftk_MAC_Update;
2385
253k
    session->end = SFTKHash_sftk_MAC_End;
2386
253k
    session->hashdestroy = SFTKHash_sftk_MAC_DestroyContext;
2387
2388
253k
    intpointer = PORT_New(CK_ULONG);
2389
253k
    if (intpointer == NULL) {
2390
0
        sftk_MAC_DestroyContext(context, PR_TRUE);
2391
0
        return CKR_HOST_MEMORY;
2392
0
    }
2393
253k
    *intpointer = mac_size;
2394
253k
    session->cipherInfo = intpointer;
2395
2396
    /* Since we're only "hashing", copy the result from session->end to the
2397
     * caller using sftk_SignCopy. */
2398
253k
    session->update = sftk_SignCopy;
2399
253k
    session->verify = sftk_HMACCmp;
2400
253k
    session->destroy = sftk_Space;
2401
2402
253k
    session->maxLen = context->mac_size;
2403
2404
253k
    return CKR_OK;
2405
253k
}
2406
2407
/*
2408
 *  SSL Macing support. SSL Macs are inited, then update with the base
2409
 * hashing algorithm, then finalized in sign and verify
2410
 */
2411
2412
/*
2413
 * FROM SSL:
2414
 * 60 bytes is 3 times the maximum length MAC size that is supported.
2415
 * We probably should have one copy of this table. We still need this table
2416
 * in ssl to 'sign' the handshake hashes.
2417
 */
2418
static unsigned char ssl_pad_1[60] = {
2419
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2420
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2421
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2422
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2423
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2424
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2425
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
2426
    0x36, 0x36, 0x36, 0x36
2427
};
2428
static unsigned char ssl_pad_2[60] = {
2429
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2430
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2431
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2432
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2433
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2434
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2435
    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
2436
    0x5c, 0x5c, 0x5c, 0x5c
2437
};
2438
2439
static SECStatus
2440
sftk_SSLMACSign(void *ctx, unsigned char *sig, unsigned int *sigLen,
2441
                unsigned int maxLen, const unsigned char *hash, unsigned int hashLen)
2442
0
{
2443
0
    SFTKSSLMACInfo *info = ctx;
2444
0
    unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
2445
0
    unsigned int out;
2446
2447
0
    PORT_Assert(info->macSize <= SFTK_MAX_MAC_LENGTH);
2448
0
    if (info->macSize > SFTK_MAX_MAC_LENGTH) {
2449
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
2450
0
        return SECFailure;
2451
0
    }
2452
2453
0
    if (info->macSize > maxLen) {
2454
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
2455
0
        return SECFailure;
2456
0
    }
2457
2458
0
    info->begin(info->hashContext);
2459
0
    info->update(info->hashContext, info->key, info->keySize);
2460
0
    info->update(info->hashContext, ssl_pad_2, info->padSize);
2461
0
    info->update(info->hashContext, hash, hashLen);
2462
0
    info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH);
2463
0
    PORT_Memcpy(sig, tmpBuf, info->macSize);
2464
0
    PORT_Memset(tmpBuf, 0, info->macSize);
2465
0
    *sigLen = info->macSize;
2466
0
    return SECSuccess;
2467
0
}
2468
2469
static SECStatus
2470
sftk_SSLMACVerify(void *ctx, const unsigned char *sig, unsigned int sigLen,
2471
                  const unsigned char *hash, unsigned int hashLen)
2472
0
{
2473
0
    SFTKSSLMACInfo *info = ctx;
2474
0
    unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
2475
0
    unsigned int out;
2476
0
    int cmp;
2477
2478
0
    PORT_Assert(info->macSize <= SFTK_MAX_MAC_LENGTH);
2479
0
    if (info->macSize > SFTK_MAX_MAC_LENGTH) {
2480
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
2481
0
        return SECFailure;
2482
0
    }
2483
2484
0
    if (info->macSize > sigLen) {
2485
0
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
2486
0
        return SECFailure;
2487
0
    }
2488
2489
0
    info->begin(info->hashContext);
2490
0
    info->update(info->hashContext, info->key, info->keySize);
2491
0
    info->update(info->hashContext, ssl_pad_2, info->padSize);
2492
0
    info->update(info->hashContext, hash, hashLen);
2493
0
    info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH);
2494
0
    cmp = NSS_SecureMemcmp(sig, tmpBuf, info->macSize);
2495
0
    PORT_Memset(tmpBuf, 0, info->macSize);
2496
0
    if (cmp == 0) {
2497
0
        return SECSuccess;
2498
0
    }
2499
2500
0
    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
2501
0
    return SECFailure;
2502
0
}
2503
2504
/*
2505
 * common HMAC initalization routine
2506
 */
2507
static CK_RV
2508
sftk_doSSLMACInit(SFTKSessionContext *context, SECOidTag oid,
2509
                  SFTKObject *key, CK_ULONG mac_size)
2510
0
{
2511
0
    SFTKAttribute *keyval;
2512
0
    SFTKBegin begin;
2513
0
    int padSize;
2514
0
    SFTKSSLMACInfo *sslmacinfo;
2515
0
    CK_RV crv = CKR_MECHANISM_INVALID;
2516
2517
0
    if (oid == SEC_OID_SHA1) {
2518
0
        crv = sftk_doSubSHA1(context);
2519
0
        if (crv != CKR_OK)
2520
0
            return crv;
2521
0
        begin = SFTKHash_SHA1_Begin;
2522
0
        padSize = 40;
2523
0
    } else {
2524
0
        crv = sftk_doSubMD5(context);
2525
0
        if (crv != CKR_OK)
2526
0
            return crv;
2527
0
        begin = SFTKHash_MD5_Begin;
2528
0
        padSize = 48;
2529
0
    }
2530
0
    context->multi = PR_TRUE;
2531
2532
0
    keyval = sftk_FindAttribute(key, CKA_VALUE);
2533
0
    if (keyval == NULL)
2534
0
        return CKR_KEY_SIZE_RANGE;
2535
2536
0
    context->hashUpdate(context->hashInfo, keyval->attrib.pValue,
2537
0
                        keyval->attrib.ulValueLen);
2538
0
    context->hashUpdate(context->hashInfo, ssl_pad_1, padSize);
2539
0
    sslmacinfo = (SFTKSSLMACInfo *)PORT_Alloc(sizeof(SFTKSSLMACInfo));
2540
0
    if (sslmacinfo == NULL) {
2541
0
        sftk_FreeAttribute(keyval);
2542
0
        return CKR_HOST_MEMORY;
2543
0
    }
2544
0
    sslmacinfo->size = sizeof(SFTKSSLMACInfo);
2545
0
    sslmacinfo->macSize = mac_size;
2546
0
    sslmacinfo->hashContext = context->hashInfo;
2547
0
    PORT_Memcpy(sslmacinfo->key, keyval->attrib.pValue,
2548
0
                keyval->attrib.ulValueLen);
2549
0
    sslmacinfo->keySize = keyval->attrib.ulValueLen;
2550
0
    sslmacinfo->begin = begin;
2551
0
    sslmacinfo->end = context->end;
2552
0
    sslmacinfo->update = context->hashUpdate;
2553
0
    sslmacinfo->padSize = padSize;
2554
0
    sftk_FreeAttribute(keyval);
2555
0
    context->cipherInfo = (void *)sslmacinfo;
2556
0
    context->destroy = sftk_ZSpace;
2557
0
    context->update = sftk_SSLMACSign;
2558
0
    context->verify = sftk_SSLMACVerify;
2559
0
    context->maxLen = mac_size;
2560
0
    return CKR_OK;
2561
0
}
2562
2563
/*
2564
 ************** Crypto Functions:     Sign  ************************
2565
 */
2566
2567
/**
2568
 * Check if We're using CBCMacing and initialize the session context if we are.
2569
 *  @param contextType SFTK_SIGN or SFTK_VERIFY
2570
 *  @param keyUsage    check whether key allows this usage
2571
 */
2572
static CK_RV
2573
sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
2574
                CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage,
2575
                SFTKContextType contextType)
2576
2577
515k
{
2578
515k
    CK_MECHANISM cbc_mechanism;
2579
515k
    CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE;
2580
515k
#ifndef NSS_DISABLE_DEPRECATED_RC2
2581
515k
    CK_RC2_CBC_PARAMS rc2_params;
2582
515k
#endif
2583
#if NSS_SOFTOKEN_DOES_RC5
2584
    CK_RC5_CBC_PARAMS rc5_params;
2585
    CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
2586
#endif
2587
515k
    unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
2588
515k
    unsigned char k2[SFTK_MAX_BLOCK_SIZE];
2589
515k
    unsigned char k3[SFTK_MAX_BLOCK_SIZE];
2590
515k
    SFTKSession *session;
2591
515k
    SFTKSessionContext *context;
2592
515k
    CK_RV crv;
2593
515k
    unsigned int blockSize;
2594
515k
    PRBool isXCBC = PR_FALSE;
2595
2596
515k
    if (!pMechanism) {
2597
0
        return CKR_MECHANISM_PARAM_INVALID;
2598
0
    }
2599
2600
515k
    switch (pMechanism->mechanism) {
2601
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
2602
0
        case CKM_RC2_MAC_GENERAL:
2603
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_MAC_GENERAL_PARAMS))) {
2604
0
                return CKR_MECHANISM_PARAM_INVALID;
2605
0
            }
2606
0
            mac_bytes =
2607
0
                ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
2608
        /* fall through */
2609
0
        case CKM_RC2_MAC:
2610
0
            if (pMechanism->mechanism == CKM_RC2_MAC &&
2611
0
                BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_CBC_PARAMS))) {
2612
0
                return CKR_MECHANISM_PARAM_INVALID;
2613
0
            }
2614
            /* this works because ulEffectiveBits is in the same place in both the
2615
             * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */
2616
0
            rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *)
2617
0
                                              pMechanism->pParameter)
2618
0
                                             ->ulEffectiveBits;
2619
0
            PORT_Memset(rc2_params.iv, 0, sizeof(rc2_params.iv));
2620
0
            cbc_mechanism.mechanism = CKM_RC2_CBC;
2621
0
            cbc_mechanism.pParameter = &rc2_params;
2622
0
            cbc_mechanism.ulParameterLen = sizeof(rc2_params);
2623
0
            blockSize = 8;
2624
0
            break;
2625
0
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
2626
2627
#if NSS_SOFTOKEN_DOES_RC5
2628
        case CKM_RC5_MAC_GENERAL:
2629
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
2630
                return CKR_MECHANISM_PARAM_INVALID;
2631
            }
2632
            mac_bytes =
2633
                ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
2634
        /* fall through */
2635
        case CKM_RC5_MAC:
2636
            /* this works because ulEffectiveBits is in the same place in both the
2637
             * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */
2638
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
2639
                return CKR_MECHANISM_PARAM_INVALID;
2640
            }
2641
            rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter;
2642
            rc5_params.ulWordsize = rc5_mac->ulWordsize;
2643
            rc5_params.ulRounds = rc5_mac->ulRounds;
2644
            rc5_params.pIv = ivBlock;
2645
            if ((blockSize = rc5_mac->ulWordsize * 2) > SFTK_MAX_BLOCK_SIZE)
2646
                return CKR_MECHANISM_PARAM_INVALID;
2647
            rc5_params.ulIvLen = blockSize;
2648
            PORT_Memset(ivBlock, 0, blockSize);
2649
            cbc_mechanism.mechanism = CKM_RC5_CBC;
2650
            cbc_mechanism.pParameter = &rc5_params;
2651
            cbc_mechanism.ulParameterLen = sizeof(rc5_params);
2652
            break;
2653
#endif
2654
        /* add cast and idea later */
2655
0
        case CKM_DES_MAC_GENERAL:
2656
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_ULONG))) {
2657
0
                return CKR_MECHANISM_PARAM_INVALID;
2658
0
            }
2659
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2660
        /* fall through */
2661
0
        case CKM_DES_MAC:
2662
0
            blockSize = 8;
2663
0
            PORT_Memset(ivBlock, 0, blockSize);
2664
0
            cbc_mechanism.mechanism = CKM_DES_CBC;
2665
0
            cbc_mechanism.pParameter = &ivBlock;
2666
0
            cbc_mechanism.ulParameterLen = blockSize;
2667
0
            break;
2668
0
        case CKM_DES3_MAC_GENERAL:
2669
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_ULONG))) {
2670
0
                return CKR_MECHANISM_PARAM_INVALID;
2671
0
            }
2672
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2673
        /* fall through */
2674
0
        case CKM_DES3_MAC:
2675
0
            blockSize = 8;
2676
0
            PORT_Memset(ivBlock, 0, blockSize);
2677
0
            cbc_mechanism.mechanism = CKM_DES3_CBC;
2678
0
            cbc_mechanism.pParameter = &ivBlock;
2679
0
            cbc_mechanism.ulParameterLen = blockSize;
2680
0
            break;
2681
0
        case CKM_CDMF_MAC_GENERAL:
2682
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_ULONG))) {
2683
0
                return CKR_MECHANISM_PARAM_INVALID;
2684
0
            }
2685
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2686
        /* fall through */
2687
0
        case CKM_CDMF_MAC:
2688
0
            blockSize = 8;
2689
0
            PORT_Memset(ivBlock, 0, blockSize);
2690
0
            cbc_mechanism.mechanism = CKM_CDMF_CBC;
2691
0
            cbc_mechanism.pParameter = &ivBlock;
2692
0
            cbc_mechanism.ulParameterLen = blockSize;
2693
0
            break;
2694
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
2695
0
        case CKM_SEED_MAC_GENERAL:
2696
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_ULONG))) {
2697
0
                return CKR_MECHANISM_PARAM_INVALID;
2698
0
            }
2699
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2700
        /* fall through */
2701
0
        case CKM_SEED_MAC:
2702
0
            blockSize = 16;
2703
0
            PORT_Memset(ivBlock, 0, blockSize);
2704
0
            cbc_mechanism.mechanism = CKM_SEED_CBC;
2705
0
            cbc_mechanism.pParameter = &ivBlock;
2706
0
            cbc_mechanism.ulParameterLen = blockSize;
2707
0
            break;
2708
0
#endif /* NSS_DISABLE_DEPRECATED_SEED */
2709
0
        case CKM_CAMELLIA_MAC_GENERAL:
2710
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_ULONG))) {
2711
0
                return CKR_MECHANISM_PARAM_INVALID;
2712
0
            }
2713
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2714
        /* fall through */
2715
0
        case CKM_CAMELLIA_MAC:
2716
0
            blockSize = 16;
2717
0
            PORT_Memset(ivBlock, 0, blockSize);
2718
0
            cbc_mechanism.mechanism = CKM_CAMELLIA_CBC;
2719
0
            cbc_mechanism.pParameter = &ivBlock;
2720
0
            cbc_mechanism.ulParameterLen = blockSize;
2721
0
            break;
2722
0
        case CKM_AES_MAC_GENERAL:
2723
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_ULONG))) {
2724
0
                return CKR_MECHANISM_PARAM_INVALID;
2725
0
            }
2726
0
            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
2727
        /* fall through */
2728
0
        case CKM_AES_MAC:
2729
0
            blockSize = 16;
2730
0
            PORT_Memset(ivBlock, 0, blockSize);
2731
0
            cbc_mechanism.mechanism = CKM_AES_CBC;
2732
0
            cbc_mechanism.pParameter = &ivBlock;
2733
0
            cbc_mechanism.ulParameterLen = blockSize;
2734
0
            break;
2735
0
        case CKM_AES_XCBC_MAC_96:
2736
0
        case CKM_AES_XCBC_MAC:
2737
            /* The only difference between CKM_AES_XCBC_MAC
2738
             * and CKM_AES_XCBC_MAC_96 is the size of the returned mac. */
2739
0
            mac_bytes = pMechanism->mechanism == CKM_AES_XCBC_MAC_96 ? 12 : 16;
2740
0
            blockSize = 16;
2741
0
            PORT_Memset(ivBlock, 0, blockSize);
2742
0
            cbc_mechanism.mechanism = CKM_AES_CBC;
2743
0
            cbc_mechanism.pParameter = &ivBlock;
2744
0
            cbc_mechanism.ulParameterLen = blockSize;
2745
            /* is XCBC requires extra processing at the end of the operation */
2746
0
            isXCBC = PR_TRUE;
2747
            /* The input key is used to generate k1, k2, and k3. k2 and k3
2748
             * are used at the end in the pad step. k1 replaces the input
2749
             * key in the aes cbc mac */
2750
0
            crv = sftk_aes_xcbc_new_keys(hSession, hKey, &hKey, k2, k3);
2751
0
            if (crv != CKR_OK) {
2752
0
                return crv;
2753
0
            }
2754
0
            break;
2755
515k
        default:
2756
515k
            return CKR_FUNCTION_NOT_SUPPORTED;
2757
515k
    }
2758
2759
    /* if MAC size is externally supplied, it should be checked.
2760
     */
2761
0
    if (mac_bytes == SFTK_INVALID_MAC_SIZE)
2762
0
        mac_bytes = blockSize >> 1;
2763
0
    else {
2764
0
        if (mac_bytes > blockSize) {
2765
0
            crv = CKR_MECHANISM_PARAM_INVALID;
2766
0
            goto fail;
2767
0
        }
2768
0
    }
2769
2770
0
    crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey,
2771
0
                         CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */
2772
0
                         keyUsage, contextType, PR_TRUE);
2773
0
    if (crv != CKR_OK)
2774
0
        goto fail;
2775
    /* Hold the session reference for the duration of the context writes;
2776
     * see comment on NSC_DigestUpdate. */
2777
0
    crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, &session);
2778
2779
    /* this shouldn't happen! */
2780
0
    PORT_Assert(crv == CKR_OK);
2781
0
    if (crv != CKR_OK)
2782
0
        goto fail;
2783
0
    context->blockSize = blockSize;
2784
0
    context->macSize = mac_bytes;
2785
0
    context->isXCBC = isXCBC;
2786
0
    if (isXCBC) {
2787
        /* save the xcbc specific parameters */
2788
0
        PORT_Memcpy(context->k2, k2, blockSize);
2789
0
        PORT_Memcpy(context->k3, k3, blockSize);
2790
0
        PORT_Memset(k2, 0, blockSize);
2791
0
        PORT_Memset(k3, 0, blockSize);
2792
        /* get rid of the temp key now that the context has been created */
2793
0
        NSC_DestroyObject(hSession, hKey);
2794
0
    }
2795
0
    sftk_FreeSession(session);
2796
0
    return CKR_OK;
2797
0
fail:
2798
0
    if (isXCBC) {
2799
0
        PORT_Memset(k2, 0, blockSize);
2800
0
        PORT_Memset(k3, 0, blockSize);
2801
0
        NSC_DestroyObject(hSession, hKey); /* get rid of our temp key */
2802
0
    }
2803
0
    return crv;
2804
0
}
2805
2806
/*
2807
 * encode RSA PKCS #1 Signature data before signing...
2808
 */
2809
static SECStatus
2810
sftk_RSAHashSign(void *ctx, unsigned char *sig,
2811
                 unsigned int *sigLen, unsigned int maxLen,
2812
                 const unsigned char *hash, unsigned int hashLen)
2813
0
{
2814
0
    SFTKHashSignInfo *info = ctx;
2815
0
    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
2816
0
    if (info->key->keyType != NSSLOWKEYRSAKey) {
2817
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
2818
0
        return SECFailure;
2819
0
    }
2820
2821
0
    return RSA_HashSign(info->hashOid, info->key, sig, sigLen, maxLen,
2822
0
                        hash, hashLen);
2823
0
}
2824
2825
/* XXX Old template; want to expunge it eventually. */
2826
static DERTemplate SECAlgorithmIDTemplate[] = {
2827
    { DER_SEQUENCE,
2828
      0, NULL, sizeof(SECAlgorithmID) },
2829
    { DER_OBJECT_ID,
2830
      offsetof(SECAlgorithmID, algorithm) },
2831
    { DER_OPTIONAL | DER_ANY,
2832
      offsetof(SECAlgorithmID, parameters) },
2833
    { 0 }
2834
};
2835
2836
/*
2837
 * XXX OLD Template.  Once all uses have been switched over to new one,
2838
 * remove this.
2839
 */
2840
static DERTemplate SGNDigestInfoTemplate[] = {
2841
    { DER_SEQUENCE,
2842
      0, NULL, sizeof(SGNDigestInfo) },
2843
    { DER_INLINE,
2844
      offsetof(SGNDigestInfo, digestAlgorithm),
2845
      SECAlgorithmIDTemplate },
2846
    { DER_OCTET_STRING,
2847
      offsetof(SGNDigestInfo, digest) },
2848
    { 0 }
2849
};
2850
2851
/*
2852
 * encode RSA PKCS #1 Signature data before signing...
2853
 */
2854
SECStatus
2855
RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key,
2856
             unsigned char *sig, unsigned int *sigLen, unsigned int maxLen,
2857
             const unsigned char *hash, unsigned int hashLen)
2858
0
{
2859
0
    SECStatus rv = SECFailure;
2860
0
    SECItem digder;
2861
0
    PLArenaPool *arena = NULL;
2862
0
    SGNDigestInfo *di = NULL;
2863
2864
0
    digder.data = NULL;
2865
2866
0
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2867
0
    if (!arena) {
2868
0
        goto loser;
2869
0
    }
2870
2871
    /* Construct digest info */
2872
0
    di = SGN_CreateDigestInfo(hashOid, hash, hashLen);
2873
0
    if (!di) {
2874
0
        goto loser;
2875
0
    }
2876
2877
    /* Der encode the digest as a DigestInfo */
2878
0
    rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di);
2879
0
    if (rv != SECSuccess) {
2880
0
        goto loser;
2881
0
    }
2882
2883
    /*
2884
    ** Encrypt signature after constructing appropriate PKCS#1 signature
2885
    ** block
2886
    */
2887
0
    rv = RSA_Sign(&key->u.rsa, sig, sigLen, maxLen, digder.data,
2888
0
                  digder.len);
2889
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2890
0
        sftk_fatalError = PR_TRUE;
2891
0
    }
2892
2893
0
loser:
2894
0
    SGN_DestroyDigestInfo(di);
2895
0
    if (arena != NULL) {
2896
0
        PORT_FreeArena(arena, PR_TRUE);
2897
0
    }
2898
0
    return rv;
2899
0
}
2900
2901
static SECStatus
2902
sftk_RSASign(void *ctx, unsigned char *output,
2903
             unsigned int *outputLen, unsigned int maxOutputLen,
2904
             const unsigned char *input, unsigned int inputLen)
2905
20.1k
{
2906
20.1k
    NSSLOWKEYPrivateKey *key = ctx;
2907
20.1k
    SECStatus rv = SECFailure;
2908
2909
20.1k
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
2910
20.1k
    if (key->keyType != NSSLOWKEYRSAKey) {
2911
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
2912
0
        return SECFailure;
2913
0
    }
2914
2915
20.1k
    rv = RSA_Sign(&key->u.rsa, output, outputLen, maxOutputLen, input,
2916
20.1k
                  inputLen);
2917
20.1k
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2918
0
        sftk_fatalError = PR_TRUE;
2919
0
    }
2920
20.1k
    return rv;
2921
20.1k
}
2922
2923
static SECStatus
2924
sftk_RSASignRaw(void *ctx, unsigned char *output,
2925
                unsigned int *outputLen, unsigned int maxOutputLen,
2926
                const unsigned char *input, unsigned int inputLen)
2927
0
{
2928
0
    NSSLOWKEYPrivateKey *key = ctx;
2929
0
    SECStatus rv = SECFailure;
2930
2931
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
2932
0
    if (key->keyType != NSSLOWKEYRSAKey) {
2933
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
2934
0
        return SECFailure;
2935
0
    }
2936
2937
0
    rv = RSA_SignRaw(&key->u.rsa, output, outputLen, maxOutputLen, input,
2938
0
                     inputLen);
2939
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2940
0
        sftk_fatalError = PR_TRUE;
2941
0
    }
2942
0
    return rv;
2943
0
}
2944
2945
static SECStatus
2946
sftk_RSASignPSS(void *ctx, unsigned char *sig,
2947
                unsigned int *sigLen, unsigned int maxLen,
2948
                const unsigned char *hash, unsigned int hashLen)
2949
2.74k
{
2950
2.74k
    SFTKPSSSignInfo *info = ctx;
2951
2.74k
    SECStatus rv = SECFailure;
2952
2.74k
    HASH_HashType hashAlg;
2953
2.74k
    HASH_HashType maskHashAlg;
2954
2.74k
    CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
2955
2956
2.74k
    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
2957
2.74k
    if (info->key->keyType != NSSLOWKEYRSAKey) {
2958
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
2959
0
        return SECFailure;
2960
0
    }
2961
2962
2.74k
    hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg);
2963
2.74k
    maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf);
2964
2965
2.74k
    rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL,
2966
2.74k
                     params->sLen, sig, sigLen, maxLen, hash, hashLen);
2967
2.74k
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2968
0
        sftk_fatalError = PR_TRUE;
2969
0
    }
2970
2.74k
    return rv;
2971
2.74k
}
2972
2973
#ifndef NSS_DISABLE_DSA
2974
static SECStatus
2975
nsc_DSA_Verify_Stub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen,
2976
                    const unsigned char *dataBuf, unsigned int dataLen)
2977
4.01k
{
2978
4.01k
    NSSLOWKEYPublicKey *key = ctx;
2979
4.01k
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen };
2980
4.01k
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2981
4.01k
    return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest);
2982
4.01k
}
2983
2984
static SECStatus
2985
nsc_DSA_Sign_Stub(void *ctx, unsigned char *sigBuf,
2986
                  unsigned int *sigLen, unsigned int maxSigLen,
2987
                  const unsigned char *dataBuf, unsigned int dataLen)
2988
0
{
2989
0
    NSSLOWKEYPrivateKey *key = ctx;
2990
0
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen };
2991
0
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
2992
0
    SECStatus rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest);
2993
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
2994
0
        sftk_fatalError = PR_TRUE;
2995
0
    }
2996
0
    *sigLen = signature.len;
2997
0
    return rv;
2998
0
}
2999
#endif
3000
3001
static SECStatus
3002
nsc_ECDSAVerifyStub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen,
3003
                    const unsigned char *dataBuf, unsigned int dataLen)
3004
544
{
3005
544
    NSSLOWKEYPublicKey *key = ctx;
3006
544
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen };
3007
544
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
3008
544
    return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest);
3009
544
}
3010
3011
static SECStatus
3012
nsc_ECDSASignStub(void *ctx, unsigned char *sigBuf,
3013
                  unsigned int *sigLen, unsigned int maxSigLen,
3014
                  const unsigned char *dataBuf, unsigned int dataLen)
3015
7.05k
{
3016
7.05k
    NSSLOWKEYPrivateKey *key = ctx;
3017
7.05k
    SECItem signature = { siBuffer, sigBuf, maxSigLen };
3018
7.05k
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
3019
3020
7.05k
    SECStatus rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest);
3021
7.05k
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
3022
0
        sftk_fatalError = PR_TRUE;
3023
0
    }
3024
7.05k
    *sigLen = signature.len;
3025
7.05k
    return rv;
3026
7.05k
}
3027
3028
static SECStatus
3029
nsc_EDDSAVerifyStub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen,
3030
                    const unsigned char *dataBuf, unsigned int dataLen)
3031
0
{
3032
0
    NSSLOWKEYPublicKey *key = ctx;
3033
0
    SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen };
3034
0
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
3035
0
    return ED_VerifyMessage(&(key->u.ec), &signature, &digest);
3036
0
}
3037
3038
static SECStatus
3039
nsc_EDDSASignStub(void *ctx, unsigned char *sigBuf,
3040
                  unsigned int *sigLen, unsigned int maxSigLen,
3041
                  const unsigned char *dataBuf, unsigned int dataLen)
3042
0
{
3043
0
    NSSLOWKEYPrivateKey *key = ctx;
3044
0
    SECItem signature = { siBuffer, sigBuf, maxSigLen };
3045
0
    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
3046
3047
0
    SECStatus rv = ED_SignMessage(&(key->u.ec), &signature, &digest);
3048
0
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
3049
0
        sftk_fatalError = PR_TRUE;
3050
0
    }
3051
0
    *sigLen = signature.len;
3052
0
    return rv;
3053
0
}
3054
3055
void
3056
sftk_MLDSASignUpdate(void *info, const unsigned char *data, unsigned int len)
3057
0
{
3058
0
    MLDSAContext *ctptr = (MLDSAContext *)info;
3059
0
    const SECItem inData = { siBuffer, (unsigned char *)data, len };
3060
0
    (void)MLDSA_SignUpdate(ctptr, &inData);
3061
0
}
3062
3063
void
3064
sftk_MLDSAVerifyUpdate(void *info, const unsigned char *data, unsigned int len)
3065
0
{
3066
0
    MLDSAContext *ctptr = (MLDSAContext *)info;
3067
0
    const SECItem inData = { siBuffer, (unsigned char *)data, len };
3068
0
    (void)MLDSA_VerifyUpdate(ctptr, &inData);
3069
0
}
3070
3071
SECStatus
3072
sftk_MLDSASignFinal(void *info, unsigned char *sig, unsigned int *sigLen,
3073
                    unsigned int maxLen, const unsigned char *data,
3074
                    unsigned int len)
3075
0
{
3076
0
    MLDSAContext *ctptr = (MLDSAContext *)info;
3077
0
    SECItem sigOut = { siBuffer, sig, maxLen };
3078
0
    SECStatus rv;
3079
3080
0
    if (len != 0) {
3081
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
3082
0
        return SECFailure;
3083
0
    }
3084
3085
0
    rv = MLDSA_SignFinal(ctptr, &sigOut);
3086
0
    *sigLen = sigOut.len;
3087
0
    return rv;
3088
0
}
3089
3090
SECStatus
3091
sftk_MLDSAVerifyFinal(void *info, const unsigned char *sig, unsigned int sigLen,
3092
                      const unsigned char *data, unsigned int len)
3093
0
{
3094
0
    MLDSAContext *ctptr = (MLDSAContext *)info;
3095
0
    const SECItem sigIn = { siBuffer, (unsigned char *)sig, sigLen };
3096
3097
0
    if (len != 0) {
3098
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
3099
0
        return SECFailure;
3100
0
    }
3101
3102
0
    return MLDSA_VerifyFinal(ctptr, &sigIn);
3103
0
}
3104
3105
unsigned int
3106
sftk_MLDSAGetSigLen(CK_ML_DSA_PARAMETER_SET_TYPE paramSet)
3107
0
{
3108
0
    switch (paramSet) {
3109
0
        case CKP_ML_DSA_44:
3110
0
            return ML_DSA_44_SIGNATURE_LEN;
3111
0
        case CKP_ML_DSA_65:
3112
0
            return ML_DSA_65_SIGNATURE_LEN;
3113
0
        case CKP_ML_DSA_87:
3114
0
            return ML_DSA_87_SIGNATURE_LEN;
3115
0
    }
3116
    /* this is a programming error if we get a valid DSA key with an unknown
3117
     * parmaSet */
3118
0
    PORT_Assert(/* unknown param set */ 0);
3119
0
    return 0;
3120
0
}
3121
3122
/* NSC_SignInit setups up the signing operations. There are three basic
3123
 * types of signing:
3124
 *      (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied
3125
 *  to data in a single Sign operation (which often looks a lot like an
3126
 *  encrypt, with data coming in and data going out).
3127
 *      (2) Hash based signing, where we continually hash the data, then apply
3128
 *  some sort of signature to the end.
3129
 *      (3) Block Encryption CBC MAC's, where the Data is encrypted with a key,
3130
 *  and only the final block is part of the mac.
3131
 *
3132
 *  For case number 3, we initialize a context much like the Encryption Context
3133
 *  (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and
3134
 *  C_Final by the following method... if it's not multi-part, and it's doesn't
3135
 *  have a hash context, it must be a block Encryption CBC MAC.
3136
 *
3137
 *  For case number 2, we initialize a hash structure, as well as make it
3138
 *  multi-part. Updates are simple calls to the hash update function. Final
3139
 *  calls the hashend, then passes the result to the 'update' function (which
3140
 *  operates as a final signature function). In some hash based MAC'ing (as
3141
 *  opposed to hash base signatures), the update function is can be simply a
3142
 *  copy (as is the case with HMAC).
3143
 */
3144
CK_RV
3145
NSC_SignInit(CK_SESSION_HANDLE hSession,
3146
             CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3147
503k
{
3148
503k
    SFTKSession *session;
3149
503k
    SFTKObject *key;
3150
503k
    SFTKSessionContext *context;
3151
503k
    CK_KEY_TYPE key_type;
3152
503k
    CK_RV crv = CKR_OK;
3153
503k
    NSSLOWKEYPrivateKey *privKey;
3154
503k
    SFTKHashSignInfo *info = NULL;
3155
503k
    SFTKPSSSignInfo *pinfo = NULL;
3156
3157
503k
    CHECK_FORK();
3158
3159
    /* Block Cipher MACing Algorithms use a different Context init method..*/
3160
503k
    crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN);
3161
503k
    if (crv != CKR_FUNCTION_NOT_SUPPORTED)
3162
0
        return crv;
3163
3164
    /* we're not using a block cipher mac */
3165
503k
    session = sftk_SessionFromHandle(hSession);
3166
503k
    if (session == NULL)
3167
0
        return CKR_SESSION_HANDLE_INVALID;
3168
503k
    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_SIGN, &key,
3169
503k
                           hKey, &key_type, CKO_PRIVATE_KEY, CKA_SIGN);
3170
503k
    if (crv != CKR_OK) {
3171
0
        sftk_FreeSession(session);
3172
0
        return crv;
3173
0
    }
3174
3175
503k
    context->multi = PR_FALSE;
3176
3177
503k
#define INIT_RSA_SIGN_MECH(mmm)             \
3178
503k
    case CKM_##mmm##_RSA_PKCS:              \
3179
0
        context->multi = PR_TRUE;           \
3180
0
        crv = sftk_doSub##mmm(context);     \
3181
0
        if (crv != CKR_OK)                  \
3182
0
            break;                          \
3183
0
        context->update = sftk_RSAHashSign; \
3184
0
        info = PORT_New(SFTKHashSignInfo);  \
3185
0
        if (info == NULL) {                 \
3186
0
            crv = CKR_HOST_MEMORY;          \
3187
0
            break;                          \
3188
0
        }                                   \
3189
0
        info->hashOid = SEC_OID_##mmm;      \
3190
0
        goto finish_rsa;
3191
3192
503k
    switch (pMechanism->mechanism) {
3193
0
        INIT_RSA_SIGN_MECH(MD5)
3194
0
        INIT_RSA_SIGN_MECH(MD2)
3195
0
        INIT_RSA_SIGN_MECH(SHA1)
3196
0
        INIT_RSA_SIGN_MECH(SHA224)
3197
0
        INIT_RSA_SIGN_MECH(SHA256)
3198
0
        INIT_RSA_SIGN_MECH(SHA384)
3199
0
        INIT_RSA_SIGN_MECH(SHA512)
3200
3201
20.1k
        case CKM_RSA_PKCS:
3202
20.1k
            context->update = sftk_RSASign;
3203
20.1k
            goto finish_rsa;
3204
0
        case CKM_RSA_X_509:
3205
0
            context->update = sftk_RSASignRaw;
3206
20.1k
        finish_rsa:
3207
20.1k
            if (key_type != CKK_RSA) {
3208
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3209
0
                break;
3210
0
            }
3211
20.1k
            context->rsa = PR_TRUE;
3212
20.1k
            privKey = sftk_GetPrivKey(key, CKK_RSA, &crv);
3213
20.1k
            if (privKey == NULL) {
3214
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3215
0
                break;
3216
0
            }
3217
            /* OK, info is allocated only if we're doing hash and sign mechanism.
3218
             * It's necessary to be able to set the correct OID in the final
3219
             * signature.
3220
             */
3221
20.1k
            if (info) {
3222
0
                info->key = privKey;
3223
0
                context->cipherInfo = info;
3224
0
                context->destroy = sftk_Space;
3225
20.1k
            } else {
3226
20.1k
                context->cipherInfo = privKey;
3227
20.1k
                context->destroy = sftk_Null;
3228
20.1k
            }
3229
20.1k
            context->maxLen = nsslowkey_PrivateModulusLen(privKey);
3230
20.1k
            break;
3231
3232
0
#define INIT_RSA_PSS_SIG_MECH(mmm)                                                            \
3233
2.22k
    case CKM_##mmm##_RSA_PKCS_PSS:                                                            \
3234
2.22k
        context->multi = PR_TRUE;                                                             \
3235
2.22k
        crv = sftk_doSub##mmm(context);                                                       \
3236
2.22k
        if (crv != CKR_OK)                                                                    \
3237
2.22k
            break;                                                                            \
3238
2.22k
        if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) {                   \
3239
0
            crv = CKR_MECHANISM_PARAM_INVALID;                                                \
3240
0
            break;                                                                            \
3241
0
        }                                                                                     \
3242
2.22k
        if (((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)->hashAlg != CKM_##mmm) { \
3243
0
            crv = CKR_MECHANISM_PARAM_INVALID;                                                \
3244
0
            break;                                                                            \
3245
0
        }                                                                                     \
3246
2.22k
        goto finish_rsa_pss;
3247
0
            INIT_RSA_PSS_SIG_MECH(SHA1)
3248
0
            INIT_RSA_PSS_SIG_MECH(SHA224)
3249
2.61k
            INIT_RSA_PSS_SIG_MECH(SHA256)
3250
1.26k
            INIT_RSA_PSS_SIG_MECH(SHA384)
3251
1.43k
            INIT_RSA_PSS_SIG_MECH(SHA512)
3252
969
        case CKM_RSA_PKCS_PSS:
3253
2.74k
        finish_rsa_pss:
3254
2.74k
            if (key_type != CKK_RSA) {
3255
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3256
0
                break;
3257
0
            }
3258
2.74k
            context->rsa = PR_TRUE;
3259
2.74k
            if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
3260
2.74k
                !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) {
3261
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3262
0
                break;
3263
0
            }
3264
2.74k
            pinfo = PORT_New(SFTKPSSSignInfo);
3265
2.74k
            if (pinfo == NULL) {
3266
0
                crv = CKR_HOST_MEMORY;
3267
0
                break;
3268
0
            }
3269
2.74k
            pinfo->size = sizeof(SFTKPSSSignInfo);
3270
2.74k
            pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter;
3271
2.74k
            pinfo->key = sftk_GetPrivKey(key, CKK_RSA, &crv);
3272
2.74k
            if (pinfo->key == NULL) {
3273
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3274
0
                break;
3275
0
            }
3276
2.74k
            context->cipherInfo = pinfo;
3277
2.74k
            context->destroy = sftk_ZSpace;
3278
2.74k
            context->update = sftk_RSASignPSS;
3279
2.74k
            context->maxLen = nsslowkey_PrivateModulusLen(pinfo->key);
3280
2.74k
            break;
3281
3282
0
#ifndef NSS_DISABLE_DSA
3283
0
#define INIT_DSA_SIG_MECH(mmm)          \
3284
835
    case CKM_DSA_##mmm:                 \
3285
835
        context->multi = PR_TRUE;       \
3286
835
        crv = sftk_doSub##mmm(context); \
3287
835
        if (crv != CKR_OK)              \
3288
835
            break;                      \
3289
835
        goto finish_dsa;
3290
0
            INIT_DSA_SIG_MECH(SHA1)
3291
0
            INIT_DSA_SIG_MECH(SHA224)
3292
0
            INIT_DSA_SIG_MECH(SHA256)
3293
0
            INIT_DSA_SIG_MECH(SHA384)
3294
0
            INIT_DSA_SIG_MECH(SHA512)
3295
0
        case CKM_DSA:
3296
0
        finish_dsa:
3297
0
            if (key_type != CKK_DSA) {
3298
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3299
0
                break;
3300
0
            }
3301
0
            privKey = sftk_GetPrivKey(key, CKK_DSA, &crv);
3302
0
            if (privKey == NULL) {
3303
0
                break;
3304
0
            }
3305
0
            context->cipherInfo = privKey;
3306
0
            context->update = nsc_DSA_Sign_Stub;
3307
0
            context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey;
3308
0
            context->maxLen = DSA_MAX_SIGNATURE_LEN;
3309
3310
0
            break;
3311
0
#endif
3312
0
        case CKM_ML_DSA: {
3313
            /* set our defaults */
3314
0
            CK_HEDGE_TYPE hedgeType = CKH_HEDGE_PREFERRED;
3315
0
            SECItem signCtx = { siBuffer, NULL, 0 };
3316
0
            MLDSAContext *ctptr = NULL;
3317
0
            SECStatus rv;
3318
3319
            /* make sure we have the right key type */
3320
0
            if (key_type != CKK_ML_DSA) {
3321
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3322
0
                break;
3323
0
            }
3324
            /* fill in our parameters from the mechanism parameters if
3325
             * supplied */
3326
0
            if (pMechanism->ulParameterLen != 0) {
3327
0
                CK_SIGN_ADDITIONAL_CONTEXT *param;
3328
0
                if (pMechanism->ulParameterLen !=
3329
0
                    sizeof(CK_SIGN_ADDITIONAL_CONTEXT)) {
3330
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
3331
0
                    break;
3332
0
                }
3333
0
                param = (CK_SIGN_ADDITIONAL_CONTEXT *)pMechanism->pParameter;
3334
0
                hedgeType = param->hedgeVariant;
3335
0
                signCtx.data = param->pContext;
3336
0
                signCtx.len = param->ulContextLen;
3337
0
            }
3338
            /* fetch the key */
3339
0
            privKey = sftk_GetPrivKey(key, key_type, &crv);
3340
0
            if (privKey == NULL) {
3341
0
                crv = CKR_HOST_MEMORY;
3342
0
                break;
3343
0
            }
3344
            /* now initialize it the signature */
3345
0
            rv = MLDSA_SignInit(&privKey->u.mldsa, hedgeType, &signCtx, &ctptr);
3346
0
            if (rv != SECSuccess) {
3347
0
                crv = sftk_MapCryptError(PORT_GetError());
3348
0
                if (privKey != key->objectInfo) {
3349
0
                    nsslowkey_DestroyPrivateKey(privKey);
3350
0
                }
3351
0
                break;
3352
0
            }
3353
            /* set up our cipher info. MLDSA is only a combined hash/sign
3354
             * so the hash update is our sign update, the hash end is a null
3355
             * function returning a zero length value, and the final gets our
3356
             * signature based on the context. Both the cipher context and the
3357
             * hash Info is the same. The MLDSA_SignFinal frees the context,
3358
             * so we don't have to */
3359
0
            context->multi = PR_TRUE;
3360
0
            context->cipherInfo = ctptr;
3361
0
            context->hashInfo = ctptr;
3362
0
            context->hashUpdate = sftk_MLDSASignUpdate;
3363
0
            context->end = sftk_NullHashEnd;
3364
0
            context->hashdestroy = sftk_Null;
3365
0
            context->destroy = sftk_Null;
3366
0
            context->update = sftk_MLDSASignFinal;
3367
0
            context->maxLen = sftk_MLDSAGetSigLen(privKey->u.mldsa.paramSet);
3368
0
            if (privKey != key->objectInfo) {
3369
0
                nsslowkey_DestroyPrivateKey(privKey);
3370
0
            }
3371
0
            break;
3372
0
        }
3373
3374
0
#define INIT_ECDSA_SIG_MECH(mmm)        \
3375
1.13k
    case CKM_ECDSA_##mmm:               \
3376
1.13k
        context->multi = PR_TRUE;       \
3377
1.13k
        crv = sftk_doSub##mmm(context); \
3378
1.13k
        if (crv != CKR_OK)              \
3379
1.13k
            break;                      \
3380
1.13k
        goto finish_ecdsa;
3381
0
            INIT_ECDSA_SIG_MECH(SHA1)
3382
0
            INIT_ECDSA_SIG_MECH(SHA224)
3383
834
            INIT_ECDSA_SIG_MECH(SHA256)
3384
834
            INIT_ECDSA_SIG_MECH(SHA384)
3385
143
            INIT_ECDSA_SIG_MECH(SHA512)
3386
6.07k
        case CKM_ECDSA:
3387
7.05k
        finish_ecdsa:
3388
7.05k
            if (key_type != CKK_EC) {
3389
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3390
0
                break;
3391
0
            }
3392
7.05k
            privKey = sftk_GetPrivKey(key, CKK_EC, &crv);
3393
7.05k
            if (privKey == NULL) {
3394
0
                crv = CKR_HOST_MEMORY;
3395
0
                break;
3396
0
            }
3397
7.05k
            context->cipherInfo = privKey;
3398
7.05k
            context->update = nsc_ECDSASignStub;
3399
7.05k
            context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey;
3400
7.05k
            context->maxLen = MAX_ECKEY_LEN * 2;
3401
3402
7.05k
            break;
3403
3404
0
        case CKM_EDDSA:
3405
0
            if (key_type != CKK_EC_EDWARDS) {
3406
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
3407
0
                break;
3408
0
            }
3409
3410
0
            if (pMechanism->pParameter) {
3411
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3412
0
                break;
3413
0
            }
3414
3415
0
            privKey = sftk_GetPrivKey(key, CKK_EC_EDWARDS, &crv);
3416
0
            if (privKey == NULL) {
3417
0
                crv = CKR_HOST_MEMORY;
3418
0
                break;
3419
0
            }
3420
0
            context->cipherInfo = privKey;
3421
0
            context->update = nsc_EDDSASignStub;
3422
0
            context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey;
3423
0
            context->maxLen = MAX_ECKEY_LEN * 2;
3424
3425
0
            break;
3426
3427
0
#define INIT_HMAC_MECH(mmm)                                        \
3428
0
    case CKM_##mmm##_HMAC_GENERAL:                                 \
3429
0
        PORT_Assert(pMechanism->pParameter);                       \
3430
0
        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_ULONG))) {        \
3431
0
            crv = CKR_MECHANISM_PARAM_INVALID;                     \
3432
0
            break;                                                 \
3433
0
        }                                                          \
3434
0
        crv = sftk_doMACInit(pMechanism->mechanism, context, key,  \
3435
0
                             *(CK_ULONG *)pMechanism->pParameter); \
3436
0
        break;                                                     \
3437
253k
    case CKM_##mmm##_HMAC:                                         \
3438
253k
        crv = sftk_doMACInit(pMechanism->mechanism, context, key,  \
3439
253k
                             mmm##_LENGTH);                        \
3440
253k
        break;
3441
3442
0
            INIT_HMAC_MECH(MD2)
3443
0
            INIT_HMAC_MECH(MD5)
3444
0
            INIT_HMAC_MECH(SHA1)
3445
0
            INIT_HMAC_MECH(SHA224)
3446
0
            INIT_HMAC_MECH(SHA256)
3447
0
            INIT_HMAC_MECH(SHA384)
3448
0
            INIT_HMAC_MECH(SHA512)
3449
0
            INIT_HMAC_MECH(SHA3_224)
3450
0
            INIT_HMAC_MECH(SHA3_256)
3451
0
            INIT_HMAC_MECH(SHA3_384)
3452
0
            INIT_HMAC_MECH(SHA3_512)
3453
3454
0
        case CKM_AES_CMAC_GENERAL:
3455
0
            PORT_Assert(pMechanism->pParameter);
3456
0
            if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) {
3457
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3458
0
                break;
3459
0
            }
3460
0
            crv = sftk_doMACInit(pMechanism->mechanism, context, key, *(CK_ULONG *)pMechanism->pParameter);
3461
0
            break;
3462
99
        case CKM_AES_CMAC:
3463
99
            crv = sftk_doMACInit(pMechanism->mechanism, context, key, AES_BLOCK_SIZE);
3464
99
            break;
3465
0
        case CKM_SSL3_MD5_MAC:
3466
0
            PORT_Assert(pMechanism->pParameter);
3467
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_ULONG))) {
3468
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3469
0
                break;
3470
0
            }
3471
0
            crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key,
3472
0
                                    *(CK_ULONG *)pMechanism->pParameter);
3473
0
            break;
3474
0
        case CKM_SSL3_SHA1_MAC:
3475
0
            PORT_Assert(pMechanism->pParameter);
3476
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_ULONG))) {
3477
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3478
0
                break;
3479
0
            }
3480
0
            crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key,
3481
0
                                    *(CK_ULONG *)pMechanism->pParameter);
3482
0
            break;
3483
0
        case CKM_TLS_PRF_GENERAL:
3484
0
            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0);
3485
0
            break;
3486
196k
        case CKM_TLS_MAC: {
3487
196k
            CK_TLS_MAC_PARAMS *tls12_mac_params;
3488
196k
            HASH_HashType tlsPrfHash;
3489
196k
            const char *label;
3490
3491
196k
            if (pMechanism->ulParameterLen != sizeof(CK_TLS_MAC_PARAMS)) {
3492
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3493
0
                break;
3494
0
            }
3495
196k
            tls12_mac_params = (CK_TLS_MAC_PARAMS *)pMechanism->pParameter;
3496
196k
            if (tls12_mac_params->prfHashMechanism == CKM_TLS_PRF) {
3497
                /* The TLS 1.0 and 1.1 PRF */
3498
70.7k
                tlsPrfHash = HASH_AlgNULL;
3499
70.7k
                if (tls12_mac_params->ulMacLength != 12) {
3500
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
3501
0
                    break;
3502
0
                }
3503
125k
            } else {
3504
                /* The hash function for the TLS 1.2 PRF */
3505
125k
                tlsPrfHash =
3506
125k
                    sftk_GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism);
3507
125k
                if (tlsPrfHash == HASH_AlgNULL ||
3508
125k
                    tls12_mac_params->ulMacLength < 12) {
3509
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
3510
0
                    break;
3511
0
                }
3512
125k
            }
3513
196k
            if (tls12_mac_params->ulServerOrClient == 1) {
3514
95.1k
                label = "server finished";
3515
101k
            } else if (tls12_mac_params->ulServerOrClient == 2) {
3516
101k
                label = "client finished";
3517
101k
            } else {
3518
0
                crv = CKR_MECHANISM_PARAM_INVALID;
3519
0
                break;
3520
0
            }
3521
196k
            crv = sftk_TLSPRFInit(context, key, key_type, tlsPrfHash,
3522
196k
                                  tls12_mac_params->ulMacLength);
3523
196k
            if (crv == CKR_OK) {
3524
196k
                context->hashUpdate(context->hashInfo, (unsigned char *)label, 15);
3525
196k
            }
3526
196k
            break;
3527
196k
        }
3528
0
        case CKM_NSS_TLS_PRF_GENERAL_SHA256:
3529
0
            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0);
3530
0
            break;
3531
3532
23.2k
        case CKM_NSS_HMAC_CONSTANT_TIME: {
3533
23.2k
            sftk_MACConstantTimeCtx *ctx =
3534
23.2k
                sftk_HMACConstantTime_New(pMechanism, key);
3535
23.2k
            CK_ULONG *intpointer;
3536
3537
23.2k
            if (ctx == NULL) {
3538
0
                crv = CKR_ARGUMENTS_BAD;
3539
0
                break;
3540
0
            }
3541
23.2k
            intpointer = PORT_New(CK_ULONG);
3542
23.2k
            if (intpointer == NULL) {
3543
0
                PORT_Free(ctx);
3544
0
                crv = CKR_HOST_MEMORY;
3545
0
                break;
3546
0
            }
3547
23.2k
            *intpointer = ctx->hash->length;
3548
3549
23.2k
            context->cipherInfo = intpointer;
3550
23.2k
            context->hashInfo = ctx;
3551
23.2k
            context->currentMech = pMechanism->mechanism;
3552
23.2k
            context->hashUpdate = sftk_HMACConstantTime_Update;
3553
23.2k
            context->hashdestroy = sftk_MACConstantTime_DestroyContext;
3554
23.2k
            context->end = sftk_MACConstantTime_EndHash;
3555
23.2k
            context->update = sftk_SignCopy;
3556
23.2k
            context->destroy = sftk_Space;
3557
23.2k
            context->maxLen = 64;
3558
23.2k
            context->multi = PR_TRUE;
3559
23.2k
            break;
3560
23.2k
        }
3561
3562
0
        case CKM_NSS_SSL3_MAC_CONSTANT_TIME: {
3563
0
            sftk_MACConstantTimeCtx *ctx =
3564
0
                sftk_SSLv3MACConstantTime_New(pMechanism, key);
3565
0
            CK_ULONG *intpointer;
3566
3567
0
            if (ctx == NULL) {
3568
0
                crv = CKR_ARGUMENTS_BAD;
3569
0
                break;
3570
0
            }
3571
0
            intpointer = PORT_New(CK_ULONG);
3572
0
            if (intpointer == NULL) {
3573
0
                PORT_Free(ctx);
3574
0
                crv = CKR_HOST_MEMORY;
3575
0
                break;
3576
0
            }
3577
0
            *intpointer = ctx->hash->length;
3578
3579
0
            context->cipherInfo = intpointer;
3580
0
            context->hashInfo = ctx;
3581
0
            context->currentMech = pMechanism->mechanism;
3582
0
            context->hashUpdate = sftk_SSLv3MACConstantTime_Update;
3583
0
            context->hashdestroy = sftk_MACConstantTime_DestroyContext;
3584
0
            context->end = sftk_MACConstantTime_EndHash;
3585
0
            context->update = sftk_SignCopy;
3586
0
            context->destroy = sftk_Space;
3587
0
            context->maxLen = 64;
3588
0
            context->multi = PR_TRUE;
3589
0
            break;
3590
0
        }
3591
3592
82
        default:
3593
82
            crv = CKR_MECHANISM_INVALID;
3594
82
            break;
3595
503k
    }
3596
3597
503k
    if (crv != CKR_OK) {
3598
82
        if (info)
3599
0
            PORT_Free(info);
3600
82
        if (pinfo)
3601
0
            PORT_ZFree(pinfo, pinfo->size);
3602
82
        sftk_FreeContext(context);
3603
82
        sftk_FreeSession(session);
3604
82
        return crv;
3605
82
    }
3606
    /* At this point info/pinfo (if allocated) are linked into
3607
     * context->cipherInfo and will be freed via sftk_FreeContext. */
3608
503k
    crv = sftk_InstallContext(session, SFTK_SIGN, context);
3609
503k
    if (crv != CKR_OK) {
3610
0
        sftk_FreeContext(context);
3611
0
    }
3612
503k
    sftk_FreeSession(session);
3613
503k
    return crv;
3614
503k
}
3615
3616
/** MAC one block of data by block cipher
3617
 */
3618
static CK_RV
3619
sftk_MACBlock(SFTKSessionContext *ctx, void *blk)
3620
0
{
3621
0
    unsigned int outlen;
3622
0
    return (SECSuccess == (ctx->update)(ctx->cipherInfo, ctx->macBuf, &outlen,
3623
0
                                        SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize))
3624
0
               ? CKR_OK
3625
0
               : sftk_MapCryptError(PORT_GetError());
3626
0
}
3627
3628
/** MAC last (incomplete) block of data by block cipher
3629
 *
3630
 *  Call once, then terminate MACing operation.
3631
 */
3632
static CK_RV
3633
sftk_MACFinal(SFTKSessionContext *ctx)
3634
0
{
3635
0
    unsigned int padLen = ctx->padDataLength;
3636
    /* pad and proceed the residual */
3637
0
    if (ctx->isXCBC) {
3638
0
        CK_RV crv = sftk_xcbc_mac_pad(ctx->padBuf, padLen, ctx->blockSize,
3639
0
                                      ctx->k2, ctx->k3);
3640
0
        if (crv != CKR_OK)
3641
0
            return crv;
3642
0
        return sftk_MACBlock(ctx, ctx->padBuf);
3643
0
    }
3644
0
    if (padLen) {
3645
        /* shd clr ctx->padLen to make sftk_MACFinal idempotent */
3646
0
        PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen);
3647
0
        return sftk_MACBlock(ctx, ctx->padBuf);
3648
0
    } else
3649
0
        return CKR_OK;
3650
0
}
3651
3652
/** The common implementation for {Sign,Verify}Update. (S/V only vary in their
3653
 * setup and final operations).
3654
 *
3655
 * A call which results in an error terminates the operation [PKCS#11,v2.11]
3656
 */
3657
static CK_RV
3658
sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
3659
               CK_ULONG ulPartLen, SFTKContextType type)
3660
310k
{
3661
310k
    SFTKSession *session;
3662
310k
    SFTKSessionContext *context;
3663
310k
    CK_RV crv;
3664
3665
    /* make sure we're legal */
3666
310k
    crv = sftk_GetContext(hSession, &context, type, PR_TRUE, &session);
3667
310k
    if (crv != CKR_OK)
3668
0
        return crv;
3669
3670
310k
    if (context->hashInfo) {
3671
310k
#if (ULONG_MAX > UINT_MAX)
3672
310k
        while (ulPartLen > UINT_MAX) {
3673
0
            (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX);
3674
0
            pPart += UINT_MAX;
3675
0
            ulPartLen -= UINT_MAX;
3676
0
        }
3677
310k
#endif
3678
310k
        (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen);
3679
310k
    } else {
3680
        /* must be block cipher MACing */
3681
3682
0
        unsigned int blkSize = context->blockSize;
3683
0
        unsigned char *residual = /* free room in context->padBuf */
3684
0
            context->padBuf + context->padDataLength;
3685
0
        unsigned int minInput = /* min input for MACing at least one block */
3686
0
            blkSize - context->padDataLength;
3687
3688
        /* not enough data even for one block */
3689
0
        if (ulPartLen <= minInput) {
3690
0
            PORT_Memcpy(residual, pPart, ulPartLen);
3691
0
            context->padDataLength += ulPartLen;
3692
0
            goto cleanup;
3693
0
        }
3694
        /* MACing residual */
3695
0
        if (context->padDataLength) {
3696
0
            PORT_Memcpy(residual, pPart, minInput);
3697
0
            ulPartLen -= minInput;
3698
0
            pPart += minInput;
3699
0
            if (CKR_OK != (crv = sftk_MACBlock(context, context->padBuf)))
3700
0
                goto terminate;
3701
0
        }
3702
        /* MACing full blocks */
3703
0
        while (ulPartLen > blkSize) {
3704
0
            if (CKR_OK != (crv = sftk_MACBlock(context, pPart)))
3705
0
                goto terminate;
3706
0
            ulPartLen -= blkSize;
3707
0
            pPart += blkSize;
3708
0
        }
3709
        /* save the residual */
3710
0
        if ((context->padDataLength = ulPartLen))
3711
0
            PORT_Memcpy(context->padBuf, pPart, ulPartLen);
3712
0
    } /* blk cipher MACing */
3713
3714
310k
    goto cleanup;
3715
3716
310k
terminate:
3717
0
    sftk_TerminateOp(session, type);
3718
310k
cleanup:
3719
310k
    sftk_FreeSession(session);
3720
310k
    return crv;
3721
0
}
3722
3723
/* NSC_SignUpdate continues a multiple-part signature operation,
3724
 * where the signature is (will be) an appendix to the data,
3725
 * and plaintext cannot be recovered from the signature
3726
 *
3727
 * A call which results in an error terminates the operation [PKCS#11,v2.11]
3728
 */
3729
CK_RV
3730
NSC_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
3731
               CK_ULONG ulPartLen)
3732
306k
{
3733
306k
    CHECK_FORK();
3734
306k
    return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN);
3735
306k
}
3736
3737
struct SFTK_SESSION_FLAGS {
3738
    CK_FLAGS flag;
3739
    SFTKContextType type;
3740
};
3741
3742
const static struct SFTK_SESSION_FLAGS sftk_session_flags[] = {
3743
    { CKF_ENCRYPT, SFTK_ENCRYPT },
3744
    { CKF_DECRYPT, SFTK_DECRYPT },
3745
    { CKF_DIGEST, SFTK_HASH },
3746
    { CKF_SIGN, SFTK_SIGN },
3747
    { CKF_SIGN_RECOVER, SFTK_SIGN_RECOVER },
3748
    { CKF_VERIFY, SFTK_VERIFY },
3749
    { CKF_VERIFY_RECOVER, SFTK_VERIFY_RECOVER },
3750
    { CKF_MESSAGE_ENCRYPT, SFTK_MESSAGE_ENCRYPT },
3751
    { CKF_MESSAGE_DECRYPT, SFTK_MESSAGE_DECRYPT },
3752
    { CKF_MESSAGE_SIGN, SFTK_MESSAGE_SIGN },
3753
    { CKF_MESSAGE_VERIFY, SFTK_MESSAGE_VERIFY },
3754
};
3755
const static int sftk_flag_count = PR_ARRAY_SIZE(sftk_session_flags);
3756
3757
/*
3758
 * Cancel one or more operations running on the existing session.
3759
 */
3760
CK_RV
3761
NSC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags)
3762
0
{
3763
0
    SFTKSession *session;
3764
0
    SFTKSessionContext *context;
3765
0
    CK_RV gcrv = CKR_OK;
3766
0
    CK_RV crv;
3767
0
    int i;
3768
3769
0
    for (i = 0; i < sftk_flag_count; i++) {
3770
0
        if (flags & sftk_session_flags[i].flag) {
3771
0
            flags &= ~sftk_session_flags[i].flag;
3772
0
            crv = sftk_GetContext(hSession, &context, sftk_session_flags[i].type, PR_TRUE, &session);
3773
0
            if (crv != CKR_OK) {
3774
0
                gcrv = CKR_OPERATION_CANCEL_FAILED;
3775
0
                continue;
3776
0
            }
3777
0
            sftk_TerminateOp(session, sftk_session_flags[i].type);
3778
0
        }
3779
0
    }
3780
0
    if (flags & CKF_FIND_OBJECTS) {
3781
0
        flags &= ~CKF_FIND_OBJECTS;
3782
0
        crv = NSC_FindObjectsFinal(hSession);
3783
0
        if (crv != CKR_OK) {
3784
0
            gcrv = CKR_OPERATION_CANCEL_FAILED;
3785
0
        }
3786
0
    }
3787
0
    if (flags) {
3788
0
        gcrv = CKR_OPERATION_CANCEL_FAILED;
3789
0
    }
3790
0
    return gcrv;
3791
0
}
3792
3793
/* NSC_SignFinal finishes a multiple-part signature operation,
3794
 * returning the signature. */
3795
CK_RV
3796
NSC_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
3797
              CK_ULONG_PTR pulSignatureLen)
3798
311k
{
3799
311k
    SFTKSession *session;
3800
311k
    SFTKSessionContext *context;
3801
311k
    unsigned int outlen = 0;
3802
311k
    unsigned int maxoutlen = *pulSignatureLen;
3803
311k
    CK_RV crv;
3804
3805
311k
    CHECK_FORK();
3806
3807
    /* make sure we're legal */
3808
311k
    crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_TRUE, &session);
3809
311k
    if (crv != CKR_OK)
3810
36.5k
        return crv;
3811
3812
274k
    if (context->hashInfo) {
3813
274k
        unsigned int digestLen;
3814
274k
        unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
3815
3816
274k
        if (!pSignature) {
3817
0
            outlen = context->maxLen;
3818
0
            goto finish;
3819
0
        }
3820
274k
        (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
3821
274k
        if (SECSuccess != (context->update)(context->cipherInfo, pSignature,
3822
274k
                                            &outlen, maxoutlen, tmpbuf, digestLen))
3823
0
            crv = sftk_MapCryptError(PORT_GetError());
3824
        /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate.
3825
         * Keeping "too small" CK_RV intact is a standard violation, but allows
3826
         * application read EXACT signature length */
3827
274k
        PORT_Memset(tmpbuf, 0, sizeof tmpbuf);
3828
274k
    } else {
3829
        /* must be block cipher MACing */
3830
0
        outlen = context->macSize;
3831
        /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/
3832
0
        if (!pSignature || maxoutlen < outlen) {
3833
0
            if (pSignature)
3834
0
                crv = CKR_BUFFER_TOO_SMALL;
3835
0
            goto finish;
3836
0
        }
3837
0
        if (CKR_OK == (crv = sftk_MACFinal(context)))
3838
0
            PORT_Memcpy(pSignature, context->macBuf, outlen);
3839
0
    }
3840
3841
274k
    sftk_TerminateOp(session, SFTK_SIGN);
3842
274k
finish:
3843
274k
    *pulSignatureLen = outlen;
3844
274k
    sftk_FreeSession(session);
3845
274k
    return crv;
3846
274k
}
3847
3848
/* NSC_Sign signs (encrypts with private key) data in a single part,
3849
 * where the signature is (will be) an appendix to the data,
3850
 * and plaintext cannot be recovered from the signature */
3851
CK_RV
3852
NSC_Sign(CK_SESSION_HANDLE hSession,
3853
         CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
3854
         CK_ULONG_PTR pulSignatureLen)
3855
50.6k
{
3856
50.6k
    SFTKSession *session;
3857
50.6k
    SFTKSessionContext *context;
3858
50.6k
    CK_RV crv;
3859
3860
50.6k
    CHECK_FORK();
3861
3862
    /* make sure we're legal */
3863
50.6k
    crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_FALSE, &session);
3864
50.6k
    if (crv != CKR_OK)
3865
0
        return crv;
3866
3867
50.6k
    if (!pSignature) {
3868
        /* see also how C_SignUpdate implements this */
3869
0
        *pulSignatureLen = (!context->multi || context->hashInfo)
3870
0
                               ? context->maxLen
3871
0
                               : context->macSize; /* must be block cipher MACing */
3872
0
        goto finish;
3873
0
    }
3874
3875
    /* multi part Signing are completely implemented by SignUpdate and
3876
     * sign Final */
3877
50.6k
    if (context->multi) {
3878
        /* SignFinal can't follow failed SignUpdate */
3879
23.3k
        if (CKR_OK == (crv = NSC_SignUpdate(hSession, pData, ulDataLen)))
3880
23.3k
            crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen);
3881
27.2k
    } else {
3882
        /* single-part PKC signature (e.g. CKM_ECDSA) */
3883
27.2k
        unsigned int outlen;
3884
27.2k
        unsigned int maxoutlen = *pulSignatureLen;
3885
27.2k
        if (SECSuccess != (*context->update)(context->cipherInfo, pSignature,
3886
27.2k
                                             &outlen, maxoutlen, pData, ulDataLen))
3887
0
            crv = sftk_MapCryptError(PORT_GetError());
3888
27.2k
        *pulSignatureLen = (CK_ULONG)outlen;
3889
        /*  "too small" here is certainly continuable */
3890
27.2k
        if (crv != CKR_BUFFER_TOO_SMALL)
3891
27.2k
            sftk_TerminateOp(session, SFTK_SIGN);
3892
27.2k
    } /* single-part */
3893
3894
50.6k
finish:
3895
50.6k
    sftk_FreeSession(session);
3896
50.6k
    return crv;
3897
50.6k
}
3898
3899
/*
3900
 ************** Crypto Functions:     Sign Recover  ************************
3901
 */
3902
/* NSC_SignRecoverInit initializes a signature operation,
3903
 * where the (digest) data can be recovered from the signature.
3904
 * E.g. encryption with the user's private key */
3905
CK_RV
3906
NSC_SignRecoverInit(CK_SESSION_HANDLE hSession,
3907
                    CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3908
0
{
3909
0
    CHECK_FORK();
3910
3911
0
    switch (pMechanism->mechanism) {
3912
0
        case CKM_RSA_PKCS:
3913
0
        case CKM_RSA_X_509:
3914
0
            return NSC_SignInit(hSession, pMechanism, hKey);
3915
0
        default:
3916
0
            break;
3917
0
    }
3918
0
    return CKR_MECHANISM_INVALID;
3919
0
}
3920
3921
/* NSC_SignRecover signs data in a single operation
3922
 * where the (digest) data can be recovered from the signature.
3923
 * E.g. encryption with the user's private key */
3924
CK_RV
3925
NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
3926
                CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
3927
0
{
3928
0
    CHECK_FORK();
3929
3930
0
    return NSC_Sign(hSession, pData, ulDataLen, pSignature, pulSignatureLen);
3931
0
}
3932
3933
/*
3934
 ************** Crypto Functions:     verify  ************************
3935
 */
3936
3937
/* Handle RSA Signature formatting */
3938
static SECStatus
3939
sftk_hashCheckSign(void *ctx, const unsigned char *sig,
3940
                   unsigned int sigLen, const unsigned char *digest,
3941
                   unsigned int digestLen)
3942
2.66k
{
3943
2.66k
    SFTKHashVerifyInfo *info = ctx;
3944
2.66k
    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
3945
2.66k
    if (info->key->keyType != NSSLOWKEYRSAKey) {
3946
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
3947
0
        return SECFailure;
3948
0
    }
3949
3950
2.66k
    return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, digest,
3951
2.66k
                             digestLen);
3952
2.66k
}
3953
3954
SECStatus
3955
RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key,
3956
                  const unsigned char *sig, unsigned int sigLen,
3957
                  const unsigned char *digestData, unsigned int digestLen)
3958
2.66k
{
3959
2.66k
    unsigned char *pkcs1DigestInfoData;
3960
2.66k
    SECItem pkcs1DigestInfo;
3961
2.66k
    SECItem digest;
3962
2.66k
    unsigned int bufferSize;
3963
2.66k
    SECStatus rv;
3964
3965
    /* pkcs1DigestInfo.data must be less than key->u.rsa.modulus.len */
3966
2.66k
    bufferSize = key->u.rsa.modulus.len;
3967
2.66k
    pkcs1DigestInfoData = PORT_ZAlloc(bufferSize);
3968
2.66k
    if (!pkcs1DigestInfoData) {
3969
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
3970
0
        return SECFailure;
3971
0
    }
3972
3973
2.66k
    pkcs1DigestInfo.data = pkcs1DigestInfoData;
3974
2.66k
    pkcs1DigestInfo.len = bufferSize;
3975
3976
    /* decrypt the block */
3977
2.66k
    rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data,
3978
2.66k
                              &pkcs1DigestInfo.len, pkcs1DigestInfo.len,
3979
2.66k
                              sig, sigLen);
3980
2.66k
    if (rv != SECSuccess) {
3981
2.65k
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
3982
2.65k
    } else {
3983
9
        digest.data = (PRUint8 *)digestData;
3984
9
        digest.len = digestLen;
3985
9
        rv = _SGN_VerifyPKCS1DigestInfo(
3986
9
            digestOid, &digest, &pkcs1DigestInfo,
3987
9
            PR_FALSE /*XXX: unsafeAllowMissingParameters*/);
3988
9
    }
3989
3990
2.66k
    PORT_ZFree(pkcs1DigestInfoData, bufferSize);
3991
2.66k
    return rv;
3992
2.66k
}
3993
3994
static SECStatus
3995
sftk_RSACheckSign(void *ctx, const unsigned char *sig,
3996
                  unsigned int sigLen, const unsigned char *digest,
3997
                  unsigned int digestLen)
3998
1.29k
{
3999
1.29k
    NSSLOWKEYPublicKey *key = ctx;
4000
1.29k
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
4001
1.29k
    if (key->keyType != NSSLOWKEYRSAKey) {
4002
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
4003
0
        return SECFailure;
4004
0
    }
4005
4006
1.29k
    return RSA_CheckSign(&key->u.rsa, sig, sigLen, digest, digestLen);
4007
1.29k
}
4008
4009
static SECStatus
4010
sftk_RSACheckSignRaw(void *ctx, const unsigned char *sig,
4011
                     unsigned int sigLen, const unsigned char *digest,
4012
                     unsigned int digestLen)
4013
0
{
4014
0
    NSSLOWKEYPublicKey *key = ctx;
4015
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
4016
0
    if (key->keyType != NSSLOWKEYRSAKey) {
4017
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
4018
0
        return SECFailure;
4019
0
    }
4020
4021
0
    return RSA_CheckSignRaw(&key->u.rsa, sig, sigLen, digest, digestLen);
4022
0
}
4023
4024
static SECStatus
4025
sftk_RSACheckSignPSS(void *ctx, const unsigned char *sig,
4026
                     unsigned int sigLen, const unsigned char *digest,
4027
                     unsigned int digestLen)
4028
2.84k
{
4029
2.84k
    SFTKPSSVerifyInfo *info = ctx;
4030
2.84k
    HASH_HashType hashAlg;
4031
2.84k
    HASH_HashType maskHashAlg;
4032
2.84k
    CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
4033
4034
2.84k
    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
4035
2.84k
    if (info->key->keyType != NSSLOWKEYRSAKey) {
4036
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
4037
0
        return SECFailure;
4038
0
    }
4039
4040
2.84k
    hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg);
4041
2.84k
    maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf);
4042
4043
2.84k
    return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg,
4044
2.84k
                            params->sLen, sig, sigLen, digest, digestLen);
4045
2.84k
}
4046
4047
/* NSC_VerifyInit initializes a verification operation,
4048
 * where the signature is an appendix to the data,
4049
 * and plaintext cannot be recovered from the signature (e.g. DSA) */
4050
CK_RV
4051
NSC_VerifyInit(CK_SESSION_HANDLE hSession,
4052
               CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4053
11.3k
{
4054
11.3k
    SFTKSession *session;
4055
11.3k
    SFTKObject *key;
4056
11.3k
    SFTKSessionContext *context;
4057
11.3k
    CK_KEY_TYPE key_type;
4058
11.3k
    CK_RV crv = CKR_OK;
4059
11.3k
    NSSLOWKEYPublicKey *pubKey;
4060
11.3k
    SFTKHashVerifyInfo *info = NULL;
4061
11.3k
    SFTKPSSVerifyInfo *pinfo = NULL;
4062
4063
11.3k
    CHECK_FORK();
4064
4065
    /* Block Cipher MACing Algorithms use a different Context init method..*/
4066
11.3k
    crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY);
4067
11.3k
    if (crv != CKR_FUNCTION_NOT_SUPPORTED)
4068
0
        return crv;
4069
4070
11.3k
    session = sftk_SessionFromHandle(hSession);
4071
11.3k
    if (session == NULL)
4072
0
        return CKR_SESSION_HANDLE_INVALID;
4073
11.3k
    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY, &key,
4074
11.3k
                           hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY);
4075
11.3k
    if (crv != CKR_OK) {
4076
0
        sftk_FreeSession(session);
4077
0
        return crv;
4078
0
    }
4079
4080
11.3k
    context->multi = PR_FALSE;
4081
4082
11.3k
#define INIT_RSA_VFY_MECH(mmm)                \
4083
11.3k
    case CKM_##mmm##_RSA_PKCS:                \
4084
2.66k
        context->multi = PR_TRUE;             \
4085
2.66k
        crv = sftk_doSub##mmm(context);       \
4086
2.66k
        if (crv != CKR_OK)                    \
4087
2.66k
            break;                            \
4088
2.66k
        context->verify = sftk_hashCheckSign; \
4089
2.66k
        info = PORT_New(SFTKHashVerifyInfo);  \
4090
2.66k
        if (info == NULL) {                   \
4091
0
            crv = CKR_HOST_MEMORY;            \
4092
0
            break;                            \
4093
0
        }                                     \
4094
2.66k
        info->hashOid = SEC_OID_##mmm;        \
4095
2.66k
        goto finish_rsa;
4096
4097
11.3k
    switch (pMechanism->mechanism) {
4098
0
        INIT_RSA_VFY_MECH(MD5)
4099
0
        INIT_RSA_VFY_MECH(MD2)
4100
2
        INIT_RSA_VFY_MECH(SHA1)
4101
0
        INIT_RSA_VFY_MECH(SHA224)
4102
5.30k
        INIT_RSA_VFY_MECH(SHA256)
4103
2
        INIT_RSA_VFY_MECH(SHA384)
4104
16
        INIT_RSA_VFY_MECH(SHA512)
4105
4106
1.29k
        case CKM_RSA_PKCS:
4107
1.29k
            context->verify = sftk_RSACheckSign;
4108
1.29k
            goto finish_rsa;
4109
0
        case CKM_RSA_X_509:
4110
0
            context->verify = sftk_RSACheckSignRaw;
4111
3.95k
        finish_rsa:
4112
3.95k
            if (key_type != CKK_RSA) {
4113
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
4114
0
                break;
4115
0
            }
4116
3.95k
            context->rsa = PR_TRUE;
4117
3.95k
            pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
4118
3.95k
            if (pubKey == NULL) {
4119
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
4120
0
                break;
4121
0
            }
4122
3.95k
            if (info) {
4123
2.66k
                info->key = pubKey;
4124
2.66k
                context->cipherInfo = info;
4125
2.66k
                context->destroy = sftk_Space;
4126
2.66k
            } else {
4127
1.29k
                context->cipherInfo = pubKey;
4128
1.29k
                context->destroy = sftk_Null;
4129
1.29k
            }
4130
3.95k
            break;
4131
4132
1.25k
            INIT_RSA_PSS_SIG_MECH(SHA1)
4133
417
            INIT_RSA_PSS_SIG_MECH(SHA224)
4134
30
            INIT_RSA_PSS_SIG_MECH(SHA256)
4135
24
            INIT_RSA_PSS_SIG_MECH(SHA384)
4136
12
            INIT_RSA_PSS_SIG_MECH(SHA512)
4137
2.39k
        case CKM_RSA_PKCS_PSS:
4138
2.84k
        finish_rsa_pss:
4139
2.84k
            if (key_type != CKK_RSA) {
4140
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
4141
0
                break;
4142
0
            }
4143
2.84k
            context->rsa = PR_TRUE;
4144
2.84k
            if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4145
2.84k
                !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) {
4146
2
                crv = CKR_MECHANISM_PARAM_INVALID;
4147
2
                break;
4148
2
            }
4149
2.84k
            pinfo = PORT_New(SFTKPSSVerifyInfo);
4150
2.84k
            if (pinfo == NULL) {
4151
0
                crv = CKR_HOST_MEMORY;
4152
0
                break;
4153
0
            }
4154
2.84k
            pinfo->size = sizeof(SFTKPSSVerifyInfo);
4155
2.84k
            pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter;
4156
2.84k
            pinfo->key = sftk_GetPubKey(key, CKK_RSA, &crv);
4157
2.84k
            if (pinfo->key == NULL) {
4158
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
4159
0
                break;
4160
0
            }
4161
2.84k
            context->cipherInfo = pinfo;
4162
2.84k
            context->destroy = sftk_ZSpace;
4163
2.84k
            context->verify = sftk_RSACheckSignPSS;
4164
2.84k
            break;
4165
4166
0
#ifndef NSS_DISABLE_DSA
4167
0
            INIT_DSA_SIG_MECH(SHA1)
4168
1
            INIT_DSA_SIG_MECH(SHA224)
4169
834
            INIT_DSA_SIG_MECH(SHA256)
4170
834
            INIT_DSA_SIG_MECH(SHA384)
4171
0
            INIT_DSA_SIG_MECH(SHA512)
4172
3.17k
        case CKM_DSA:
4173
4.01k
        finish_dsa:
4174
4.01k
            if (key_type != CKK_DSA) {
4175
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
4176
0
                break;
4177
0
            }
4178
4.01k
            pubKey = sftk_GetPubKey(key, CKK_DSA, &crv);
4179
4.01k
            if (pubKey == NULL) {
4180
0
                break;
4181
0
            }
4182
4.01k
            context->cipherInfo = pubKey;
4183
4.01k
            context->verify = nsc_DSA_Verify_Stub;
4184
4.01k
            context->destroy = sftk_Null;
4185
4.01k
            break;
4186
0
#endif
4187
0
        case CKM_ML_DSA: {
4188
            /* set our defaults */
4189
0
            SECItem signCtx = { siBuffer, NULL, 0 };
4190
0
            MLDSAContext *ctptr = NULL;
4191
0
            SECStatus rv;
4192
4193
            /* make sure we have the right key type */
4194
0
            if (key_type != CKK_ML_DSA) {
4195
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
4196
0
                break;
4197
0
            }
4198
            /* fill in our parameters from the mechanism parameters if
4199
             * supplied */
4200
0
            if (pMechanism->ulParameterLen != 0) {
4201
0
                CK_SIGN_ADDITIONAL_CONTEXT *param;
4202
0
                if (pMechanism->ulParameterLen !=
4203
0
                    sizeof(CK_SIGN_ADDITIONAL_CONTEXT)) {
4204
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
4205
0
                    break;
4206
0
                }
4207
0
                param = (CK_SIGN_ADDITIONAL_CONTEXT *)pMechanism->pParameter;
4208
0
                signCtx.data = param->pContext;
4209
0
                signCtx.len = param->ulContextLen;
4210
0
            }
4211
            /* fetch the key */
4212
0
            pubKey = sftk_GetPubKey(key, key_type, &crv);
4213
0
            if (pubKey == NULL) {
4214
                /* crv already set */
4215
0
                break;
4216
0
            }
4217
            /* now initialize it the signature */
4218
0
            rv = MLDSA_VerifyInit(&(pubKey->u.mldsa), &signCtx, &ctptr);
4219
0
            if (rv != SECSuccess) {
4220
0
                crv = sftk_MapVerifyError(PORT_GetError());
4221
0
                break;
4222
0
            }
4223
            /* set up our cipher info. MLDSA is only a combined hash/sign
4224
             * so the hash update is our sign update, the hash end is a null
4225
             * function returning a zero length value, and the final gets our
4226
             * signature based on the context. Both the cipher context and the
4227
             * hash Info is the same. The MLDSA_VerifyFinal frees the context,
4228
             * so we don't have to */
4229
0
            context->multi = PR_TRUE;
4230
0
            context->cipherInfo = ctptr;
4231
0
            context->hashInfo = ctptr;
4232
0
            context->hashUpdate = sftk_MLDSAVerifyUpdate;
4233
0
            context->end = sftk_NullHashEnd;
4234
0
            context->hashdestroy = sftk_Null;
4235
0
            context->destroy = sftk_Null;
4236
0
            context->verify = sftk_MLDSAVerifyFinal;
4237
0
            context->maxLen = sftk_MLDSAGetSigLen(pubKey->u.mldsa.paramSet);
4238
0
            break;
4239
0
        }
4240
4241
0
            INIT_ECDSA_SIG_MECH(SHA1)
4242
1
            INIT_ECDSA_SIG_MECH(SHA224)
4243
147
            INIT_ECDSA_SIG_MECH(SHA256)
4244
147
            INIT_ECDSA_SIG_MECH(SHA384)
4245
11
            INIT_ECDSA_SIG_MECH(SHA512)
4246
385
        case CKM_ECDSA:
4247
544
        finish_ecdsa:
4248
544
            if (key_type != CKK_EC) {
4249
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
4250
0
                break;
4251
0
            }
4252
544
            pubKey = sftk_GetPubKey(key, CKK_EC, &crv);
4253
544
            if (pubKey == NULL) {
4254
0
                crv = CKR_HOST_MEMORY;
4255
0
                break;
4256
0
            }
4257
544
            context->cipherInfo = pubKey;
4258
544
            context->verify = nsc_ECDSAVerifyStub;
4259
544
            context->destroy = sftk_Null;
4260
544
            break;
4261
4262
0
            INIT_HMAC_MECH(MD2)
4263
0
            INIT_HMAC_MECH(MD5)
4264
0
            INIT_HMAC_MECH(SHA1)
4265
0
            INIT_HMAC_MECH(SHA224)
4266
0
            INIT_HMAC_MECH(SHA256)
4267
0
            INIT_HMAC_MECH(SHA384)
4268
0
            INIT_HMAC_MECH(SHA512)
4269
0
            INIT_HMAC_MECH(SHA3_224)
4270
0
            INIT_HMAC_MECH(SHA3_256)
4271
0
            INIT_HMAC_MECH(SHA3_384)
4272
0
            INIT_HMAC_MECH(SHA3_512)
4273
4274
0
        case CKM_EDDSA:
4275
0
            if (key_type != CKK_EC_EDWARDS) {
4276
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
4277
0
                break;
4278
0
            }
4279
0
            pubKey = sftk_GetPubKey(key, CKK_EC_EDWARDS, &crv);
4280
0
            if (pubKey == NULL) {
4281
0
                crv = CKR_HOST_MEMORY;
4282
0
                break;
4283
0
            }
4284
4285
0
            if (pMechanism->pParameter) {
4286
0
                crv = CKR_FUNCTION_NOT_SUPPORTED;
4287
0
                break;
4288
0
            }
4289
4290
0
            context->cipherInfo = pubKey;
4291
0
            context->verify = nsc_EDDSAVerifyStub;
4292
0
            context->destroy = sftk_Null;
4293
0
            break;
4294
4295
0
        case CKM_SSL3_MD5_MAC:
4296
0
            PORT_Assert(pMechanism->pParameter);
4297
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_ULONG))) {
4298
0
                crv = CKR_MECHANISM_PARAM_INVALID;
4299
0
                break;
4300
0
            }
4301
0
            crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key,
4302
0
                                    *(CK_ULONG *)pMechanism->pParameter);
4303
0
            break;
4304
0
        case CKM_SSL3_SHA1_MAC:
4305
0
            PORT_Assert(pMechanism->pParameter);
4306
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_ULONG))) {
4307
0
                crv = CKR_MECHANISM_PARAM_INVALID;
4308
0
                break;
4309
0
            }
4310
0
            crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key,
4311
0
                                    *(CK_ULONG *)pMechanism->pParameter);
4312
0
            break;
4313
0
        case CKM_TLS_PRF_GENERAL:
4314
0
            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0);
4315
0
            break;
4316
0
        case CKM_NSS_TLS_PRF_GENERAL_SHA256:
4317
0
            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0);
4318
0
            break;
4319
4320
0
        default:
4321
0
            crv = CKR_MECHANISM_INVALID;
4322
0
            break;
4323
11.3k
    }
4324
4325
11.3k
    if (crv != CKR_OK) {
4326
2
        if (info)
4327
0
            PORT_Free(info);
4328
2
        if (pinfo)
4329
0
            PORT_ZFree(pinfo, pinfo->size);
4330
2
        sftk_FreeContext(context);
4331
2
        sftk_FreeSession(session);
4332
2
        return crv;
4333
2
    }
4334
    /* At this point info/pinfo (if allocated) are linked into
4335
     * context->cipherInfo and will be freed via sftk_FreeContext. */
4336
11.3k
    crv = sftk_InstallContext(session, SFTK_VERIFY, context);
4337
11.3k
    if (crv != CKR_OK) {
4338
0
        sftk_FreeContext(context);
4339
0
    }
4340
11.3k
    sftk_FreeSession(session);
4341
11.3k
    return crv;
4342
11.3k
}
4343
4344
/* NSC_Verify verifies a signature in a single-part operation,
4345
 * where the signature is an appendix to the data,
4346
 * and plaintext cannot be recovered from the signature */
4347
CK_RV
4348
NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
4349
           CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
4350
11.3k
{
4351
11.3k
    SFTKSession *session;
4352
11.3k
    SFTKSessionContext *context;
4353
11.3k
    CK_RV crv;
4354
4355
11.3k
    CHECK_FORK();
4356
4357
    /* make sure we're legal */
4358
11.3k
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session);
4359
11.3k
    if (crv != CKR_OK)
4360
0
        return crv;
4361
4362
    /* multi part Verifying are completely implemented by VerifyUpdate and
4363
     * VerifyFinal */
4364
11.3k
    if (context->multi) {
4365
        /* VerifyFinal can't follow failed VerifyUpdate */
4366
4.10k
        if (CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen)))
4367
4.10k
            crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen);
4368
7.25k
    } else {
4369
7.25k
        if (SECSuccess != (*context->verify)(context->cipherInfo, pSignature,
4370
7.25k
                                             ulSignatureLen, pData, ulDataLen))
4371
7.20k
            crv = sftk_MapCryptError(PORT_GetError());
4372
4373
7.25k
        sftk_TerminateOp(session, SFTK_VERIFY);
4374
7.25k
    }
4375
11.3k
    sftk_FreeSession(session);
4376
11.3k
    return crv;
4377
11.3k
}
4378
4379
/* NSC_VerifyUpdate continues a multiple-part verification operation,
4380
 * where the signature is an appendix to the data,
4381
 * and plaintext cannot be recovered from the signature
4382
 *
4383
 * A call which results in an error terminates the operation [PKCS#11,v2.11]
4384
 */
4385
CK_RV
4386
NSC_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
4387
                 CK_ULONG ulPartLen)
4388
4.10k
{
4389
4.10k
    CHECK_FORK();
4390
4.10k
    return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY);
4391
4.10k
}
4392
4393
/* NSC_VerifyFinal finishes a multiple-part verification operation,
4394
 * checking the signature. */
4395
CK_RV
4396
NSC_VerifyFinal(CK_SESSION_HANDLE hSession,
4397
                CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
4398
4.10k
{
4399
4.10k
    SFTKSession *session;
4400
4.10k
    SFTKSessionContext *context;
4401
4.10k
    CK_RV crv;
4402
4403
4.10k
    CHECK_FORK();
4404
4405
4.10k
    if (!pSignature)
4406
0
        return CKR_ARGUMENTS_BAD;
4407
4408
    /* make sure we're legal */
4409
4.10k
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session);
4410
4.10k
    if (crv != CKR_OK)
4411
0
        return crv;
4412
4413
4.10k
    if (context->hashInfo) {
4414
4.10k
        unsigned int digestLen;
4415
4.10k
        unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
4416
4417
4.10k
        (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
4418
4.10k
        if (SECSuccess != (context->verify)(context->cipherInfo, pSignature,
4419
4.10k
                                            ulSignatureLen, tmpbuf, digestLen))
4420
3.85k
            crv = sftk_MapCryptError(PORT_GetError());
4421
4.10k
        PORT_Memset(tmpbuf, 0, sizeof tmpbuf);
4422
4.10k
    } else if (ulSignatureLen != context->macSize) {
4423
        /* must be block cipher MACing */
4424
0
        crv = CKR_SIGNATURE_LEN_RANGE;
4425
0
    } else if (CKR_OK == (crv = sftk_MACFinal(context))) {
4426
0
        if (NSS_SecureMemcmp(pSignature, context->macBuf, ulSignatureLen))
4427
0
            crv = CKR_SIGNATURE_INVALID;
4428
0
    }
4429
4430
4.10k
    sftk_TerminateOp(session, SFTK_VERIFY);
4431
4.10k
    sftk_FreeSession(session);
4432
4.10k
    return crv;
4433
4.10k
}
4434
4435
/*
4436
 ************** Crypto Functions:     Verify  Signature ************************
4437
 * some algorithms need the signature at the beginning of the verification,
4438
 * VerifySignature provides such and API. For algorithms that don't need
4439
 * the signature first, we stash the signature and just pass it to
4440
 * NSC_VerifyXXX.
4441
 */
4442
CK_RV
4443
NSC_VerifySignatureInit(CK_SESSION_HANDLE hSession,
4444
                        CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
4445
                        CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
4446
11.3k
{
4447
11.3k
    SFTKSession *session;
4448
11.3k
    SFTKSessionContext *context;
4449
11.3k
    CK_RV crv;
4450
11.3k
    SECItem tmpItem;
4451
4452
11.3k
    crv = NSC_VerifyInit(hSession, pMechanism, hKey);
4453
11.3k
    if (crv != CKR_OK) {
4454
2
        return crv;
4455
2
    }
4456
4457
11.3k
    CHECK_FORK();
4458
4459
11.3k
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session);
4460
11.3k
    if (crv != CKR_OK)
4461
0
        return crv;
4462
4463
11.3k
    tmpItem.type = siBuffer;
4464
11.3k
    tmpItem.data = pSignature;
4465
11.3k
    tmpItem.len = ulSignatureLen;
4466
11.3k
    context->signature = SECITEM_DupItem(&tmpItem);
4467
11.3k
    if (!context->signature) {
4468
0
        sftk_TerminateOp(session, SFTK_VERIFY);
4469
0
        sftk_FreeSession(session);
4470
0
        return CKR_HOST_MEMORY;
4471
0
    }
4472
11.3k
    sftk_FreeSession(session);
4473
11.3k
    return CKR_OK;
4474
11.3k
}
4475
4476
CK_RV
4477
NSC_VerifySignature(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
4478
                    CK_ULONG ulDataLen)
4479
11.3k
{
4480
11.3k
    SFTKSession *session;
4481
11.3k
    SFTKSessionContext *context;
4482
11.3k
    CK_RV crv;
4483
4484
11.3k
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session);
4485
11.3k
    if (crv != CKR_OK)
4486
0
        return crv;
4487
4488
    /* make sure we're legal */
4489
11.3k
    if (!context->signature) {
4490
0
        sftk_FreeSession(session);
4491
0
        return CKR_OPERATION_NOT_INITIALIZED;
4492
0
    }
4493
11.3k
    crv = NSC_Verify(hSession, pData, ulDataLen,
4494
11.3k
                     context->signature->data, context->signature->len);
4495
    /* we free the signature here because the context is part of the session and has
4496
     * a lifetime tied to the session. So we want to hold our reference to the
4497
     * session so it doesn't go away on us */
4498
11.3k
    sftk_FreeSession(session);
4499
11.3k
    return crv;
4500
11.3k
}
4501
4502
CK_RV
4503
NSC_VerifySignatureUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
4504
                          CK_ULONG ulPartLen)
4505
0
{
4506
0
    SFTKSession *session;
4507
0
    SFTKSessionContext *context;
4508
0
    CK_RV crv;
4509
4510
    /* make sure we're legal */
4511
0
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session);
4512
0
    if (crv != CKR_OK)
4513
0
        return crv;
4514
4515
    /* like verify above, we bother keeping the session to make sure the context
4516
     * doesn't go way on use. there's little chance that it will since that application
4517
     * must protect against multiple threads calling the same same session at the same
4518
     * time (nss has session locks for this), but there are a couple of corner cases,
4519
     * (like close all sessions, or shutting down the whole module. Also if the
4520
     * application breaks the contract, we want to just fail rather than crash */
4521
0
    if (!context->signature) {
4522
0
        sftk_FreeSession(session);
4523
0
        return CKR_OPERATION_NOT_INITIALIZED;
4524
0
    }
4525
0
    sftk_FreeSession(session);
4526
0
    return NSC_VerifyUpdate(hSession, pPart, ulPartLen);
4527
0
}
4528
4529
CK_RV
4530
NSC_VerifySignatureFinal(CK_SESSION_HANDLE hSession)
4531
0
{
4532
0
    SFTKSession *session;
4533
0
    SFTKSessionContext *context;
4534
0
    CK_RV crv;
4535
4536
    /* make sure we're legal */
4537
0
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session);
4538
0
    if (crv != CKR_OK)
4539
0
        return crv;
4540
4541
0
    if (!context->signature) {
4542
0
        sftk_FreeSession(session);
4543
0
        return CKR_OPERATION_NOT_INITIALIZED;
4544
0
    }
4545
0
    crv = NSC_VerifyFinal(hSession, context->signature->data,
4546
0
                          context->signature->len);
4547
    /* see comment in NSC_VerifySignature() */
4548
0
    sftk_FreeSession(session);
4549
0
    return crv;
4550
0
}
4551
4552
/*
4553
 ************** Crypto Functions:     Verify  Recover ************************
4554
 */
4555
static SECStatus
4556
sftk_RSACheckSignRecover(void *ctx, unsigned char *data,
4557
                         unsigned int *dataLen, unsigned int maxDataLen,
4558
                         const unsigned char *sig, unsigned int sigLen)
4559
17.4k
{
4560
17.4k
    NSSLOWKEYPublicKey *key = ctx;
4561
17.4k
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
4562
17.4k
    if (key->keyType != NSSLOWKEYRSAKey) {
4563
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
4564
0
        return SECFailure;
4565
0
    }
4566
4567
17.4k
    return RSA_CheckSignRecover(&key->u.rsa, data, dataLen, maxDataLen,
4568
17.4k
                                sig, sigLen);
4569
17.4k
}
4570
4571
static SECStatus
4572
sftk_RSACheckSignRecoverRaw(void *ctx, unsigned char *data,
4573
                            unsigned int *dataLen, unsigned int maxDataLen,
4574
                            const unsigned char *sig, unsigned int sigLen)
4575
0
{
4576
0
    NSSLOWKEYPublicKey *key = ctx;
4577
0
    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
4578
0
    if (key->keyType != NSSLOWKEYRSAKey) {
4579
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
4580
0
        return SECFailure;
4581
0
    }
4582
4583
0
    return RSA_CheckSignRecoverRaw(&key->u.rsa, data, dataLen, maxDataLen,
4584
0
                                   sig, sigLen);
4585
0
}
4586
4587
/* NSC_VerifyRecoverInit initializes a signature verification operation,
4588
 * where the data is recovered from the signature.
4589
 * E.g. Decryption with the user's public key */
4590
CK_RV
4591
NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
4592
                      CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4593
17.4k
{
4594
17.4k
    SFTKSession *session;
4595
17.4k
    SFTKObject *key;
4596
17.4k
    SFTKSessionContext *context;
4597
17.4k
    CK_KEY_TYPE key_type;
4598
17.4k
    CK_RV crv = CKR_OK;
4599
17.4k
    NSSLOWKEYPublicKey *pubKey;
4600
4601
17.4k
    CHECK_FORK();
4602
4603
17.4k
    session = sftk_SessionFromHandle(hSession);
4604
17.4k
    if (session == NULL)
4605
0
        return CKR_SESSION_HANDLE_INVALID;
4606
17.4k
    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY_RECOVER,
4607
17.4k
                           &key, hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY_RECOVER);
4608
17.4k
    if (crv != CKR_OK) {
4609
0
        sftk_FreeSession(session);
4610
0
        return crv;
4611
0
    }
4612
4613
17.4k
    context->multi = PR_TRUE;
4614
4615
17.4k
    switch (pMechanism->mechanism) {
4616
17.4k
        case CKM_RSA_PKCS:
4617
17.4k
        case CKM_RSA_X_509:
4618
17.4k
            if (key_type != CKK_RSA) {
4619
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
4620
0
                break;
4621
0
            }
4622
17.4k
            context->multi = PR_FALSE;
4623
17.4k
            context->rsa = PR_TRUE;
4624
17.4k
            pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
4625
17.4k
            if (pubKey == NULL) {
4626
0
                break;
4627
0
            }
4628
17.4k
            context->cipherInfo = pubKey;
4629
17.4k
            context->update = pMechanism->mechanism == CKM_RSA_X_509
4630
17.4k
                                  ? sftk_RSACheckSignRecoverRaw
4631
17.4k
                                  : sftk_RSACheckSignRecover;
4632
17.4k
            context->destroy = sftk_Null;
4633
17.4k
            break;
4634
0
        default:
4635
0
            crv = CKR_MECHANISM_INVALID;
4636
0
            break;
4637
17.4k
    }
4638
4639
17.4k
    if (crv != CKR_OK) {
4640
0
        PORT_Free(context);
4641
0
        sftk_FreeSession(session);
4642
0
        return crv;
4643
0
    }
4644
17.4k
    crv = sftk_InstallContext(session, SFTK_VERIFY_RECOVER, context);
4645
17.4k
    if (crv != CKR_OK) {
4646
0
        sftk_FreeContext(context);
4647
0
    }
4648
17.4k
    sftk_FreeSession(session);
4649
17.4k
    return crv;
4650
17.4k
}
4651
4652
/* NSC_VerifyRecover verifies a signature in a single-part operation,
4653
 * where the data is recovered from the signature.
4654
 * E.g. Decryption with the user's public key */
4655
CK_RV
4656
NSC_VerifyRecover(CK_SESSION_HANDLE hSession,
4657
                  CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen,
4658
                  CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
4659
17.4k
{
4660
17.4k
    SFTKSession *session;
4661
17.4k
    SFTKSessionContext *context;
4662
17.4k
    unsigned int outlen;
4663
17.4k
    unsigned int maxoutlen = *pulDataLen;
4664
17.4k
    CK_RV crv;
4665
17.4k
    SECStatus rv;
4666
4667
17.4k
    CHECK_FORK();
4668
4669
    /* make sure we're legal */
4670
17.4k
    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY_RECOVER,
4671
17.4k
                          PR_FALSE, &session);
4672
17.4k
    if (crv != CKR_OK)
4673
0
        return crv;
4674
17.4k
    if (pData == NULL) {
4675
        /* to return the actual size, we need  to do the decrypt, just return
4676
         * the max size, which is the size of the input signature. */
4677
0
        *pulDataLen = ulSignatureLen;
4678
0
        rv = SECSuccess;
4679
0
        goto finish;
4680
0
    }
4681
4682
17.4k
    rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
4683
17.4k
                            pSignature, ulSignatureLen);
4684
17.4k
    *pulDataLen = (CK_ULONG)outlen;
4685
4686
17.4k
    sftk_TerminateOp(session, SFTK_VERIFY_RECOVER);
4687
17.4k
finish:
4688
17.4k
    sftk_FreeSession(session);
4689
17.4k
    return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError());
4690
17.4k
}
4691
4692
/*
4693
 **************************** Random Functions:  ************************
4694
 */
4695
4696
/* NSC_SeedRandom mixes additional seed material into the token's random number
4697
 * generator. */
4698
CK_RV
4699
NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
4700
               CK_ULONG ulSeedLen)
4701
0
{
4702
0
    SECStatus rv;
4703
4704
0
    CHECK_FORK();
4705
4706
0
    rv = RNG_RandomUpdate(pSeed, ulSeedLen);
4707
0
    return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
4708
0
}
4709
4710
/* NSC_GenerateRandom generates random data. */
4711
CK_RV
4712
NSC_GenerateRandom(CK_SESSION_HANDLE hSession,
4713
                   CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
4714
352k
{
4715
352k
    SECStatus rv;
4716
4717
352k
    CHECK_FORK();
4718
4719
352k
    rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen);
4720
    /*
4721
     * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't
4722
     * seeded with enough entropy.
4723
     */
4724
352k
    return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
4725
352k
}
4726
4727
/*
4728
 **************************** Key Functions:  ************************
4729
 */
4730
4731
/*
4732
 * generate a password based encryption key. This code uses
4733
 * PKCS5 to do the work.
4734
 */
4735
static CK_RV
4736
nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism,
4737
                void *buf, CK_ULONG *key_length, PRBool faulty3DES)
4738
622
{
4739
622
    SECItem *pbe_key = NULL, iv, pwitem;
4740
622
    CK_PBE_PARAMS *pbe_params = NULL;
4741
622
    CK_PKCS5_PBKD2_PARAMS2 *pbkd2_params = NULL;
4742
4743
622
    *key_length = 0;
4744
622
    iv.data = NULL;
4745
622
    iv.len = 0;
4746
4747
622
    if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
4748
622
        pbkd2_params = (CK_PKCS5_PBKD2_PARAMS2 *)pMechanism->pParameter;
4749
622
        if (!pMechanism->pParameter) {
4750
0
            return CKR_MECHANISM_PARAM_INVALID;
4751
0
        }
4752
4753
622
#ifdef SOFTOKEN_USE_PKCS5_PBKD2_PARAMS2_ONLY
4754
622
        if (pMechanism->ulParameterLen < sizeof(CK_PKCS5_PBKD2_PARAMS2)) {
4755
0
            return CKR_MECHANISM_PARAM_INVALID;
4756
0
        }
4757
622
        pwitem.len = pbkd2_params->ulPasswordLen;
4758
#else
4759
        int v2;
4760
        if (pMechanism->ulParameterLen < PR_MIN(sizeof(CK_PKCS5_PBKD2_PARAMS),
4761
                                                sizeof(CK_PKCS5_PBKD2_PARAMS2))) {
4762
            return CKR_MECHANISM_PARAM_INVALID;
4763
        }
4764
4765
        if (sizeof(CK_PKCS5_PBKD2_PARAMS2) != sizeof(CK_PKCS5_PBKD2_PARAMS)) {
4766
            if (pMechanism->ulParameterLen == sizeof(CK_PKCS5_PBKD2_PARAMS)) {
4767
                v2 = 0;
4768
            } else if (pMechanism->ulParameterLen == sizeof(CK_PKCS5_PBKD2_PARAMS2)) {
4769
                v2 = 1;
4770
            } else {
4771
                return CKR_MECHANISM_PARAM_INVALID;
4772
            }
4773
        } else {
4774
            /* it's unlikely that the password will be longer than 8192 bytes, if so it is
4775
             * most likely a pointer => CK_PKCS5_PBKD2_PARAMS */
4776
            v2 = pbkd2_params->ulPasswordLen <= CK_PKCS5_PBKD2_PARAMS_PTR_BOUNDARY;
4777
        }
4778
        pwitem.len = v2 ? pbkd2_params->ulPasswordLen : *((CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter)->ulPasswordLen;
4779
#endif
4780
622
        pwitem.data = (unsigned char *)pbkd2_params->pPassword;
4781
622
    } else {
4782
0
        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
4783
0
            return CKR_MECHANISM_PARAM_INVALID;
4784
0
        }
4785
0
        pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
4786
0
        pwitem.data = (unsigned char *)pbe_params->pPassword;
4787
0
        pwitem.len = pbe_params->ulPasswordLen;
4788
0
    }
4789
622
    pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES);
4790
622
    if (pbe_key == NULL) {
4791
0
        return CKR_HOST_MEMORY;
4792
0
    }
4793
4794
622
    PORT_Memcpy(buf, pbe_key->data, pbe_key->len);
4795
622
    *key_length = pbe_key->len;
4796
622
    SECITEM_ZfreeItem(pbe_key, PR_TRUE);
4797
622
    pbe_key = NULL;
4798
4799
622
    if (iv.data) {
4800
0
        if (pbe_params && pbe_params->pInitVector != NULL) {
4801
0
            PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len);
4802
0
        }
4803
0
        PORT_Free(iv.data);
4804
0
    }
4805
4806
622
    return CKR_OK;
4807
622
}
4808
4809
/*
4810
 * this is coded for "full" support. These selections will be limitted to
4811
 * the official subset by freebl.
4812
 */
4813
static unsigned int
4814
sftk_GetSubPrimeFromPrime(unsigned int primeBits)
4815
0
{
4816
0
    if (primeBits <= 1024) {
4817
0
        return 160;
4818
0
    } else if (primeBits <= 2048) {
4819
0
        return 224;
4820
0
    } else if (primeBits <= 3072) {
4821
0
        return 256;
4822
0
    } else if (primeBits <= 7680) {
4823
0
        return 384;
4824
0
    } else {
4825
0
        return 512;
4826
0
    }
4827
0
}
4828
4829
static CK_RV
4830
nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key)
4831
0
{
4832
0
    SFTKAttribute *attribute;
4833
0
    CK_ULONG counter;
4834
0
    unsigned int seedBits = 0;
4835
0
    unsigned int subprimeBits = 0;
4836
0
    unsigned int primeBits;
4837
0
    unsigned int j = 8; /* default to 1024 bits */
4838
0
    CK_RV crv = CKR_OK;
4839
0
    PQGParams *params = NULL;
4840
0
    PQGVerify *vfy = NULL;
4841
0
    SECStatus rv;
4842
4843
0
    attribute = sftk_FindAttribute(key, CKA_PRIME_BITS);
4844
0
    if (attribute == NULL) {
4845
0
        attribute = sftk_FindAttribute(key, CKA_PRIME);
4846
0
        if (attribute == NULL) {
4847
0
            return CKR_TEMPLATE_INCOMPLETE;
4848
0
        } else {
4849
0
            primeBits = attribute->attrib.ulValueLen;
4850
0
            sftk_FreeAttribute(attribute);
4851
0
        }
4852
0
    } else {
4853
0
        primeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
4854
0
        sftk_FreeAttribute(attribute);
4855
0
    }
4856
0
    if (primeBits < 1024) {
4857
0
        j = PQG_PBITS_TO_INDEX(primeBits);
4858
0
        if (j == (unsigned int)-1) {
4859
0
            return CKR_ATTRIBUTE_VALUE_INVALID;
4860
0
        }
4861
0
    }
4862
4863
0
    attribute = sftk_FindAttribute(key, CKA_NSS_PQG_SEED_BITS);
4864
0
    if (attribute != NULL) {
4865
0
        seedBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
4866
0
        sftk_FreeAttribute(attribute);
4867
0
    }
4868
4869
0
    attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS);
4870
0
    if (attribute != NULL) {
4871
0
        subprimeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
4872
0
        sftk_FreeAttribute(attribute);
4873
0
    }
4874
4875
    /* if P and Q are supplied, we want to generate a new G */
4876
0
    attribute = sftk_FindAttribute(key, CKA_PRIME);
4877
0
    if (attribute != NULL) {
4878
0
        PLArenaPool *arena;
4879
4880
0
        sftk_FreeAttribute(attribute);
4881
0
        arena = PORT_NewArena(1024);
4882
0
        if (arena == NULL) {
4883
0
            crv = CKR_HOST_MEMORY;
4884
0
            goto loser;
4885
0
        }
4886
0
        params = PORT_ArenaAlloc(arena, sizeof(*params));
4887
0
        if (params == NULL) {
4888
0
            crv = CKR_HOST_MEMORY;
4889
0
            goto loser;
4890
0
        }
4891
0
        params->arena = arena;
4892
0
        crv = sftk_Attribute2SSecItem(arena, &params->prime, key, CKA_PRIME);
4893
0
        if (crv != CKR_OK) {
4894
0
            goto loser;
4895
0
        }
4896
0
        crv = sftk_Attribute2SSecItem(arena, &params->subPrime,
4897
0
                                      key, CKA_SUBPRIME);
4898
0
        if (crv != CKR_OK) {
4899
0
            goto loser;
4900
0
        }
4901
4902
0
        arena = PORT_NewArena(1024);
4903
0
        if (arena == NULL) {
4904
0
            crv = CKR_HOST_MEMORY;
4905
0
            goto loser;
4906
0
        }
4907
0
        vfy = PORT_ArenaAlloc(arena, sizeof(*vfy));
4908
0
        if (vfy == NULL) {
4909
0
            crv = CKR_HOST_MEMORY;
4910
0
            goto loser;
4911
0
        }
4912
0
        vfy->arena = arena;
4913
0
        crv = sftk_Attribute2SSecItem(arena, &vfy->seed, key, CKA_NSS_PQG_SEED);
4914
0
        if (crv != CKR_OK) {
4915
0
            goto loser;
4916
0
        }
4917
0
        crv = sftk_Attribute2SSecItem(arena, &vfy->h, key, CKA_NSS_PQG_H);
4918
0
        if (crv != CKR_OK) {
4919
0
            goto loser;
4920
0
        }
4921
0
        sftk_DeleteAttributeType(key, CKA_PRIME);
4922
0
        sftk_DeleteAttributeType(key, CKA_SUBPRIME);
4923
0
        sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED);
4924
0
        sftk_DeleteAttributeType(key, CKA_NSS_PQG_H);
4925
0
    }
4926
4927
0
    sftk_DeleteAttributeType(key, CKA_PRIME_BITS);
4928
0
    sftk_DeleteAttributeType(key, CKA_SUBPRIME_BITS);
4929
0
    sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED_BITS);
4930
4931
    /* use the old PQG interface if we have old input data */
4932
0
    if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) {
4933
0
        if (seedBits == 0) {
4934
0
            rv = PQG_ParamGen(j, &params, &vfy);
4935
0
        } else {
4936
0
            rv = PQG_ParamGenSeedLen(j, seedBits / 8, &params, &vfy);
4937
0
        }
4938
0
    } else {
4939
0
        if (subprimeBits == 0) {
4940
0
            subprimeBits = sftk_GetSubPrimeFromPrime(primeBits);
4941
0
        }
4942
0
        if (seedBits == 0) {
4943
0
            seedBits = primeBits;
4944
0
        }
4945
0
        rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits / 8, &params, &vfy);
4946
0
    }
4947
4948
0
    if (rv != SECSuccess) {
4949
0
        if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
4950
0
            sftk_fatalError = PR_TRUE;
4951
0
        }
4952
0
        return sftk_MapCryptError(PORT_GetError());
4953
0
    }
4954
0
    crv = sftk_AddAttributeType(key, CKA_PRIME,
4955
0
                                params->prime.data, params->prime.len);
4956
0
    if (crv != CKR_OK)
4957
0
        goto loser;
4958
0
    crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
4959
0
                                params->subPrime.data, params->subPrime.len);
4960
0
    if (crv != CKR_OK)
4961
0
        goto loser;
4962
0
    crv = sftk_AddAttributeType(key, CKA_BASE,
4963
0
                                params->base.data, params->base.len);
4964
0
    if (crv != CKR_OK)
4965
0
        goto loser;
4966
0
    counter = vfy->counter;
4967
0
    crv = sftk_AddAttributeType(key, CKA_NSS_PQG_COUNTER,
4968
0
                                &counter, sizeof(counter));
4969
0
    if (crv != CKR_OK)
4970
0
        goto loser;
4971
0
    crv = sftk_AddAttributeType(key, CKA_NSS_PQG_SEED,
4972
0
                                vfy->seed.data, vfy->seed.len);
4973
0
    if (crv != CKR_OK)
4974
0
        goto loser;
4975
0
    crv = sftk_AddAttributeType(key, CKA_NSS_PQG_H,
4976
0
                                vfy->h.data, vfy->h.len);
4977
0
    if (crv != CKR_OK)
4978
0
        goto loser;
4979
4980
0
loser:
4981
0
    if (params) {
4982
0
        PQG_DestroyParams(params);
4983
0
    }
4984
4985
0
    if (vfy) {
4986
0
        PQG_DestroyVerify(vfy);
4987
0
    }
4988
0
    return crv;
4989
0
}
4990
4991
static CK_RV
4992
nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type,
4993
                    CK_ULONG *key_length)
4994
33.4k
{
4995
33.4k
    CK_RV crv = CKR_OK;
4996
4997
33.4k
    switch (mechanism) {
4998
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
4999
0
        case CKM_RC2_KEY_GEN:
5000
0
            *key_type = CKK_RC2;
5001
0
            if (*key_length == 0)
5002
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5003
0
            break;
5004
0
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
5005
#if NSS_SOFTOKEN_DOES_RC5
5006
        case CKM_RC5_KEY_GEN:
5007
            *key_type = CKK_RC5;
5008
            if (*key_length == 0)
5009
                crv = CKR_TEMPLATE_INCOMPLETE;
5010
            break;
5011
#endif
5012
0
        case CKM_RC4_KEY_GEN:
5013
0
            *key_type = CKK_RC4;
5014
0
            if (*key_length == 0)
5015
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5016
0
            break;
5017
1.49k
        case CKM_GENERIC_SECRET_KEY_GEN:
5018
1.49k
            *key_type = CKK_GENERIC_SECRET;
5019
1.49k
            if (*key_length == 0)
5020
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5021
1.49k
            break;
5022
0
        case CKM_CDMF_KEY_GEN:
5023
0
            *key_type = CKK_CDMF;
5024
0
            *key_length = 8;
5025
0
            break;
5026
0
        case CKM_DES_KEY_GEN:
5027
0
            *key_type = CKK_DES;
5028
0
            *key_length = 8;
5029
0
            break;
5030
0
        case CKM_DES2_KEY_GEN:
5031
0
            *key_type = CKK_DES2;
5032
0
            *key_length = 16;
5033
0
            break;
5034
83
        case CKM_DES3_KEY_GEN:
5035
83
            *key_type = CKK_DES3;
5036
83
            *key_length = 24;
5037
83
            break;
5038
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
5039
0
        case CKM_SEED_KEY_GEN:
5040
0
            *key_type = CKK_SEED;
5041
0
            *key_length = 16;
5042
0
            break;
5043
0
#endif /* NSS_DISABLE_DEPRECATED_SEED */
5044
0
        case CKM_CAMELLIA_KEY_GEN:
5045
0
            *key_type = CKK_CAMELLIA;
5046
0
            if (*key_length == 0)
5047
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5048
0
            break;
5049
4
        case CKM_AES_KEY_GEN:
5050
4
            *key_type = CKK_AES;
5051
4
            if (*key_length == 0)
5052
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5053
4
            break;
5054
31.8k
        case CKM_NSS_CHACHA20_KEY_GEN:
5055
31.8k
            *key_type = CKK_NSS_CHACHA20;
5056
31.8k
            *key_length = 32;
5057
31.8k
            break;
5058
0
        case CKM_CHACHA20_KEY_GEN:
5059
0
            *key_type = CKK_CHACHA20;
5060
0
            *key_length = 32;
5061
0
            break;
5062
0
        case CKM_HKDF_KEY_GEN:
5063
0
            *key_type = CKK_HKDF;
5064
0
            if (*key_length == 0)
5065
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5066
0
            break;
5067
0
        default:
5068
0
            PORT_Assert(0);
5069
0
            crv = CKR_MECHANISM_INVALID;
5070
0
            break;
5071
33.4k
    }
5072
5073
33.4k
    return crv;
5074
33.4k
}
5075
5076
CK_RV
5077
nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe)
5078
0
{
5079
0
    SECItem salt;
5080
0
    CK_PBE_PARAMS *pbe_params = NULL;
5081
0
    NSSPKCS5PBEParameter *params;
5082
0
    PLArenaPool *arena = NULL;
5083
0
    SECStatus rv;
5084
5085
0
    *pbe = NULL;
5086
5087
0
    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
5088
0
    if (arena == NULL) {
5089
0
        return CKR_HOST_MEMORY;
5090
0
    }
5091
5092
0
    params = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena,
5093
0
                                                      sizeof(NSSPKCS5PBEParameter));
5094
0
    if (params == NULL) {
5095
0
        PORT_FreeArena(arena, PR_TRUE);
5096
0
        return CKR_HOST_MEMORY;
5097
0
    }
5098
0
    if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
5099
0
        PORT_FreeArena(arena, PR_TRUE);
5100
0
        return CKR_MECHANISM_PARAM_INVALID;
5101
0
    }
5102
5103
0
    params->poolp = arena;
5104
0
    params->ivLen = 0;
5105
0
    params->pbeType = NSSPKCS5_PKCS12_V2;
5106
0
    params->hashType = HASH_AlgSHA1;
5107
0
    params->encAlg = SEC_OID_SHA1; /* any invalid value */
5108
0
    params->is2KeyDES = PR_FALSE;
5109
0
    params->keyID = pbeBitGenIntegrityKey;
5110
0
    pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
5111
0
    params->iter = pbe_params->ulIteration;
5112
5113
0
    salt.data = (unsigned char *)pbe_params->pSalt;
5114
0
    salt.len = (unsigned int)pbe_params->ulSaltLen;
5115
0
    salt.type = siBuffer;
5116
0
    rv = SECITEM_CopyItem(arena, &params->salt, &salt);
5117
0
    if (rv != SECSuccess) {
5118
0
        PORT_FreeArena(arena, PR_TRUE);
5119
0
        return CKR_HOST_MEMORY;
5120
0
    }
5121
0
    switch (pMechanism->mechanism) {
5122
0
        case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN:
5123
0
        case CKM_PBA_SHA1_WITH_SHA1_HMAC:
5124
0
            params->hashType = HASH_AlgSHA1;
5125
0
            params->keyLen = 20;
5126
0
            break;
5127
0
        case CKM_NSS_PBE_MD5_HMAC_KEY_GEN:
5128
0
            params->hashType = HASH_AlgMD5;
5129
0
            params->keyLen = 16;
5130
0
            break;
5131
0
        case CKM_NSS_PBE_MD2_HMAC_KEY_GEN:
5132
0
            params->hashType = HASH_AlgMD2;
5133
0
            params->keyLen = 16;
5134
0
            break;
5135
0
        case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
5136
0
            params->hashType = HASH_AlgSHA224;
5137
0
            params->keyLen = 28;
5138
0
            break;
5139
0
        case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
5140
0
            params->hashType = HASH_AlgSHA256;
5141
0
            params->keyLen = 32;
5142
0
            break;
5143
0
        case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
5144
0
            params->hashType = HASH_AlgSHA384;
5145
0
            params->keyLen = 48;
5146
0
            break;
5147
0
        case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
5148
0
            params->hashType = HASH_AlgSHA512;
5149
0
            params->keyLen = 64;
5150
0
            break;
5151
0
        default:
5152
0
            PORT_FreeArena(arena, PR_TRUE);
5153
0
            return CKR_MECHANISM_INVALID;
5154
0
    }
5155
0
    *pbe = params;
5156
0
    return CKR_OK;
5157
0
}
5158
5159
/* maybe this should be table driven? */
5160
static CK_RV
5161
nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
5162
                   CK_KEY_TYPE *key_type, CK_ULONG *key_length)
5163
622
{
5164
622
    CK_RV crv = CKR_OK;
5165
622
    SECOidData *oid;
5166
622
    CK_PBE_PARAMS *pbe_params = NULL;
5167
622
    NSSPKCS5PBEParameter *params = NULL;
5168
622
    HASH_HashType hashType = HASH_AlgSHA1;
5169
622
    CK_PKCS5_PBKD2_PARAMS2 *pbkd2_params = NULL;
5170
622
    SECItem salt;
5171
622
    CK_ULONG iteration = 0;
5172
5173
622
    *pbe = NULL;
5174
5175
622
    oid = SECOID_FindOIDByMechanism(pMechanism->mechanism);
5176
622
    if (oid == NULL) {
5177
0
        return CKR_MECHANISM_INVALID;
5178
0
    }
5179
5180
622
    if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
5181
622
        if (pMechanism->ulParameterLen < PR_MIN(sizeof(CK_PKCS5_PBKD2_PARAMS2),
5182
622
                                                sizeof(CK_PKCS5_PBKD2_PARAMS))) {
5183
0
            return CKR_MECHANISM_PARAM_INVALID;
5184
0
        }
5185
622
        pbkd2_params = (CK_PKCS5_PBKD2_PARAMS2 *)pMechanism->pParameter;
5186
622
        switch (pbkd2_params->prf) {
5187
209
            case CKP_PKCS5_PBKD2_HMAC_SHA1:
5188
209
                hashType = HASH_AlgSHA1;
5189
209
                break;
5190
61
            case CKP_PKCS5_PBKD2_HMAC_SHA224:
5191
61
                hashType = HASH_AlgSHA224;
5192
61
                break;
5193
259
            case CKP_PKCS5_PBKD2_HMAC_SHA256:
5194
259
                hashType = HASH_AlgSHA256;
5195
259
                break;
5196
57
            case CKP_PKCS5_PBKD2_HMAC_SHA384:
5197
57
                hashType = HASH_AlgSHA384;
5198
57
                break;
5199
36
            case CKP_PKCS5_PBKD2_HMAC_SHA512:
5200
36
                hashType = HASH_AlgSHA512;
5201
36
                break;
5202
0
            default:
5203
0
                return CKR_MECHANISM_PARAM_INVALID;
5204
622
        }
5205
622
        if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) {
5206
0
            return CKR_MECHANISM_PARAM_INVALID;
5207
0
        }
5208
622
        salt.data = (unsigned char *)pbkd2_params->pSaltSourceData;
5209
622
        salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen;
5210
622
        iteration = pbkd2_params->iterations;
5211
622
    } else {
5212
0
        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
5213
0
            return CKR_MECHANISM_PARAM_INVALID;
5214
0
        }
5215
0
        pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
5216
0
        salt.data = (unsigned char *)pbe_params->pSalt;
5217
0
        salt.len = (unsigned int)pbe_params->ulSaltLen;
5218
0
        iteration = pbe_params->ulIteration;
5219
0
    }
5220
622
    params = nsspkcs5_NewParam(oid->offset, hashType, &salt, iteration);
5221
622
    if (params == NULL) {
5222
0
        return CKR_MECHANISM_INVALID;
5223
0
    }
5224
5225
622
    switch (params->encAlg) {
5226
0
        case SEC_OID_DES_CBC:
5227
0
            *key_type = CKK_DES;
5228
0
            *key_length = params->keyLen;
5229
0
            break;
5230
0
        case SEC_OID_DES_EDE3_CBC:
5231
0
            *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3;
5232
0
            *key_length = params->keyLen;
5233
0
            break;
5234
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
5235
0
        case SEC_OID_RC2_CBC:
5236
0
            *key_type = CKK_RC2;
5237
0
            *key_length = params->keyLen;
5238
0
            break;
5239
0
#endif /* NSS_DISABLE_DEPRECATED_RC2 */
5240
0
        case SEC_OID_RC4:
5241
0
            *key_type = CKK_RC4;
5242
0
            *key_length = params->keyLen;
5243
0
            break;
5244
622
        case SEC_OID_PKCS5_PBKDF2:
5245
            /* key type must already be set */
5246
622
            if (*key_type == CKK_INVALID_KEY_TYPE) {
5247
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5248
0
                break;
5249
0
            }
5250
            /* PBKDF2 needs to calculate the key length from the other parameters
5251
             */
5252
622
            if (*key_length == 0) {
5253
0
                *key_length = sftk_MapKeySize(*key_type);
5254
0
            }
5255
622
            if (*key_length == 0) {
5256
0
                crv = CKR_TEMPLATE_INCOMPLETE;
5257
0
                break;
5258
0
            }
5259
622
            params->keyLen = *key_length;
5260
622
            break;
5261
0
        default:
5262
0
            crv = CKR_MECHANISM_INVALID;
5263
0
            break;
5264
622
    }
5265
622
    if (crv == CKR_OK) {
5266
622
        *pbe = params;
5267
622
    } else {
5268
0
        nsspkcs5_DestroyPBEParameter(params);
5269
0
    }
5270
622
    return crv;
5271
622
}
5272
5273
/* NSC_GenerateKey generates a secret key, creating a new key object. */
5274
CK_RV
5275
NSC_GenerateKey(CK_SESSION_HANDLE hSession,
5276
                CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
5277
                CK_OBJECT_HANDLE_PTR phKey)
5278
93.0k
{
5279
93.0k
    SFTKObject *key;
5280
93.0k
    SFTKSession *session;
5281
93.0k
    PRBool checkWeak = PR_FALSE;
5282
93.0k
    CK_ULONG key_length = 0;
5283
93.0k
    CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE;
5284
93.0k
    CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
5285
93.0k
    CK_RV crv = CKR_OK;
5286
93.0k
    CK_BBOOL cktrue = CK_TRUE;
5287
93.0k
    NSSPKCS5PBEParameter *pbe_param = NULL;
5288
93.0k
    int i;
5289
93.0k
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
5290
93.0k
    unsigned char buf[MAX_KEY_LEN];
5291
93.0k
    enum { nsc_pbe,
5292
93.0k
           nsc_ssl,
5293
93.0k
           nsc_bulk,
5294
93.0k
           nsc_param,
5295
93.0k
           nsc_jpake } key_gen_type;
5296
93.0k
    SSL3RSAPreMasterSecret *rsa_pms;
5297
93.0k
    CK_VERSION *version;
5298
    /* in very old versions of NSS, there were implementation errors with key
5299
     * generation methods.  We want to beable to read these, but not
5300
     * produce them any more.  The affected algorithm was 3DES.
5301
     */
5302
93.0k
    PRBool faultyPBE3DES = PR_FALSE;
5303
93.0k
    HASH_HashType hashType = HASH_AlgNULL;
5304
5305
93.0k
    CHECK_FORK();
5306
5307
93.0k
    if (!slot) {
5308
0
        return CKR_SESSION_HANDLE_INVALID;
5309
0
    }
5310
    /*
5311
     * now lets create an object to hang the attributes off of
5312
     */
5313
93.0k
    key = sftk_NewObject(slot); /* fill in the handle later */
5314
93.0k
    if (key == NULL) {
5315
0
        return CKR_HOST_MEMORY;
5316
0
    }
5317
5318
    /*
5319
     * load the template values into the object
5320
     */
5321
315k
    for (i = 0; i < (int)ulCount; i++) {
5322
222k
        if (pTemplate[i].type == CKA_VALUE_LEN) {
5323
33.9k
            key_length = *(CK_ULONG *)pTemplate[i].pValue;
5324
33.9k
            continue;
5325
33.9k
        }
5326
        /* some algorithms need keytype specified */
5327
188k
        if (pTemplate[i].type == CKA_KEY_TYPE) {
5328
622
            key_type = *(CK_ULONG *)pTemplate[i].pValue;
5329
622
            continue;
5330
622
        }
5331
5332
188k
        crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
5333
188k
        if (crv != CKR_OK) {
5334
0
            break;
5335
0
        }
5336
188k
    }
5337
93.0k
    if (crv != CKR_OK) {
5338
0
        goto loser;
5339
0
    }
5340
5341
    /* make sure we don't have any class, key_type, or value fields */
5342
93.0k
    sftk_DeleteAttributeType(key, CKA_CLASS);
5343
93.0k
    sftk_DeleteAttributeType(key, CKA_KEY_TYPE);
5344
93.0k
    sftk_DeleteAttributeType(key, CKA_VALUE);
5345
5346
    /* Now Set up the parameters to generate the key (based on mechanism) */
5347
93.0k
    key_gen_type = nsc_bulk; /* bulk key by default */
5348
93.0k
    switch (pMechanism->mechanism) {
5349
0
        case CKM_CDMF_KEY_GEN:
5350
0
        case CKM_DES_KEY_GEN:
5351
0
        case CKM_DES2_KEY_GEN:
5352
83
        case CKM_DES3_KEY_GEN:
5353
83
            checkWeak = PR_TRUE;
5354
/* fall through */
5355
83
#ifndef NSS_DISABLE_DEPRECATED_RC2
5356
83
        case CKM_RC2_KEY_GEN:
5357
83
#endif
5358
83
        case CKM_RC4_KEY_GEN:
5359
1.57k
        case CKM_GENERIC_SECRET_KEY_GEN:
5360
1.57k
#ifndef NSS_DISABLE_DEPRECATED_SEED
5361
1.57k
        case CKM_SEED_KEY_GEN:
5362
1.57k
#endif
5363
1.57k
        case CKM_CAMELLIA_KEY_GEN:
5364
1.57k
        case CKM_AES_KEY_GEN:
5365
33.4k
        case CKM_NSS_CHACHA20_KEY_GEN:
5366
33.4k
        case CKM_CHACHA20_KEY_GEN:
5367
#if NSS_SOFTOKEN_DOES_RC5
5368
        case CKM_RC5_KEY_GEN:
5369
#endif
5370
33.4k
            crv = nsc_SetupBulkKeyGen(pMechanism->mechanism, &key_type, &key_length);
5371
33.4k
            break;
5372
59.0k
        case CKM_SSL3_PRE_MASTER_KEY_GEN:
5373
59.0k
            key_type = CKK_GENERIC_SECRET;
5374
59.0k
            key_length = 48;
5375
59.0k
            key_gen_type = nsc_ssl;
5376
59.0k
            break;
5377
0
        case CKM_PBA_SHA1_WITH_SHA1_HMAC:
5378
0
        case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN:
5379
0
        case CKM_NSS_PBE_MD5_HMAC_KEY_GEN:
5380
0
        case CKM_NSS_PBE_MD2_HMAC_KEY_GEN:
5381
0
        case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
5382
0
        case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
5383
0
        case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
5384
0
        case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
5385
0
            key_gen_type = nsc_pbe;
5386
0
            key_type = CKK_GENERIC_SECRET;
5387
0
            crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param);
5388
0
            break;
5389
0
        case CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC:
5390
0
            faultyPBE3DES = PR_TRUE;
5391
        /* fall through */
5392
0
        case CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC:
5393
0
#ifndef NSS_DISABLE_DEPRECATED_RC2
5394
0
        case CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC:
5395
0
        case CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC:
5396
0
        case CKM_PBE_SHA1_RC2_128_CBC:
5397
0
        case CKM_PBE_SHA1_RC2_40_CBC:
5398
0
#endif
5399
0
        case CKM_NSS_PBE_SHA1_DES_CBC:
5400
0
        case CKM_NSS_PBE_SHA1_40_BIT_RC4:
5401
0
        case CKM_NSS_PBE_SHA1_128_BIT_RC4:
5402
0
        case CKM_PBE_SHA1_DES3_EDE_CBC:
5403
0
        case CKM_PBE_SHA1_DES2_EDE_CBC:
5404
0
        case CKM_PBE_SHA1_RC4_128:
5405
0
        case CKM_PBE_SHA1_RC4_40:
5406
0
        case CKM_PBE_MD5_DES_CBC:
5407
0
        case CKM_PBE_MD2_DES_CBC:
5408
622
        case CKM_PKCS5_PBKD2:
5409
622
            key_gen_type = nsc_pbe;
5410
622
            crv = nsc_SetupPBEKeyGen(pMechanism, &pbe_param, &key_type, &key_length);
5411
622
            break;
5412
            /*#ifndef NSS_DISABLE_DSA */
5413
            /* some applications use CKM_DSA_PARAMETER_GEN for weak DH keys...
5414
             * most notably tests and even ssl... continue to allow it for now */
5415
0
        case CKM_DSA_PARAMETER_GEN:
5416
0
            key_gen_type = nsc_param;
5417
0
            key_type = CKK_DSA;
5418
0
            objclass = CKO_DOMAIN_PARAMETERS;
5419
0
            crv = CKR_OK;
5420
0
            break;
5421
            /* #endif */
5422
0
        case CKM_NSS_JPAKE_ROUND1_SHA1:
5423
0
            hashType = HASH_AlgSHA1;
5424
0
            goto jpake1;
5425
0
        case CKM_NSS_JPAKE_ROUND1_SHA256:
5426
0
            hashType = HASH_AlgSHA256;
5427
0
            goto jpake1;
5428
0
        case CKM_NSS_JPAKE_ROUND1_SHA384:
5429
0
            hashType = HASH_AlgSHA384;
5430
0
            goto jpake1;
5431
0
        case CKM_NSS_JPAKE_ROUND1_SHA512:
5432
0
            hashType = HASH_AlgSHA512;
5433
0
            goto jpake1;
5434
0
        jpake1:
5435
0
            key_gen_type = nsc_jpake;
5436
0
            key_type = CKK_NSS_JPAKE_ROUND1;
5437
0
            objclass = CKO_PRIVATE_KEY;
5438
0
            if (pMechanism->pParameter == NULL ||
5439
0
                pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) {
5440
0
                crv = CKR_MECHANISM_PARAM_INVALID;
5441
0
                break;
5442
0
            }
5443
0
            if (sftk_isTrue(key, CKA_TOKEN)) {
5444
0
                crv = CKR_TEMPLATE_INCONSISTENT;
5445
0
                break;
5446
0
            }
5447
0
            crv = CKR_OK;
5448
0
            break;
5449
0
        default:
5450
0
            crv = CKR_MECHANISM_INVALID;
5451
0
            break;
5452
93.0k
    }
5453
5454
    /* make sure we aren't going to overflow the buffer */
5455
93.0k
    if (sizeof(buf) < key_length) {
5456
        /* someone is getting pretty optimistic about how big their key can
5457
         * be... */
5458
0
        crv = CKR_TEMPLATE_INCONSISTENT;
5459
0
    }
5460
5461
93.0k
    if (crv != CKR_OK) {
5462
0
        if (pbe_param) {
5463
0
            nsspkcs5_DestroyPBEParameter(pbe_param);
5464
0
        }
5465
0
        goto loser;
5466
0
    }
5467
5468
    /* if there was no error,
5469
     * key_type *MUST* be set in the switch statement above */
5470
93.0k
    PORT_Assert(key_type != CKK_INVALID_KEY_TYPE);
5471
5472
    /*
5473
     * now to the actual key gen.
5474
     */
5475
93.0k
    switch (key_gen_type) {
5476
622
        case nsc_pbe:
5477
622
            crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length,
5478
622
                                  faultyPBE3DES);
5479
622
            nsspkcs5_DestroyPBEParameter(pbe_param);
5480
622
            break;
5481
59.0k
        case nsc_ssl:
5482
59.0k
            rsa_pms = (SSL3RSAPreMasterSecret *)buf;
5483
59.0k
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_VERSION))) {
5484
0
                crv = CKR_MECHANISM_PARAM_INVALID;
5485
0
                goto loser;
5486
0
            }
5487
59.0k
            version = (CK_VERSION *)pMechanism->pParameter;
5488
59.0k
            rsa_pms->client_version[0] = version->major;
5489
59.0k
            rsa_pms->client_version[1] = version->minor;
5490
59.0k
            crv =
5491
59.0k
                NSC_GenerateRandom(0, &rsa_pms->random[0], sizeof(rsa_pms->random));
5492
59.0k
            break;
5493
33.4k
        case nsc_bulk:
5494
            /* get the key, check for weak keys and repeat if found */
5495
33.4k
            do {
5496
33.4k
                crv = NSC_GenerateRandom(0, buf, key_length);
5497
33.4k
            } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf, key_type));
5498
33.4k
            break;
5499
0
        case nsc_param:
5500
            /* generate parameters */
5501
0
            *buf = 0;
5502
0
            crv = nsc_parameter_gen(key_type, key);
5503
0
            break;
5504
0
        case nsc_jpake:
5505
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_NSS_JPAKERound1Params))) {
5506
0
                crv = CKR_MECHANISM_PARAM_INVALID;
5507
0
                goto loser;
5508
0
            }
5509
0
            crv = jpake_Round1(hashType,
5510
0
                               (CK_NSS_JPAKERound1Params *)pMechanism->pParameter,
5511
0
                               key);
5512
0
            break;
5513
93.0k
    }
5514
5515
93.0k
    if (crv != CKR_OK) {
5516
0
        goto loser;
5517
0
    }
5518
5519
    /* Add the class, key_type, and value */
5520
93.0k
    crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS));
5521
93.0k
    if (crv != CKR_OK) {
5522
0
        goto loser;
5523
0
    }
5524
93.0k
    crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE));
5525
93.0k
    if (crv != CKR_OK) {
5526
0
        goto loser;
5527
0
    }
5528
93.0k
    if (key_length != 0) {
5529
93.0k
        crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length);
5530
93.0k
        if (crv != CKR_OK) {
5531
0
            goto loser;
5532
0
        }
5533
93.0k
    }
5534
5535
    /* get the session */
5536
93.0k
    session = sftk_SessionFromHandle(hSession);
5537
93.0k
    if (session == NULL) {
5538
0
        crv = CKR_SESSION_HANDLE_INVALID;
5539
0
        goto loser;
5540
0
    }
5541
5542
    /*
5543
     * handle the base object stuff
5544
     */
5545
93.0k
    crv = sftk_handleObject(key, session);
5546
    /* we need to do this check at the end, so we can check the generated key
5547
     * length against fips requirements */
5548
93.0k
    sftk_setFIPS(key, sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE,
5549
93.0k
                                           key, 0));
5550
93.0k
    session->lastOpWasFIPS = sftk_hasFIPS(key);
5551
93.0k
    sftk_FreeSession(session);
5552
93.0k
    if (crv != CKR_OK) {
5553
0
        goto loser;
5554
0
    }
5555
93.0k
    if (sftk_isTrue(key, CKA_SENSITIVE)) {
5556
0
        crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL));
5557
0
    }
5558
93.0k
    if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) {
5559
0
        crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL));
5560
0
    }
5561
93.0k
    if (crv != CKR_OK) {
5562
0
        NSC_DestroyObject(hSession, key->handle);
5563
0
        goto loser;
5564
0
    }
5565
93.0k
    *phKey = key->handle;
5566
93.0k
loser:
5567
93.0k
    PORT_Memset(buf, 0, sizeof buf);
5568
93.0k
    sftk_FreeObject(key);
5569
93.0k
    return crv;
5570
93.0k
}
5571
5572
/* takes raw sessions and key handles and determines if the keys
5573
 * have the same value. */
5574
PRBool
5575
sftk_compareKeysEqual(CK_SESSION_HANDLE hSession,
5576
                      CK_OBJECT_HANDLE key1, CK_OBJECT_HANDLE key2)
5577
0
{
5578
0
    PRBool result = PR_FALSE;
5579
0
    SFTKSession *session;
5580
0
    SFTKObject *key1obj = NULL;
5581
0
    SFTKObject *key2obj = NULL;
5582
0
    SFTKAttribute *att1 = NULL;
5583
0
    SFTKAttribute *att2 = NULL;
5584
5585
    /* fetch the pkcs11 objects from the handles */
5586
0
    session = sftk_SessionFromHandle(hSession);
5587
0
    if (session == NULL) {
5588
0
        return PR_FALSE;
5589
0
    }
5590
5591
0
    key1obj = sftk_ObjectFromHandle(key1, session);
5592
0
    key2obj = sftk_ObjectFromHandle(key2, session);
5593
0
    sftk_FreeSession(session);
5594
0
    if ((key1obj == NULL) || (key2obj == NULL)) {
5595
0
        goto loser;
5596
0
    }
5597
    /* fetch the value attributes */
5598
0
    att1 = sftk_FindAttribute(key1obj, CKA_VALUE);
5599
0
    if (att1 == NULL) {
5600
0
        goto loser;
5601
0
    }
5602
0
    att2 = sftk_FindAttribute(key2obj, CKA_VALUE);
5603
0
    if (att2 == NULL) {
5604
0
        goto loser;
5605
0
    }
5606
    /* make sure that they are equal */
5607
0
    if (att1->attrib.ulValueLen != att2->attrib.ulValueLen) {
5608
0
        goto loser;
5609
0
    }
5610
0
    if (PORT_Memcmp(att1->attrib.pValue, att2->attrib.pValue,
5611
0
                    att1->attrib.ulValueLen) != 0) {
5612
0
        goto loser;
5613
0
    }
5614
0
    result = PR_TRUE;
5615
0
loser:
5616
0
    if (att1) {
5617
0
        sftk_FreeAttribute(att1);
5618
0
    }
5619
0
    if (att2) {
5620
0
        sftk_FreeAttribute(att2);
5621
0
    }
5622
0
    if (key1obj) {
5623
0
        sftk_FreeObject(key1obj);
5624
0
    }
5625
0
    if (key2obj) {
5626
0
        sftk_FreeObject(key2obj);
5627
0
    }
5628
0
    return result;
5629
0
}
5630
5631
5
#define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */
5632
5633
/*
5634
 * FIPS 140-3 pairwise consistency check utilized to validate key pair.
5635
 *
5636
 * This function returns
5637
 *   CKR_OK               if pairwise consistency check passed
5638
 *   CKR_GENERAL_ERROR    if pairwise consistency check failed
5639
 *   other error codes    if paiswise consistency check could not be
5640
 *                        performed, for example, CKR_HOST_MEMORY.
5641
 */
5642
static CK_RV
5643
sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, SFTKSlot *slot,
5644
                              SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType)
5645
23.5k
{
5646
    /*
5647
     *                      Key type    Mechanism type
5648
     *                      --------------------------------
5649
     * For encrypt/decrypt: CKK_RSA  => CKM_RSA_PKCS_OAEP
5650
     *                      others   => CKM_INVALID_MECHANISM
5651
     *
5652
     * For sign/verify:     CKK_RSA  => CKM_SHA256_RSA_PKCS_PSS
5653
     *                      CKK_DSA  => CKM_DSA_SHA256
5654
     *                      CKK_EC   => CKM_ECDSA_SHA256
5655
     *                      CKK_ML_DSA => CKM_ML_DSA
5656
     *                      others   => CKM_INVALID_MECHANISM
5657
     *
5658
     * None of these mechanisms has a parameter.
5659
     *
5660
     * For derive           CKK_DH   => CKM_DH_PKCS_DERIVE
5661
     *                      CKK_EC   => CKM_ECDH1_DERIVE
5662
     *                      CKK_EC_MONTGOMERY   => CKM_ECDH1_DERIVE
5663
     *                      others   => CKM_INVALID_MECHANISM
5664
     *
5665
     * For KEM mechanisms:
5666
     *                     CKK_NSS_KYBER   => don't
5667
     *                     CKK_NSS_ML_KEM  => don't
5668
     *                     CKK_ML_KEM      => CM_ML_KEM
5669
     *
5670
     * The parameters for these mechanisms is the public key.
5671
     */
5672
23.5k
    CK_MECHANISM mech = { 0, NULL, 0 };
5673
5674
23.5k
    CK_ULONG modulusLen = 0;
5675
23.5k
#ifndef NSS_DISABLE_DSA
5676
23.5k
    CK_ULONG subPrimeLen = 0;
5677
23.5k
#endif
5678
23.5k
    PRBool isEncryptable = PR_FALSE;
5679
23.5k
    PRBool canSignVerify = PR_FALSE;
5680
23.5k
    PRBool isDerivable = PR_FALSE;
5681
23.5k
    PRBool isKEM = PR_FALSE;
5682
23.5k
    CK_RV crv;
5683
5684
    /* Variables used for Encrypt/Decrypt functions. */
5685
23.5k
    unsigned char *known_message = (unsigned char *)"Known Crypto Message";
5686
23.5k
    unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH];
5687
23.5k
    CK_ULONG bytes_decrypted;
5688
23.5k
    unsigned char *ciphertext;
5689
23.5k
    unsigned char *text_compared;
5690
23.5k
    CK_ULONG bytes_encrypted;
5691
23.5k
    CK_ULONG bytes_compared;
5692
5693
    /* Variables used for Signature/Verification functions. */
5694
23.5k
    unsigned char *signature;
5695
23.5k
    CK_ULONG signature_length;
5696
23.5k
    SFTKAttribute *attribute;
5697
5698
23.5k
    switch (keyType) {
5699
0
        case CKK_RSA:
5700
            /* Get modulus length of private key. */
5701
0
            attribute = sftk_FindAttribute(privateKey, CKA_MODULUS);
5702
0
            if (attribute == NULL) {
5703
0
                return CKR_DEVICE_ERROR;
5704
0
            }
5705
0
            modulusLen = attribute->attrib.ulValueLen;
5706
0
            if (*(unsigned char *)attribute->attrib.pValue == 0) {
5707
0
                modulusLen--;
5708
0
            }
5709
0
            sftk_FreeAttribute(attribute);
5710
0
#if RSA_MIN_MODULUS_BITS < 1023
5711
            /* if we allow weak RSA keys, and this is a weak RSA key and
5712
             * we aren't in FIPS mode, skip the tests, These keys are
5713
             * factorable anyway, the pairwise test doen't matter. */
5714
0
            if ((modulusLen < 1023) && !sftk_isFIPS(slot->slotID)) {
5715
0
                return CKR_OK;
5716
0
            }
5717
0
#endif
5718
0
            break;
5719
0
#ifndef NSS_DISABLE_DSA
5720
0
        case CKK_DSA:
5721
            /* Get subprime length of private key. */
5722
0
            attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME);
5723
0
            if (attribute == NULL) {
5724
0
                return CKR_DEVICE_ERROR;
5725
0
            }
5726
0
            subPrimeLen = attribute->attrib.ulValueLen;
5727
0
            if (subPrimeLen > 1 &&
5728
0
                *(unsigned char *)attribute->attrib.pValue == 0) {
5729
0
                subPrimeLen--;
5730
0
            }
5731
0
            sftk_FreeAttribute(attribute);
5732
0
            break;
5733
0
#endif
5734
0
        case CKK_NSS_KYBER:
5735
13.6k
        case CKK_NSS_ML_KEM:
5736
            /* these aren't FIPS. we use them to generate keys without a
5737
             * pairwise consistency check */
5738
13.6k
            return CKR_OK;
5739
23.5k
    }
5740
5741
    /**************************************************/
5742
    /* Pairwise Consistency Check of Encrypt/Decrypt. */
5743
    /**************************************************/
5744
5745
9.86k
    isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT);
5746
5747
    /*
5748
     * If the decryption attribute is set, attempt to encrypt
5749
     * with the public key and decrypt with the private key.
5750
     */
5751
9.86k
    if (isEncryptable) {
5752
0
        if (keyType != CKK_RSA) {
5753
0
            return CKR_DEVICE_ERROR;
5754
0
        }
5755
0
        bytes_encrypted = modulusLen;
5756
0
        mech.mechanism = CKM_RSA_PKCS_OAEP;
5757
0
        CK_RSA_PKCS_OAEP_PARAMS oaepParams;
5758
0
        oaepParams.hashAlg = CKM_SHA256;
5759
0
        oaepParams.mgf = CKG_MGF1_SHA256;
5760
0
        oaepParams.source = CKZ_DATA_SPECIFIED;
5761
0
        oaepParams.pSourceData = NULL;
5762
0
        oaepParams.ulSourceDataLen = 0;
5763
0
        mech.pParameter = &oaepParams;
5764
0
        mech.ulParameterLen = sizeof(oaepParams);
5765
5766
        /* Allocate space for ciphertext. */
5767
0
        ciphertext = (unsigned char *)PORT_ZAlloc(bytes_encrypted);
5768
0
        if (ciphertext == NULL) {
5769
0
            return CKR_HOST_MEMORY;
5770
0
        }
5771
5772
        /* Prepare for encryption using the public key. */
5773
0
        crv = NSC_EncryptInit(hSession, &mech, publicKey->handle);
5774
0
        if (crv != CKR_OK) {
5775
0
            PORT_Free(ciphertext);
5776
0
            return crv;
5777
0
        }
5778
5779
        /* Encrypt using the public key. */
5780
0
        crv = NSC_Encrypt(hSession,
5781
0
                          known_message,
5782
0
                          PAIRWISE_MESSAGE_LENGTH,
5783
0
                          ciphertext,
5784
0
                          &bytes_encrypted);
5785
0
        if (crv != CKR_OK) {
5786
0
            PORT_Free(ciphertext);
5787
0
            return crv;
5788
0
        }
5789
5790
        /* Always use the smaller of these two values . . . */
5791
0
        bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH);
5792
5793
        /*
5794
         * If there was a failure, the plaintext
5795
         * goes at the end, therefore . . .
5796
         */
5797
0
        text_compared = ciphertext + bytes_encrypted - bytes_compared;
5798
5799
        /*
5800
         * Check to ensure that ciphertext does
5801
         * NOT EQUAL known input message text
5802
         * per FIPS PUB 140-2 directive.
5803
         */
5804
0
        if (PORT_Memcmp(text_compared, known_message,
5805
0
                        bytes_compared) == 0) {
5806
            /* Set error to Invalid PRIVATE Key. */
5807
0
            PORT_SetError(SEC_ERROR_INVALID_KEY);
5808
0
            PORT_Free(ciphertext);
5809
0
            return CKR_GENERAL_ERROR;
5810
0
        }
5811
5812
        /* Prepare for decryption using the private key. */
5813
0
        crv = NSC_DecryptInit(hSession, &mech, privateKey->handle);
5814
0
        if (crv != CKR_OK) {
5815
0
            PORT_Free(ciphertext);
5816
0
            return crv;
5817
0
        }
5818
5819
0
        memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH);
5820
5821
        /*
5822
         * Initialize bytes decrypted to be the
5823
         * expected PAIRWISE_MESSAGE_LENGTH.
5824
         */
5825
0
        bytes_decrypted = PAIRWISE_MESSAGE_LENGTH;
5826
5827
        /*
5828
         * Decrypt using the private key.
5829
         * NOTE:  No need to reset the
5830
         *        value of bytes_encrypted.
5831
         */
5832
0
        crv = NSC_Decrypt(hSession,
5833
0
                          ciphertext,
5834
0
                          bytes_encrypted,
5835
0
                          plaintext,
5836
0
                          &bytes_decrypted);
5837
5838
        /* Finished with ciphertext; free it. */
5839
0
        PORT_Free(ciphertext);
5840
5841
0
        if (crv != CKR_OK) {
5842
0
            return crv;
5843
0
        }
5844
5845
        /*
5846
         * Check to ensure that the output plaintext
5847
         * does EQUAL known input message text.
5848
         */
5849
0
        if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) ||
5850
0
            (PORT_Memcmp(plaintext, known_message,
5851
0
                         PAIRWISE_MESSAGE_LENGTH) != 0)) {
5852
            /* Set error to Bad PUBLIC Key. */
5853
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
5854
0
            return CKR_GENERAL_ERROR;
5855
0
        }
5856
0
    }
5857
5858
    /**********************************************/
5859
    /* Pairwise Consistency Check of Sign/Verify. */
5860
    /**********************************************/
5861
5862
9.86k
    canSignVerify = sftk_isTrue(privateKey, CKA_SIGN);
5863
    /* Unfortunately CKA_SIGN is always true in lg dbs. We have to check the
5864
     * actual curve to determine if we can do sign/verify. */
5865
9.86k
    if (canSignVerify && keyType == CKK_EC) {
5866
3.35k
        NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(privateKey, CKK_EC, &crv);
5867
3.35k
        if (privKey && privKey->u.ec.ecParams.name == ECCurve25519) {
5868
3.35k
            canSignVerify = PR_FALSE;
5869
3.35k
        }
5870
3.35k
    }
5871
5872
9.86k
    if (canSignVerify) {
5873
1
        CK_RSA_PKCS_PSS_PARAMS pssParams;
5874
        /* Determine length of signature. */
5875
1
        switch (keyType) {
5876
0
            case CKK_RSA:
5877
0
                signature_length = modulusLen;
5878
0
                mech.mechanism = CKM_SHA256_RSA_PKCS_PSS;
5879
0
                pssParams.hashAlg = CKM_SHA256;
5880
0
                pssParams.mgf = CKG_MGF1_SHA256;
5881
0
                pssParams.sLen = 0;
5882
0
                mech.pParameter = &pssParams;
5883
0
                mech.ulParameterLen = sizeof(pssParams);
5884
0
                break;
5885
0
#ifndef NSS_DISABLE_DSA
5886
0
            case CKK_DSA:
5887
0
                signature_length = DSA_MAX_SIGNATURE_LEN;
5888
0
                mech.mechanism = CKM_DSA_SHA256;
5889
0
                break;
5890
0
#endif
5891
1
            case CKK_EC:
5892
1
                signature_length = MAX_ECKEY_LEN * 2;
5893
1
                mech.mechanism = CKM_ECDSA_SHA256;
5894
1
                break;
5895
0
            case CKK_ML_DSA:
5896
0
                signature_length = MAX_ML_DSA_SIGNATURE_LEN;
5897
0
                mech.mechanism = CKM_ML_DSA;
5898
0
                break;
5899
0
            case CKK_EC_EDWARDS:
5900
0
                signature_length = ED25519_SIGN_LEN;
5901
0
                mech.mechanism = CKM_EDDSA;
5902
0
                break;
5903
0
            default:
5904
0
                return CKR_DEVICE_ERROR;
5905
1
        }
5906
5907
        /* Allocate space for signature data. */
5908
1
        signature = (unsigned char *)PORT_ZAlloc(signature_length);
5909
1
        if (signature == NULL) {
5910
0
            return CKR_HOST_MEMORY;
5911
0
        }
5912
5913
        /* Sign the known hash using the private key. */
5914
1
        crv = NSC_SignInit(hSession, &mech, privateKey->handle);
5915
1
        if (crv != CKR_OK) {
5916
0
            PORT_Free(signature);
5917
0
            return crv;
5918
0
        }
5919
5920
1
        crv = NSC_Sign(hSession,
5921
1
                       known_message,
5922
1
                       PAIRWISE_MESSAGE_LENGTH,
5923
1
                       signature,
5924
1
                       &signature_length);
5925
1
        if (crv != CKR_OK) {
5926
0
            PORT_Free(signature);
5927
0
            return crv;
5928
0
        }
5929
5930
        /* detect trivial signing transforms */
5931
1
        if ((signature_length >= PAIRWISE_MESSAGE_LENGTH) &&
5932
1
            (PORT_Memcmp(known_message, signature + (signature_length - PAIRWISE_MESSAGE_LENGTH), PAIRWISE_MESSAGE_LENGTH) == 0)) {
5933
0
            PORT_Free(signature);
5934
0
            return CKR_GENERAL_ERROR;
5935
0
        }
5936
5937
        /* Verify the known hash using the public key. */
5938
1
        crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
5939
1
        if (crv != CKR_OK) {
5940
0
            PORT_Free(signature);
5941
0
            return crv;
5942
0
        }
5943
5944
1
        crv = NSC_Verify(hSession,
5945
1
                         known_message,
5946
1
                         PAIRWISE_MESSAGE_LENGTH,
5947
1
                         signature,
5948
1
                         signature_length);
5949
5950
        /* Free signature data. */
5951
1
        PORT_Free(signature);
5952
5953
1
        if ((crv == CKR_SIGNATURE_LEN_RANGE) ||
5954
1
            (crv == CKR_SIGNATURE_INVALID)) {
5955
0
            return CKR_GENERAL_ERROR;
5956
0
        }
5957
1
        if (crv != CKR_OK) {
5958
0
            return crv;
5959
0
        }
5960
1
    }
5961
5962
    /**********************************************/
5963
    /* Pairwise Consistency Check for Derivation  */
5964
    /**********************************************/
5965
5966
9.86k
    isDerivable = sftk_isTrue(privateKey, CKA_DERIVE);
5967
5968
9.86k
    if (isDerivable) {
5969
9.86k
        SFTKAttribute *pubAttribute = NULL;
5970
9.86k
        PRBool isFIPS = sftk_isFIPS(slot->slotID);
5971
9.86k
        NSSLOWKEYPrivateKey *lowPrivKey = NULL;
5972
9.86k
        ECPrivateKey *ecPriv = NULL;
5973
9.86k
        SECItem *lowPubValue = NULL;
5974
9.86k
        SECItem item = { siBuffer, NULL, 0 };
5975
9.86k
        SECStatus rv;
5976
5977
9.86k
        crv = CKR_OK; /*paranoia, already get's set before we drop to the end */
5978
5979
        /* FIPS 140-3 requires we verify that the resulting key is a valid key
5980
         * by recalculating the public can an compare it to our own public
5981
         * key. */
5982
9.86k
        lowPrivKey = sftk_GetPrivKey(privateKey, keyType, &crv);
5983
9.86k
        if (lowPrivKey == NULL) {
5984
0
            return sftk_MapCryptError(PORT_GetError());
5985
0
        }
5986
        /* recalculate the public key from the private key */
5987
9.86k
        switch (keyType) {
5988
6.43k
            case CKK_DH:
5989
6.43k
                rv = DH_Derive(&lowPrivKey->u.dh.base, &lowPrivKey->u.dh.prime,
5990
6.43k
                               &lowPrivKey->u.dh.privateValue, &item, 0);
5991
6.43k
                if (rv != SECSuccess) {
5992
0
                    return CKR_GENERAL_ERROR;
5993
0
                }
5994
6.43k
                lowPubValue = SECITEM_DupItem(&item);
5995
6.43k
                SECITEM_ZfreeItem(&item, PR_FALSE);
5996
6.43k
                pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE);
5997
6.43k
                break;
5998
0
            case CKK_EC_MONTGOMERY:
5999
3.43k
            case CKK_EC:
6000
3.43k
                rv = EC_NewKeyFromSeed(&lowPrivKey->u.ec.ecParams, &ecPriv,
6001
3.43k
                                       lowPrivKey->u.ec.privateValue.data,
6002
3.43k
                                       lowPrivKey->u.ec.privateValue.len);
6003
3.43k
                if (rv != SECSuccess) {
6004
0
                    return CKR_GENERAL_ERROR;
6005
0
                }
6006
                /* make sure it has the same encoding */
6007
3.43k
                if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") ||
6008
3.43k
                    lowPrivKey->u.ec.ecParams.type != ec_params_named) {
6009
3.35k
                    lowPubValue = SECITEM_DupItem(&ecPriv->publicValue);
6010
3.35k
                } else {
6011
80
                    lowPubValue = SEC_ASN1EncodeItem(NULL, NULL, &ecPriv->publicValue,
6012
80
                                                     SEC_ASN1_GET(SEC_OctetStringTemplate));
6013
80
                }
6014
3.43k
                pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT);
6015
                /* clear out our generated private key */
6016
3.43k
                PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
6017
3.43k
                break;
6018
0
            default:
6019
0
                return CKR_DEVICE_ERROR;
6020
9.86k
        }
6021
6022
        /* now compare new public key with our already generated key */
6023
9.86k
        if ((pubAttribute == NULL) || (lowPubValue == NULL) ||
6024
9.86k
            (pubAttribute->attrib.ulValueLen != lowPubValue->len) ||
6025
9.86k
            (PORT_Memcmp(pubAttribute->attrib.pValue, lowPubValue->data,
6026
9.86k
                         lowPubValue->len) != 0)) {
6027
0
            if (pubAttribute)
6028
0
                sftk_FreeAttribute(pubAttribute);
6029
0
            if (lowPubValue)
6030
0
                SECITEM_ZfreeItem(lowPubValue, PR_TRUE);
6031
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
6032
0
            return CKR_GENERAL_ERROR;
6033
0
        }
6034
9.86k
        SECITEM_ZfreeItem(lowPubValue, PR_TRUE);
6035
6036
        /* FIPS requires full validation, but in fipx mode NSC_Derive
6037
         * only does partial validation with approved primes, now handle
6038
         * full validation */
6039
9.86k
        if (isFIPS && keyType == CKK_DH) {
6040
0
            SECItem pubKey = { siBuffer, pubAttribute->attrib.pValue,
6041
0
                               pubAttribute->attrib.ulValueLen };
6042
0
            SECItem base = { siBuffer, NULL, 0 };
6043
0
            SECItem prime = { siBuffer, NULL, 0 };
6044
0
            SECItem subPrime = { siBuffer, NULL, 0 };
6045
0
            SECItem generator = { siBuffer, NULL, 0 };
6046
0
            const SECItem *subPrimePtr = &subPrime;
6047
6048
0
            crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
6049
0
            if (crv != CKR_OK) {
6050
0
                goto done;
6051
0
            }
6052
0
            crv = sftk_Attribute2SecItem(NULL, &base, privateKey, CKA_BASE);
6053
0
            if (crv != CKR_OK) {
6054
0
                goto done;
6055
0
            }
6056
            /* we ignore the return code an only look at the length */
6057
            /* do we have a known prime ? */
6058
0
            subPrimePtr = sftk_VerifyDH_Prime(&prime, &generator, isFIPS);
6059
0
            if (subPrimePtr == NULL) {
6060
0
                if (subPrime.len == 0) {
6061
                    /* if not a known prime, subprime must be supplied */
6062
0
                    crv = CKR_ATTRIBUTE_VALUE_INVALID;
6063
0
                    goto done;
6064
0
                } else {
6065
                    /* not a known prime, check for primality of prime
6066
                     * and subPrime */
6067
0
                    if (!KEA_PrimeCheck(&prime)) {
6068
0
                        crv = CKR_ATTRIBUTE_VALUE_INVALID;
6069
0
                        goto done;
6070
0
                    }
6071
0
                    if (!KEA_PrimeCheck(&subPrime)) {
6072
0
                        crv = CKR_ATTRIBUTE_VALUE_INVALID;
6073
0
                        goto done;
6074
0
                    }
6075
                    /* if we aren't using a defined group, make sure base is in the
6076
                     * subgroup. If it's not, then our key could fail or succeed sometimes.
6077
                     * This makes the failure reliable */
6078
0
                    if (!KEA_Verify(&base, &prime, &subPrime)) {
6079
0
                        crv = CKR_ATTRIBUTE_VALUE_INVALID;
6080
0
                    }
6081
0
                }
6082
0
                subPrimePtr = &subPrime;
6083
0
            } else {
6084
                /* we're using a known group, make sure we are using the known generator for that group */
6085
0
                if (SECITEM_CompareItem(&generator, &base) != 0) {
6086
0
                    crv = CKR_ATTRIBUTE_VALUE_INVALID;
6087
0
                    goto done;
6088
0
                }
6089
0
                if (subPrime.len != 0) {
6090
                    /* we have a known prime and a supplied subPrime,
6091
                     * make sure the subPrime matches the subPrime for
6092
                     * the known Prime */
6093
0
                    if (SECITEM_CompareItem(subPrimePtr, &subPrime) != 0) {
6094
0
                        crv = CKR_ATTRIBUTE_VALUE_INVALID;
6095
0
                        goto done;
6096
0
                    }
6097
0
                }
6098
0
            }
6099
0
            if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) {
6100
0
                crv = CKR_ATTRIBUTE_VALUE_INVALID;
6101
0
            }
6102
0
        done:
6103
0
            SECITEM_ZfreeItem(&base, PR_FALSE);
6104
0
            SECITEM_ZfreeItem(&subPrime, PR_FALSE);
6105
0
            SECITEM_ZfreeItem(&prime, PR_FALSE);
6106
0
        }
6107
        /* clean up before we return */
6108
9.86k
        sftk_FreeAttribute(pubAttribute);
6109
9.86k
        if (crv != CKR_OK) {
6110
0
            return crv;
6111
0
        }
6112
9.86k
    }
6113
6114
9.86k
    isKEM = sftk_isTrue(privateKey, CKA_DECAPSULATE);
6115
9.86k
    if (isKEM) {
6116
0
        unsigned char *cipher_text = NULL;
6117
0
        CK_ULONG cipher_text_length = 0;
6118
0
        CK_OBJECT_HANDLE key1 = CK_INVALID_HANDLE;
6119
0
        CK_OBJECT_HANDLE key2 = CK_INVALID_HANDLE;
6120
0
        CK_KEY_TYPE genClass = CKO_SECRET_KEY;
6121
0
        CK_ATTRIBUTE template = { CKA_CLASS, NULL, 0 };
6122
6123
0
        template.pValue = &genClass;
6124
0
        template.ulValueLen = sizeof(genClass);
6125
0
        crv = CKR_OK;
6126
0
        switch (keyType) {
6127
0
            case CKK_ML_KEM:
6128
0
                cipher_text_length = MAX_ML_KEM_CIPHER_LENGTH;
6129
0
                mech.mechanism = CKM_ML_KEM;
6130
0
                break;
6131
0
            default:
6132
0
                return CKR_DEVICE_ERROR;
6133
0
        }
6134
        /* Allocate space for kem cipher text. */
6135
0
        cipher_text = (unsigned char *)PORT_ZAlloc(cipher_text_length);
6136
0
        if (cipher_text == NULL) {
6137
0
            return CKR_HOST_MEMORY;
6138
0
        }
6139
0
        crv = NSC_Encapsulate(hSession, &mech, publicKey->handle, &template, 1,
6140
0
                              &key1, cipher_text, &cipher_text_length);
6141
0
        if (crv != CKR_OK) {
6142
0
            goto kem_done;
6143
0
        }
6144
0
        crv = NSC_Decapsulate(hSession, &mech, privateKey->handle,
6145
0
                              cipher_text, cipher_text_length, &template, 1,
6146
0
                              &key2);
6147
0
        if (crv != CKR_OK) {
6148
0
            goto kem_done;
6149
0
        }
6150
0
        if (!sftk_compareKeysEqual(hSession, key1, key2)) {
6151
0
            crv = CKR_GENERAL_ERROR;
6152
0
            goto kem_done;
6153
0
        }
6154
0
    kem_done:
6155
        /* PORT_Free already checks for NULL */
6156
0
        PORT_Free(cipher_text);
6157
0
        if (key1 != CK_INVALID_HANDLE) {
6158
0
            NSC_DestroyObject(hSession, key1);
6159
0
        }
6160
0
        if (key2 != CK_INVALID_HANDLE) {
6161
0
            NSC_DestroyObject(hSession, key2);
6162
0
        }
6163
0
        if (crv != CKR_OK) {
6164
0
            return crv;
6165
0
        }
6166
0
    }
6167
6168
9.86k
    return CKR_OK;
6169
9.86k
}
6170
6171
/* NSC_GenerateKeyPair generates a public-key/private-key pair,
6172
 * creating new key objects. */
6173
CK_RV
6174
NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
6175
                    CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
6176
                    CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
6177
                    CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,
6178
                    CK_OBJECT_HANDLE_PTR phPrivateKey)
6179
96.4k
{
6180
96.4k
    SFTKObject *publicKey, *privateKey;
6181
96.4k
    SFTKSession *session;
6182
96.4k
    CK_KEY_TYPE key_type;
6183
96.4k
    CK_RV crv = CKR_OK;
6184
96.4k
    CK_BBOOL cktrue = CK_TRUE;
6185
96.4k
    SECStatus rv;
6186
96.4k
    CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
6187
96.4k
    CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
6188
96.4k
    int i;
6189
96.4k
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
6190
96.4k
    unsigned int bitSize;
6191
6192
    /* RSA */
6193
96.4k
    int public_modulus_bits = 0;
6194
96.4k
    SECItem pubExp;
6195
96.4k
    RSAPrivateKey *rsaPriv;
6196
6197
96.4k
    DHParams dhParam;
6198
96.4k
#ifndef NSS_DISABLE_DSA
6199
    /* DSA */
6200
96.4k
    PQGParams pqgParam;
6201
96.4k
    DSAPrivateKey *dsaPriv;
6202
96.4k
#endif
6203
96.4k
    MLDSAPrivateKey mldsaPriv;
6204
96.4k
    MLDSAPublicKey mldsaPub;
6205
6206
    /* Diffie Hellman */
6207
96.4k
    DHPrivateKey *dhPriv;
6208
6209
    /* Elliptic Curve Cryptography */
6210
96.4k
    SECItem ecEncodedParams; /* DER Encoded parameters */
6211
96.4k
    ECPrivateKey *ecPriv;
6212
96.4k
    ECParams *ecParams;
6213
6214
    /* parameter set, mostly pq keys */
6215
96.4k
    CK_ULONG genParamSet = 0;
6216
6217
96.4k
    CHECK_FORK();
6218
6219
96.4k
    if (!slot) {
6220
0
        return CKR_SESSION_HANDLE_INVALID;
6221
0
    }
6222
    /*
6223
     * now lets create an object to hang the attributes off of
6224
     */
6225
96.4k
    publicKey = sftk_NewObject(slot); /* fill in the handle later */
6226
96.4k
    if (publicKey == NULL) {
6227
0
        return CKR_HOST_MEMORY;
6228
0
    }
6229
6230
    /*
6231
     * load the template values into the publicKey
6232
     */
6233
791k
    for (i = 0; i < (int)ulPublicKeyAttributeCount; i++) {
6234
695k
        if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) {
6235
0
            public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;
6236
0
            continue;
6237
0
        }
6238
6239
695k
        if ((pPublicKeyTemplate[i].type == CKA_PARAMETER_SET) ||
6240
681k
            (pPublicKeyTemplate[i].type == CKA_NSS_PARAMETER_SET)) {
6241
13.6k
            genParamSet = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;
6242
13.6k
            continue;
6243
13.6k
        }
6244
6245
681k
        crv = sftk_AddAttributeType(publicKey,
6246
681k
                                    sftk_attr_expand(&pPublicKeyTemplate[i]));
6247
681k
        if (crv != CKR_OK)
6248
0
            break;
6249
681k
    }
6250
6251
96.4k
    if (crv != CKR_OK) {
6252
0
        sftk_FreeObject(publicKey);
6253
0
        return CKR_HOST_MEMORY;
6254
0
    }
6255
6256
96.4k
    privateKey = sftk_NewObject(slot); /* fill in the handle later */
6257
96.4k
    if (privateKey == NULL) {
6258
0
        sftk_FreeObject(publicKey);
6259
0
        return CKR_HOST_MEMORY;
6260
0
    }
6261
    /*
6262
     * now load the private key template
6263
     */
6264
784k
    for (i = 0; i < (int)ulPrivateKeyAttributeCount; i++) {
6265
688k
        if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) {
6266
0
            continue;
6267
0
        }
6268
6269
688k
        crv = sftk_AddAttributeType(privateKey,
6270
688k
                                    sftk_attr_expand(&pPrivateKeyTemplate[i]));
6271
688k
        if (crv != CKR_OK)
6272
0
            break;
6273
688k
    }
6274
6275
96.4k
    if (crv != CKR_OK) {
6276
0
        sftk_FreeObject(publicKey);
6277
0
        sftk_FreeObject(privateKey);
6278
0
        return CKR_HOST_MEMORY;
6279
0
    }
6280
96.4k
    sftk_DeleteAttributeType(privateKey, CKA_CLASS);
6281
96.4k
    sftk_DeleteAttributeType(privateKey, CKA_KEY_TYPE);
6282
96.4k
    sftk_DeleteAttributeType(privateKey, CKA_VALUE);
6283
96.4k
    sftk_DeleteAttributeType(publicKey, CKA_CLASS);
6284
96.4k
    sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE);
6285
96.4k
    sftk_DeleteAttributeType(publicKey, CKA_VALUE);
6286
6287
    /* Now Set up the parameters to generate the key (based on mechanism) */
6288
96.4k
    switch (pMechanism->mechanism) {
6289
0
        case CKM_RSA_PKCS_KEY_PAIR_GEN:
6290
            /* format the keys */
6291
0
            sftk_DeleteAttributeType(publicKey, CKA_MODULUS);
6292
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
6293
0
            sftk_DeleteAttributeType(privateKey, CKA_MODULUS);
6294
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIVATE_EXPONENT);
6295
0
            sftk_DeleteAttributeType(privateKey, CKA_PUBLIC_EXPONENT);
6296
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIME_1);
6297
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIME_2);
6298
0
            sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_1);
6299
0
            sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_2);
6300
0
            sftk_DeleteAttributeType(privateKey, CKA_COEFFICIENT);
6301
0
            key_type = CKK_RSA;
6302
0
            if (public_modulus_bits == 0) {
6303
0
                crv = CKR_TEMPLATE_INCOMPLETE;
6304
0
                break;
6305
0
            }
6306
0
            if (public_modulus_bits < RSA_MIN_MODULUS_BITS) {
6307
0
                crv = CKR_ATTRIBUTE_VALUE_INVALID;
6308
0
                break;
6309
0
            }
6310
0
            if (public_modulus_bits % 2 != 0) {
6311
0
                crv = CKR_ATTRIBUTE_VALUE_INVALID;
6312
0
                break;
6313
0
            }
6314
6315
            /* extract the exponent */
6316
0
            crv = sftk_Attribute2SSecItem(NULL, &pubExp, publicKey, CKA_PUBLIC_EXPONENT);
6317
0
            if (crv != CKR_OK)
6318
0
                break;
6319
0
            bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len);
6320
0
            if (bitSize < 2) {
6321
0
                crv = CKR_ATTRIBUTE_VALUE_INVALID;
6322
0
                SECITEM_ZfreeItem(&pubExp, PR_FALSE);
6323
0
                break;
6324
0
            }
6325
0
            crv = sftk_AddAttributeType(privateKey, CKA_PUBLIC_EXPONENT,
6326
0
                                        sftk_item_expand(&pubExp));
6327
0
            if (crv != CKR_OK) {
6328
0
                SECITEM_ZfreeItem(&pubExp, PR_FALSE);
6329
0
                break;
6330
0
            }
6331
6332
0
            rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp);
6333
0
            SECITEM_ZfreeItem(&pubExp, PR_FALSE);
6334
0
            if (rsaPriv == NULL) {
6335
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
6336
0
                    sftk_fatalError = PR_TRUE;
6337
0
                }
6338
0
                crv = sftk_MapCryptError(PORT_GetError());
6339
0
                break;
6340
0
            }
6341
            /* now fill in the RSA dependent paramenters in the public key */
6342
0
            crv = sftk_AddAttributeType(publicKey, CKA_MODULUS,
6343
0
                                        sftk_item_expand(&rsaPriv->modulus));
6344
0
            if (crv != CKR_OK)
6345
0
                goto kpg_done;
6346
            /* now fill in the RSA dependent paramenters in the private key */
6347
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
6348
0
                                        sftk_item_expand(&rsaPriv->modulus));
6349
0
            if (crv != CKR_OK)
6350
0
                goto kpg_done;
6351
0
            crv = sftk_AddAttributeType(privateKey, CKA_MODULUS,
6352
0
                                        sftk_item_expand(&rsaPriv->modulus));
6353
0
            if (crv != CKR_OK)
6354
0
                goto kpg_done;
6355
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIVATE_EXPONENT,
6356
0
                                        sftk_item_expand(&rsaPriv->privateExponent));
6357
0
            if (crv != CKR_OK)
6358
0
                goto kpg_done;
6359
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIME_1,
6360
0
                                        sftk_item_expand(&rsaPriv->prime1));
6361
0
            if (crv != CKR_OK)
6362
0
                goto kpg_done;
6363
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIME_2,
6364
0
                                        sftk_item_expand(&rsaPriv->prime2));
6365
0
            if (crv != CKR_OK)
6366
0
                goto kpg_done;
6367
0
            crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_1,
6368
0
                                        sftk_item_expand(&rsaPriv->exponent1));
6369
0
            if (crv != CKR_OK)
6370
0
                goto kpg_done;
6371
0
            crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_2,
6372
0
                                        sftk_item_expand(&rsaPriv->exponent2));
6373
0
            if (crv != CKR_OK)
6374
0
                goto kpg_done;
6375
0
            crv = sftk_AddAttributeType(privateKey, CKA_COEFFICIENT,
6376
0
                                        sftk_item_expand(&rsaPriv->coefficient));
6377
0
        kpg_done:
6378
            /* Should zeroize the contents first, since this func doesn't. */
6379
0
            PORT_FreeArena(rsaPriv->arena, PR_TRUE);
6380
0
            break;
6381
0
#ifndef NSS_DISABLE_DSA
6382
0
        case CKM_DSA_KEY_PAIR_GEN:
6383
0
            sftk_DeleteAttributeType(publicKey, CKA_VALUE);
6384
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
6385
0
            sftk_DeleteAttributeType(privateKey, CKA_PRIME);
6386
0
            sftk_DeleteAttributeType(privateKey, CKA_SUBPRIME);
6387
0
            sftk_DeleteAttributeType(privateKey, CKA_BASE);
6388
0
            key_type = CKK_DSA;
6389
6390
            /* extract the necessary parameters and copy them to the private key */
6391
0
            crv = sftk_Attribute2SSecItem(NULL, &pqgParam.prime, publicKey, CKA_PRIME);
6392
0
            if (crv != CKR_OK)
6393
0
                break;
6394
0
            crv = sftk_Attribute2SSecItem(NULL, &pqgParam.subPrime, publicKey,
6395
0
                                          CKA_SUBPRIME);
6396
0
            if (crv != CKR_OK) {
6397
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
6398
0
                break;
6399
0
            }
6400
0
            crv = sftk_Attribute2SSecItem(NULL, &pqgParam.base, publicKey, CKA_BASE);
6401
0
            if (crv != CKR_OK) {
6402
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
6403
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
6404
0
                break;
6405
0
            }
6406
0
            crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
6407
0
                                        sftk_item_expand(&pqgParam.prime));
6408
0
            if (crv != CKR_OK) {
6409
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
6410
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
6411
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
6412
0
                break;
6413
0
            }
6414
0
            crv = sftk_AddAttributeType(privateKey, CKA_SUBPRIME,
6415
0
                                        sftk_item_expand(&pqgParam.subPrime));
6416
0
            if (crv != CKR_OK) {
6417
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
6418
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
6419
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
6420
0
                break;
6421
0
            }
6422
0
            crv = sftk_AddAttributeType(privateKey, CKA_BASE,
6423
0
                                        sftk_item_expand(&pqgParam.base));
6424
0
            if (crv != CKR_OK) {
6425
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
6426
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
6427
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
6428
0
                break;
6429
0
            }
6430
6431
            /*
6432
             * these are checked by DSA_NewKey
6433
             */
6434
0
            bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data,
6435
0
                                           pqgParam.subPrime.len);
6436
0
            if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) {
6437
0
                crv = CKR_TEMPLATE_INCOMPLETE;
6438
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
6439
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
6440
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
6441
0
                break;
6442
0
            }
6443
0
            bitSize = sftk_GetLengthInBits(pqgParam.prime.data, pqgParam.prime.len);
6444
0
            if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) {
6445
0
                crv = CKR_TEMPLATE_INCOMPLETE;
6446
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
6447
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
6448
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
6449
0
                break;
6450
0
            }
6451
0
            bitSize = sftk_GetLengthInBits(pqgParam.base.data, pqgParam.base.len);
6452
0
            if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) {
6453
0
                crv = CKR_TEMPLATE_INCOMPLETE;
6454
0
                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
6455
0
                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
6456
0
                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
6457
0
                break;
6458
0
            }
6459
6460
            /* Generate the key */
6461
0
            rv = DSA_NewKey(&pqgParam, &dsaPriv);
6462
6463
0
            SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
6464
0
            SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
6465
0
            SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
6466
6467
0
            if (rv != SECSuccess) {
6468
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
6469
0
                    sftk_fatalError = PR_TRUE;
6470
0
                }
6471
0
                crv = sftk_MapCryptError(PORT_GetError());
6472
0
                break;
6473
0
            }
6474
6475
            /* store the generated key into the attributes */
6476
0
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
6477
0
                                        sftk_item_expand(&dsaPriv->publicValue));
6478
0
            if (crv != CKR_OK)
6479
0
                goto dsagn_done;
6480
6481
            /* now fill in the RSA dependent paramenters in the private key */
6482
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
6483
0
                                        sftk_item_expand(&dsaPriv->publicValue));
6484
0
            if (crv != CKR_OK)
6485
0
                goto dsagn_done;
6486
0
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
6487
0
                                        sftk_item_expand(&dsaPriv->privateValue));
6488
6489
0
        dsagn_done:
6490
            /* should zeroize, since this function doesn't. */
6491
0
            PORT_FreeArena(dsaPriv->params.arena, PR_TRUE);
6492
0
            break;
6493
0
#endif
6494
6.83k
        case CKM_DH_PKCS_KEY_PAIR_GEN:
6495
6.83k
            sftk_DeleteAttributeType(privateKey, CKA_PRIME);
6496
6.83k
            sftk_DeleteAttributeType(privateKey, CKA_BASE);
6497
6.83k
            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
6498
6.83k
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
6499
6.83k
            key_type = CKK_DH;
6500
6501
            /* extract the necessary parameters and copy them to private keys */
6502
6.83k
            crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey,
6503
6.83k
                                          CKA_PRIME);
6504
6.83k
            if (crv != CKR_OK)
6505
0
                break;
6506
6.83k
            crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);
6507
6.83k
            if (crv != CKR_OK) {
6508
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
6509
0
                break;
6510
0
            }
6511
6.83k
            crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
6512
6.83k
                                        sftk_item_expand(&dhParam.prime));
6513
6.83k
            if (crv != CKR_OK) {
6514
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
6515
0
                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
6516
0
                break;
6517
0
            }
6518
6.83k
            crv = sftk_AddAttributeType(privateKey, CKA_BASE,
6519
6.83k
                                        sftk_item_expand(&dhParam.base));
6520
6.83k
            if (crv != CKR_OK) {
6521
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
6522
0
                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
6523
0
                break;
6524
0
            }
6525
6.83k
            bitSize = sftk_GetLengthInBits(dhParam.prime.data, dhParam.prime.len);
6526
6.83k
            if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) {
6527
0
                crv = CKR_TEMPLATE_INCOMPLETE;
6528
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
6529
0
                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
6530
0
                break;
6531
0
            }
6532
6.83k
            bitSize = sftk_GetLengthInBits(dhParam.base.data, dhParam.base.len);
6533
6.83k
            if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) {
6534
0
                crv = CKR_TEMPLATE_INCOMPLETE;
6535
0
                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
6536
0
                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
6537
0
                break;
6538
0
            }
6539
6540
6.83k
            rv = DH_NewKey(&dhParam, &dhPriv);
6541
6.83k
            SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
6542
6.83k
            SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
6543
6.83k
            if (rv != SECSuccess) {
6544
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
6545
0
                    sftk_fatalError = PR_TRUE;
6546
0
                }
6547
0
                crv = sftk_MapCryptError(PORT_GetError());
6548
0
                break;
6549
0
            }
6550
6551
6.83k
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
6552
6.83k
                                        sftk_item_expand(&dhPriv->publicValue));
6553
6.83k
            if (crv != CKR_OK)
6554
0
                goto dhgn_done;
6555
6556
6.83k
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
6557
6.83k
                                        sftk_item_expand(&dhPriv->publicValue));
6558
6.83k
            if (crv != CKR_OK)
6559
0
                goto dhgn_done;
6560
6561
6.83k
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
6562
6.83k
                                        sftk_item_expand(&dhPriv->privateValue));
6563
6564
6.83k
        dhgn_done:
6565
            /* should zeroize, since this function doesn't. */
6566
6.83k
            PORT_FreeArena(dhPriv->arena, PR_TRUE);
6567
6.83k
            break;
6568
6569
3.45k
        case CKM_EC_KEY_PAIR_GEN:
6570
75.9k
        case CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN:
6571
75.9k
            sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS);
6572
75.9k
            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
6573
75.9k
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
6574
75.9k
            key_type = CKK_EC;
6575
6576
            /* extract the necessary parameters and copy them to private keys */
6577
75.9k
            crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey,
6578
75.9k
                                          CKA_EC_PARAMS);
6579
75.9k
            if (crv != CKR_OK)
6580
0
                break;
6581
6582
75.9k
            crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS,
6583
75.9k
                                        sftk_item_expand(&ecEncodedParams));
6584
75.9k
            if (crv != CKR_OK) {
6585
0
                SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
6586
0
                break;
6587
0
            }
6588
6589
            /* Decode ec params before calling EC_NewKey */
6590
75.9k
            rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
6591
75.9k
            SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
6592
75.9k
            if (rv != SECSuccess) {
6593
422
                crv = sftk_MapCryptError(PORT_GetError());
6594
422
                break;
6595
422
            }
6596
75.4k
            rv = EC_NewKey(ecParams, &ecPriv);
6597
75.4k
            if (rv != SECSuccess) {
6598
323
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
6599
0
                    sftk_fatalError = PR_TRUE;
6600
0
                }
6601
323
                PORT_FreeArena(ecParams->arena, PR_TRUE);
6602
323
                crv = sftk_MapCryptError(PORT_GetError());
6603
323
                break;
6604
323
            }
6605
6606
75.1k
            if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") ||
6607
75.1k
                ecParams->type != ec_params_named) {
6608
18.8k
                PORT_FreeArena(ecParams->arena, PR_TRUE);
6609
18.8k
                crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
6610
18.8k
                                            sftk_item_expand(&ecPriv->publicValue));
6611
56.2k
            } else {
6612
56.2k
                PORT_FreeArena(ecParams->arena, PR_TRUE);
6613
56.2k
                SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
6614
56.2k
                                                       &ecPriv->publicValue,
6615
56.2k
                                                       SEC_ASN1_GET(SEC_OctetStringTemplate));
6616
56.2k
                if (!pubValue) {
6617
0
                    crv = CKR_ARGUMENTS_BAD;
6618
0
                    goto ecgn_done;
6619
0
                }
6620
56.2k
                crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
6621
56.2k
                                            sftk_item_expand(pubValue));
6622
56.2k
                SECITEM_ZfreeItem(pubValue, PR_TRUE);
6623
56.2k
            }
6624
75.1k
            if (crv != CKR_OK)
6625
0
                goto ecgn_done;
6626
6627
75.1k
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
6628
75.1k
                                        sftk_item_expand(&ecPriv->privateValue));
6629
75.1k
            if (crv != CKR_OK)
6630
0
                goto ecgn_done;
6631
6632
75.1k
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
6633
75.1k
                                        sftk_item_expand(&ecPriv->publicValue));
6634
75.1k
        ecgn_done:
6635
            /* should zeroize, since this function doesn't. */
6636
75.1k
            PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
6637
75.1k
            break;
6638
6639
0
#ifndef NSS_DISABLE_KYBER
6640
0
        case CKM_NSS_KYBER_KEY_PAIR_GEN:
6641
0
            key_type = CKK_NSS_KYBER;
6642
0
            goto do_ml_kem;
6643
0
#endif
6644
13.6k
        case CKM_NSS_ML_KEM_KEY_PAIR_GEN:
6645
13.6k
            key_type = CKK_NSS_ML_KEM;
6646
13.6k
            goto do_ml_kem;
6647
6648
0
        case CKM_ML_KEM_KEY_PAIR_GEN:
6649
0
            key_type = CKK_ML_KEM;
6650
6651
13.6k
        do_ml_kem:
6652
13.6k
            sftk_DeleteAttributeType(publicKey, CKA_VALUE);
6653
13.6k
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
6654
13.6k
            sftk_DeleteAttributeType(privateKey, CKA_SEED);
6655
13.6k
            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
6656
13.6k
            SECItem privKey = { siBuffer, NULL, 0 };
6657
13.6k
            SECItem pubKey = { siBuffer, NULL, 0 };
6658
13.6k
            SECItem seed = { siBuffer, NULL, 0 };
6659
13.6k
            unsigned char seedData[KYBER_KEYPAIR_COIN_BYTES];
6660
6661
            /* generate the seed here so we can record it with
6662
             * the private key */
6663
13.6k
            seed.data = seedData;
6664
13.6k
            seed.len = sizeof(seedData);
6665
13.6k
            rv = RNG_GenerateGlobalRandomBytes(seed.data, seed.len);
6666
13.6k
            if (rv != SECSuccess) {
6667
0
                fprintf(stderr, "Generate bytes failed nbytes=%d err=%d\n",
6668
0
                        seed.len, PORT_GetError());
6669
0
                crv = sftk_MapCryptError(PORT_GetError());
6670
0
                goto kyber_done;
6671
0
            }
6672
6673
13.6k
            KyberParams kyberParams = sftk_kyber_PK11ParamToInternal(genParamSet);
6674
13.6k
            if (!sftk_kyber_AllocPrivKeyItem(kyberParams, &privKey)) {
6675
0
                crv = CKR_HOST_MEMORY;
6676
0
                goto kyber_done;
6677
0
            }
6678
13.6k
            if (!sftk_kyber_AllocPubKeyItem(kyberParams, &pubKey)) {
6679
0
                crv = CKR_HOST_MEMORY;
6680
0
                goto kyber_done;
6681
0
            }
6682
13.6k
            rv = Kyber_NewKey(kyberParams, &seed, &privKey, &pubKey);
6683
13.6k
            if (rv != SECSuccess) {
6684
0
                fprintf(stderr, "Generate Kyber_NewKey failed nbytes=%d err=%d\n",
6685
0
                        seed.len, PORT_GetError());
6686
0
                crv = sftk_MapCryptError(PORT_GetError());
6687
0
                goto kyber_done;
6688
0
            }
6689
6690
13.6k
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE, sftk_item_expand(&pubKey));
6691
13.6k
            if (crv != CKR_OK) {
6692
0
                goto kyber_done;
6693
0
            }
6694
13.6k
            crv = sftk_AddAttributeType(publicKey, CKA_PARAMETER_SET,
6695
13.6k
                                        &genParamSet,
6696
13.6k
                                        sizeof(CK_ML_KEM_PARAMETER_SET_TYPE));
6697
13.6k
            if (crv != CKR_OK) {
6698
0
                goto kyber_done;
6699
0
            }
6700
13.6k
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
6701
13.6k
                                        sftk_item_expand(&privKey));
6702
13.6k
            if (crv != CKR_OK) {
6703
0
                goto kyber_done;
6704
0
            }
6705
13.6k
            crv = sftk_AddAttributeType(privateKey, CKA_SEED,
6706
13.6k
                                        sftk_item_expand(&seed));
6707
13.6k
            if (crv != CKR_OK) {
6708
0
                goto kyber_done;
6709
0
            }
6710
            /* pseudo attribute that says the seed came with the key
6711
             * so don't try to regenerate the key in handleObject.
6712
             * it will be removed before the object sees the light of
6713
             * day. */
6714
13.6k
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_SEED_OK,
6715
13.6k
                                        NULL, 0);
6716
13.6k
            if (crv != CKR_OK) {
6717
0
                goto kyber_done;
6718
0
            }
6719
13.6k
            crv = sftk_AddAttributeType(privateKey, CKA_PARAMETER_SET,
6720
13.6k
                                        &genParamSet,
6721
13.6k
                                        sizeof(CK_ML_KEM_PARAMETER_SET_TYPE));
6722
13.6k
            if (crv != CKR_OK) {
6723
0
                goto kyber_done;
6724
0
            }
6725
13.6k
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
6726
13.6k
                                        sftk_item_expand(&pubKey));
6727
13.6k
        kyber_done:
6728
13.6k
            PORT_SafeZero(seed.data, seed.len);
6729
13.6k
            SECITEM_ZfreeItem(&privKey, PR_FALSE);
6730
13.6k
            SECITEM_FreeItem(&pubKey, PR_FALSE);
6731
13.6k
            break;
6732
6733
0
        case CKM_ML_DSA_KEY_PAIR_GEN:
6734
0
            sftk_DeleteAttributeType(publicKey, CKA_VALUE);
6735
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
6736
0
            sftk_DeleteAttributeType(privateKey, CKA_SEED);
6737
0
            key_type = CKK_ML_DSA;
6738
6739
            /*
6740
             * the parameters are recognized by us
6741
             */
6742
0
            bitSize = sftk_MLDSAGetSigLen(genParamSet);
6743
0
            if (bitSize == 0) {
6744
0
                crv = CKR_TEMPLATE_INCOMPLETE;
6745
0
                break;
6746
0
            }
6747
6748
            /* Generate the key */
6749
0
            rv = MLDSA_NewKey(genParamSet, NULL, &mldsaPriv, &mldsaPub);
6750
6751
0
            if (rv != SECSuccess) {
6752
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
6753
0
                    sftk_fatalError = PR_TRUE;
6754
0
                }
6755
0
                crv = sftk_MapCryptError(PORT_GetError());
6756
0
                break;
6757
0
            }
6758
6759
            /* store the generated key into the attributes */
6760
0
            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
6761
0
                                        mldsaPub.keyVal, mldsaPub.keyValLen);
6762
0
            if (crv != CKR_OK)
6763
0
                goto mldsagn_done;
6764
0
            crv = sftk_AddAttributeType(publicKey, CKA_PARAMETER_SET,
6765
0
                                        &genParamSet, sizeof(CK_ML_DSA_PARAMETER_SET_TYPE));
6766
0
            if (crv != CKR_OK) {
6767
0
                goto mldsagn_done;
6768
0
            }
6769
6770
            /* now fill in the ML-DSA specfic paramenters in the private key */
6771
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
6772
0
                                        mldsaPub.keyVal, mldsaPub.keyValLen);
6773
0
            if (crv != CKR_OK)
6774
0
                goto mldsagn_done;
6775
6776
0
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
6777
0
                                        mldsaPriv.keyVal,
6778
0
                                        mldsaPriv.keyValLen);
6779
0
            if (crv != CKR_OK)
6780
0
                goto mldsagn_done;
6781
0
            crv = sftk_AddAttributeType(privateKey, CKA_PARAMETER_SET,
6782
0
                                        &genParamSet, sizeof(CK_ML_DSA_PARAMETER_SET_TYPE));
6783
0
            if (crv != CKR_OK) {
6784
0
                goto mldsagn_done;
6785
0
            }
6786
6787
0
            if (mldsaPriv.seedLen != 0) {
6788
0
                crv = sftk_AddAttributeType(privateKey, CKA_SEED,
6789
0
                                            mldsaPriv.seed, mldsaPriv.seedLen);
6790
0
                if (crv != CKR_OK) {
6791
0
                    goto mldsagn_done;
6792
0
                }
6793
                /* pseudo attribute that says the seed came with the key
6794
                 * so don't try to regenerate the key in handleObject.
6795
                 * it will be removed before the object sees the light of
6796
                 * day. */
6797
0
                crv = sftk_AddAttributeType(privateKey, CKA_NSS_SEED_OK,
6798
0
                                            NULL, 0);
6799
                /* it was either this or  a comment 'fall through' which would
6800
                 * be cryptic to some users */
6801
0
                if (crv != CKR_OK) {
6802
0
                    goto mldsagn_done;
6803
0
                }
6804
0
            }
6805
0
        mldsagn_done:
6806
0
            PORT_SafeZero(&mldsaPriv, sizeof(mldsaPriv));
6807
0
            PORT_SafeZero(&mldsaPub, sizeof(mldsaPub));
6808
0
            break;
6809
6810
0
        case CKM_EC_MONTGOMERY_KEY_PAIR_GEN:
6811
0
        case CKM_EC_EDWARDS_KEY_PAIR_GEN:
6812
0
            sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS);
6813
0
            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
6814
0
            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
6815
0
            key_type = (pMechanism->mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN) ? CKK_EC_EDWARDS : CKK_EC_MONTGOMERY;
6816
6817
            /* extract the necessary parameters and copy them to private keys */
6818
0
            crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey,
6819
0
                                          CKA_EC_PARAMS);
6820
0
            if (crv != CKR_OK) {
6821
0
                break;
6822
0
            }
6823
6824
0
            crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS,
6825
0
                                        sftk_item_expand(&ecEncodedParams));
6826
0
            if (crv != CKR_OK) {
6827
0
                SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
6828
0
                break;
6829
0
            }
6830
6831
            /* Decode ec params before calling EC_NewKey */
6832
0
            rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
6833
0
            SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
6834
0
            if (rv != SECSuccess) {
6835
0
                crv = sftk_MapCryptError(PORT_GetError());
6836
0
                break;
6837
0
            }
6838
6839
0
            rv = EC_NewKey(ecParams, &ecPriv);
6840
0
            if (rv != SECSuccess) {
6841
0
                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
6842
0
                    sftk_fatalError = PR_TRUE;
6843
0
                }
6844
0
                PORT_FreeArena(ecParams->arena, PR_TRUE);
6845
0
                crv = sftk_MapCryptError(PORT_GetError());
6846
0
                break;
6847
0
            }
6848
0
            PORT_FreeArena(ecParams->arena, PR_TRUE);
6849
0
            crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
6850
0
                                        sftk_item_expand(&ecPriv->publicValue));
6851
0
            if (crv != CKR_OK)
6852
0
                goto edgn_done;
6853
6854
0
            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
6855
0
                                        sftk_item_expand(&ecPriv->privateValue));
6856
0
            if (crv != CKR_OK)
6857
0
                goto edgn_done;
6858
6859
0
            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
6860
0
                                        sftk_item_expand(&ecPriv->publicValue));
6861
0
        edgn_done:
6862
            /* should zeroize, since this function doesn't. */
6863
0
            PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
6864
0
            break;
6865
6866
0
        default:
6867
0
            crv = CKR_MECHANISM_INVALID;
6868
96.4k
    }
6869
6870
96.4k
    if (crv != CKR_OK) {
6871
745
        sftk_FreeObject(privateKey);
6872
745
        sftk_FreeObject(publicKey);
6873
745
        return crv;
6874
745
    }
6875
6876
    /* Add the class, key_type The loop lets us check errors blow out
6877
     *  on errors and clean up at the bottom */
6878
95.6k
    session = NULL; /* make pedtantic happy... session cannot leave the*/
6879
                    /* loop below NULL unless an error is set... */
6880
95.6k
    do {
6881
95.6k
        crv = sftk_AddAttributeType(privateKey, CKA_CLASS, &privClass,
6882
95.6k
                                    sizeof(CK_OBJECT_CLASS));
6883
95.6k
        if (crv != CKR_OK)
6884
0
            break;
6885
95.6k
        crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &pubClass,
6886
95.6k
                                    sizeof(CK_OBJECT_CLASS));
6887
95.6k
        if (crv != CKR_OK)
6888
0
            break;
6889
95.6k
        crv = sftk_AddAttributeType(privateKey, CKA_KEY_TYPE, &key_type,
6890
95.6k
                                    sizeof(CK_KEY_TYPE));
6891
95.6k
        if (crv != CKR_OK)
6892
0
            break;
6893
95.6k
        crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &key_type,
6894
95.6k
                                    sizeof(CK_KEY_TYPE));
6895
95.6k
        if (crv != CKR_OK)
6896
0
            break;
6897
95.6k
        session = sftk_SessionFromHandle(hSession);
6898
95.6k
        if (session == NULL)
6899
0
            crv = CKR_SESSION_HANDLE_INVALID;
6900
95.6k
    } while (0);
6901
6902
95.6k
    if (crv != CKR_OK) {
6903
0
        sftk_FreeObject(privateKey);
6904
0
        sftk_FreeObject(publicKey);
6905
0
        return crv;
6906
0
    }
6907
6908
    /*
6909
     * handle the base object cleanup for the public Key
6910
     */
6911
95.6k
    crv = sftk_handleObject(privateKey, session);
6912
95.6k
    if (crv != CKR_OK) {
6913
0
        sftk_FreeSession(session);
6914
0
        sftk_FreeObject(privateKey);
6915
0
        sftk_FreeObject(publicKey);
6916
0
        return crv;
6917
0
    }
6918
6919
    /*
6920
     * handle the base object cleanup for the private Key
6921
     * If we have any problems, we destroy the public Key we've
6922
     * created and linked.
6923
     */
6924
95.6k
    crv = sftk_handleObject(publicKey, session);
6925
95.6k
    if (crv != CKR_OK) {
6926
402
        sftk_FreeSession(session);
6927
402
        sftk_FreeObject(publicKey);
6928
402
        NSC_DestroyObject(hSession, privateKey->handle);
6929
402
        sftk_FreeObject(privateKey);
6930
402
        return crv;
6931
402
    }
6932
95.2k
    if (sftk_isTrue(privateKey, CKA_SENSITIVE)) {
6933
3.35k
        crv = sftk_forceAttribute(privateKey, CKA_ALWAYS_SENSITIVE,
6934
3.35k
                                  &cktrue, sizeof(CK_BBOOL));
6935
3.35k
    }
6936
95.2k
    if (crv == CKR_OK && sftk_isTrue(publicKey, CKA_SENSITIVE)) {
6937
0
        crv = sftk_forceAttribute(publicKey, CKA_ALWAYS_SENSITIVE,
6938
0
                                  &cktrue, sizeof(CK_BBOOL));
6939
0
    }
6940
95.2k
    if (crv == CKR_OK && !sftk_isTrue(privateKey, CKA_EXTRACTABLE)) {
6941
0
        crv = sftk_forceAttribute(privateKey, CKA_NEVER_EXTRACTABLE,
6942
0
                                  &cktrue, sizeof(CK_BBOOL));
6943
0
    }
6944
95.2k
    if (crv == CKR_OK && !sftk_isTrue(publicKey, CKA_EXTRACTABLE)) {
6945
95.2k
        crv = sftk_forceAttribute(publicKey, CKA_NEVER_EXTRACTABLE,
6946
95.2k
                                  &cktrue, sizeof(CK_BBOOL));
6947
95.2k
    }
6948
6949
95.2k
    if (crv == CKR_OK &&
6950
95.2k
        pMechanism->mechanism != CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN) {
6951
        /* Perform FIPS 140-2 pairwise consistency check. */
6952
23.5k
        crv = sftk_PairwiseConsistencyCheck(hSession, slot,
6953
23.5k
                                            publicKey, privateKey, key_type);
6954
23.5k
        if (crv != CKR_OK) {
6955
0
            if (sftk_audit_enabled) {
6956
0
                char msg[128];
6957
0
                PR_snprintf(msg, sizeof msg,
6958
0
                            "C_GenerateKeyPair(hSession=0x%08lX, "
6959
0
                            "pMechanism->mechanism=0x%08lX)=0x%08lX "
6960
0
                            "self-test: pair-wise consistency test failed",
6961
0
                            (PRUint32)hSession, (PRUint32)pMechanism->mechanism,
6962
0
                            (PRUint32)crv);
6963
0
                sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg);
6964
0
            }
6965
0
        }
6966
23.5k
    }
6967
6968
95.2k
    if (crv != CKR_OK) {
6969
0
        sftk_FreeSession(session);
6970
0
        NSC_DestroyObject(hSession, publicKey->handle);
6971
0
        sftk_FreeObject(publicKey);
6972
0
        NSC_DestroyObject(hSession, privateKey->handle);
6973
0
        sftk_FreeObject(privateKey);
6974
0
        return crv;
6975
0
    }
6976
    /* we need to do this check at the end to make sure the generated key
6977
     * meets the key length requirements */
6978
95.2k
    sftk_setFIPS(privateKey, sftk_operationIsFIPS(slot, pMechanism,
6979
95.2k
                                                  CKA_NSS_GENERATE_KEY_PAIR,
6980
95.2k
                                                  privateKey, 0));
6981
95.2k
    session->lastOpWasFIPS = sftk_hasFIPS(privateKey);
6982
95.2k
    sftk_setFIPS(publicKey, session->lastOpWasFIPS);
6983
95.2k
    sftk_FreeSession(session);
6984
95.2k
    *phPrivateKey = privateKey->handle;
6985
95.2k
    *phPublicKey = publicKey->handle;
6986
95.2k
    sftk_FreeObject(publicKey);
6987
95.2k
    sftk_FreeObject(privateKey);
6988
6989
95.2k
    return CKR_OK;
6990
95.2k
}
6991
6992
static SECItem *
6993
sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp)
6994
0
{
6995
0
    NSSLOWKEYPrivateKey *lk = NULL;
6996
0
    NSSLOWKEYPrivateKeyInfo *pki = NULL;
6997
0
    SFTKAttribute *attribute = NULL;
6998
0
    PLArenaPool *arena = NULL;
6999
0
    SECOidTag algorithm = SEC_OID_UNKNOWN;
7000
0
    void *dummy, *param = NULL;
7001
0
    SECStatus rv = SECSuccess;
7002
0
    SECItem *encodedKey = NULL;
7003
#ifdef EC_DEBUG
7004
    SECItem *fordebug;
7005
#endif
7006
0
    int savelen;
7007
7008
0
    if (!key) {
7009
0
        *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */
7010
0
        return NULL;
7011
0
    }
7012
7013
0
    attribute = sftk_FindAttribute(key, CKA_KEY_TYPE);
7014
0
    if (!attribute) {
7015
0
        *crvp = CKR_KEY_TYPE_INCONSISTENT;
7016
0
        return NULL;
7017
0
    }
7018
7019
0
    lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp);
7020
0
    sftk_FreeAttribute(attribute);
7021
0
    if (!lk) {
7022
0
        return NULL;
7023
0
    }
7024
7025
0
    arena = PORT_NewArena(2048); /* XXX different size? */
7026
0
    if (!arena) {
7027
0
        *crvp = CKR_HOST_MEMORY;
7028
0
        rv = SECFailure;
7029
0
        goto loser;
7030
0
    }
7031
7032
0
    pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena,
7033
0
                                                      sizeof(NSSLOWKEYPrivateKeyInfo));
7034
0
    if (!pki) {
7035
0
        *crvp = CKR_HOST_MEMORY;
7036
0
        rv = SECFailure;
7037
0
        goto loser;
7038
0
    }
7039
0
    pki->arena = arena;
7040
7041
0
    param = NULL;
7042
0
    switch (lk->keyType) {
7043
0
        case NSSLOWKEYRSAKey:
7044
0
            prepare_low_rsa_priv_key_for_asn1(lk);
7045
0
            dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
7046
0
                                       nsslowkey_RSAPrivateKeyTemplate);
7047
7048
            /* determine RSA key type from the CKA_PUBLIC_KEY_INFO if present */
7049
0
            attribute = sftk_FindAttribute(key, CKA_PUBLIC_KEY_INFO);
7050
0
            if (attribute) {
7051
0
                NSSLOWKEYSubjectPublicKeyInfo *publicKeyInfo;
7052
0
                SECItem spki;
7053
7054
0
                spki.data = attribute->attrib.pValue;
7055
0
                spki.len = attribute->attrib.ulValueLen;
7056
7057
0
                publicKeyInfo = PORT_ArenaZAlloc(arena,
7058
0
                                                 sizeof(NSSLOWKEYSubjectPublicKeyInfo));
7059
0
                if (!publicKeyInfo) {
7060
0
                    sftk_FreeAttribute(attribute);
7061
0
                    *crvp = CKR_HOST_MEMORY;
7062
0
                    rv = SECFailure;
7063
0
                    goto loser;
7064
0
                }
7065
0
                rv = SEC_QuickDERDecodeItem(arena, publicKeyInfo,
7066
0
                                            nsslowkey_SubjectPublicKeyInfoTemplate,
7067
0
                                            &spki);
7068
0
                if (rv != SECSuccess) {
7069
0
                    sftk_FreeAttribute(attribute);
7070
0
                    *crvp = CKR_KEY_TYPE_INCONSISTENT;
7071
0
                    goto loser;
7072
0
                }
7073
0
                algorithm = SECOID_GetAlgorithmTag(&publicKeyInfo->algorithm);
7074
0
                if (algorithm != SEC_OID_PKCS1_RSA_ENCRYPTION &&
7075
0
                    algorithm != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
7076
0
                    sftk_FreeAttribute(attribute);
7077
0
                    rv = SECFailure;
7078
0
                    *crvp = CKR_KEY_TYPE_INCONSISTENT;
7079
0
                    goto loser;
7080
0
                }
7081
0
                param = SECITEM_DupItem(&publicKeyInfo->algorithm.parameters);
7082
0
                if (!param) {
7083
0
                    sftk_FreeAttribute(attribute);
7084
0
                    rv = SECFailure;
7085
0
                    *crvp = CKR_HOST_MEMORY;
7086
0
                    goto loser;
7087
0
                }
7088
0
                sftk_FreeAttribute(attribute);
7089
0
            } else {
7090
                /* default to PKCS #1 */
7091
0
                algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
7092
0
            }
7093
0
            break;
7094
0
        case NSSLOWKEYDSAKey:
7095
0
            prepare_low_dsa_priv_key_export_for_asn1(lk);
7096
0
            dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
7097
0
                                       nsslowkey_DSAPrivateKeyExportTemplate);
7098
0
            prepare_low_pqg_params_for_asn1(&lk->u.dsa.params);
7099
0
            param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params),
7100
0
                                       nsslowkey_PQGParamsTemplate);
7101
0
            algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE;
7102
0
            break;
7103
0
        case NSSLOWKEYECKey:
7104
0
            prepare_low_ec_priv_key_for_asn1(lk);
7105
            /* Public value is encoded as a bit string so adjust length
7106
             * to be in bits before ASN encoding and readjust
7107
             * immediately after.
7108
             *
7109
             * Since the SECG specification recommends not including the
7110
             * parameters as part of ECPrivateKey, we zero out the curveOID
7111
             * length before encoding and restore it later.
7112
             */
7113
0
            lk->u.ec.publicValue.len <<= 3;
7114
0
            savelen = lk->u.ec.ecParams.curveOID.len;
7115
0
            lk->u.ec.ecParams.curveOID.len = 0;
7116
0
            dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
7117
0
                                       nsslowkey_ECPrivateKeyTemplate);
7118
0
            lk->u.ec.ecParams.curveOID.len = savelen;
7119
0
            lk->u.ec.publicValue.len >>= 3;
7120
7121
#ifdef EC_DEBUG
7122
            fordebug = &pki->privateKey;
7123
            SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType,
7124
                      fordebug);
7125
#endif
7126
7127
0
            param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding);
7128
7129
0
            algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
7130
0
            break;
7131
0
        case NSSLOWKEYMLKEMKey: {
7132
0
            SECItem seed = { siBuffer, NULL, 0 };
7133
0
            SECItem rawKey = { siBuffer, NULL, 0 };
7134
0
            dummy = NULL;
7135
7136
0
            switch (lk->u.mlkem.mlkemParams) {
7137
0
                case params_ml_kem768:
7138
0
                case params_ml_kem768_test_mode:
7139
0
                    algorithm = SEC_OID_ML_KEM_768;
7140
0
                    break;
7141
0
                case params_ml_kem1024:
7142
0
                case params_ml_kem1024_test_mode:
7143
0
                    algorithm = SEC_OID_ML_KEM_1024;
7144
0
                    break;
7145
0
                default:
7146
0
                    algorithm = SEC_OID_UNKNOWN;
7147
0
                    break;
7148
0
            }
7149
0
            if (algorithm == SEC_OID_UNKNOWN) {
7150
0
                break;
7151
0
            }
7152
            /* save the seed and key items before they are overwritten */
7153
0
            if (lk->u.mlkem.seed.len != 0) {
7154
0
                seed = lk->u.mlkem.seed;
7155
0
            }
7156
0
            rawKey = lk->u.mlkem.key;
7157
0
            if (lk == key->objectInfo) {
7158
                /* we have a cached key, and we are about to
7159
                 * overwrite it, let's get a duplicate first */
7160
0
                lk = nsslowkey_CopyPrivateKey(lk);
7161
0
                if (lk == NULL) {
7162
0
                    break;
7163
0
                }
7164
0
            }
7165
            /* this overwrites the mlkem data, but we don't need it any
7166
             * more because we are discarding lk once we encode. This
7167
             * allows us to use the same template for mlkem and mldsa
7168
             * (and presumably other pq algorithms, though mlfn and mlshl
7169
             * don't have additional seeds) */
7170
0
            lk->u.genpq.seedItem = seed;
7171
0
            lk->u.genpq.keyItem = rawKey;
7172
0
            if (seed.len) {
7173
0
                dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
7174
0
                                           nsslowkey_PQBothSeedAndPrivateKeyTemplate);
7175
0
            } else {
7176
0
                dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
7177
0
                                           nsslowkey_PQPrivateKeyTemplate);
7178
0
            }
7179
0
        } break;
7180
0
        case NSSLOWKEYMLDSAKey: {
7181
0
            SECItem seed = { siBuffer, NULL, 0 };
7182
0
            SECItem keyVal = { siBuffer, NULL, 0 };
7183
0
            dummy = NULL;
7184
7185
            /* paramSet sets the algorithm */
7186
0
            switch (lk->u.mldsa.paramSet) {
7187
0
                case CKP_ML_DSA_44:
7188
0
                    algorithm = SEC_OID_ML_DSA_44_PUBLIC_KEY;
7189
0
                    break;
7190
0
                case CKP_ML_DSA_65:
7191
0
                    algorithm = SEC_OID_ML_DSA_65_PUBLIC_KEY;
7192
0
                    break;
7193
0
                case CKP_ML_DSA_87:
7194
0
                    algorithm = SEC_OID_ML_DSA_87_PUBLIC_KEY;
7195
0
                    break;
7196
0
                default:
7197
0
                    algorithm = SEC_OID_UNKNOWN;
7198
0
                    break;
7199
0
            }
7200
0
            if (algorithm == SEC_OID_UNKNOWN) {
7201
0
                break;
7202
0
            }
7203
7204
            /* if we have the seed, copy it */
7205
0
            if (lk->u.mldsa.seedLen != 0) {
7206
0
                rv = SECITEM_MakeItem(arena, &seed, lk->u.mldsa.seed,
7207
0
                                      lk->u.mldsa.seedLen);
7208
0
                if (rv != SECSuccess) {
7209
0
                    break;
7210
0
                }
7211
0
            }
7212
0
            rv = SECITEM_MakeItem(arena, &keyVal, lk->u.mldsa.keyVal,
7213
0
                                  lk->u.mldsa.keyValLen);
7214
0
            if (rv != SECSuccess) {
7215
0
                break;
7216
0
            }
7217
0
            if (lk == key->objectInfo) {
7218
                /* we have a cached key, and we are about to
7219
                 * overwrite it, let's get a duplicate first */
7220
0
                lk = nsslowkey_CopyPrivateKey(lk);
7221
0
                if (lk == NULL) {
7222
0
                    break;
7223
0
                }
7224
0
            }
7225
            /* this overwrites the mldsa data, but we don't need it any
7226
             * more because we are discarding lk once we encode */
7227
0
            lk->u.genpq.seedItem = seed;
7228
0
            lk->u.genpq.keyItem = keyVal;
7229
7230
0
            if (seed.len) {
7231
0
                dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
7232
0
                                           nsslowkey_PQBothSeedAndPrivateKeyTemplate);
7233
0
            } else {
7234
0
                dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
7235
0
                                           nsslowkey_PQPrivateKeyTemplate);
7236
0
            }
7237
0
        } break;
7238
7239
0
        case NSSLOWKEYDHKey:
7240
0
        default:
7241
0
            dummy = NULL;
7242
0
            break;
7243
0
    }
7244
7245
0
    if (!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) {
7246
0
        *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
7247
0
        rv = SECFailure;
7248
0
        goto loser;
7249
0
    }
7250
7251
0
    rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm,
7252
0
                               (SECItem *)param);
7253
0
    if (rv != SECSuccess) {
7254
0
        *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
7255
0
        rv = SECFailure;
7256
0
        goto loser;
7257
0
    }
7258
7259
0
    dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
7260
0
                                  NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
7261
0
    if (!dummy) {
7262
0
        *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
7263
0
        rv = SECFailure;
7264
0
        goto loser;
7265
0
    }
7266
7267
0
    encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki,
7268
0
                                    nsslowkey_PrivateKeyInfoTemplate);
7269
0
    *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR;
7270
7271
#ifdef EC_DEBUG
7272
    fordebug = encodedKey;
7273
    SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType,
7274
              fordebug);
7275
#endif
7276
0
loser:
7277
0
    if (arena) {
7278
0
        PORT_FreeArena(arena, PR_TRUE);
7279
0
    }
7280
7281
0
    if (lk && (lk != key->objectInfo)) {
7282
0
        nsslowkey_DestroyPrivateKey(lk);
7283
0
    }
7284
7285
0
    if (param) {
7286
0
        SECITEM_ZfreeItem((SECItem *)param, PR_TRUE);
7287
0
    }
7288
7289
0
    if (rv != SECSuccess) {
7290
0
        return NULL;
7291
0
    }
7292
7293
0
    return encodedKey;
7294
0
}
7295
7296
/* it doesn't matter yet, since we colapse error conditions in the
7297
 * level above, but we really should map those few key error differences */
7298
static CK_RV
7299
sftk_mapWrap(CK_RV crv)
7300
110k
{
7301
110k
    switch (crv) {
7302
0
        case CKR_ENCRYPTED_DATA_INVALID:
7303
0
            crv = CKR_WRAPPED_KEY_INVALID;
7304
0
            break;
7305
110k
    }
7306
110k
    return crv;
7307
110k
}
7308
7309
/* NSC_WrapKey wraps (i.e., encrypts) a key. */
7310
CK_RV
7311
NSC_WrapKey(CK_SESSION_HANDLE hSession,
7312
            CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
7313
            CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
7314
            CK_ULONG_PTR pulWrappedKeyLen)
7315
71.0k
{
7316
71.0k
    SFTKSession *session;
7317
71.0k
    SFTKAttribute *attribute;
7318
71.0k
    SFTKObject *key;
7319
71.0k
    CK_RV crv;
7320
7321
71.0k
    CHECK_FORK();
7322
7323
71.0k
    session = sftk_SessionFromHandle(hSession);
7324
71.0k
    if (session == NULL) {
7325
0
        return CKR_SESSION_HANDLE_INVALID;
7326
0
    }
7327
7328
71.0k
    key = sftk_ObjectFromHandle(hKey, session);
7329
71.0k
    if (key == NULL) {
7330
0
        sftk_FreeSession(session);
7331
0
        return CKR_KEY_HANDLE_INVALID;
7332
0
    }
7333
7334
71.0k
    switch (key->objclass) {
7335
71.0k
        case CKO_SECRET_KEY: {
7336
71.0k
            SFTKSessionContext *context = NULL;
7337
71.0k
            SECItem pText;
7338
7339
71.0k
            attribute = sftk_FindAttribute(key, CKA_VALUE);
7340
7341
71.0k
            if (attribute == NULL) {
7342
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
7343
0
                break;
7344
0
            }
7345
71.0k
            crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
7346
71.0k
                                 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
7347
71.0k
            if (crv != CKR_OK) {
7348
40
                sftk_FreeAttribute(attribute);
7349
40
                break;
7350
40
            }
7351
7352
71.0k
            pText.type = siBuffer;
7353
71.0k
            pText.data = (unsigned char *)attribute->attrib.pValue;
7354
71.0k
            pText.len = attribute->attrib.ulValueLen;
7355
7356
            /* Find out if this is a block cipher. The context was just
7357
             * installed by sftk_CryptInit above, so we already hold a
7358
             * session reference and the context's type is SFTK_ENCRYPT
7359
             * by construction. */
7360
71.0k
            context = sftk_ReturnContextByType(session, SFTK_ENCRYPT);
7361
71.0k
            if (!context) {
7362
0
                sftk_FreeAttribute(attribute);
7363
0
                crv = CKR_OPERATION_NOT_INITIALIZED;
7364
0
                break;
7365
0
            }
7366
71.0k
            if (context->blockSize > 1) {
7367
55.4k
                unsigned int remainder = pText.len % context->blockSize;
7368
55.4k
                if (!context->doPad && remainder) {
7369
                    /* When wrapping secret keys with unpadded block ciphers,
7370
                    ** the keys are zero padded, if necessary, to fill out
7371
                    ** a full block.
7372
                    */
7373
0
                    pText.len += context->blockSize - remainder;
7374
0
                    pText.data = PORT_ZAlloc(pText.len);
7375
0
                    if (pText.data)
7376
0
                        memcpy(pText.data, attribute->attrib.pValue,
7377
0
                               attribute->attrib.ulValueLen);
7378
0
                    else {
7379
0
                        sftk_FreeAttribute(attribute);
7380
0
                        crv = CKR_HOST_MEMORY;
7381
0
                        break;
7382
0
                    }
7383
0
                }
7384
55.4k
            }
7385
7386
71.0k
            crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data,
7387
71.0k
                              pText.len, pWrappedKey, pulWrappedKeyLen);
7388
            /* always force a finalize, both on errors and when
7389
             * we are just getting the size */
7390
71.0k
            if (crv != CKR_OK || pWrappedKey == NULL) {
7391
0
                sftk_UninstallContext(session, SFTK_ENCRYPT);
7392
0
            }
7393
7394
71.0k
            if (pText.data != (unsigned char *)attribute->attrib.pValue)
7395
0
                PORT_ZFree(pText.data, pText.len);
7396
71.0k
            sftk_FreeAttribute(attribute);
7397
71.0k
            break;
7398
71.0k
        }
7399
7400
0
        case CKO_PRIVATE_KEY: {
7401
0
            SECItem *bpki = sftk_PackagePrivateKey(key, &crv);
7402
7403
0
            if (!bpki) {
7404
0
                break;
7405
0
            }
7406
7407
0
            crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
7408
0
                                 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
7409
0
            if (crv != CKR_OK) {
7410
0
                SECITEM_ZfreeItem(bpki, PR_TRUE);
7411
0
                crv = CKR_KEY_TYPE_INCONSISTENT;
7412
0
                break;
7413
0
            }
7414
7415
0
            crv = NSC_Encrypt(hSession, bpki->data, bpki->len,
7416
0
                              pWrappedKey, pulWrappedKeyLen);
7417
            /* always force a finalize */
7418
0
            if (crv != CKR_OK || pWrappedKey == NULL) {
7419
0
                sftk_UninstallContext(session, SFTK_ENCRYPT);
7420
0
            }
7421
0
            SECITEM_ZfreeItem(bpki, PR_TRUE);
7422
0
            break;
7423
0
        }
7424
7425
0
        default:
7426
0
            crv = CKR_KEY_TYPE_INCONSISTENT;
7427
0
            break;
7428
71.0k
    }
7429
71.0k
    sftk_FreeObject(key);
7430
71.0k
    sftk_FreeSession(session);
7431
71.0k
    return sftk_mapWrap(crv);
7432
71.0k
}
7433
7434
/*
7435
 * import a pprivate key info into the desired slot
7436
 */
7437
static SECStatus
7438
sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki)
7439
0
{
7440
0
    CK_BBOOL cktrue = CK_TRUE;
7441
0
    CK_BBOOL ckfalse = CK_FALSE;
7442
0
    CK_KEY_TYPE keyType = CKK_RSA;
7443
0
    SECStatus rv = SECFailure;
7444
0
    const SEC_ASN1Template *keyTemplate, *paramTemplate;
7445
0
    void *paramDest = NULL;
7446
0
    PLArenaPool *arena;
7447
0
    NSSLOWKEYPrivateKey *lpk = NULL;
7448
0
    NSSLOWKEYPrivateKeyInfo *pki = NULL;
7449
0
    CK_RV crv = CKR_KEY_TYPE_INCONSISTENT;
7450
0
    CK_ULONG paramSet = 0;
7451
7452
0
    arena = PORT_NewArena(2048);
7453
0
    if (!arena) {
7454
0
        return SECFailure;
7455
0
    }
7456
7457
0
    pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena,
7458
0
                                                      sizeof(NSSLOWKEYPrivateKeyInfo));
7459
0
    if (!pki) {
7460
0
        PORT_FreeArena(arena, PR_FALSE);
7461
0
        return SECFailure;
7462
0
    }
7463
7464
0
    if (SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) != SECSuccess) {
7465
0
        PORT_FreeArena(arena, PR_TRUE);
7466
0
        return SECFailure;
7467
0
    }
7468
7469
0
    lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena,
7470
0
                                                  sizeof(NSSLOWKEYPrivateKey));
7471
0
    if (lpk == NULL) {
7472
0
        goto loser;
7473
0
    }
7474
0
    lpk->arena = arena;
7475
7476
0
    switch (SECOID_GetAlgorithmTag(&pki->algorithm)) {
7477
0
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
7478
0
        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
7479
0
            keyTemplate = nsslowkey_RSAPrivateKeyTemplate;
7480
0
            paramTemplate = NULL;
7481
0
            paramDest = NULL;
7482
0
            lpk->keyType = NSSLOWKEYRSAKey;
7483
0
            prepare_low_rsa_priv_key_for_asn1(lpk);
7484
0
            break;
7485
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
7486
0
            keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate;
7487
0
            paramTemplate = nsslowkey_PQGParamsTemplate;
7488
0
            paramDest = &(lpk->u.dsa.params);
7489
0
            lpk->keyType = NSSLOWKEYDSAKey;
7490
0
            prepare_low_dsa_priv_key_export_for_asn1(lpk);
7491
0
            prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params);
7492
0
            break;
7493
        /* case NSSLOWKEYDHKey: */
7494
0
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
7495
0
            keyTemplate = nsslowkey_ECPrivateKeyTemplate;
7496
0
            paramTemplate = NULL;
7497
0
            paramDest = &(lpk->u.ec.ecParams.DEREncoding);
7498
0
            lpk->keyType = NSSLOWKEYECKey;
7499
0
            prepare_low_ec_priv_key_for_asn1(lpk);
7500
0
            prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams);
7501
0
            break;
7502
0
        case SEC_OID_ML_KEM_768:
7503
0
            paramSet = CKP_ML_KEM_768;
7504
0
            goto mlkem_next;
7505
0
        case SEC_OID_ML_KEM_1024:
7506
0
            paramSet = CKP_ML_KEM_1024;
7507
0
        mlkem_next:
7508
0
            lpk->keyType = NSSLOWKEYMLKEMKey;
7509
0
            goto pq_next;
7510
0
        case SEC_OID_ML_DSA_44_PUBLIC_KEY:
7511
0
            paramSet = CKP_ML_DSA_44;
7512
0
            goto mldsa_next;
7513
0
        case SEC_OID_ML_DSA_65_PUBLIC_KEY:
7514
0
            paramSet = CKP_ML_DSA_65;
7515
0
            goto mldsa_next;
7516
0
        case SEC_OID_ML_DSA_87_PUBLIC_KEY:
7517
0
            paramSet = CKP_ML_DSA_87;
7518
0
        mldsa_next:
7519
0
            lpk->keyType = NSSLOWKEYMLDSAKey;
7520
0
        pq_next:
7521
0
            if (pki->privateKey.data == NULL || pki->privateKey.len == 0) {
7522
0
                PORT_SetError(SEC_ERROR_BAD_KEY);
7523
0
                goto loser;
7524
0
            }
7525
0
            switch (pki->privateKey.data[0]) {
7526
0
                case SEC_ASN1_CONTEXT_SPECIFIC | 0:
7527
0
                    keyTemplate = nsslowkey_PQSeedTemplate;
7528
0
                    break;
7529
0
                case SEC_ASN1_OCTET_STRING:
7530
0
                    keyTemplate = nsslowkey_PQPrivateKeyTemplate;
7531
0
                    break;
7532
0
                case SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE:
7533
0
                    keyTemplate = nsslowkey_PQBothSeedAndPrivateKeyTemplate;
7534
0
                    break;
7535
0
                default:
7536
0
                    keyTemplate = NULL;
7537
0
                    break;
7538
0
            }
7539
7540
0
            paramTemplate = NULL;
7541
0
            paramDest = NULL;
7542
            /* genpq encodes ocect, not integer, so no need to prep it */
7543
0
            break;
7544
0
        default:
7545
0
            keyTemplate = NULL;
7546
0
            paramTemplate = NULL;
7547
0
            paramDest = NULL;
7548
0
            break;
7549
0
    }
7550
7551
0
    if (!keyTemplate) {
7552
0
        goto loser;
7553
0
    }
7554
7555
    /* decode the private key and any algorithm parameters */
7556
0
    rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
7557
7558
0
    if (lpk->keyType == NSSLOWKEYECKey) {
7559
        /* convert length in bits to length in bytes */
7560
0
        lpk->u.ec.publicValue.len >>= 3;
7561
0
        rv = SECITEM_CopyItem(arena,
7562
0
                              &(lpk->u.ec.ecParams.DEREncoding),
7563
0
                              &(pki->algorithm.parameters));
7564
0
        if (rv != SECSuccess) {
7565
0
            goto loser;
7566
0
        }
7567
0
    }
7568
7569
0
    if (rv != SECSuccess) {
7570
0
        goto loser;
7571
0
    }
7572
0
    if (paramDest && paramTemplate) {
7573
0
        rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate,
7574
0
                                    &(pki->algorithm.parameters));
7575
0
        if (rv != SECSuccess) {
7576
0
            goto loser;
7577
0
        }
7578
0
    }
7579
7580
0
    rv = SECFailure;
7581
7582
0
    switch (lpk->keyType) {
7583
0
        case NSSLOWKEYRSAKey:
7584
0
            keyType = CKK_RSA;
7585
0
            if (sftk_hasAttribute(key, CKA_NSS_DB)) {
7586
0
                sftk_DeleteAttributeType(key, CKA_NSS_DB);
7587
0
            }
7588
0
            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
7589
0
                                        sizeof(keyType));
7590
0
            if (crv != CKR_OK)
7591
0
                break;
7592
0
            crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue,
7593
0
                                        sizeof(CK_BBOOL));
7594
0
            if (crv != CKR_OK)
7595
0
                break;
7596
0
            crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue,
7597
0
                                        sizeof(CK_BBOOL));
7598
0
            if (crv != CKR_OK)
7599
0
                break;
7600
0
            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
7601
0
                                        sizeof(CK_BBOOL));
7602
0
            if (crv != CKR_OK)
7603
0
                break;
7604
0
            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
7605
0
                                        sizeof(CK_BBOOL));
7606
0
            if (crv != CKR_OK)
7607
0
                break;
7608
0
            crv = sftk_AddAttributeType(key, CKA_MODULUS,
7609
0
                                        sftk_item_expand(&lpk->u.rsa.modulus));
7610
0
            if (crv != CKR_OK)
7611
0
                break;
7612
0
            crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT,
7613
0
                                        sftk_item_expand(&lpk->u.rsa.publicExponent));
7614
0
            if (crv != CKR_OK)
7615
0
                break;
7616
0
            crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT,
7617
0
                                        sftk_item_expand(&lpk->u.rsa.privateExponent));
7618
0
            if (crv != CKR_OK)
7619
0
                break;
7620
0
            crv = sftk_AddAttributeType(key, CKA_PRIME_1,
7621
0
                                        sftk_item_expand(&lpk->u.rsa.prime1));
7622
0
            if (crv != CKR_OK)
7623
0
                break;
7624
0
            crv = sftk_AddAttributeType(key, CKA_PRIME_2,
7625
0
                                        sftk_item_expand(&lpk->u.rsa.prime2));
7626
0
            if (crv != CKR_OK)
7627
0
                break;
7628
0
            crv = sftk_AddAttributeType(key, CKA_EXPONENT_1,
7629
0
                                        sftk_item_expand(&lpk->u.rsa.exponent1));
7630
0
            if (crv != CKR_OK)
7631
0
                break;
7632
0
            crv = sftk_AddAttributeType(key, CKA_EXPONENT_2,
7633
0
                                        sftk_item_expand(&lpk->u.rsa.exponent2));
7634
0
            if (crv != CKR_OK)
7635
0
                break;
7636
0
            crv = sftk_AddAttributeType(key, CKA_COEFFICIENT,
7637
0
                                        sftk_item_expand(&lpk->u.rsa.coefficient));
7638
0
            break;
7639
0
        case NSSLOWKEYDSAKey:
7640
0
            keyType = CKK_DSA;
7641
0
            crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
7642
0
            if (crv != CKR_OK)
7643
0
                break;
7644
0
            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
7645
0
                                        sizeof(keyType));
7646
0
            if (crv != CKR_OK)
7647
0
                break;
7648
0
            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
7649
0
                                        sizeof(CK_BBOOL));
7650
0
            if (crv != CKR_OK)
7651
0
                break;
7652
0
            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &ckfalse,
7653
0
                                        sizeof(CK_BBOOL));
7654
0
            if (crv != CKR_OK)
7655
0
                break;
7656
0
            crv = sftk_AddAttributeType(key, CKA_PRIME,
7657
0
                                        sftk_item_expand(&lpk->u.dsa.params.prime));
7658
0
            if (crv != CKR_OK)
7659
0
                break;
7660
0
            crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
7661
0
                                        sftk_item_expand(&lpk->u.dsa.params.subPrime));
7662
0
            if (crv != CKR_OK)
7663
0
                break;
7664
0
            crv = sftk_AddAttributeType(key, CKA_BASE,
7665
0
                                        sftk_item_expand(&lpk->u.dsa.params.base));
7666
0
            if (crv != CKR_OK)
7667
0
                break;
7668
0
            crv = sftk_AddAttributeType(key, CKA_VALUE,
7669
0
                                        sftk_item_expand(&lpk->u.dsa.privateValue));
7670
0
            if (crv != CKR_OK)
7671
0
                break;
7672
0
            break;
7673
0
        case NSSLOWKEYMLKEMKey:
7674
0
            keyType = CKK_ML_KEM;
7675
0
            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
7676
0
                                        sizeof(keyType));
7677
0
            if (crv != CKR_OK)
7678
0
                break;
7679
0
            crv = sftk_AddAttributeType(key, CKA_DECAPSULATE, &cktrue,
7680
0
                                        sizeof(CK_BBOOL));
7681
0
            if (crv != CKR_OK)
7682
0
                break;
7683
0
            crv = sftk_AddAttributeType(key, CKA_PARAMETER_SET, &paramSet,
7684
0
                                        sizeof(CK_ML_KEM_PARAMETER_SET_TYPE));
7685
0
            if (crv != CKR_OK)
7686
0
                break;
7687
0
            if (lpk->u.genpq.seedItem.len != 0) {
7688
0
                crv = sftk_AddAttributeType(key, CKA_SEED,
7689
0
                                            sftk_item_expand(&lpk->u.genpq.seedItem));
7690
0
                if (crv != CKR_OK)
7691
0
                    break;
7692
0
            }
7693
7694
            /* if we were given just the seed, we'll regenerate the key
7695
             * from the seed in handleObject */
7696
0
            if (lpk->u.genpq.keyItem.len != 0) {
7697
0
                crv = sftk_AddAttributeType(key, CKA_VALUE,
7698
0
                                            sftk_item_expand(&lpk->u.genpq.keyItem));
7699
                /* I know,  this is redundant, but it would be too easy
7700
                 * for someone to add another sftk_AddAttributeType after
7701
                 * this without adding this check back because of the if */
7702
0
                if (crv != CKR_OK)
7703
0
                    break;
7704
0
            }
7705
0
            break;
7706
0
        case NSSLOWKEYMLDSAKey:
7707
0
            keyType = CKK_ML_DSA;
7708
0
            crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
7709
0
            if (crv != CKR_OK)
7710
0
                break;
7711
0
            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
7712
0
                                        sizeof(keyType));
7713
0
            if (crv != CKR_OK)
7714
0
                break;
7715
0
            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
7716
0
                                        sizeof(CK_BBOOL));
7717
0
            if (crv != CKR_OK)
7718
0
                break;
7719
0
            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &ckfalse,
7720
0
                                        sizeof(CK_BBOOL));
7721
0
            if (crv != CKR_OK)
7722
0
                break;
7723
0
            crv = sftk_AddAttributeType(key, CKA_PARAMETER_SET, &paramSet,
7724
0
                                        sizeof(CK_ML_DSA_PARAMETER_SET_TYPE));
7725
0
            if (crv != CKR_OK)
7726
0
                break;
7727
0
            if (lpk->u.genpq.seedItem.len != 0) {
7728
0
                crv = sftk_AddAttributeType(key, CKA_SEED,
7729
0
                                            sftk_item_expand(&lpk->u.genpq.seedItem));
7730
0
                if (crv != CKR_OK)
7731
0
                    break;
7732
0
            }
7733
7734
            /* if we were given just the seed, we'll regenerate the key
7735
             * from the seed in handleObject */
7736
0
            if (lpk->u.genpq.keyItem.len != 0) {
7737
0
                crv = sftk_AddAttributeType(key, CKA_VALUE,
7738
0
                                            sftk_item_expand(&lpk->u.genpq.keyItem));
7739
                /* I know,  this is redundant, but it would be too easy
7740
                 * for someone to add another sftk_AddAttributeType after
7741
                 * this without adding this check back because of the if */
7742
0
                if (crv != CKR_OK)
7743
0
                    break;
7744
0
            }
7745
0
            break;
7746
#ifdef notdef
7747
        case NSSLOWKEYDHKey:
7748
            template = dhTemplate;
7749
            templateCount = sizeof(dhTemplate) / sizeof(CK_ATTRIBUTE);
7750
            keyType = CKK_DH;
7751
            break;
7752
#endif
7753
        /* what about fortezza??? */
7754
0
        case NSSLOWKEYECKey:
7755
0
            keyType = CKK_EC;
7756
            /* if we weren't passed the CKA_NSS_DB, get it
7757
             * from the public key */
7758
0
            if (!sftk_hasAttribute(key, CKA_NSS_DB)) {
7759
0
                if (lpk->u.ec.publicValue.len == 0) {
7760
0
                    crv = CKR_KEY_TYPE_INCONSISTENT;
7761
0
                    goto loser;
7762
0
                }
7763
0
                crv = sftk_AddAttributeType(key, CKA_NSS_DB,
7764
0
                                            sftk_item_expand(&lpk->u.ec.publicValue));
7765
0
                if (crv != CKR_OK) {
7766
0
                    goto loser;
7767
0
                }
7768
0
            }
7769
0
            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
7770
0
                                        sizeof(keyType));
7771
0
            if (crv != CKR_OK)
7772
0
                break;
7773
0
            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
7774
0
                                        sizeof(CK_BBOOL));
7775
0
            if (crv != CKR_OK)
7776
0
                break;
7777
0
            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &ckfalse,
7778
0
                                        sizeof(CK_BBOOL));
7779
0
            if (crv != CKR_OK)
7780
0
                break;
7781
0
            crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue,
7782
0
                                        sizeof(CK_BBOOL));
7783
0
            if (crv != CKR_OK)
7784
0
                break;
7785
0
            crv = sftk_AddAttributeType(key, CKA_EC_PARAMS,
7786
0
                                        sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding));
7787
0
            if (crv != CKR_OK)
7788
0
                break;
7789
0
            crv = sftk_AddAttributeType(key, CKA_VALUE,
7790
0
                                        sftk_item_expand(&lpk->u.ec.privateValue));
7791
0
            if (crv != CKR_OK)
7792
0
                break;
7793
            /* XXX Do we need to decode the EC Params here ?? */
7794
0
            break;
7795
0
        default:
7796
0
            crv = CKR_KEY_TYPE_INCONSISTENT;
7797
0
            break;
7798
0
    }
7799
7800
0
    if (crv != CKR_OK) {
7801
0
        goto loser;
7802
0
    }
7803
7804
    /* For RSA-PSS, record the original algorithm parameters so
7805
     * they can be encrypted altoghether when wrapping */
7806
0
    if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
7807
0
        NSSLOWKEYSubjectPublicKeyInfo spki;
7808
0
        NSSLOWKEYPublicKey pubk;
7809
0
        SECItem *publicKeyInfo;
7810
7811
0
        memset(&spki, 0, sizeof(NSSLOWKEYSubjectPublicKeyInfo));
7812
0
        rv = SECOID_CopyAlgorithmID(arena, &spki.algorithm, &pki->algorithm);
7813
0
        if (rv != SECSuccess) {
7814
0
            crv = CKR_HOST_MEMORY;
7815
0
            goto loser;
7816
0
        }
7817
7818
0
        prepare_low_rsa_pub_key_for_asn1(&pubk);
7819
7820
0
        rv = SECITEM_CopyItem(arena, &pubk.u.rsa.modulus, &lpk->u.rsa.modulus);
7821
0
        if (rv != SECSuccess) {
7822
0
            crv = CKR_HOST_MEMORY;
7823
0
            goto loser;
7824
0
        }
7825
0
        rv = SECITEM_CopyItem(arena, &pubk.u.rsa.publicExponent, &lpk->u.rsa.publicExponent);
7826
0
        if (rv != SECSuccess) {
7827
0
            crv = CKR_HOST_MEMORY;
7828
0
            goto loser;
7829
0
        }
7830
0
        pubk.u.rsa.needVerify = PR_FALSE; /* We're just encoding the key from the
7831
                                           * private key */
7832
7833
0
        if (SEC_ASN1EncodeItem(arena, &spki.subjectPublicKey,
7834
0
                               &pubk, nsslowkey_RSAPublicKeyTemplate) == NULL) {
7835
0
            crv = CKR_HOST_MEMORY;
7836
0
            goto loser;
7837
0
        }
7838
7839
0
        publicKeyInfo = SEC_ASN1EncodeItem(arena, NULL,
7840
0
                                           &spki, nsslowkey_SubjectPublicKeyInfoTemplate);
7841
0
        if (!publicKeyInfo) {
7842
0
            crv = CKR_HOST_MEMORY;
7843
0
            goto loser;
7844
0
        }
7845
0
        crv = sftk_AddAttributeType(key, CKA_PUBLIC_KEY_INFO,
7846
0
                                    sftk_item_expand(publicKeyInfo));
7847
0
    }
7848
7849
0
loser:
7850
0
    if (lpk) {
7851
0
        nsslowkey_DestroyPrivateKey(lpk);
7852
0
    }
7853
7854
0
    if (crv != CKR_OK) {
7855
0
        return SECFailure;
7856
0
    }
7857
7858
0
    return SECSuccess;
7859
0
}
7860
7861
/* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
7862
CK_RV
7863
NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
7864
              CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
7865
              CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
7866
              CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
7867
              CK_OBJECT_HANDLE_PTR phKey)
7868
43.3k
{
7869
43.3k
    SFTKObject *key = NULL;
7870
43.3k
    SFTKSession *session;
7871
43.3k
    CK_ULONG key_length = 0;
7872
43.3k
    unsigned char *buf = NULL;
7873
43.3k
    CK_RV crv = CKR_OK;
7874
43.3k
    int i;
7875
43.3k
    CK_ULONG bsize = ulWrappedKeyLen;
7876
43.3k
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
7877
43.3k
    SECItem bpki;
7878
43.3k
    CK_OBJECT_CLASS target_type = CKO_SECRET_KEY;
7879
7880
43.3k
    CHECK_FORK();
7881
7882
43.3k
    if (!slot) {
7883
0
        return CKR_SESSION_HANDLE_INVALID;
7884
0
    }
7885
    /*
7886
     * now lets create an object to hang the attributes off of
7887
     */
7888
43.3k
    key = sftk_NewObject(slot); /* fill in the handle later */
7889
43.3k
    if (key == NULL) {
7890
0
        return CKR_HOST_MEMORY;
7891
0
    }
7892
7893
    /*
7894
     * load the template values into the object
7895
     */
7896
173k
    for (i = 0; i < (int)ulAttributeCount; i++) {
7897
130k
        if (pTemplate[i].type == CKA_VALUE_LEN) {
7898
0
            key_length = *(CK_ULONG *)pTemplate[i].pValue;
7899
0
            continue;
7900
0
        }
7901
130k
        if (pTemplate[i].type == CKA_CLASS) {
7902
43.3k
            target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
7903
43.3k
        }
7904
130k
        crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
7905
130k
        if (crv != CKR_OK)
7906
0
            break;
7907
130k
    }
7908
43.3k
    if (crv != CKR_OK) {
7909
0
        sftk_FreeObject(key);
7910
0
        return crv;
7911
0
    }
7912
7913
43.3k
    crv = sftk_CryptInit(hSession, pMechanism, hUnwrappingKey, CKA_UNWRAP,
7914
43.3k
                         CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE);
7915
43.3k
    if (crv != CKR_OK) {
7916
0
        sftk_FreeObject(key);
7917
0
        return sftk_mapWrap(crv);
7918
0
    }
7919
7920
    /* allocate the buffer to decrypt into
7921
     * this assumes the unwrapped key is never larger than the
7922
     * wrapped key. For all the mechanisms we support this is true */
7923
43.3k
    buf = (unsigned char *)PORT_Alloc(ulWrappedKeyLen);
7924
43.3k
    bsize = ulWrappedKeyLen;
7925
7926
43.3k
    crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize);
7927
43.3k
    if (crv != CKR_OK) {
7928
39.3k
        sftk_FreeObject(key);
7929
39.3k
        PORT_Free(buf);
7930
39.3k
        return sftk_mapWrap(crv);
7931
39.3k
    }
7932
7933
4.04k
    switch (target_type) {
7934
4.04k
        case CKO_SECRET_KEY:
7935
4.04k
            if (!sftk_hasAttribute(key, CKA_KEY_TYPE)) {
7936
0
                crv = CKR_TEMPLATE_INCOMPLETE;
7937
0
                break;
7938
0
            }
7939
7940
4.04k
            if (key_length == 0 || key_length > bsize) {
7941
4.04k
                key_length = bsize;
7942
4.04k
            }
7943
4.04k
            if (key_length > MAX_KEY_LEN) {
7944
0
                crv = CKR_TEMPLATE_INCONSISTENT;
7945
0
                break;
7946
0
            }
7947
7948
            /* add the value */
7949
4.04k
            crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length);
7950
4.04k
            break;
7951
0
        case CKO_PRIVATE_KEY:
7952
0
            bpki.data = (unsigned char *)buf;
7953
0
            bpki.len = bsize;
7954
0
            crv = CKR_OK;
7955
0
            if (sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) {
7956
0
                crv = CKR_TEMPLATE_INCOMPLETE;
7957
0
            }
7958
0
            break;
7959
0
        default:
7960
0
            crv = CKR_TEMPLATE_INCONSISTENT;
7961
0
            break;
7962
4.04k
    }
7963
7964
4.04k
    PORT_ZFree(buf, bsize);
7965
4.04k
    if (crv != CKR_OK) {
7966
0
        sftk_FreeObject(key);
7967
0
        return crv;
7968
0
    }
7969
7970
    /* get the session */
7971
4.04k
    session = sftk_SessionFromHandle(hSession);
7972
4.04k
    if (session == NULL) {
7973
0
        sftk_FreeObject(key);
7974
0
        return CKR_SESSION_HANDLE_INVALID;
7975
0
    }
7976
7977
    /* mark the key as FIPS if the previous operation was all FIPS */
7978
4.04k
    sftk_setFIPS(key, session->lastOpWasFIPS);
7979
    /*
7980
     * handle the base object stuff
7981
     */
7982
4.04k
    crv = sftk_handleObject(key, session);
7983
4.04k
    *phKey = key->handle;
7984
4.04k
    sftk_FreeSession(session);
7985
4.04k
    sftk_FreeObject(key);
7986
7987
4.04k
    return crv;
7988
4.04k
}
7989
7990
CK_RV
7991
NSC_WrapKeyAuthenticated(CK_SESSION_HANDLE hSession,
7992
                         CK_MECHANISM_PTR pMechanism,
7993
                         CK_OBJECT_HANDLE hWrappingKey,
7994
                         CK_OBJECT_HANDLE hKey,
7995
                         CK_BYTE_PTR pAssociatedData,
7996
                         CK_ULONG ulAssociatedDataLen,
7997
                         CK_BYTE_PTR pWrappedKey,
7998
                         CK_ULONG_PTR pulWrappedKeyLen)
7999
0
{
8000
0
    CHECK_FORK();
8001
8002
0
    return CKR_FUNCTION_NOT_SUPPORTED;
8003
0
}
8004
8005
CK_RV
8006
NSC_UnwrapKeyAuthenticated(CK_SESSION_HANDLE hSession,
8007
                           CK_MECHANISM_PTR pMechanism,
8008
                           CK_OBJECT_HANDLE hUnwrappingKey,
8009
                           CK_BYTE_PTR pWrappedKey,
8010
                           CK_ULONG ulWrappedKeyLen,
8011
                           CK_ATTRIBUTE_PTR pTemplate,
8012
                           CK_ULONG ulAttributeCount,
8013
                           CK_BYTE_PTR pAssociatedData,
8014
                           CK_ULONG ulAssociatedDataLen,
8015
                           CK_OBJECT_HANDLE_PTR phKey)
8016
0
{
8017
0
    CHECK_FORK();
8018
8019
0
    return CKR_FUNCTION_NOT_SUPPORTED;
8020
0
}
8021
8022
/*
8023
 * The SSL key gen mechanism create's lots of keys. This function handles the
8024
 * details of each of these key creation.
8025
 */
8026
static CK_RV
8027
sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey,
8028
                 PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize,
8029
                 CK_OBJECT_HANDLE *keyHandle)
8030
420k
{
8031
420k
    SFTKObject *key;
8032
420k
    SFTKSession *session;
8033
420k
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
8034
420k
    CK_BBOOL cktrue = CK_TRUE;
8035
420k
    CK_BBOOL ckfalse = CK_FALSE;
8036
420k
    CK_RV crv = CKR_HOST_MEMORY;
8037
8038
    /*
8039
     * now lets create an object to hang the attributes off of
8040
     */
8041
420k
    *keyHandle = CK_INVALID_HANDLE;
8042
420k
    key = sftk_NewObject(baseKey->slot);
8043
420k
    if (key == NULL)
8044
0
        return CKR_HOST_MEMORY;
8045
420k
    SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
8046
420k
    PORT_Assert(sessKey);
8047
420k
    sessKey->wasDerived = PR_TRUE;
8048
8049
420k
    crv = sftk_CopyObject(key, baseKey);
8050
420k
    if (crv != CKR_OK)
8051
0
        goto loser;
8052
420k
    if (isMacKey) {
8053
224k
        crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType));
8054
224k
        if (crv != CKR_OK)
8055
0
            goto loser;
8056
224k
        crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
8057
224k
        if (crv != CKR_OK)
8058
0
            goto loser;
8059
224k
        crv = sftk_forceAttribute(key, CKA_ENCRYPT, &ckfalse, sizeof(CK_BBOOL));
8060
224k
        if (crv != CKR_OK)
8061
0
            goto loser;
8062
224k
        crv = sftk_forceAttribute(key, CKA_DECRYPT, &ckfalse, sizeof(CK_BBOOL));
8063
224k
        if (crv != CKR_OK)
8064
0
            goto loser;
8065
224k
        crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
8066
224k
        if (crv != CKR_OK)
8067
0
            goto loser;
8068
224k
        crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
8069
224k
        if (crv != CKR_OK)
8070
0
            goto loser;
8071
224k
        crv = sftk_forceAttribute(key, CKA_WRAP, &ckfalse, sizeof(CK_BBOOL));
8072
224k
        if (crv != CKR_OK)
8073
0
            goto loser;
8074
224k
        crv = sftk_forceAttribute(key, CKA_UNWRAP, &ckfalse, sizeof(CK_BBOOL));
8075
224k
        if (crv != CKR_OK)
8076
0
            goto loser;
8077
224k
    }
8078
420k
    crv = sftk_forceAttribute(key, CKA_VALUE, keyBlock, keySize);
8079
420k
    if (crv != CKR_OK)
8080
0
        goto loser;
8081
8082
    /* get the session */
8083
420k
    crv = CKR_HOST_MEMORY;
8084
420k
    session = sftk_SessionFromHandle(hSession);
8085
420k
    if (session == NULL) {
8086
0
        goto loser;
8087
0
    }
8088
8089
420k
    crv = sftk_handleObject(key, session);
8090
420k
    sftk_FreeSession(session);
8091
420k
    *keyHandle = key->handle;
8092
420k
loser:
8093
420k
    if (key)
8094
420k
        sftk_FreeObject(key);
8095
420k
    return crv;
8096
420k
}
8097
8098
/*
8099
 * if there is an error, we need to free the keys we already created in SSL
8100
 * This is the routine that will do it..
8101
 */
8102
static void
8103
sftk_freeSSLKeys(CK_SESSION_HANDLE session,
8104
                 CK_SSL3_KEY_MAT_OUT *returnedMaterial)
8105
0
{
8106
0
    if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) {
8107
0
        NSC_DestroyObject(session, returnedMaterial->hClientMacSecret);
8108
0
    }
8109
0
    if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) {
8110
0
        NSC_DestroyObject(session, returnedMaterial->hServerMacSecret);
8111
0
    }
8112
0
    if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) {
8113
0
        NSC_DestroyObject(session, returnedMaterial->hClientKey);
8114
0
    }
8115
0
    if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) {
8116
0
        NSC_DestroyObject(session, returnedMaterial->hServerKey);
8117
0
    }
8118
0
}
8119
8120
/*
8121
 * when deriving from sensitive and extractable keys, we need to preserve some
8122
 * of the semantics in the derived key. This helper routine maintains these
8123
 * semantics.
8124
 */
8125
static CK_RV
8126
sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey,
8127
                          PRBool canBeData)
8128
580k
{
8129
580k
    PRBool hasSensitive;
8130
580k
    PRBool sensitive = PR_FALSE;
8131
580k
    CK_BBOOL bFalse = CK_FALSE;
8132
580k
    PRBool hasExtractable;
8133
580k
    PRBool extractable = PR_TRUE;
8134
580k
    CK_BBOOL bTrue = CK_TRUE;
8135
580k
    CK_RV crv = CKR_OK;
8136
580k
    SFTKAttribute *att;
8137
580k
    PRBool isData = PR_TRUE;
8138
8139
580k
    if (canBeData) {
8140
460k
        CK_OBJECT_CLASS objClass;
8141
8142
        /* if the target key is actually data, don't set the unexpected
8143
         * attributes */
8144
460k
        crv = sftk_GetULongAttribute(destKey, CKA_CLASS, &objClass);
8145
460k
        if (crv != CKR_OK) {
8146
0
            return crv;
8147
0
        }
8148
460k
        if (objClass == CKO_DATA) {
8149
134k
            return CKR_OK;
8150
134k
        }
8151
8152
        /* if the base key is data, it doesn't have sensitive attributes,
8153
         * allow the destKey to get it's own */
8154
325k
        crv = sftk_GetULongAttribute(baseKey, CKA_CLASS, &objClass);
8155
325k
        if (crv != CKR_OK) {
8156
0
            return crv;
8157
0
        }
8158
325k
        if (objClass == CKO_DATA) {
8159
10.7k
            isData = PR_TRUE;
8160
10.7k
        }
8161
325k
    }
8162
8163
446k
    hasSensitive = PR_FALSE;
8164
446k
    att = sftk_FindAttribute(destKey, CKA_SENSITIVE);
8165
446k
    if (att) {
8166
0
        hasSensitive = PR_TRUE;
8167
0
        sensitive = (PRBool) * (CK_BBOOL *)att->attrib.pValue;
8168
0
        sftk_FreeAttribute(att);
8169
0
    }
8170
8171
446k
    hasExtractable = PR_FALSE;
8172
446k
    att = sftk_FindAttribute(destKey, CKA_EXTRACTABLE);
8173
446k
    if (att) {
8174
0
        hasExtractable = PR_TRUE;
8175
0
        extractable = (PRBool) * (CK_BBOOL *)att->attrib.pValue;
8176
0
        sftk_FreeAttribute(att);
8177
0
    }
8178
8179
    /* don't make a key more accessible */
8180
446k
    if (sftk_isTrue(baseKey, CKA_SENSITIVE) && hasSensitive &&
8181
0
        (sensitive == PR_FALSE)) {
8182
0
        return CKR_KEY_FUNCTION_NOT_PERMITTED;
8183
0
    }
8184
446k
    if (!sftk_isTrue(baseKey, CKA_EXTRACTABLE) && hasExtractable &&
8185
0
        (extractable == PR_TRUE)) {
8186
0
        return CKR_KEY_FUNCTION_NOT_PERMITTED;
8187
0
    }
8188
8189
    /* inherit parent's sensitivity */
8190
446k
    if (!hasSensitive) {
8191
446k
        att = sftk_FindAttribute(baseKey, CKA_SENSITIVE);
8192
446k
        if (att != NULL) {
8193
431k
            crv = sftk_defaultAttribute(destKey,
8194
431k
                                        sftk_attr_expand(&att->attrib));
8195
431k
            sftk_FreeAttribute(att);
8196
431k
        } else if (isData) {
8197
14.0k
            crv = sftk_defaultAttribute(destKey, CKA_SENSITIVE,
8198
14.0k
                                        &bFalse, sizeof(bFalse));
8199
14.0k
        } else {
8200
0
            return CKR_KEY_TYPE_INCONSISTENT;
8201
0
        }
8202
446k
        if (crv != CKR_OK)
8203
0
            return crv;
8204
446k
    }
8205
446k
    if (!hasExtractable) {
8206
446k
        att = sftk_FindAttribute(baseKey, CKA_EXTRACTABLE);
8207
446k
        if (att != NULL) {
8208
431k
            crv = sftk_defaultAttribute(destKey,
8209
431k
                                        sftk_attr_expand(&att->attrib));
8210
431k
            sftk_FreeAttribute(att);
8211
431k
        } else if (isData) {
8212
14.0k
            crv = sftk_defaultAttribute(destKey, CKA_EXTRACTABLE,
8213
14.0k
                                        &bTrue, sizeof(bTrue));
8214
14.0k
        } else {
8215
0
            return CKR_KEY_TYPE_INCONSISTENT;
8216
0
        }
8217
446k
        if (crv != CKR_OK)
8218
0
            return crv;
8219
446k
    }
8220
8221
    /* we should inherit the parent's always extractable/ never sensitive info,
8222
     * but handleObject always forces this attributes, so we would need to do
8223
     * something special. */
8224
446k
    return CKR_OK;
8225
446k
}
8226
8227
/*
8228
 * make known fixed PKCS #11 key types to their sizes in bytes
8229
 */
8230
unsigned long
8231
sftk_MapKeySize(CK_KEY_TYPE keyType)
8232
252k
{
8233
252k
    switch (keyType) {
8234
3
        case CKK_CDMF:
8235
3
            return 8;
8236
12.0k
        case CKK_DES:
8237
12.0k
            return 8;
8238
0
        case CKK_DES2:
8239
0
            return 16;
8240
22.9k
        case CKK_DES3:
8241
22.9k
            return 24;
8242
        /* IDEA and CAST need to be added */
8243
217k
        default:
8244
217k
            break;
8245
252k
    }
8246
217k
    return 0;
8247
252k
}
8248
8249
/* Inputs:
8250
 *  key_len: Length of derived key to be generated.
8251
 *  SharedSecret: a shared secret that is the output of a key agreement primitive.
8252
 *  SharedInfo: (Optional) some data shared by the entities computing the secret key.
8253
 *  SharedInfoLen: the length in octets of SharedInfo
8254
 *  Hash: The hash function to be used in the KDF
8255
 *  HashLen: the length in octets of the output of Hash
8256
 * Output:
8257
 *  key: Pointer to a buffer containing derived key, if return value is SECSuccess.
8258
 */
8259
static CK_RV
8260
sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret,
8261
                            CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
8262
                            SECStatus Hash(unsigned char *, const unsigned char *, PRUint32),
8263
                            CK_ULONG HashLen)
8264
9
{
8265
9
    unsigned char *buffer = NULL, *output_buffer = NULL;
8266
9
    PRUint32 buffer_len, max_counter, i;
8267
9
    SECStatus rv;
8268
9
    CK_RV crv;
8269
8270
    /* Check that key_len isn't too long.  The maximum key length could be
8271
     * greatly increased if the code below did not limit the 4-byte counter
8272
     * to a maximum value of 255. */
8273
9
    if (key_len > 254 * HashLen)
8274
0
        return CKR_ARGUMENTS_BAD;
8275
8276
9
    if (SharedInfo == NULL)
8277
9
        SharedInfoLen = 0;
8278
8279
9
    if (SharedSecret->len > PR_UINT32_MAX - 4 ||
8280
9
        SharedInfoLen > PR_UINT32_MAX - 4 - SharedSecret->len)
8281
0
        return CKR_ARGUMENTS_BAD;
8282
8283
9
    buffer_len = SharedSecret->len + 4 + SharedInfoLen;
8284
9
    buffer = (CK_BYTE *)PORT_Alloc(buffer_len);
8285
9
    if (buffer == NULL) {
8286
0
        crv = CKR_HOST_MEMORY;
8287
0
        goto loser;
8288
0
    }
8289
8290
9
    max_counter = key_len / HashLen;
8291
9
    if (key_len > max_counter * HashLen)
8292
6
        max_counter++;
8293
8294
9
    output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen);
8295
9
    if (output_buffer == NULL) {
8296
0
        crv = CKR_HOST_MEMORY;
8297
0
        goto loser;
8298
0
    }
8299
8300
    /* Populate buffer with SharedSecret || Counter || [SharedInfo]
8301
     * where Counter is 0x00000001 */
8302
9
    PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len);
8303
9
    buffer[SharedSecret->len] = 0;
8304
9
    buffer[SharedSecret->len + 1] = 0;
8305
9
    buffer[SharedSecret->len + 2] = 0;
8306
9
    buffer[SharedSecret->len + 3] = 1;
8307
9
    if (SharedInfo) {
8308
0
        PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen);
8309
0
    }
8310
8311
21
    for (i = 0; i < max_counter; i++) {
8312
12
        rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len);
8313
12
        if (rv != SECSuccess) {
8314
            /* 'Hash' should not fail. */
8315
0
            crv = CKR_FUNCTION_FAILED;
8316
0
            goto loser;
8317
0
        }
8318
8319
        /* Increment counter (assumes max_counter < 255) */
8320
12
        buffer[SharedSecret->len + 3]++;
8321
12
    }
8322
8323
9
    PORT_ZFree(buffer, buffer_len);
8324
9
    if (key_len < max_counter * HashLen) {
8325
6
        PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len);
8326
6
    }
8327
9
    *key = output_buffer;
8328
8329
9
    return CKR_OK;
8330
8331
0
loser:
8332
0
    if (buffer) {
8333
0
        PORT_ZFree(buffer, buffer_len);
8334
0
    }
8335
0
    if (output_buffer) {
8336
0
        PORT_ZFree(output_buffer, max_counter * HashLen);
8337
0
    }
8338
0
    return crv;
8339
9
}
8340
8341
static CK_RV
8342
sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len,
8343
                    SECItem *SharedSecret,
8344
                    CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
8345
                    CK_EC_KDF_TYPE kdf)
8346
9
{
8347
9
    if (kdf == CKD_SHA1_KDF)
8348
3
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
8349
3
                                           SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH);
8350
6
    else if (kdf == CKD_SHA224_KDF)
8351
0
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
8352
0
                                           SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH);
8353
6
    else if (kdf == CKD_SHA256_KDF)
8354
3
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
8355
3
                                           SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH);
8356
3
    else if (kdf == CKD_SHA384_KDF)
8357
1
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
8358
1
                                           SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH);
8359
2
    else if (kdf == CKD_SHA512_KDF)
8360
2
        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
8361
2
                                           SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH);
8362
0
    else
8363
0
        return CKR_MECHANISM_INVALID;
8364
9
}
8365
8366
/*
8367
 *  Handle the derive from a block encryption cipher
8368
 */
8369
CK_RV
8370
sftk_DeriveEncrypt(SFTKCipher encrypt, void *cipherInfo,
8371
                   int blockSize, SFTKObject *key, CK_ULONG keySize,
8372
                   unsigned char *data, CK_ULONG len)
8373
0
{
8374
    /* large enough for a 512-bit key */
8375
0
    unsigned char tmpdata[SFTK_MAX_DERIVE_KEY_SIZE];
8376
0
    SECStatus rv;
8377
0
    unsigned int outLen;
8378
0
    CK_RV crv;
8379
8380
0
    if ((len % blockSize) != 0) {
8381
0
        return CKR_MECHANISM_PARAM_INVALID;
8382
0
    }
8383
0
    if (len > SFTK_MAX_DERIVE_KEY_SIZE) {
8384
0
        return CKR_MECHANISM_PARAM_INVALID;
8385
0
    }
8386
0
    if (keySize && (len < keySize)) {
8387
0
        return CKR_MECHANISM_PARAM_INVALID;
8388
0
    }
8389
0
    if (keySize == 0) {
8390
0
        keySize = len;
8391
0
    }
8392
8393
0
    rv = (*encrypt)(cipherInfo, (unsigned char *)&tmpdata, &outLen, len, data, len);
8394
0
    if (rv != SECSuccess) {
8395
0
        crv = sftk_MapCryptError(PORT_GetError());
8396
0
        return crv;
8397
0
    }
8398
8399
0
    crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize);
8400
0
    PORT_Memset(tmpdata, 0, sizeof tmpdata);
8401
0
    return crv;
8402
0
}
8403
8404
CK_RV
8405
sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession,
8406
          SFTKObject *sourceKey, const unsigned char *sourceKeyBytes,
8407
          int sourceKeyLen, SFTKObject *key, unsigned char *outKeyBytes,
8408
          int keySize, PRBool canBeData, PRBool isFIPS)
8409
460k
{
8410
460k
    SFTKSession *session;
8411
460k
    SFTKAttribute *saltKey_att = NULL;
8412
460k
    const SECHashObject *rawHash;
8413
460k
    unsigned hashLen;
8414
460k
    unsigned genLen = 0;
8415
460k
    unsigned char hashbuf[HASH_LENGTH_MAX];
8416
460k
    unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH];
8417
460k
    unsigned char *keyBlockAlloc = NULL;    /* allocated keyBlock */
8418
460k
    unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */
8419
460k
    const unsigned char *prk;               /* psuedo-random key */
8420
460k
    CK_ULONG prkLen;
8421
460k
    const unsigned char *okm; /* output keying material */
8422
460k
    HASH_HashType hashType = sftk_GetHashTypeFromMechanism(params->prfHashMechanism);
8423
460k
    SFTKObject *saltKey = NULL;
8424
460k
    CK_RV crv = CKR_OK;
8425
8426
    /* Spec says it should be the base hash, but also accept the HMAC */
8427
460k
    if (hashType == HASH_AlgNULL) {
8428
0
        hashType = sftk_HMACMechanismToHash(params->prfHashMechanism);
8429
0
    }
8430
460k
    rawHash = HASH_GetRawHashObject(hashType);
8431
460k
    if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) {
8432
0
        return CKR_MECHANISM_INVALID;
8433
0
    }
8434
460k
    hashLen = rawHash->length;
8435
8436
460k
    if ((!params->bExpand && !params->bExtract) ||
8437
460k
        (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) ||
8438
460k
        (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) {
8439
0
        return CKR_MECHANISM_PARAM_INVALID;
8440
0
    }
8441
460k
    if ((params->bExpand && keySize == 0) ||
8442
460k
        (!params->bExpand && keySize > hashLen) ||
8443
460k
        (params->bExpand && keySize > 255 * hashLen)) {
8444
138
        return CKR_TEMPLATE_INCONSISTENT;
8445
138
    }
8446
8447
460k
    if (!params->bExpand) {
8448
36.0k
        keySize = hashLen;
8449
36.0k
    }
8450
8451
    /* sourceKey is NULL if we are called from the POST, skip the
8452
     * sensitiveCheck */
8453
460k
    if (sourceKey != NULL) {
8454
460k
        crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData);
8455
460k
        if (crv != CKR_OK)
8456
0
            return crv;
8457
        /* if the source key is data, clear the FIPS flag
8458
         * and only get the FIPS state from the salt */
8459
460k
        if (sourceKey->objclass == CKO_DATA) {
8460
17.4k
            sftk_setFIPS(key, PR_FALSE);
8461
17.4k
        }
8462
460k
    }
8463
8464
    /* HKDF-Extract(salt, base key value) */
8465
460k
    if (params->bExtract) {
8466
36.4k
        CK_BYTE *salt;
8467
36.4k
        CK_ULONG saltLen;
8468
36.4k
        HMACContext *hmac;
8469
36.4k
        unsigned int bufLen;
8470
36.4k
        SFTKSource saltKeySource = SFTK_SOURCE_DEFAULT;
8471
8472
36.4k
        switch (params->ulSaltType) {
8473
17.1k
            case CKF_HKDF_SALT_NULL:
8474
17.1k
                saltLen = hashLen;
8475
17.1k
                salt = hashbuf;
8476
17.1k
                memset(salt, 0, saltLen);
8477
17.1k
                break;
8478
5.79k
            case CKF_HKDF_SALT_DATA:
8479
5.79k
                salt = params->pSalt;
8480
5.79k
                saltLen = params->ulSaltLen;
8481
5.79k
                if ((salt == NULL) || (params->ulSaltLen == 0)) {
8482
0
                    return CKR_MECHANISM_PARAM_INVALID;
8483
0
                }
8484
5.79k
                break;
8485
13.4k
            case CKF_HKDF_SALT_KEY:
8486
                /* lookup key */
8487
13.4k
                session = sftk_SessionFromHandle(hSession);
8488
13.4k
                if (session == NULL) {
8489
0
                    return CKR_SESSION_HANDLE_INVALID;
8490
0
                }
8491
8492
13.4k
                saltKey = sftk_ObjectFromHandle(params->hSaltKey, session);
8493
13.4k
                sftk_FreeSession(session);
8494
13.4k
                if (saltKey == NULL) {
8495
0
                    return CKR_KEY_HANDLE_INVALID;
8496
0
                }
8497
                /* if the base key is not fips, but the salt key is, the
8498
                 * resulting key can be fips */
8499
13.4k
                if (isFIPS && !sftk_hasFIPS(key) && sftk_hasFIPS(saltKey)) {
8500
0
                    CK_MECHANISM mech;
8501
0
                    mech.mechanism = CKM_HKDF_DERIVE;
8502
0
                    mech.pParameter = params;
8503
0
                    mech.ulParameterLen = sizeof(*params);
8504
0
                    sftk_setFIPS(key, sftk_operationIsFIPS(saltKey->slot,
8505
0
                                                           &mech, CKA_DERIVE,
8506
0
                                                           saltKey,
8507
0
                                                           keySize * PR_BITS_PER_BYTE));
8508
0
                }
8509
13.4k
                saltKeySource = saltKey->source;
8510
13.4k
                saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE);
8511
13.4k
                if (saltKey_att == NULL) {
8512
0
                    sftk_FreeObject(saltKey);
8513
0
                    return CKR_KEY_HANDLE_INVALID;
8514
0
                }
8515
                /* save the resulting salt */
8516
13.4k
                salt = saltKey_att->attrib.pValue;
8517
13.4k
                saltLen = saltKey_att->attrib.ulValueLen;
8518
13.4k
                break;
8519
0
            default:
8520
0
                return CKR_MECHANISM_PARAM_INVALID;
8521
0
                break;
8522
36.4k
        }
8523
        /* only TLS style usage is FIPS approved,
8524
         * turn off the FIPS indicator for other usages */
8525
36.4k
        if (isFIPS && key && sourceKey) {
8526
0
            PRBool fipsOK = PR_FALSE;
8527
            /* case one: mix the kea with a previous or default
8528
             * salt */
8529
0
            if ((sourceKey->source == SFTK_SOURCE_KEA) &&
8530
0
                (saltKeySource == SFTK_SOURCE_HKDF_EXPAND) &&
8531
0
                (saltLen == rawHash->length)) {
8532
0
                fipsOK = PR_TRUE;
8533
0
            }
8534
            /* case two: restart, remix the previous secret as a salt */
8535
0
            if ((sourceKey->objclass == CKO_DATA) &&
8536
0
                (NSS_SecureMemcmpZero(sourceKeyBytes, sourceKeyLen) == 0) &&
8537
0
                (sourceKeyLen == rawHash->length) &&
8538
0
                (saltKeySource == SFTK_SOURCE_HKDF_EXPAND) &&
8539
0
                (saltLen == rawHash->length)) {
8540
0
                fipsOK = PR_TRUE;
8541
0
            }
8542
0
            if (!fipsOK) {
8543
0
                sftk_setFIPS(key, PR_FALSE);
8544
0
            }
8545
0
        }
8546
36.4k
        if (key)
8547
36.4k
            key->source = SFTK_SOURCE_HKDF_EXTRACT;
8548
8549
36.4k
        hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
8550
36.4k
        if (saltKey_att) {
8551
13.4k
            sftk_FreeAttribute(saltKey_att);
8552
13.4k
        }
8553
36.4k
        if (saltKey) {
8554
13.4k
            sftk_FreeObject(saltKey);
8555
13.4k
        }
8556
36.4k
        if (!hmac) {
8557
0
            return CKR_HOST_MEMORY;
8558
0
        }
8559
36.4k
        HMAC_Begin(hmac);
8560
36.4k
        HMAC_Update(hmac, sourceKeyBytes, sourceKeyLen);
8561
36.4k
        HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf));
8562
36.4k
        HMAC_Destroy(hmac, PR_TRUE);
8563
36.4k
        PORT_Assert(bufLen == rawHash->length);
8564
36.4k
        prk = hashbuf;
8565
36.4k
        prkLen = bufLen;
8566
424k
    } else {
8567
        /* PRK = base key value */
8568
424k
        prk = sourceKeyBytes;
8569
424k
        prkLen = sourceKeyLen;
8570
424k
    }
8571
8572
    /* HKDF-Expand */
8573
460k
    if (!params->bExpand) {
8574
36.0k
        okm = prk;
8575
36.0k
        genLen = hashLen;
8576
424k
    } else {
8577
        /* T(1) = HMAC-Hash(prk, "" | info | 0x01)
8578
         * T(n) = HMAC-Hash(prk, T(n-1) | info | n
8579
         * key material = T(1) | ... | T(n)
8580
         */
8581
424k
        HMACContext *hmac;
8582
424k
        CK_BYTE bi;
8583
424k
        unsigned iterations;
8584
8585
        /* only TLS style usage is FIPS approved,
8586
         * turn off the FIPS indicator for other usages */
8587
424k
        if (isFIPS && key && sftk_hasFIPS(key) && sourceKey) {
8588
            /* only one case,
8589
             *  1) Expand only
8590
             *  2) with a key whose source was
8591
             *  SFTK_SOURCE_HKDF_EXPAND or SFTK_SOURCE_HKDF_EXTRACT
8592
             *  3) source key length == rawHash->length
8593
             *  4) Info has tls or dtls
8594
             * If any of those conditions aren't met, then we turn
8595
             * off the fips indicator */
8596
0
            if (params->bExtract ||
8597
0
                ((sourceKey->source != SFTK_SOURCE_HKDF_EXTRACT) &&
8598
0
                 (sourceKey->source != SFTK_SOURCE_HKDF_EXPAND)) ||
8599
0
                (sourceKeyLen != rawHash->length) ||
8600
0
                (params->ulInfoLen < 7) ||
8601
0
                ((PORT_Memcmp(&params->pInfo[3], "tls", 3) != 0) &&
8602
0
                 (PORT_Memcmp(&params->pInfo[3], "dtls", 4) != 0))) {
8603
0
                sftk_setFIPS(key, PR_FALSE);
8604
0
            }
8605
0
        }
8606
424k
        if (key)
8607
424k
            key->source = SFTK_SOURCE_HKDF_EXPAND;
8608
8609
424k
        genLen = PR_ROUNDUP(keySize, hashLen);
8610
424k
        iterations = genLen / hashLen;
8611
8612
424k
        if (genLen > sizeof(keyBlock)) {
8613
260
            keyBlockAlloc = PORT_Alloc(genLen);
8614
260
            if (keyBlockAlloc == NULL) {
8615
0
                return CKR_HOST_MEMORY;
8616
0
            }
8617
260
            keyBlockData = keyBlockAlloc;
8618
260
        }
8619
424k
        hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS);
8620
424k
        if (hmac == NULL) {
8621
0
            PORT_Free(keyBlockAlloc);
8622
0
            return CKR_HOST_MEMORY;
8623
0
        }
8624
902k
        for (bi = 1; bi <= iterations && bi > 0; ++bi) {
8625
477k
            unsigned len;
8626
477k
            HMAC_Begin(hmac);
8627
477k
            if (bi > 1) {
8628
53.0k
                HMAC_Update(hmac, &keyBlockData[(bi - 2) * hashLen], hashLen);
8629
53.0k
            }
8630
477k
            if (params->ulInfoLen != 0) {
8631
437k
                HMAC_Update(hmac, params->pInfo, params->ulInfoLen);
8632
437k
            }
8633
477k
            HMAC_Update(hmac, &bi, 1);
8634
477k
            HMAC_Finish(hmac, &keyBlockData[(bi - 1) * hashLen], &len,
8635
477k
                        hashLen);
8636
477k
            PORT_Assert(len == hashLen);
8637
477k
        }
8638
424k
        HMAC_Destroy(hmac, PR_TRUE);
8639
424k
        okm = &keyBlockData[0];
8640
424k
    }
8641
    /* key material = okm */
8642
460k
    crv = CKR_OK;
8643
460k
    if (key) {
8644
460k
        crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize);
8645
460k
    } else {
8646
0
        PORT_Assert(outKeyBytes != NULL);
8647
0
        PORT_Memcpy(outKeyBytes, okm, keySize);
8648
0
    }
8649
460k
    PORT_Memset(keyBlockData, 0, genLen);
8650
460k
    PORT_Memset(hashbuf, 0, sizeof(hashbuf));
8651
460k
    PORT_Free(keyBlockAlloc);
8652
460k
    return crv;
8653
460k
}
8654
8655
/*
8656
 * SSL Key generation given pre master secret
8657
 */
8658
0
#define NUM_MIXERS 9
8659
static const char *const mixers[NUM_MIXERS] = {
8660
    "A",
8661
    "BB",
8662
    "CCC",
8663
    "DDDD",
8664
    "EEEEE",
8665
    "FFFFFF",
8666
    "GGGGGGG",
8667
    "HHHHHHHH",
8668
    "IIIIIIIII"
8669
};
8670
102k
#define SSL3_PMS_LENGTH 48
8671
416k
#define SSL3_MASTER_SECRET_LENGTH 48
8672
1.05M
#define SSL3_RANDOM_LENGTH 32
8673
8674
/* NSC_DeriveKey derives a key from a base key, creating a new key object. */
8675
CK_RV
8676
NSC_DeriveKey(CK_SESSION_HANDLE hSession,
8677
              CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
8678
              CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
8679
              CK_OBJECT_HANDLE_PTR phKey)
8680
802k
{
8681
802k
    SFTKSession *session;
8682
802k
    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
8683
802k
    SFTKObject *key;
8684
802k
    SFTKObject *sourceKey;
8685
802k
    SFTKAttribute *att = NULL;
8686
802k
    SFTKAttribute *att2 = NULL;
8687
802k
    unsigned char *buf;
8688
802k
    SHA1Context *sha;
8689
802k
    MD5Context *md5;
8690
802k
    MD2Context *md2;
8691
802k
    CK_ULONG macSize;
8692
802k
    CK_ULONG tmpKeySize;
8693
802k
    CK_ULONG IVSize;
8694
802k
    CK_ULONG keySize = 0;
8695
802k
    CK_RV crv = CKR_OK;
8696
802k
    CK_BBOOL cktrue = CK_TRUE;
8697
802k
    CK_BBOOL ckfalse = CK_FALSE;
8698
802k
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
8699
802k
    CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
8700
802k
    CK_KEY_DERIVATION_STRING_DATA *stringPtr;
8701
802k
    PRBool isTLS = PR_FALSE;
8702
802k
    PRBool isDH = PR_FALSE;
8703
802k
    HASH_HashType tlsPrfHash = HASH_AlgNULL;
8704
802k
    SECStatus rv;
8705
802k
    int i;
8706
802k
    unsigned int outLen;
8707
802k
    unsigned char sha_out[SHA1_LENGTH];
8708
802k
    unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH];
8709
802k
    PRBool isFIPS;
8710
802k
    HASH_HashType hashType;
8711
802k
    CK_MECHANISM_TYPE hashMech;
8712
802k
    PRBool extractValue = PR_TRUE;
8713
802k
    CK_IKE1_EXTENDED_DERIVE_PARAMS ikeAppB;
8714
802k
    CK_IKE1_EXTENDED_DERIVE_PARAMS *pIkeAppB;
8715
8716
802k
    CHECK_FORK();
8717
8718
802k
    if (!slot) {
8719
0
        return CKR_SESSION_HANDLE_INVALID;
8720
0
    }
8721
802k
    if (!pMechanism) {
8722
0
        return CKR_MECHANISM_PARAM_INVALID;
8723
0
    }
8724
802k
    CK_MECHANISM_TYPE mechanism = pMechanism->mechanism;
8725
8726
    /*
8727
     * now lets create an object to hang the attributes off of
8728
     */
8729
802k
    if (phKey) {
8730
802k
        *phKey = CK_INVALID_HANDLE;
8731
802k
    }
8732
8733
802k
    key = sftk_NewObject(slot); /* fill in the handle later */
8734
802k
    if (key == NULL) {
8735
0
        return CKR_HOST_MEMORY;
8736
0
    }
8737
802k
    isFIPS = sftk_isFIPS(slot->slotID);
8738
8739
    /*
8740
     * load the template values into the object
8741
     */
8742
4.66M
    for (i = 0; i < (int)ulAttributeCount; i++) {
8743
3.86M
        crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
8744
3.86M
        if (crv != CKR_OK)
8745
0
            break;
8746
8747
3.86M
        if (pTemplate[i].type == CKA_KEY_TYPE) {
8748
668k
            keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue;
8749
668k
        }
8750
3.86M
        if (pTemplate[i].type == CKA_VALUE_LEN) {
8751
585k
            keySize = *(CK_ULONG *)pTemplate[i].pValue;
8752
585k
        }
8753
3.86M
    }
8754
802k
    if (crv != CKR_OK) {
8755
0
        sftk_FreeObject(key);
8756
0
        return crv;
8757
0
    }
8758
8759
802k
    if (keySize == 0) {
8760
217k
        keySize = sftk_MapKeySize(keyType);
8761
217k
    }
8762
8763
802k
    switch (mechanism) {
8764
0
        case CKM_NSS_JPAKE_ROUND2_SHA1:   /* fall through */
8765
0
        case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */
8766
0
        case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */
8767
0
        case CKM_NSS_JPAKE_ROUND2_SHA512:
8768
0
            extractValue = PR_FALSE;
8769
0
            classType = CKO_PRIVATE_KEY;
8770
0
            break;
8771
0
        case CKM_NSS_PUB_FROM_PRIV:
8772
0
            extractValue = PR_FALSE;
8773
0
            classType = CKO_PUBLIC_KEY;
8774
0
            break;
8775
134k
        case CKM_HKDF_DATA:                              /* fall through */
8776
134k
        case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA:  /* fall through */
8777
134k
        case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */
8778
134k
        case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA:
8779
134k
            classType = CKO_DATA;
8780
134k
            break;
8781
0
        case CKM_NSS_JPAKE_FINAL_SHA1:   /* fall through */
8782
0
        case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
8783
0
        case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
8784
0
        case CKM_NSS_JPAKE_FINAL_SHA512:
8785
0
            extractValue = PR_FALSE;
8786
        /* fall through */
8787
668k
        default:
8788
668k
            classType = CKO_SECRET_KEY;
8789
802k
    }
8790
8791
802k
    crv = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType));
8792
802k
    if (crv != CKR_OK) {
8793
0
        sftk_FreeObject(key);
8794
0
        return crv;
8795
0
    }
8796
8797
    /* look up the base key we're deriving with */
8798
802k
    session = sftk_SessionFromHandle(hSession);
8799
802k
    if (session == NULL) {
8800
0
        sftk_FreeObject(key);
8801
0
        return CKR_SESSION_HANDLE_INVALID;
8802
0
    }
8803
8804
802k
    sourceKey = sftk_ObjectFromHandle(hBaseKey, session);
8805
    /* is this eventually succeeds, lastOpWasFIPS will be set the resulting key's
8806
     * FIPS state below. */
8807
802k
    session->lastOpWasFIPS = PR_FALSE;
8808
802k
    sftk_FreeSession(session);
8809
802k
    if (sourceKey == NULL) {
8810
0
        sftk_FreeObject(key);
8811
0
        return CKR_KEY_HANDLE_INVALID;
8812
0
    }
8813
8814
802k
    if (extractValue) {
8815
        /* get the value of the base key */
8816
802k
        att = sftk_FindAttribute(sourceKey, CKA_VALUE);
8817
802k
        if (att == NULL) {
8818
0
            sftk_FreeObject(key);
8819
0
            sftk_FreeObject(sourceKey);
8820
0
            return CKR_KEY_HANDLE_INVALID;
8821
0
        }
8822
802k
    }
8823
802k
    sftk_setFIPS(key, sftk_operationIsFIPS(slot, pMechanism,
8824
802k
                                           CKA_DERIVE, sourceKey,
8825
802k
                                           keySize * PR_BITS_PER_BYTE));
8826
8827
802k
    switch (mechanism) {
8828
        /* get a public key from a private key. nsslowkey_ConvertToPublickey()
8829
         * will generate the public portion if it doesn't already exist. */
8830
0
        case CKM_NSS_PUB_FROM_PRIV: {
8831
0
            NSSLOWKEYPrivateKey *privKey;
8832
0
            NSSLOWKEYPublicKey *pubKey;
8833
0
            int error;
8834
8835
0
            crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType);
8836
0
            if (crv != CKR_OK) {
8837
0
                break;
8838
0
            }
8839
8840
            /* privKey is stored in sourceKey and will be destroyed when
8841
             * the sourceKey is freed. */
8842
0
            privKey = sftk_GetPrivKey(sourceKey, keyType, &crv);
8843
0
            if (privKey == NULL) {
8844
0
                break;
8845
0
            }
8846
0
            pubKey = nsslowkey_ConvertToPublicKey(privKey);
8847
0
            if (pubKey == NULL) {
8848
0
                error = PORT_GetError();
8849
0
                crv = sftk_MapCryptError(error);
8850
0
                break;
8851
0
            }
8852
0
            crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey);
8853
0
            nsslowkey_DestroyPublicKey(pubKey);
8854
0
            break;
8855
0
        }
8856
0
        case CKM_NSS_IKE_PRF_DERIVE:
8857
0
        case CKM_IKE_PRF_DERIVE:
8858
0
            if (pMechanism->ulParameterLen !=
8859
0
                sizeof(CK_IKE_PRF_DERIVE_PARAMS)) {
8860
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8861
0
                break;
8862
0
            }
8863
0
            crv = sftk_ike_prf(hSession, att,
8864
0
                               (CK_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key);
8865
0
            break;
8866
0
        case CKM_NSS_IKE1_PRF_DERIVE:
8867
0
        case CKM_IKE1_PRF_DERIVE:
8868
0
            if (pMechanism->ulParameterLen !=
8869
0
                sizeof(CK_IKE1_PRF_DERIVE_PARAMS)) {
8870
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8871
0
                break;
8872
0
            }
8873
0
            crv = sftk_ike1_prf(hSession, att,
8874
0
                                (CK_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter,
8875
0
                                key, keySize);
8876
0
            break;
8877
0
        case CKM_NSS_IKE1_APP_B_PRF_DERIVE:
8878
0
        case CKM_IKE1_EXTENDED_DERIVE:
8879
0
            pIkeAppB = (CK_IKE1_EXTENDED_DERIVE_PARAMS *)pMechanism->pParameter;
8880
0
            if (pMechanism->ulParameterLen ==
8881
0
                sizeof(CK_MECHANISM_TYPE)) {
8882
0
                ikeAppB.prfMechanism = *(CK_MECHANISM_TYPE *)pMechanism->pParameter;
8883
0
                ikeAppB.bHasKeygxy = PR_FALSE;
8884
0
                ikeAppB.hKeygxy = CK_INVALID_HANDLE;
8885
0
                ikeAppB.pExtraData = NULL;
8886
0
                ikeAppB.ulExtraDataLen = 0;
8887
0
                pIkeAppB = &ikeAppB;
8888
0
            } else if (pMechanism->ulParameterLen !=
8889
0
                       sizeof(CK_IKE1_EXTENDED_DERIVE_PARAMS)) {
8890
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8891
0
                break;
8892
0
            }
8893
0
            crv = sftk_ike1_appendix_b_prf(hSession, att, pIkeAppB, key,
8894
0
                                           keySize);
8895
0
            break;
8896
0
        case CKM_NSS_IKE_PRF_PLUS_DERIVE:
8897
0
        case CKM_IKE2_PRF_PLUS_DERIVE:
8898
0
            if (pMechanism->ulParameterLen !=
8899
0
                sizeof(CK_IKE2_PRF_PLUS_DERIVE_PARAMS)) {
8900
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8901
0
                break;
8902
0
            }
8903
0
            crv = sftk_ike_prf_plus(hSession, att,
8904
0
                                    (CK_IKE2_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter,
8905
0
                                    key, keySize);
8906
0
            break;
8907
        /*
8908
         * generate the master secret
8909
         */
8910
84.5k
        case CKM_TLS12_MASTER_KEY_DERIVE:
8911
105k
        case CKM_TLS12_MASTER_KEY_DERIVE_DH:
8912
105k
        case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256:
8913
105k
        case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256:
8914
116k
        case CKM_TLS_MASTER_KEY_DERIVE:
8915
146k
        case CKM_TLS_MASTER_KEY_DERIVE_DH:
8916
146k
        case CKM_SSL3_MASTER_KEY_DERIVE:
8917
146k
        case CKM_SSL3_MASTER_KEY_DERIVE_DH: {
8918
146k
            CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master;
8919
146k
            SSL3RSAPreMasterSecret *rsa_pms;
8920
146k
            unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
8921
8922
146k
            if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) ||
8923
105k
                (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
8924
105k
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) {
8925
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8926
0
                    break;
8927
0
                }
8928
105k
                CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master =
8929
105k
                    (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter;
8930
105k
                tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_master->prfHashMechanism);
8931
105k
                if (tlsPrfHash == HASH_AlgNULL) {
8932
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
8933
0
                    break;
8934
0
                }
8935
105k
            } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) ||
8936
41.1k
                       (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) {
8937
0
                tlsPrfHash = HASH_AlgSHA256;
8938
0
            }
8939
8940
146k
            if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) &&
8941
146k
                (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) {
8942
146k
                isTLS = PR_TRUE;
8943
146k
            }
8944
146k
            if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) ||
8945
146k
                (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) ||
8946
116k
                (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) ||
8947
116k
                (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
8948
51.1k
                isDH = PR_TRUE;
8949
51.1k
            }
8950
8951
            /* first do the consistency checks */
8952
146k
            if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
8953
3.85k
                crv = CKR_KEY_TYPE_INCONSISTENT;
8954
3.85k
                break;
8955
3.85k
            }
8956
142k
            att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
8957
142k
            if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
8958
142k
                                   CKK_GENERIC_SECRET)) {
8959
0
                if (att2)
8960
0
                    sftk_FreeAttribute(att2);
8961
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
8962
0
                break;
8963
0
            }
8964
142k
            sftk_FreeAttribute(att2);
8965
142k
            if (keyType != CKK_GENERIC_SECRET) {
8966
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
8967
0
                break;
8968
0
            }
8969
142k
            if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
8970
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
8971
0
                break;
8972
0
            }
8973
8974
            /* finally do the key gen */
8975
142k
            ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)
8976
142k
                              pMechanism->pParameter;
8977
8978
142k
            if (ssl3_master->pVersion) {
8979
91.7k
                SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
8980
91.7k
                rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue;
8981
                /* don't leak more key material then necessary for SSL to work */
8982
91.7k
                if ((sessKey == NULL) || sessKey->wasDerived) {
8983
0
                    ssl3_master->pVersion->major = 0xff;
8984
0
                    ssl3_master->pVersion->minor = 0xff;
8985
91.7k
                } else {
8986
91.7k
                    ssl3_master->pVersion->major = rsa_pms->client_version[0];
8987
91.7k
                    ssl3_master->pVersion->minor = rsa_pms->client_version[1];
8988
91.7k
                }
8989
91.7k
            }
8990
142k
            if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) {
8991
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8992
0
                break;
8993
0
            }
8994
142k
            if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) {
8995
0
                crv = CKR_MECHANISM_PARAM_INVALID;
8996
0
                break;
8997
0
            }
8998
142k
            PORT_Memcpy(crsrdata,
8999
142k
                        ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
9000
142k
            PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
9001
142k
                        ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
9002
9003
142k
            if (isTLS) {
9004
142k
                SECStatus status;
9005
142k
                SECItem crsr = { siBuffer, NULL, 0 };
9006
142k
                SECItem master = { siBuffer, NULL, 0 };
9007
142k
                SECItem pms = { siBuffer, NULL, 0 };
9008
9009
142k
                crsr.data = crsrdata;
9010
142k
                crsr.len = sizeof crsrdata;
9011
142k
                master.data = key_block;
9012
142k
                master.len = SSL3_MASTER_SECRET_LENGTH;
9013
142k
                pms.data = (unsigned char *)att->attrib.pValue;
9014
142k
                pms.len = att->attrib.ulValueLen;
9015
9016
142k
                if (tlsPrfHash != HASH_AlgNULL) {
9017
102k
                    status = TLS_P_hash(tlsPrfHash, &pms, "master secret",
9018
102k
                                        &crsr, &master, isFIPS);
9019
102k
                } else {
9020
40.3k
                    status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS);
9021
40.3k
                }
9022
142k
                if (status != SECSuccess) {
9023
0
                    PORT_Memset(crsrdata, 0, sizeof crsrdata);
9024
0
                    crv = CKR_FUNCTION_FAILED;
9025
0
                    break;
9026
0
                }
9027
142k
            } else {
9028
                /* now allocate the hash contexts */
9029
0
                md5 = MD5_NewContext();
9030
0
                if (md5 == NULL) {
9031
0
                    PORT_Memset(crsrdata, 0, sizeof crsrdata);
9032
0
                    crv = CKR_HOST_MEMORY;
9033
0
                    break;
9034
0
                }
9035
0
                sha = SHA1_NewContext();
9036
0
                if (sha == NULL) {
9037
0
                    PORT_Memset(crsrdata, 0, sizeof crsrdata);
9038
0
                    PORT_Free(md5);
9039
0
                    crv = CKR_HOST_MEMORY;
9040
0
                    break;
9041
0
                }
9042
0
                for (i = 0; i < 3; i++) {
9043
0
                    SHA1_Begin(sha);
9044
0
                    SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i]));
9045
0
                    SHA1_Update(sha, (const unsigned char *)att->attrib.pValue,
9046
0
                                att->attrib.ulValueLen);
9047
0
                    SHA1_Update(sha, crsrdata, sizeof crsrdata);
9048
0
                    SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
9049
0
                    PORT_Assert(outLen == SHA1_LENGTH);
9050
9051
0
                    MD5_Begin(md5);
9052
0
                    MD5_Update(md5, (const unsigned char *)att->attrib.pValue,
9053
0
                               att->attrib.ulValueLen);
9054
0
                    MD5_Update(md5, sha_out, outLen);
9055
0
                    MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH);
9056
0
                    PORT_Assert(outLen == MD5_LENGTH);
9057
0
                }
9058
0
                PORT_Free(md5);
9059
0
                PORT_Free(sha);
9060
0
                PORT_Memset(crsrdata, 0, sizeof crsrdata);
9061
0
                PORT_Memset(sha_out, 0, sizeof sha_out);
9062
0
            }
9063
9064
            /* store the results */
9065
142k
            crv = sftk_forceAttribute(key, CKA_VALUE, key_block, SSL3_MASTER_SECRET_LENGTH);
9066
142k
            PORT_Memset(key_block, 0, sizeof key_block);
9067
142k
            if (crv != CKR_OK)
9068
0
                break;
9069
142k
            keyType = CKK_GENERIC_SECRET;
9070
142k
            crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType));
9071
142k
            if (isTLS) {
9072
                /* TLS's master secret is used to "sign" finished msgs with PRF. */
9073
                /* XXX This seems like a hack.   But SFTK_Derive only accepts
9074
                 * one "operation" argument. */
9075
142k
                crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
9076
142k
                if (crv != CKR_OK)
9077
0
                    break;
9078
142k
                crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
9079
142k
                if (crv != CKR_OK)
9080
0
                    break;
9081
                /* While we're here, we might as well force this, too. */
9082
142k
                crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
9083
142k
                if (crv != CKR_OK)
9084
0
                    break;
9085
142k
            }
9086
142k
            break;
9087
142k
        }
9088
9089
        /* Extended master key derivation [draft-ietf-tls-session-hash] */
9090
142k
        case CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE:
9091
9.21k
        case CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE_DH:
9092
9.21k
        case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE:
9093
9.21k
        case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: {
9094
9.21k
            CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params;
9095
9.21k
            SSL3RSAPreMasterSecret *rsa_pms;
9096
9.21k
            SECStatus status;
9097
9.21k
            SECItem pms = { siBuffer, NULL, 0 };
9098
9.21k
            SECItem seed = { siBuffer, NULL, 0 };
9099
9.21k
            SECItem master = { siBuffer, NULL, 0 };
9100
9101
9.21k
            ems_params = (CK_TLS12_EXTENDED_MASTER_KEY_DERIVE_PARAMS *)
9102
9.21k
                             pMechanism->pParameter;
9103
9104
            /* First do the consistency checks */
9105
9.21k
            if (((mechanism == CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE) ||
9106
2.59k
                 (mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE)) &&
9107
6.62k
                (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
9108
56
                crv = CKR_KEY_TYPE_INCONSISTENT;
9109
56
                break;
9110
56
            }
9111
9.15k
            att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
9112
9.15k
            if ((att2 == NULL) ||
9113
9.15k
                (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) {
9114
0
                if (att2)
9115
0
                    sftk_FreeAttribute(att2);
9116
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
9117
0
                break;
9118
0
            }
9119
9.15k
            sftk_FreeAttribute(att2);
9120
9.15k
            if (keyType != CKK_GENERIC_SECRET) {
9121
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
9122
0
                break;
9123
0
            }
9124
9.15k
            if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
9125
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
9126
0
                break;
9127
0
            }
9128
9129
            /* Do the key derivation */
9130
9.15k
            pms.data = (unsigned char *)att->attrib.pValue;
9131
9.15k
            pms.len = att->attrib.ulValueLen;
9132
9.15k
            seed.data = ems_params->pSessionHash;
9133
9.15k
            seed.len = ems_params->ulSessionHashLen;
9134
9.15k
            master.data = key_block;
9135
9.15k
            master.len = SSL3_MASTER_SECRET_LENGTH;
9136
9.15k
            if (ems_params->prfHashMechanism == CKM_TLS_PRF) {
9137
                /*
9138
                 * In this case, the session hash is the concatenation of SHA-1
9139
                 * and MD5, so it should be 36 bytes long.
9140
                 */
9141
1.37k
                if (seed.len != MD5_LENGTH + SHA1_LENGTH) {
9142
0
                    crv = CKR_TEMPLATE_INCONSISTENT;
9143
0
                    break;
9144
0
                }
9145
9146
1.37k
                status = TLS_PRF(&pms, "extended master secret",
9147
1.37k
                                 &seed, &master, isFIPS);
9148
7.78k
            } else {
9149
7.78k
                const SECHashObject *hashObj;
9150
9151
7.78k
                tlsPrfHash = sftk_GetHashTypeFromMechanism(ems_params->prfHashMechanism);
9152
7.78k
                if (tlsPrfHash == HASH_AlgNULL) {
9153
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
9154
0
                    break;
9155
0
                }
9156
9157
7.78k
                hashObj = HASH_GetRawHashObject(tlsPrfHash);
9158
7.78k
                if (seed.len != hashObj->length) {
9159
0
                    crv = CKR_TEMPLATE_INCONSISTENT;
9160
0
                    break;
9161
0
                }
9162
9163
7.78k
                status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret",
9164
7.78k
                                    &seed, &master, isFIPS);
9165
7.78k
            }
9166
9.15k
            if (status != SECSuccess) {
9167
0
                crv = CKR_FUNCTION_FAILED;
9168
0
                break;
9169
0
            }
9170
9171
            /* Reflect the version if required */
9172
9.15k
            if (ems_params->pVersion) {
9173
6.56k
                SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
9174
6.56k
                rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue;
9175
                /* don't leak more key material than necessary for SSL to work */
9176
6.56k
                if ((sessKey == NULL) || sessKey->wasDerived) {
9177
0
                    ems_params->pVersion->major = 0xff;
9178
0
                    ems_params->pVersion->minor = 0xff;
9179
6.56k
                } else {
9180
6.56k
                    ems_params->pVersion->major = rsa_pms->client_version[0];
9181
6.56k
                    ems_params->pVersion->minor = rsa_pms->client_version[1];
9182
6.56k
                }
9183
6.56k
            }
9184
9185
            /* Store the results */
9186
9.15k
            crv = sftk_forceAttribute(key, CKA_VALUE, key_block,
9187
9.15k
                                      SSL3_MASTER_SECRET_LENGTH);
9188
9.15k
            PORT_Memset(key_block, 0, sizeof key_block);
9189
9.15k
            break;
9190
9.15k
        }
9191
9192
74.9k
        case CKM_TLS12_KEY_AND_MAC_DERIVE:
9193
74.9k
        case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256:
9194
112k
        case CKM_TLS_KEY_AND_MAC_DERIVE:
9195
112k
        case CKM_SSL3_KEY_AND_MAC_DERIVE: {
9196
112k
            CK_SSL3_KEY_MAT_PARAMS *ssl3_keys;
9197
112k
            CK_SSL3_KEY_MAT_OUT *ssl3_keys_out;
9198
112k
            CK_ULONG effKeySize;
9199
112k
            unsigned int block_needed;
9200
112k
            unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
9201
9202
112k
            if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) {
9203
74.9k
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) {
9204
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
9205
0
                    break;
9206
0
                }
9207
74.9k
                CK_TLS12_KEY_MAT_PARAMS *tls12_keys =
9208
74.9k
                    (CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter;
9209
74.9k
                tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_keys->prfHashMechanism);
9210
74.9k
                if (tlsPrfHash == HASH_AlgNULL) {
9211
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
9212
0
                    break;
9213
0
                }
9214
74.9k
            } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) {
9215
0
                tlsPrfHash = HASH_AlgSHA256;
9216
0
            }
9217
9218
112k
            if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) {
9219
112k
                isTLS = PR_TRUE;
9220
112k
            }
9221
9222
112k
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
9223
112k
            if (crv != CKR_OK)
9224
0
                break;
9225
9226
112k
            if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) {
9227
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
9228
0
                break;
9229
0
            }
9230
112k
            att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
9231
112k
            if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
9232
112k
                                   CKK_GENERIC_SECRET)) {
9233
0
                if (att2)
9234
0
                    sftk_FreeAttribute(att2);
9235
0
                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
9236
0
                break;
9237
0
            }
9238
112k
            sftk_FreeAttribute(att2);
9239
112k
            md5 = MD5_NewContext();
9240
112k
            if (md5 == NULL) {
9241
0
                crv = CKR_HOST_MEMORY;
9242
0
                break;
9243
0
            }
9244
112k
            sha = SHA1_NewContext();
9245
112k
            if (sha == NULL) {
9246
0
                MD5_DestroyContext(md5, PR_TRUE);
9247
0
                crv = CKR_HOST_MEMORY;
9248
0
                break;
9249
0
            }
9250
9251
112k
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_SSL3_KEY_MAT_PARAMS))) {
9252
0
                MD5_DestroyContext(md5, PR_TRUE);
9253
0
                SHA1_DestroyContext(sha, PR_TRUE);
9254
0
                crv = CKR_MECHANISM_PARAM_INVALID;
9255
0
                break;
9256
0
            }
9257
112k
            ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter;
9258
9259
112k
            PORT_Memcpy(srcrdata,
9260
112k
                        ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
9261
112k
            PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH,
9262
112k
                        ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
9263
9264
            /*
9265
             * clear out our returned keys so we can recover on failure
9266
             */
9267
112k
            ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;
9268
112k
            ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE;
9269
112k
            ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE;
9270
112k
            ssl3_keys_out->hClientKey = CK_INVALID_HANDLE;
9271
112k
            ssl3_keys_out->hServerKey = CK_INVALID_HANDLE;
9272
9273
            /*
9274
             * How much key material do we need?
9275
             */
9276
112k
            macSize = ssl3_keys->ulMacSizeInBits / 8;
9277
112k
            effKeySize = ssl3_keys->ulKeySizeInBits / 8;
9278
112k
            IVSize = ssl3_keys->ulIVSizeInBits / 8;
9279
112k
            if (keySize == 0) {
9280
14.6k
                effKeySize = keySize;
9281
14.6k
            }
9282
9283
            /* bIsExport must be false. */
9284
112k
            if (ssl3_keys->bIsExport) {
9285
0
                MD5_DestroyContext(md5, PR_TRUE);
9286
0
                SHA1_DestroyContext(sha, PR_TRUE);
9287
0
                PORT_Memset(srcrdata, 0, sizeof srcrdata);
9288
0
                crv = CKR_MECHANISM_PARAM_INVALID;
9289
0
                break;
9290
0
            }
9291
9292
            /* Compute the amount of key material consumed using keySize
9293
             * (from CKA_VALUE_LEN, which is what actually indexes key_block
9294
             * below), not effKeySize. Bound each term first to prevent
9295
             * integer overflow in the sum, then reject if the total exceeds
9296
             * the buffer -- clamping block_needed would not bound the later
9297
             * indexing and would permit a stack OOB read. */
9298
112k
            (void)effKeySize;
9299
112k
            if (macSize > sizeof key_block || IVSize > sizeof key_block ||
9300
112k
                keySize > sizeof key_block ||
9301
112k
                2 * (macSize + keySize + IVSize) > sizeof key_block) {
9302
0
                MD5_DestroyContext(md5, PR_TRUE);
9303
0
                SHA1_DestroyContext(sha, PR_TRUE);
9304
0
                PORT_Memset(srcrdata, 0, sizeof srcrdata);
9305
0
                crv = CKR_MECHANISM_PARAM_INVALID;
9306
0
                break;
9307
0
            }
9308
112k
            block_needed = 2 * (macSize + keySize + IVSize);
9309
9310
            /*
9311
             * generate the key material: This looks amazingly similar to the
9312
             * PMS code, and is clearly crying out for a function to provide it.
9313
             */
9314
112k
            if (isTLS) {
9315
112k
                SECStatus status;
9316
112k
                SECItem srcr = { siBuffer, NULL, 0 };
9317
112k
                SECItem keyblk = { siBuffer, NULL, 0 };
9318
112k
                SECItem master = { siBuffer, NULL, 0 };
9319
9320
112k
                srcr.data = srcrdata;
9321
112k
                srcr.len = sizeof srcrdata;
9322
112k
                keyblk.data = key_block;
9323
112k
                keyblk.len = block_needed;
9324
112k
                master.data = (unsigned char *)att->attrib.pValue;
9325
112k
                master.len = att->attrib.ulValueLen;
9326
9327
112k
                if (tlsPrfHash != HASH_AlgNULL) {
9328
74.9k
                    status = TLS_P_hash(tlsPrfHash, &master, "key expansion",
9329
74.9k
                                        &srcr, &keyblk, isFIPS);
9330
74.9k
                } else {
9331
37.4k
                    status = TLS_PRF(&master, "key expansion", &srcr, &keyblk,
9332
37.4k
                                     isFIPS);
9333
37.4k
                }
9334
112k
                if (status != SECSuccess) {
9335
0
                    goto key_and_mac_derive_fail;
9336
0
                }
9337
112k
            } else {
9338
0
                unsigned int block_bytes = 0;
9339
                /* key_block =
9340
                 *     MD5(master_secret + SHA('A' + master_secret +
9341
                 *                      ServerHello.random + ClientHello.random)) +
9342
                 *     MD5(master_secret + SHA('BB' + master_secret +
9343
                 *                      ServerHello.random + ClientHello.random)) +
9344
                 *     MD5(master_secret + SHA('CCC' + master_secret +
9345
                 *                      ServerHello.random + ClientHello.random)) +
9346
                 *     [...];
9347
                 */
9348
0
                for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) {
9349
0
                    SHA1_Begin(sha);
9350
0
                    SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i]));
9351
0
                    SHA1_Update(sha, (const unsigned char *)att->attrib.pValue,
9352
0
                                att->attrib.ulValueLen);
9353
0
                    SHA1_Update(sha, srcrdata, sizeof srcrdata);
9354
0
                    SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
9355
0
                    PORT_Assert(outLen == SHA1_LENGTH);
9356
0
                    MD5_Begin(md5);
9357
0
                    MD5_Update(md5, (const unsigned char *)att->attrib.pValue,
9358
0
                               att->attrib.ulValueLen);
9359
0
                    MD5_Update(md5, sha_out, outLen);
9360
0
                    MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH);
9361
0
                    PORT_Assert(outLen == MD5_LENGTH);
9362
0
                    block_bytes += outLen;
9363
0
                }
9364
0
                PORT_Memset(sha_out, 0, sizeof sha_out);
9365
0
            }
9366
9367
            /*
9368
             * Put the key material where it goes.
9369
             */
9370
112k
            i = 0; /* now shows how much consumed */
9371
9372
            /*
9373
             * The key_block is partitioned as follows:
9374
             * client_write_MAC_secret[CipherSpec.hash_size]
9375
             */
9376
112k
            crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
9377
112k
                                   &ssl3_keys_out->hClientMacSecret);
9378
112k
            if (crv != CKR_OK)
9379
0
                goto key_and_mac_derive_fail;
9380
9381
112k
            i += macSize;
9382
9383
            /*
9384
             * server_write_MAC_secret[CipherSpec.hash_size]
9385
             */
9386
112k
            crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
9387
112k
                                   &ssl3_keys_out->hServerMacSecret);
9388
112k
            if (crv != CKR_OK) {
9389
0
                goto key_and_mac_derive_fail;
9390
0
            }
9391
112k
            i += macSize;
9392
9393
112k
            if (keySize) {
9394
                /*
9395
                ** Generate Domestic write keys and IVs.
9396
                ** client_write_key[CipherSpec.key_material]
9397
                */
9398
97.7k
                crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
9399
97.7k
                                       keySize, &ssl3_keys_out->hClientKey);
9400
97.7k
                if (crv != CKR_OK) {
9401
0
                    goto key_and_mac_derive_fail;
9402
0
                }
9403
97.7k
                i += keySize;
9404
9405
                /*
9406
                ** server_write_key[CipherSpec.key_material]
9407
                */
9408
97.7k
                crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
9409
97.7k
                                       keySize, &ssl3_keys_out->hServerKey);
9410
97.7k
                if (crv != CKR_OK) {
9411
0
                    goto key_and_mac_derive_fail;
9412
0
                }
9413
97.7k
                i += keySize;
9414
9415
                /*
9416
                ** client_write_IV[CipherSpec.IV_size]
9417
                */
9418
97.7k
                if (IVSize > 0) {
9419
94.7k
                    PORT_Memcpy(ssl3_keys_out->pIVClient,
9420
94.7k
                                &key_block[i], IVSize);
9421
94.7k
                    i += IVSize;
9422
94.7k
                }
9423
9424
                /*
9425
                ** server_write_IV[CipherSpec.IV_size]
9426
                */
9427
97.7k
                if (IVSize > 0) {
9428
94.7k
                    PORT_Memcpy(ssl3_keys_out->pIVServer,
9429
94.7k
                                &key_block[i], IVSize);
9430
94.7k
                    i += IVSize;
9431
94.7k
                }
9432
97.7k
                PORT_Assert(i <= sizeof key_block);
9433
97.7k
            }
9434
9435
112k
            crv = CKR_OK;
9436
9437
112k
            if (0) {
9438
0
            key_and_mac_derive_fail:
9439
0
                if (crv == CKR_OK)
9440
0
                    crv = CKR_FUNCTION_FAILED;
9441
0
                sftk_freeSSLKeys(hSession, ssl3_keys_out);
9442
0
            }
9443
112k
            PORT_Memset(srcrdata, 0, sizeof srcrdata);
9444
112k
            PORT_Memset(key_block, 0, sizeof key_block);
9445
112k
            MD5_DestroyContext(md5, PR_TRUE);
9446
112k
            SHA1_DestroyContext(sha, PR_TRUE);
9447
112k
            sftk_FreeObject(key);
9448
112k
            key = NULL;
9449
112k
            break;
9450
112k
        }
9451
9452
0
        case CKM_DES3_ECB_ENCRYPT_DATA:
9453
0
        case CKM_DES3_CBC_ENCRYPT_DATA: {
9454
0
            void *cipherInfo;
9455
0
            unsigned char des3key[MAX_DES3_KEY_SIZE];
9456
0
            CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr;
9457
0
            int mode;
9458
0
            unsigned char *iv;
9459
0
            unsigned char *data;
9460
0
            CK_ULONG len;
9461
9462
0
            if (mechanism == CKM_DES3_ECB_ENCRYPT_DATA) {
9463
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
9464
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
9465
0
                    break;
9466
0
                }
9467
0
                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
9468
0
                                pMechanism->pParameter;
9469
0
                mode = NSS_DES_EDE3;
9470
0
                iv = NULL;
9471
0
                data = stringPtr->pData;
9472
0
                len = stringPtr->ulLen;
9473
0
            } else {
9474
0
                mode = NSS_DES_EDE3_CBC;
9475
0
                desEncryptPtr =
9476
0
                    (CK_DES_CBC_ENCRYPT_DATA_PARAMS *)
9477
0
                        pMechanism->pParameter;
9478
0
                iv = desEncryptPtr->iv;
9479
0
                data = desEncryptPtr->pData;
9480
0
                len = desEncryptPtr->length;
9481
0
            }
9482
0
            if (att->attrib.ulValueLen == 16) {
9483
0
                PORT_Memcpy(des3key, att->attrib.pValue, 16);
9484
0
                PORT_Memcpy(des3key + 16, des3key, 8);
9485
0
            } else if (att->attrib.ulValueLen == 24) {
9486
0
                PORT_Memcpy(des3key, att->attrib.pValue, 24);
9487
0
            } else {
9488
0
                crv = CKR_KEY_SIZE_RANGE;
9489
0
                break;
9490
0
            }
9491
0
            cipherInfo = DES_CreateContext(des3key, iv, mode, PR_TRUE);
9492
0
            PORT_Memset(des3key, 0, 24);
9493
0
            if (cipherInfo == NULL) {
9494
0
                crv = CKR_HOST_MEMORY;
9495
0
                break;
9496
0
            }
9497
0
            crv = sftk_DeriveEncrypt(SFTKCipher_DES_Encrypt,
9498
0
                                     cipherInfo, 8, key, keySize,
9499
0
                                     data, len);
9500
0
            DES_DestroyContext(cipherInfo, PR_TRUE);
9501
0
            break;
9502
0
        }
9503
9504
0
        case CKM_AES_ECB_ENCRYPT_DATA:
9505
0
        case CKM_AES_CBC_ENCRYPT_DATA: {
9506
0
            void *cipherInfo;
9507
0
            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
9508
0
            int mode;
9509
0
            unsigned char *iv;
9510
0
            unsigned char *data;
9511
0
            CK_ULONG len;
9512
9513
0
            if (mechanism == CKM_AES_ECB_ENCRYPT_DATA) {
9514
0
                mode = NSS_AES;
9515
0
                iv = NULL;
9516
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
9517
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
9518
0
                    break;
9519
0
                }
9520
0
                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
9521
0
                data = stringPtr->pData;
9522
0
                len = stringPtr->ulLen;
9523
0
            } else {
9524
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
9525
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
9526
0
                    break;
9527
0
                }
9528
0
                aesEncryptPtr =
9529
0
                    (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)pMechanism->pParameter;
9530
0
                mode = NSS_AES_CBC;
9531
0
                iv = aesEncryptPtr->iv;
9532
0
                data = aesEncryptPtr->pData;
9533
0
                len = aesEncryptPtr->length;
9534
0
            }
9535
9536
0
            cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue,
9537
0
                                           iv, mode, PR_TRUE,
9538
0
                                           att->attrib.ulValueLen, 16);
9539
0
            if (cipherInfo == NULL) {
9540
0
                crv = CKR_HOST_MEMORY;
9541
0
                break;
9542
0
            }
9543
0
            crv = sftk_DeriveEncrypt(SFTKCipher_AES_Encrypt,
9544
0
                                     cipherInfo, 16, key, keySize,
9545
0
                                     data, len);
9546
0
            AES_DestroyContext(cipherInfo, PR_TRUE);
9547
0
            break;
9548
0
        }
9549
9550
0
        case CKM_CAMELLIA_ECB_ENCRYPT_DATA:
9551
0
        case CKM_CAMELLIA_CBC_ENCRYPT_DATA: {
9552
0
            void *cipherInfo;
9553
0
            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
9554
0
            int mode;
9555
0
            unsigned char *iv;
9556
0
            unsigned char *data;
9557
0
            CK_ULONG len;
9558
9559
0
            if (mechanism == CKM_CAMELLIA_ECB_ENCRYPT_DATA) {
9560
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
9561
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
9562
0
                    break;
9563
0
                }
9564
0
                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
9565
0
                                pMechanism->pParameter;
9566
0
                aesEncryptPtr = NULL;
9567
0
                mode = NSS_CAMELLIA;
9568
0
                data = stringPtr->pData;
9569
0
                len = stringPtr->ulLen;
9570
0
                iv = NULL;
9571
0
            } else {
9572
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
9573
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
9574
0
                    break;
9575
0
                }
9576
0
                stringPtr = NULL;
9577
0
                aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
9578
0
                                    pMechanism->pParameter;
9579
0
                mode = NSS_CAMELLIA_CBC;
9580
0
                iv = aesEncryptPtr->iv;
9581
0
                data = aesEncryptPtr->pData;
9582
0
                len = aesEncryptPtr->length;
9583
0
            }
9584
9585
0
            cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue,
9586
0
                                                iv, mode, PR_TRUE,
9587
0
                                                att->attrib.ulValueLen);
9588
0
            if (cipherInfo == NULL) {
9589
0
                crv = CKR_HOST_MEMORY;
9590
0
                break;
9591
0
            }
9592
0
            crv = sftk_DeriveEncrypt(SFTKCipher_Camellia_Encrypt,
9593
0
                                     cipherInfo, 16, key, keySize,
9594
0
                                     data, len);
9595
0
            Camellia_DestroyContext(cipherInfo, PR_TRUE);
9596
0
            break;
9597
0
        }
9598
9599
0
#ifndef NSS_DISABLE_DEPRECATED_SEED
9600
0
        case CKM_SEED_ECB_ENCRYPT_DATA:
9601
0
        case CKM_SEED_CBC_ENCRYPT_DATA: {
9602
0
            void *cipherInfo;
9603
0
            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
9604
0
            int mode;
9605
0
            unsigned char *iv;
9606
0
            unsigned char *data;
9607
0
            CK_ULONG len;
9608
9609
0
            if (mechanism == CKM_SEED_ECB_ENCRYPT_DATA) {
9610
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
9611
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
9612
0
                    break;
9613
0
                }
9614
0
                mode = NSS_SEED;
9615
0
                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
9616
0
                                pMechanism->pParameter;
9617
0
                aesEncryptPtr = NULL;
9618
0
                data = stringPtr->pData;
9619
0
                len = stringPtr->ulLen;
9620
0
                iv = NULL;
9621
0
            } else {
9622
0
                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
9623
0
                    crv = CKR_MECHANISM_PARAM_INVALID;
9624
0
                    break;
9625
0
                }
9626
0
                mode = NSS_SEED_CBC;
9627
0
                aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
9628
0
                                    pMechanism->pParameter;
9629
0
                iv = aesEncryptPtr->iv;
9630
0
                data = aesEncryptPtr->pData;
9631
0
                len = aesEncryptPtr->length;
9632
0
            }
9633
9634
0
            cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue,
9635
0
                                            iv, mode, PR_TRUE);
9636
0
            if (cipherInfo == NULL) {
9637
0
                crv = CKR_HOST_MEMORY;
9638
0
                break;
9639
0
            }
9640
0
            crv = sftk_DeriveEncrypt(SFTKCipher_SEED_Encrypt,
9641
0
                                     cipherInfo, 16, key, keySize,
9642
0
                                     data, len);
9643
0
            SEED_DestroyContext(cipherInfo, PR_TRUE);
9644
0
            break;
9645
0
        }
9646
0
#endif /* NSS_DISABLE_DEPRECATED_SEED */
9647
9648
736
        case CKM_CONCATENATE_BASE_AND_KEY: {
9649
736
            SFTKObject *paramKey;
9650
9651
736
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
9652
736
            if (crv != CKR_OK)
9653
0
                break;
9654
9655
736
            session = sftk_SessionFromHandle(hSession);
9656
736
            if (session == NULL) {
9657
0
                crv = CKR_SESSION_HANDLE_INVALID;
9658
0
                break;
9659
0
            }
9660
9661
736
            paramKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *)
9662
736
                                                  pMechanism->pParameter,
9663
736
                                             session);
9664
736
            sftk_FreeSession(session);
9665
736
            if (paramKey == NULL) {
9666
0
                crv = CKR_KEY_HANDLE_INVALID;
9667
0
                break;
9668
0
            }
9669
9670
736
            if (sftk_isTrue(paramKey, CKA_SENSITIVE)) {
9671
0
                crv = sftk_forceAttribute(key, CKA_SENSITIVE, &cktrue,
9672
0
                                          sizeof(CK_BBOOL));
9673
0
                if (crv != CKR_OK) {
9674
0
                    sftk_FreeObject(paramKey);
9675
0
                    break;
9676
0
                }
9677
0
            }
9678
9679
736
            if (sftk_hasAttribute(paramKey, CKA_EXTRACTABLE) && !sftk_isTrue(paramKey, CKA_EXTRACTABLE)) {
9680
0
                crv = sftk_forceAttribute(key, CKA_EXTRACTABLE, &ckfalse, sizeof(CK_BBOOL));
9681
0
                if (crv != CKR_OK) {
9682
0
                    sftk_FreeObject(paramKey);
9683
0
                    break;
9684
0
                }
9685
0
            }
9686
9687
736
            att2 = sftk_FindAttribute(paramKey, CKA_VALUE);
9688
736
            if (att2 == NULL) {
9689
0
                sftk_FreeObject(paramKey);
9690
0
                crv = CKR_KEY_HANDLE_INVALID;
9691
0
                break;
9692
0
            }
9693
736
            tmpKeySize = att->attrib.ulValueLen + att2->attrib.ulValueLen;
9694
736
            if (keySize == 0)
9695
736
                keySize = tmpKeySize;
9696
736
            if (keySize > tmpKeySize) {
9697
0
                sftk_FreeAttribute(att2);
9698
0
                sftk_FreeObject(paramKey);
9699
0
                crv = CKR_TEMPLATE_INCONSISTENT;
9700
0
                break;
9701
0
            }
9702
736
            buf = (unsigned char *)PORT_Alloc(tmpKeySize);
9703
736
            if (buf == NULL) {
9704
0
                sftk_FreeAttribute(att2);
9705
0
                sftk_FreeObject(paramKey);
9706
0
                crv = CKR_HOST_MEMORY;
9707
0
                break;
9708
0
            }
9709
9710
736
            PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
9711
736
            PORT_Memcpy(buf + att->attrib.ulValueLen,
9712
736
                        att2->attrib.pValue, att2->attrib.ulValueLen);
9713
9714
736
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
9715
736
            PORT_ZFree(buf, tmpKeySize);
9716
            /* preserve the source of the original base key */
9717
736
            key->source = sourceKey->source;
9718
9719
            /* make sure this is fully fips approved, and mark it
9720
             * unapproved if not */
9721
736
            if (sftk_hasFIPS(key)) {
9722
0
                sftk_setFIPS(key, sftk_hasFIPS(paramKey));
9723
0
            }
9724
736
            sftk_FreeAttribute(att2);
9725
736
            sftk_FreeObject(paramKey);
9726
736
            break;
9727
736
        }
9728
9729
0
        case CKM_CONCATENATE_BASE_AND_DATA:
9730
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
9731
0
            if (crv != CKR_OK)
9732
0
                break;
9733
9734
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
9735
0
                crv = CKR_MECHANISM_PARAM_INVALID;
9736
0
                break;
9737
0
            }
9738
0
            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
9739
0
            tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
9740
0
            if (keySize == 0)
9741
0
                keySize = tmpKeySize;
9742
0
            if (keySize > tmpKeySize) {
9743
0
                crv = CKR_TEMPLATE_INCONSISTENT;
9744
0
                break;
9745
0
            }
9746
0
            buf = (unsigned char *)PORT_Alloc(tmpKeySize);
9747
0
            if (buf == NULL) {
9748
0
                crv = CKR_HOST_MEMORY;
9749
0
                break;
9750
0
            }
9751
9752
0
            PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
9753
0
            PORT_Memcpy(buf + att->attrib.ulValueLen, stringPtr->pData,
9754
0
                        stringPtr->ulLen);
9755
9756
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
9757
0
            PORT_ZFree(buf, tmpKeySize);
9758
0
            break;
9759
6.70k
        case CKM_CONCATENATE_DATA_AND_BASE:
9760
6.70k
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
9761
6.70k
            if (crv != CKR_OK)
9762
0
                break;
9763
9764
6.70k
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
9765
0
                crv = CKR_MECHANISM_PARAM_INVALID;
9766
0
                break;
9767
0
            }
9768
6.70k
            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
9769
6.70k
            tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
9770
6.70k
            if (keySize == 0)
9771
6.70k
                keySize = tmpKeySize;
9772
6.70k
            if (keySize > tmpKeySize) {
9773
0
                crv = CKR_TEMPLATE_INCONSISTENT;
9774
0
                break;
9775
0
            }
9776
6.70k
            buf = (unsigned char *)PORT_Alloc(tmpKeySize);
9777
6.70k
            if (buf == NULL) {
9778
0
                crv = CKR_HOST_MEMORY;
9779
0
                break;
9780
0
            }
9781
9782
6.70k
            PORT_Memcpy(buf, stringPtr->pData, stringPtr->ulLen);
9783
6.70k
            PORT_Memcpy(buf + stringPtr->ulLen, att->attrib.pValue,
9784
6.70k
                        att->attrib.ulValueLen);
9785
9786
6.70k
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
9787
6.70k
            PORT_ZFree(buf, tmpKeySize);
9788
6.70k
            break;
9789
0
        case CKM_XOR_BASE_AND_DATA:
9790
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
9791
0
            if (crv != CKR_OK)
9792
0
                break;
9793
9794
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
9795
0
                crv = CKR_MECHANISM_PARAM_INVALID;
9796
0
                break;
9797
0
            }
9798
0
            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
9799
0
            tmpKeySize = PR_MIN(att->attrib.ulValueLen, stringPtr->ulLen);
9800
0
            if (keySize == 0)
9801
0
                keySize = tmpKeySize;
9802
0
            if (keySize > tmpKeySize) {
9803
0
                crv = CKR_TEMPLATE_INCONSISTENT;
9804
0
                break;
9805
0
            }
9806
0
            buf = (unsigned char *)PORT_Alloc(keySize);
9807
0
            if (buf == NULL) {
9808
0
                crv = CKR_HOST_MEMORY;
9809
0
                break;
9810
0
            }
9811
9812
0
            PORT_Memcpy(buf, att->attrib.pValue, keySize);
9813
0
            for (i = 0; i < (int)keySize; i++) {
9814
0
                buf[i] ^= stringPtr->pData[i];
9815
0
            }
9816
9817
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
9818
0
            PORT_ZFree(buf, keySize);
9819
0
            break;
9820
9821
0
        case CKM_EXTRACT_KEY_FROM_KEY: {
9822
0
            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_EXTRACT_PARAMS))) {
9823
0
                crv = CKR_MECHANISM_PARAM_INVALID;
9824
0
                break;
9825
0
            }
9826
            /* the following assumes 8 bits per byte */
9827
0
            CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;
9828
0
            CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */
9829
0
            CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */
9830
9831
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
9832
0
            if (crv != CKR_OK)
9833
0
                break;
9834
9835
0
            if (keySize == 0) {
9836
0
                crv = CKR_TEMPLATE_INCOMPLETE;
9837
0
                break;
9838
0
            }
9839
            /* make sure we have enough bits in the original key */
9840
0
            if (att->attrib.ulValueLen <
9841
0
                (offset + keySize + ((shift != 0) ? 1 : 0))) {
9842
0
                crv = CKR_MECHANISM_PARAM_INVALID;
9843
0
                break;
9844
0
            }
9845
0
            buf = (unsigned char *)PORT_Alloc(keySize);
9846
0
            if (buf == NULL) {
9847
0
                crv = CKR_HOST_MEMORY;
9848
0
                break;
9849
0
            }
9850
9851
            /* copy the bits we need into the new key */
9852
0
            for (i = 0; i < (int)keySize; i++) {
9853
0
                unsigned char *value =
9854
0
                    ((unsigned char *)att->attrib.pValue) + offset + i;
9855
0
                if (shift) {
9856
0
                    buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift));
9857
0
                } else {
9858
0
                    buf[i] = value[0];
9859
0
                }
9860
0
            }
9861
9862
0
            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
9863
0
            PORT_ZFree(buf, keySize);
9864
0
            break;
9865
0
        }
9866
0
        case CKM_MD2_KEY_DERIVATION:
9867
0
            if (keySize == 0)
9868
0
                keySize = MD2_LENGTH;
9869
0
            if (keySize > MD2_LENGTH) {
9870
0
                crv = CKR_TEMPLATE_INCONSISTENT;
9871
0
                break;
9872
0
            }
9873
            /* now allocate the hash contexts */
9874
0
            md2 = MD2_NewContext();
9875
0
            if (md2 == NULL) {
9876
0
                crv = CKR_HOST_MEMORY;
9877
0
                break;
9878
0
            }
9879
0
            MD2_Begin(md2);
9880
0
            MD2_Update(md2, (const unsigned char *)att->attrib.pValue,
9881
0
                       att->attrib.ulValueLen);
9882
0
            MD2_End(md2, key_block, &outLen, MD2_LENGTH);
9883
0
            MD2_DestroyContext(md2, PR_TRUE);
9884
9885
0
            crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);
9886
0
            PORT_Memset(key_block, 0, MD2_LENGTH);
9887
0
            break;
9888
0
#define DERIVE_KEY_HASH(hash)                                                \
9889
0
    case CKM_##hash##_KEY_DERIVATION:                                        \
9890
0
        if (keySize == 0)                                                    \
9891
0
            keySize = hash##_LENGTH;                                         \
9892
0
        if (keySize > hash##_LENGTH) {                                       \
9893
0
            crv = CKR_TEMPLATE_INCONSISTENT;                                 \
9894
0
            break;                                                           \
9895
0
        }                                                                    \
9896
0
        hash##_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, \
9897
0
                       att->attrib.ulValueLen);                              \
9898
0
        crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);       \
9899
0
        PORT_Memset(key_block, 0, hash##_LENGTH);                            \
9900
0
        break;
9901
0
            DERIVE_KEY_HASH(MD5)
9902
0
            DERIVE_KEY_HASH(SHA1)
9903
0
            DERIVE_KEY_HASH(SHA224)
9904
0
            DERIVE_KEY_HASH(SHA256)
9905
0
            DERIVE_KEY_HASH(SHA384)
9906
0
            DERIVE_KEY_HASH(SHA512)
9907
0
            DERIVE_KEY_HASH(SHA3_224)
9908
0
            DERIVE_KEY_HASH(SHA3_256)
9909
0
            DERIVE_KEY_HASH(SHA3_384)
9910
0
            DERIVE_KEY_HASH(SHA3_512)
9911
9912
5.14k
        case CKM_DH_PKCS_DERIVE: {
9913
5.14k
            SECItem derived, dhPublic;
9914
5.14k
            SECItem dhPrime, dhValue;
9915
5.14k
            const SECItem *subPrime;
9916
            /* sourceKey - values for the local existing low key */
9917
            /* get prime and value attributes */
9918
5.14k
            crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
9919
5.14k
            if (crv != CKR_OK)
9920
0
                break;
9921
9922
5.14k
            dhPublic.data = pMechanism->pParameter;
9923
5.14k
            dhPublic.len = pMechanism->ulParameterLen;
9924
9925
            /* if the prime is an approved prime, we can skip all the other
9926
             * checks. */
9927
5.14k
            subPrime = sftk_VerifyDH_Prime(&dhPrime, NULL, isFIPS);
9928
5.14k
            if (subPrime == NULL) {
9929
8
                SECItem dhSubPrime;
9930
                /* If the caller set the subprime value, it means that
9931
                 * either the caller knows the subprime value and wants us
9932
                 * to validate the key against the subprime, or that the
9933
                 * caller wants us to verify that the prime is a safe prime
9934
                 * by passing in subprime = (prime-1)/2 */
9935
8
                dhSubPrime.data = NULL;
9936
8
                dhSubPrime.len = 0;
9937
8
                crv = sftk_Attribute2SecItem(NULL, &dhSubPrime,
9938
8
                                             sourceKey, CKA_SUBPRIME);
9939
                /* we ignore the value of crv here, We treat a valid
9940
                 * return of len = 0 and a failure to find a subrime the same
9941
                 * NOTE: we free the subprime in both cases depending on
9942
                 * PORT_Free of NULL to be a noop */
9943
8
                if (dhSubPrime.len != 0) {
9944
0
                    PRBool isSafe = PR_FALSE;
9945
9946
                    /* Callers can set dhSubPrime to q=(p-1)/2 to force
9947
                     * checks for safe primes. If so we only need to check
9948
                     * q and p for primality and skip the group test.  */
9949
0
                    rv = sftk_IsSafePrime(&dhPrime, &dhSubPrime, &isSafe);
9950
0
                    if (rv != SECSuccess) {
9951
                        /* either p or q was even and therefore not prime,
9952
                         * we can stop processing here and fail now */
9953
0
                        crv = CKR_ARGUMENTS_BAD;
9954
0
                        SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
9955
0
                        SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
9956
0
                        break;
9957
0
                    }
9958
9959
                    /* first make sure the primes are really prime */
9960
0
                    if (!KEA_PrimeCheck(&dhPrime)) {
9961
0
                        crv = CKR_ARGUMENTS_BAD;
9962
0
                        SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
9963
0
                        SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
9964
0
                        break;
9965
0
                    }
9966
0
                    if (!KEA_PrimeCheck(&dhSubPrime)) {
9967
0
                        crv = CKR_ARGUMENTS_BAD;
9968
0
                        SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
9969
0
                        SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
9970
0
                        break;
9971
0
                    }
9972
0
                    if (isFIPS || !isSafe) {
9973
                        /* With safe primes, there is only one other small
9974
                         * subgroup. As long as y isn't 0, 1, or -1 mod p,
9975
                         * any other y is safe. Only do the full check for
9976
                         * non-safe primes, except in FIPS mode we need
9977
                         * to do this check on all primes in which
9978
                         * we receive the subprime value */
9979
0
                        if (!KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime)) {
9980
0
                            crv = CKR_ARGUMENTS_BAD;
9981
0
                            SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
9982
0
                            SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
9983
0
                            break;
9984
0
                        }
9985
0
                    }
9986
8
                } else if (isFIPS) {
9987
                    /* In FIPS mode we only accept approved primes, or
9988
                     * primes with the full subprime value */
9989
0
                    crv = CKR_ARGUMENTS_BAD;
9990
0
                    SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
9991
0
                    break;
9992
0
                }
9993
                /* checks are complete, no need for the subPrime any longer */
9994
8
                SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
9995
8
            }
9996
9997
            /* now that the prime is validated, get the private value */
9998
5.14k
            crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
9999
5.14k
            if (crv != CKR_OK) {
10000
0
                SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
10001
0
                break;
10002
0
            }
10003
10004
            /* calculate private value - oct */
10005
5.14k
            rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
10006
10007
5.14k
            SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
10008
5.14k
            SECITEM_ZfreeItem(&dhValue, PR_FALSE);
10009
10010
5.14k
            if (rv == SECSuccess) {
10011
5.14k
                key->source = SFTK_SOURCE_KEA;
10012
5.14k
                sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
10013
5.14k
                SECITEM_ZfreeItem(&derived, PR_FALSE);
10014
5.14k
                crv = CKR_OK;
10015
5.14k
            } else
10016
0
                crv = CKR_HOST_MEMORY;
10017
10018
5.14k
            break;
10019
5.14k
        }
10020
10021
60.9k
        case CKM_ECDH1_DERIVE:
10022
60.9k
        case CKM_ECDH1_COFACTOR_DERIVE: {
10023
60.9k
            SECItem ecScalar, ecPoint;
10024
60.9k
            SECItem tmp;
10025
60.9k
            PRBool withCofactor = PR_FALSE;
10026
60.9k
            unsigned char *secret;
10027
60.9k
            unsigned char *keyData = NULL;
10028
60.9k
            unsigned int secretlen, pubKeyLen;
10029
60.9k
            CK_ECDH1_DERIVE_PARAMS *mechParams;
10030
60.9k
            NSSLOWKEYPrivateKey *privKey;
10031
60.9k
            PLArenaPool *arena = NULL;
10032
10033
            /* Check mechanism parameters */
10034
60.9k
            mechParams = (CK_ECDH1_DERIVE_PARAMS *)pMechanism->pParameter;
10035
60.9k
            if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) ||
10036
60.9k
                ((mechParams->kdf == CKD_NULL) &&
10037
60.0k
                 ((mechParams->ulSharedDataLen != 0) ||
10038
60.0k
                  (mechParams->pSharedData != NULL)))) {
10039
0
                crv = CKR_MECHANISM_PARAM_INVALID;
10040
0
                break;
10041
0
            }
10042
10043
60.9k
            privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv);
10044
60.9k
            if (privKey == NULL) {
10045
0
                break;
10046
0
            }
10047
10048
            /* Now we are working with a non-NULL private key */
10049
60.9k
            SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue);
10050
10051
60.9k
            ecPoint.data = mechParams->pPublicData;
10052
60.9k
            ecPoint.len = mechParams->ulPublicDataLen;
10053
10054
60.9k
            pubKeyLen = EC_GetPointSize(&privKey->u.ec.ecParams);
10055
10056
            /* if the len is too large, might be an encoded point */
10057
60.9k
            if (ecPoint.len > pubKeyLen) {
10058
1.97k
                SECItem newPoint;
10059
10060
1.97k
                arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
10061
1.97k
                if (arena == NULL) {
10062
0
                    goto ec_loser;
10063
0
                }
10064
10065
1.97k
                rv = SEC_QuickDERDecodeItem(arena, &newPoint,
10066
1.97k
                                            SEC_ASN1_GET(SEC_OctetStringTemplate),
10067
1.97k
                                            &ecPoint);
10068
1.97k
                if (rv != SECSuccess) {
10069
650
                    goto ec_loser;
10070
650
                }
10071
1.32k
                ecPoint = newPoint;
10072
1.32k
            }
10073
10074
60.3k
            if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) {
10075
0
                withCofactor = PR_TRUE;
10076
0
            }
10077
10078
60.3k
            rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
10079
60.3k
                             withCofactor, &tmp);
10080
60.3k
            SECITEM_ZfreeItem(&ecScalar, PR_FALSE);
10081
60.3k
            ecScalar.data = NULL;
10082
60.3k
            if (privKey != sourceKey->objectInfo) {
10083
0
                nsslowkey_DestroyPrivateKey(privKey);
10084
0
                privKey = NULL;
10085
0
            }
10086
60.3k
            if (arena) {
10087
1.32k
                PORT_FreeArena(arena, PR_FALSE);
10088
1.32k
                arena = NULL;
10089
1.32k
            }
10090
10091
60.3k
            if (rv != SECSuccess) {
10092
3.20k
                crv = sftk_MapCryptError(PORT_GetError());
10093
3.20k
                break;
10094
3.20k
            }
10095
10096
            /*
10097
             * apply the kdf function.
10098
             */
10099
57.1k
            if (mechParams->kdf == CKD_NULL) {
10100
                /*
10101
                 * tmp is the raw data created by ECDH_Derive,
10102
                 * secret and secretlen are the values we will
10103
                 * eventually pass as our generated key.
10104
                 */
10105
57.1k
                secret = tmp.data;
10106
57.1k
                secretlen = tmp.len;
10107
57.1k
            } else {
10108
9
                secretlen = keySize;
10109
9
                sftk_setFIPS(key, PR_FALSE);
10110
9
                crv = sftk_ANSI_X9_63_kdf(&secret, keySize,
10111
9
                                          &tmp, mechParams->pSharedData,
10112
9
                                          mechParams->ulSharedDataLen, mechParams->kdf);
10113
9
                PORT_ZFree(tmp.data, tmp.len);
10114
9
                if (crv != CKR_OK) {
10115
0
                    break;
10116
0
                }
10117
9
                tmp.data = secret;
10118
9
                tmp.len = secretlen;
10119
9
            }
10120
10121
            /*
10122
             * if keySize is supplied, then we are generating a key of a specific
10123
             * length. This is done by taking the least significant 'keySize'
10124
             * bytes from the unsigned value calculated by ECDH. Note: this may
10125
             * mean padding temp with extra leading zeros from what ECDH_Derive
10126
             * already returned (which itself may contain leading zeros).
10127
             */
10128
57.1k
            if (keySize) {
10129
57.1k
                if (secretlen < keySize) {
10130
1
                    keyData = PORT_ZAlloc(keySize);
10131
1
                    if (!keyData) {
10132
0
                        PORT_ZFree(tmp.data, tmp.len);
10133
0
                        crv = CKR_HOST_MEMORY;
10134
0
                        break;
10135
0
                    }
10136
1
                    PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen);
10137
1
                    secret = keyData;
10138
57.1k
                } else {
10139
57.1k
                    secret += (secretlen - keySize);
10140
57.1k
                }
10141
57.1k
                secretlen = keySize;
10142
57.1k
            }
10143
57.1k
            key->source = SFTK_SOURCE_KEA;
10144
10145
57.1k
            sftk_forceAttribute(key, CKA_VALUE, secret, secretlen);
10146
57.1k
            PORT_ZFree(tmp.data, tmp.len);
10147
57.1k
            if (keyData) {
10148
1
                PORT_ZFree(keyData, keySize);
10149
1
            }
10150
57.1k
            break;
10151
10152
650
        ec_loser:
10153
650
            crv = CKR_ARGUMENTS_BAD;
10154
650
            SECITEM_ZfreeItem(&ecScalar, PR_FALSE);
10155
650
            if (privKey != sourceKey->objectInfo)
10156
0
                nsslowkey_DestroyPrivateKey(privKey);
10157
650
            if (arena) {
10158
650
                PORT_FreeArena(arena, PR_TRUE);
10159
650
            }
10160
650
            break;
10161
57.1k
        }
10162
        /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */
10163
33
        case CKM_NSS_HKDF_SHA1:
10164
33
            hashMech = CKM_SHA_1;
10165
33
            goto hkdf;
10166
172
        case CKM_NSS_HKDF_SHA256:
10167
172
            hashMech = CKM_SHA256;
10168
172
            goto hkdf;
10169
102
        case CKM_NSS_HKDF_SHA384:
10170
102
            hashMech = CKM_SHA384;
10171
102
            goto hkdf;
10172
237
        case CKM_NSS_HKDF_SHA512:
10173
237
            hashMech = CKM_SHA512;
10174
237
            goto hkdf;
10175
544
        hkdf : {
10176
544
            const CK_NSS_HKDFParams *params =
10177
544
                (const CK_NSS_HKDFParams *)pMechanism->pParameter;
10178
544
            CK_HKDF_PARAMS hkdfParams;
10179
10180
544
            if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams)) {
10181
0
                crv = CKR_MECHANISM_PARAM_INVALID;
10182
0
                break;
10183
0
            }
10184
544
            hkdfParams.bExtract = params->bExtract;
10185
544
            hkdfParams.bExpand = params->bExpand;
10186
544
            if (params->pSalt) {
10187
137
                hkdfParams.ulSaltType = CKF_HKDF_SALT_DATA;
10188
407
            } else {
10189
407
                hkdfParams.ulSaltType = CKF_HKDF_SALT_NULL;
10190
407
            }
10191
544
            hkdfParams.pSalt = params->pSalt;
10192
544
            hkdfParams.ulSaltLen = params->ulSaltLen;
10193
544
            hkdfParams.hSaltKey = CK_INVALID_HANDLE;
10194
544
            hkdfParams.pInfo = params->pInfo;
10195
544
            hkdfParams.ulInfoLen = params->ulInfoLen;
10196
544
            hkdfParams.prfHashMechanism = hashMech;
10197
10198
544
            crv = sftk_HKDF(&hkdfParams, hSession, sourceKey,
10199
544
                            att->attrib.pValue, att->attrib.ulValueLen,
10200
544
                            key, NULL, keySize, PR_FALSE, isFIPS);
10201
544
        } break;
10202
325k
        case CKM_HKDF_DERIVE:
10203
460k
        case CKM_HKDF_DATA: /* only difference is the class of key */
10204
460k
            if ((pMechanism->pParameter == NULL) ||
10205
460k
                (pMechanism->ulParameterLen != sizeof(CK_HKDF_PARAMS))) {
10206
0
                crv = CKR_MECHANISM_PARAM_INVALID;
10207
0
                break;
10208
0
            }
10209
460k
            crv = sftk_HKDF((CK_HKDF_PARAMS_PTR)pMechanism->pParameter,
10210
460k
                            hSession, sourceKey, att->attrib.pValue,
10211
460k
                            att->attrib.ulValueLen, key, NULL, keySize, PR_TRUE,
10212
460k
                            isFIPS);
10213
460k
            break;
10214
0
        case CKM_NSS_JPAKE_ROUND2_SHA1:
10215
0
            hashType = HASH_AlgSHA1;
10216
0
            goto jpake2;
10217
0
        case CKM_NSS_JPAKE_ROUND2_SHA256:
10218
0
            hashType = HASH_AlgSHA256;
10219
0
            goto jpake2;
10220
0
        case CKM_NSS_JPAKE_ROUND2_SHA384:
10221
0
            hashType = HASH_AlgSHA384;
10222
0
            goto jpake2;
10223
0
        case CKM_NSS_JPAKE_ROUND2_SHA512:
10224
0
            hashType = HASH_AlgSHA512;
10225
0
            goto jpake2;
10226
0
        jpake2:
10227
0
            if (pMechanism->pParameter == NULL ||
10228
0
                pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params))
10229
0
                crv = CKR_MECHANISM_PARAM_INVALID;
10230
0
            if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN))
10231
0
                crv = CKR_TEMPLATE_INCONSISTENT;
10232
0
            if (crv == CKR_OK)
10233
0
                crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
10234
0
            if (crv == CKR_OK)
10235
0
                crv = jpake_Round2(hashType,
10236
0
                                   (CK_NSS_JPAKERound2Params *)pMechanism->pParameter,
10237
0
                                   sourceKey, key);
10238
0
            break;
10239
10240
0
        case CKM_NSS_JPAKE_FINAL_SHA1:
10241
0
            hashType = HASH_AlgSHA1;
10242
0
            goto jpakeFinal;
10243
0
        case CKM_NSS_JPAKE_FINAL_SHA256:
10244
0
            hashType = HASH_AlgSHA256;
10245
0
            goto jpakeFinal;
10246
0
        case CKM_NSS_JPAKE_FINAL_SHA384:
10247
0
            hashType = HASH_AlgSHA384;
10248
0
            goto jpakeFinal;
10249
0
        case CKM_NSS_JPAKE_FINAL_SHA512:
10250
0
            hashType = HASH_AlgSHA512;
10251
0
            goto jpakeFinal;
10252
0
        jpakeFinal:
10253
0
            if (pMechanism->pParameter == NULL ||
10254
0
                pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams))
10255
0
                crv = CKR_MECHANISM_PARAM_INVALID;
10256
            /* We purposely do not do the derive sensitivity check; we want to be
10257
               able to derive non-sensitive keys while allowing the ROUND1 and
10258
               ROUND2 keys to be sensitive (which they always are, since they are
10259
               in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE
10260
               in the template in order for the resultant keyblock key to be
10261
               sensitive.
10262
             */
10263
0
            if (crv == CKR_OK)
10264
0
                crv = jpake_Final(hashType,
10265
0
                                  (CK_NSS_JPAKEFinalParams *)pMechanism->pParameter,
10266
0
                                  sourceKey, key);
10267
0
            break;
10268
10269
0
        case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA:         /* fall through */
10270
0
        case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA:        /* fall through */
10271
0
        case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */
10272
0
        case CKM_SP800_108_COUNTER_KDF:                         /* fall through */
10273
0
        case CKM_SP800_108_FEEDBACK_KDF:                        /* fall through */
10274
0
        case CKM_SP800_108_DOUBLE_PIPELINE_KDF:
10275
0
            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
10276
0
            if (crv != CKR_OK) {
10277
0
                break;
10278
0
            }
10279
10280
0
            crv = kbkdf_Dispatch(mechanism, hSession, pMechanism, sourceKey, key, keySize);
10281
0
            break;
10282
0
        default:
10283
0
            crv = CKR_MECHANISM_INVALID;
10284
802k
    }
10285
802k
    if (att) {
10286
802k
        sftk_FreeAttribute(att);
10287
802k
    }
10288
802k
    sftk_FreeObject(sourceKey);
10289
802k
    if (crv != CKR_OK) {
10290
7.90k
        if (key)
10291
7.90k
            sftk_FreeObject(key);
10292
7.90k
        return crv;
10293
7.90k
    }
10294
10295
    /* link the key object into the list */
10296
794k
    if (key) {
10297
682k
        SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
10298
682k
        if (sessKey == NULL) {
10299
0
            sftk_FreeObject(key);
10300
0
            return CKR_DEVICE_ERROR;
10301
0
        }
10302
682k
        sessKey->wasDerived = PR_TRUE;
10303
682k
        session = sftk_SessionFromHandle(hSession);
10304
682k
        if (session == NULL) {
10305
0
            sftk_FreeObject(key);
10306
0
            return CKR_HOST_MEMORY;
10307
0
        }
10308
10309
682k
        crv = sftk_handleObject(key, session);
10310
682k
        session->lastOpWasFIPS = sftk_hasFIPS(key);
10311
682k
        sftk_FreeSession(session);
10312
682k
        if (phKey) {
10313
682k
            *phKey = key->handle;
10314
682k
        }
10315
682k
        sftk_FreeObject(key);
10316
682k
    }
10317
794k
    return crv;
10318
794k
}
10319
10320
/* NSC_GetFunctionStatus obtains an updated status of a function running
10321
 * in parallel with an application. */
10322
CK_RV
10323
NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)
10324
0
{
10325
0
    CHECK_FORK();
10326
10327
0
    return CKR_FUNCTION_NOT_PARALLEL;
10328
0
}
10329
10330
/* NSC_CancelFunction cancels a function running in parallel */
10331
CK_RV
10332
NSC_CancelFunction(CK_SESSION_HANDLE hSession)
10333
0
{
10334
0
    CHECK_FORK();
10335
10336
0
    return CKR_FUNCTION_NOT_PARALLEL;
10337
0
}
10338
10339
/* NSC_GetOperationState saves the state of the cryptographic
10340
 * operation in a session.
10341
 * NOTE: This code only works for digest functions for now. eventually need
10342
 * to add full flatten/resurect to our state stuff so that all types of state
10343
 * can be saved */
10344
CK_RV
10345
NSC_GetOperationState(CK_SESSION_HANDLE hSession,
10346
                      CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
10347
194k
{
10348
194k
    SFTKSessionContext *context;
10349
194k
    SFTKSession *session;
10350
194k
    CK_RV crv;
10351
194k
    CK_ULONG pOSLen = *pulOperationStateLen;
10352
10353
194k
    CHECK_FORK();
10354
10355
    /* make sure we're legal */
10356
194k
    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
10357
194k
    if (crv != CKR_OK)
10358
0
        return crv;
10359
10360
    /* a zero cipherInfoLen signals that this context cannot be serialized */
10361
194k
    if (context->cipherInfoLen == 0) {
10362
0
        sftk_FreeSession(session);
10363
0
        return CKR_STATE_UNSAVEABLE;
10364
0
    }
10365
10366
194k
    *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) + sizeof(SFTKContextType);
10367
194k
    if (pOperationState == NULL) {
10368
24.9k
        sftk_FreeSession(session);
10369
24.9k
        return CKR_OK;
10370
169k
    } else {
10371
169k
        if (pOSLen < *pulOperationStateLen) {
10372
0
            sftk_FreeSession(session);
10373
0
            return CKR_BUFFER_TOO_SMALL;
10374
0
        }
10375
169k
    }
10376
169k
    PORT_Memcpy(pOperationState, &context->type, sizeof(SFTKContextType));
10377
169k
    pOperationState += sizeof(SFTKContextType);
10378
169k
    PORT_Memcpy(pOperationState, &context->currentMech,
10379
169k
                sizeof(CK_MECHANISM_TYPE));
10380
169k
    pOperationState += sizeof(CK_MECHANISM_TYPE);
10381
169k
    PORT_Memcpy(pOperationState, context->cipherInfo, context->cipherInfoLen);
10382
169k
    sftk_FreeSession(session);
10383
169k
    return CKR_OK;
10384
194k
}
10385
10386
#define sftk_Decrement(stateSize, len) \
10387
509k
    stateSize = ((stateSize) > (CK_ULONG)(len)) ? ((stateSize) - (CK_ULONG)(len)) : 0;
10388
10389
/* NSC_SetOperationState restores the state of the cryptographic
10390
 * operation in a session. This is coded like it can restore lots of
10391
 * states, but it only works for truly flat cipher structures. */
10392
CK_RV
10393
NSC_SetOperationState(CK_SESSION_HANDLE hSession,
10394
                      CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen,
10395
                      CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
10396
169k
{
10397
169k
    SFTKSessionContext *context;
10398
169k
    SFTKSession *session;
10399
169k
    SFTKContextType type;
10400
169k
    CK_MECHANISM mech;
10401
169k
    CK_RV crv = CKR_OK;
10402
10403
169k
    CHECK_FORK();
10404
10405
339k
    while (ulOperationStateLen != 0) {
10406
        /* get what type of state we're dealing with... */
10407
169k
        PORT_Memcpy(&type, pOperationState, sizeof(SFTKContextType));
10408
10409
        /* fix up session contexts based on type */
10410
169k
        session = sftk_SessionFromHandle(hSession);
10411
169k
        if (session == NULL)
10412
0
            return CKR_SESSION_HANDLE_INVALID;
10413
169k
        sftk_UninstallContext(session, type);
10414
169k
        pOperationState += sizeof(SFTKContextType);
10415
169k
        sftk_Decrement(ulOperationStateLen, sizeof(SFTKContextType));
10416
10417
        /* get the mechanism structure */
10418
169k
        PORT_Memcpy(&mech.mechanism, pOperationState, sizeof(CK_MECHANISM_TYPE));
10419
169k
        pOperationState += sizeof(CK_MECHANISM_TYPE);
10420
169k
        sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE));
10421
        /* should be filled in... but not necessary for hash */
10422
169k
        mech.pParameter = NULL;
10423
169k
        mech.ulParameterLen = 0;
10424
169k
        switch (type) {
10425
169k
            case SFTK_HASH:
10426
169k
                crv = NSC_DigestInit(hSession, &mech);
10427
169k
                if (crv != CKR_OK)
10428
0
                    break;
10429
                /* NSC_DigestInit just installed a SFTK_HASH context on
10430
                 * this session; the outer session reference keeps it
10431
                 * alive across the load below. */
10432
169k
                context = sftk_ReturnContextByType(session, SFTK_HASH);
10433
169k
                if (context == NULL || context->type != SFTK_HASH) {
10434
0
                    crv = CKR_OPERATION_NOT_INITIALIZED;
10435
0
                    break;
10436
0
                }
10437
169k
                if (context->cipherInfoLen == 0) {
10438
0
                    crv = CKR_SAVED_STATE_INVALID;
10439
0
                    break;
10440
0
                }
10441
169k
                PORT_Memcpy(context->cipherInfo, pOperationState,
10442
169k
                            context->cipherInfoLen);
10443
169k
                pOperationState += context->cipherInfoLen;
10444
169k
                sftk_Decrement(ulOperationStateLen, context->cipherInfoLen);
10445
169k
                break;
10446
0
            default:
10447
                /* do sign/encrypt/decrypt later */
10448
0
                crv = CKR_SAVED_STATE_INVALID;
10449
169k
        }
10450
169k
        sftk_FreeSession(session);
10451
169k
        if (crv != CKR_OK)
10452
0
            break;
10453
169k
    }
10454
169k
    return crv;
10455
169k
}
10456
10457
/* Dual-function cryptographic operations */
10458
10459
/* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption
10460
 * operation. */
10461
CK_RV
10462
NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
10463
                        CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
10464
                        CK_ULONG_PTR pulEncryptedPartLen)
10465
0
{
10466
0
    CK_RV crv;
10467
10468
0
    CHECK_FORK();
10469
10470
0
    crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
10471
0
                            pulEncryptedPartLen);
10472
0
    if (crv != CKR_OK)
10473
0
        return crv;
10474
0
    crv = NSC_DigestUpdate(hSession, pPart, ulPartLen);
10475
10476
0
    return crv;
10477
0
}
10478
10479
/* NSC_DecryptDigestUpdate continues a multiple-part decryption and
10480
 * digesting operation. */
10481
CK_RV
10482
NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
10483
                        CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
10484
                        CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
10485
0
{
10486
0
    CK_RV crv;
10487
10488
0
    CHECK_FORK();
10489
10490
0
    crv = NSC_DecryptUpdate(hSession, pEncryptedPart, ulEncryptedPartLen,
10491
0
                            pPart, pulPartLen);
10492
0
    if (crv != CKR_OK)
10493
0
        return crv;
10494
0
    crv = NSC_DigestUpdate(hSession, pPart, *pulPartLen);
10495
10496
0
    return crv;
10497
0
}
10498
10499
/* NSC_SignEncryptUpdate continues a multiple-part signing and
10500
 * encryption operation. */
10501
CK_RV
10502
NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
10503
                      CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
10504
                      CK_ULONG_PTR pulEncryptedPartLen)
10505
0
{
10506
0
    CK_RV crv;
10507
10508
0
    CHECK_FORK();
10509
10510
0
    crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
10511
0
                            pulEncryptedPartLen);
10512
0
    if (crv != CKR_OK)
10513
0
        return crv;
10514
0
    crv = NSC_SignUpdate(hSession, pPart, ulPartLen);
10515
10516
0
    return crv;
10517
0
}
10518
10519
/* NSC_DecryptVerifyUpdate continues a multiple-part decryption
10520
 * and verify operation. */
10521
CK_RV
10522
NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
10523
                        CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
10524
                        CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
10525
0
{
10526
0
    CK_RV crv;
10527
10528
0
    CHECK_FORK();
10529
10530
0
    crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
10531
0
                            pData, pulDataLen);
10532
0
    if (crv != CKR_OK)
10533
0
        return crv;
10534
0
    crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen);
10535
10536
0
    return crv;
10537
0
}
10538
10539
/* NSC_DigestKey continues a multi-part message-digesting operation,
10540
 * by digesting the value of a secret key as part of the data already digested.
10541
 */
10542
CK_RV
10543
NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
10544
0
{
10545
0
    SFTKSession *session = NULL;
10546
0
    SFTKObject *key = NULL;
10547
0
    SFTKAttribute *att;
10548
0
    CK_RV crv;
10549
10550
0
    CHECK_FORK();
10551
10552
0
    session = sftk_SessionFromHandle(hSession);
10553
0
    if (session == NULL)
10554
0
        return CKR_SESSION_HANDLE_INVALID;
10555
10556
0
    key = sftk_ObjectFromHandle(hKey, session);
10557
0
    sftk_FreeSession(session);
10558
0
    if (key == NULL)
10559
0
        return CKR_KEY_HANDLE_INVALID;
10560
10561
    /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */
10562
10563
    /* make sure it's a valid  key for this operation */
10564
0
    if (key->objclass != CKO_SECRET_KEY) {
10565
0
        sftk_FreeObject(key);
10566
0
        return CKR_KEY_TYPE_INCONSISTENT;
10567
0
    }
10568
    /* get the key value */
10569
0
    att = sftk_FindAttribute(key, CKA_VALUE);
10570
0
    if (!att) {
10571
0
        sftk_FreeObject(key);
10572
0
        return CKR_KEY_HANDLE_INVALID;
10573
0
    }
10574
0
    crv = NSC_DigestUpdate(hSession, (CK_BYTE_PTR)att->attrib.pValue,
10575
0
                           att->attrib.ulValueLen);
10576
0
    sftk_FreeAttribute(att);
10577
0
    sftk_FreeObject(key);
10578
0
    return crv;
10579
0
}