/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 | 467k | #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 | 721k | #define CKM_SHA1 CKM_SHA_1 |
71 | 175k | #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 | 157k | { |
82 | 157k | return; |
83 | 157k | } |
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 | 4.88M | { \ |
112 | 4.88M | ctxtype *ctx = vctx; \ |
113 | 4.88M | mmm##_Update(ctx, input, len); \ |
114 | 4.88M | } \ pkcs11c.c:SFTKHash_MD2_Update Line | Count | Source | 111 | 10.1k | { \ | 112 | 10.1k | ctxtype *ctx = vctx; \ | 113 | 10.1k | mmm##_Update(ctx, input, len); \ | 114 | 10.1k | } \ |
pkcs11c.c:SFTKHash_MD5_Update Line | Count | Source | 111 | 846k | { \ | 112 | 846k | ctxtype *ctx = vctx; \ | 113 | 846k | mmm##_Update(ctx, input, len); \ | 114 | 846k | } \ |
pkcs11c.c:SFTKHash_SHA1_Update Line | Count | Source | 111 | 950k | { \ | 112 | 950k | ctxtype *ctx = vctx; \ | 113 | 950k | mmm##_Update(ctx, input, len); \ | 114 | 950k | } \ |
pkcs11c.c:SFTKHash_SHA224_Update Line | Count | Source | 111 | 1.09M | { \ | 112 | 1.09M | ctxtype *ctx = vctx; \ | 113 | 1.09M | mmm##_Update(ctx, input, len); \ | 114 | 1.09M | } \ |
pkcs11c.c:SFTKHash_SHA256_Update Line | Count | Source | 111 | 216k | { \ | 112 | 216k | ctxtype *ctx = vctx; \ | 113 | 216k | mmm##_Update(ctx, input, len); \ | 114 | 216k | } \ |
pkcs11c.c:SFTKHash_SHA384_Update Line | Count | Source | 111 | 349k | { \ | 112 | 349k | ctxtype *ctx = vctx; \ | 113 | 349k | mmm##_Update(ctx, input, len); \ | 114 | 349k | } \ |
pkcs11c.c:SFTKHash_SHA512_Update Line | Count | Source | 111 | 130k | { \ | 112 | 130k | ctxtype *ctx = vctx; \ | 113 | 130k | mmm##_Update(ctx, input, len); \ | 114 | 130k | } \ |
pkcs11c.c:SFTKHash_SHA3_224_Update Line | Count | Source | 111 | 20.4k | { \ | 112 | 20.4k | ctxtype *ctx = vctx; \ | 113 | 20.4k | mmm##_Update(ctx, input, len); \ | 114 | 20.4k | } \ |
pkcs11c.c:SFTKHash_SHA3_256_Update Line | Count | Source | 111 | 1.05M | { \ | 112 | 1.05M | ctxtype *ctx = vctx; \ | 113 | 1.05M | mmm##_Update(ctx, input, len); \ | 114 | 1.05M | } \ |
pkcs11c.c:SFTKHash_SHA3_384_Update Line | Count | Source | 111 | 70.4k | { \ | 112 | 70.4k | ctxtype *ctx = vctx; \ | 113 | 70.4k | mmm##_Update(ctx, input, len); \ | 114 | 70.4k | } \ |
pkcs11c.c:SFTKHash_SHA3_512_Update Line | Count | Source | 111 | 79.2k | { \ | 112 | 79.2k | ctxtype *ctx = vctx; \ | 113 | 79.2k | mmm##_Update(ctx, input, len); \ | 114 | 79.2k | } \ |
pkcs11c.c:SFTKHash_sftk_MAC_Update Line | Count | Source | 111 | 62.6k | { \ | 112 | 62.6k | ctxtype *ctx = vctx; \ | 113 | 62.6k | mmm##_Update(ctx, input, len); \ | 114 | 62.6k | } \ |
|
115 | | static void \ |
116 | | SFTKHash_##mmm##_End(void *vctx, unsigned char *digest, \ |
117 | | unsigned int *len, unsigned int maxLen) \ |
118 | 747k | { \ |
119 | 747k | ctxtype *ctx = vctx; \ |
120 | 747k | mmm##_End(ctx, digest, len, maxLen); \ |
121 | 747k | } \ pkcs11c.c:SFTKHash_MD2_End Line | Count | Source | 118 | 19 | { \ | 119 | 19 | ctxtype *ctx = vctx; \ | 120 | 19 | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 19 | } \ |
pkcs11c.c:SFTKHash_MD5_End Line | Count | Source | 118 | 89.6k | { \ | 119 | 89.6k | ctxtype *ctx = vctx; \ | 120 | 89.6k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 89.6k | } \ |
pkcs11c.c:SFTKHash_SHA1_End Line | Count | Source | 118 | 312k | { \ | 119 | 312k | ctxtype *ctx = vctx; \ | 120 | 312k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 312k | } \ |
pkcs11c.c:SFTKHash_SHA224_End Line | Count | Source | 118 | 58.4k | { \ | 119 | 58.4k | ctxtype *ctx = vctx; \ | 120 | 58.4k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 58.4k | } \ |
pkcs11c.c:SFTKHash_SHA256_End Line | Count | Source | 118 | 148k | { \ | 119 | 148k | ctxtype *ctx = vctx; \ | 120 | 148k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 148k | } \ |
pkcs11c.c:SFTKHash_SHA384_End Line | Count | Source | 118 | 60.2k | { \ | 119 | 60.2k | ctxtype *ctx = vctx; \ | 120 | 60.2k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 60.2k | } \ |
pkcs11c.c:SFTKHash_SHA512_End Line | Count | Source | 118 | 19.1k | { \ | 119 | 19.1k | ctxtype *ctx = vctx; \ | 120 | 19.1k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 19.1k | } \ |
pkcs11c.c:SFTKHash_SHA3_224_End Line | Count | Source | 118 | 4.52k | { \ | 119 | 4.52k | ctxtype *ctx = vctx; \ | 120 | 4.52k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 4.52k | } \ |
pkcs11c.c:SFTKHash_SHA3_256_End Line | Count | Source | 118 | 3.31k | { \ | 119 | 3.31k | ctxtype *ctx = vctx; \ | 120 | 3.31k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 3.31k | } \ |
pkcs11c.c:SFTKHash_SHA3_384_End Line | Count | Source | 118 | 7.45k | { \ | 119 | 7.45k | ctxtype *ctx = vctx; \ | 120 | 7.45k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 7.45k | } \ |
pkcs11c.c:SFTKHash_SHA3_512_End Line | Count | Source | 118 | 587 | { \ | 119 | 587 | ctxtype *ctx = vctx; \ | 120 | 587 | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 587 | } \ |
pkcs11c.c:SFTKHash_sftk_MAC_End Line | Count | Source | 118 | 43.2k | { \ | 119 | 43.2k | ctxtype *ctx = vctx; \ | 120 | 43.2k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 43.2k | } \ |
|
122 | | static void \ |
123 | | SFTKHash_##mmm##_DestroyContext(void *vctx, PRBool freeit) \ |
124 | 1.31M | { \ |
125 | 1.31M | ctxtype *ctx = vctx; \ |
126 | 1.31M | mmm##_DestroyContext(ctx, freeit); \ |
127 | 1.31M | } pkcs11c.c:SFTKHash_MD2_DestroyContext Line | Count | Source | 124 | 276 | { \ | 125 | 276 | ctxtype *ctx = vctx; \ | 126 | 276 | mmm##_DestroyContext(ctx, freeit); \ | 127 | 276 | } |
pkcs11c.c:SFTKHash_MD5_DestroyContext Line | Count | Source | 124 | 137k | { \ | 125 | 137k | ctxtype *ctx = vctx; \ | 126 | 137k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 137k | } |
pkcs11c.c:SFTKHash_SHA1_DestroyContext Line | Count | Source | 124 | 360k | { \ | 125 | 360k | ctxtype *ctx = vctx; \ | 126 | 360k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 360k | } |
pkcs11c.c:SFTKHash_SHA224_DestroyContext Line | Count | Source | 124 | 225k | { \ | 125 | 225k | ctxtype *ctx = vctx; \ | 126 | 225k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 225k | } |
pkcs11c.c:SFTKHash_SHA256_DestroyContext Line | Count | Source | 124 | 175k | { \ | 125 | 175k | ctxtype *ctx = vctx; \ | 126 | 175k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 175k | } |
pkcs11c.c:SFTKHash_SHA384_DestroyContext Line | Count | Source | 124 | 72.2k | { \ | 125 | 72.2k | ctxtype *ctx = vctx; \ | 126 | 72.2k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 72.2k | } |
pkcs11c.c:SFTKHash_SHA512_DestroyContext Line | Count | Source | 124 | 62.0k | { \ | 125 | 62.0k | ctxtype *ctx = vctx; \ | 126 | 62.0k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 62.0k | } |
pkcs11c.c:SFTKHash_SHA3_224_DestroyContext Line | Count | Source | 124 | 7.09k | { \ | 125 | 7.09k | ctxtype *ctx = vctx; \ | 126 | 7.09k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 7.09k | } |
pkcs11c.c:SFTKHash_SHA3_256_DestroyContext Line | Count | Source | 124 | 12.8k | { \ | 125 | 12.8k | ctxtype *ctx = vctx; \ | 126 | 12.8k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 12.8k | } |
pkcs11c.c:SFTKHash_SHA3_384_DestroyContext Line | Count | Source | 124 | 9.85k | { \ | 125 | 9.85k | ctxtype *ctx = vctx; \ | 126 | 9.85k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 9.85k | } |
pkcs11c.c:SFTKHash_SHA3_512_DestroyContext Line | Count | Source | 124 | 1.87k | { \ | 125 | 1.87k | ctxtype *ctx = vctx; \ | 126 | 1.87k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 1.87k | } |
pkcs11c.c:SFTKHash_sftk_MAC_DestroyContext Line | Count | Source | 124 | 252k | { \ | 125 | 252k | ctxtype *ctx = vctx; \ | 126 | 252k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 252k | } |
|
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 | 138k | { \ |
162 | 138k | ctxtype *ctx = vctx; \ |
163 | 138k | return mmm(ctx, output, outputLen, maxOutputLen, \ |
164 | 138k | input, inputLen); \ |
165 | 138k | } Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC2_Encrypt pkcs11c.c:SFTKCipher_RC2_Decrypt Line | Count | Source | 161 | 624 | { \ | 162 | 624 | ctxtype *ctx = vctx; \ | 163 | 624 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 624 | input, inputLen); \ | 165 | 624 | } |
pkcs11c.c:SFTKCipher_RC4_Encrypt Line | Count | Source | 161 | 49 | { \ | 162 | 49 | ctxtype *ctx = vctx; \ | 163 | 49 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 49 | input, inputLen); \ | 165 | 49 | } |
pkcs11c.c:SFTKCipher_RC4_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_DES_Encrypt Line | Count | Source | 161 | 62.6k | { \ | 162 | 62.6k | ctxtype *ctx = vctx; \ | 163 | 62.6k | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 62.6k | input, inputLen); \ | 165 | 62.6k | } |
pkcs11c.c:SFTKCipher_DES_Decrypt Line | Count | Source | 161 | 26.5k | { \ | 162 | 26.5k | ctxtype *ctx = vctx; \ | 163 | 26.5k | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 26.5k | input, inputLen); \ | 165 | 26.5k | } |
pkcs11c.c:SFTKCipher_SEED_Encrypt Line | Count | Source | 161 | 556 | { \ | 162 | 556 | ctxtype *ctx = vctx; \ | 163 | 556 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 556 | input, inputLen); \ | 165 | 556 | } |
pkcs11c.c:SFTKCipher_SEED_Decrypt Line | Count | Source | 161 | 1.75k | { \ | 162 | 1.75k | ctxtype *ctx = vctx; \ | 163 | 1.75k | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 1.75k | input, inputLen); \ | 165 | 1.75k | } |
pkcs11c.c:SFTKCipher_Camellia_Encrypt Line | Count | Source | 161 | 724 | { \ | 162 | 724 | ctxtype *ctx = vctx; \ | 163 | 724 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 724 | input, inputLen); \ | 165 | 724 | } |
pkcs11c.c:SFTKCipher_Camellia_Decrypt Line | Count | Source | 161 | 6.82k | { \ | 162 | 6.82k | ctxtype *ctx = vctx; \ | 163 | 6.82k | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 6.82k | input, inputLen); \ | 165 | 6.82k | } |
pkcs11c.c:SFTKCipher_AES_Encrypt Line | Count | Source | 161 | 24.0k | { \ | 162 | 24.0k | ctxtype *ctx = vctx; \ | 163 | 24.0k | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 24.0k | input, inputLen); \ | 165 | 24.0k | } |
pkcs11c.c:SFTKCipher_AES_Decrypt Line | Count | Source | 161 | 14.2k | { \ | 162 | 14.2k | ctxtype *ctx = vctx; \ | 163 | 14.2k | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 14.2k | input, inputLen); \ | 165 | 14.2k | } |
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_EncryptKWP Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_DecryptKWP Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_Encrypt Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_Decrypt |
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 | 280k | { \ |
175 | 280k | ctxtype *ctx = vctx; \ |
176 | 280k | mmm##_DestroyContext(ctx, freeit); \ |
177 | 280k | } pkcs11c.c:SFTKCipher_RC2_DestroyContext Line | Count | Source | 174 | 5.77k | { \ | 175 | 5.77k | ctxtype *ctx = vctx; \ | 176 | 5.77k | mmm##_DestroyContext(ctx, freeit); \ | 177 | 5.77k | } |
pkcs11c.c:SFTKCipher_RC4_DestroyContext Line | Count | Source | 174 | 5.82k | { \ | 175 | 5.82k | ctxtype *ctx = vctx; \ | 176 | 5.82k | mmm##_DestroyContext(ctx, freeit); \ | 177 | 5.82k | } |
pkcs11c.c:SFTKCipher_DES_DestroyContext Line | Count | Source | 174 | 102k | { \ | 175 | 102k | ctxtype *ctx = vctx; \ | 176 | 102k | mmm##_DestroyContext(ctx, freeit); \ | 177 | 102k | } |
pkcs11c.c:SFTKCipher_SEED_DestroyContext Line | Count | Source | 174 | 15.0k | { \ | 175 | 15.0k | ctxtype *ctx = vctx; \ | 176 | 15.0k | mmm##_DestroyContext(ctx, freeit); \ | 177 | 15.0k | } |
pkcs11c.c:SFTKCipher_Camellia_DestroyContext Line | Count | Source | 174 | 32.9k | { \ | 175 | 32.9k | ctxtype *ctx = vctx; \ | 176 | 32.9k | mmm##_DestroyContext(ctx, freeit); \ | 177 | 32.9k | } |
pkcs11c.c:SFTKCipher_AES_DestroyContext Line | Count | Source | 174 | 116k | { \ | 175 | 116k | ctxtype *ctx = vctx; \ | 176 | 116k | mmm##_DestroyContext(ctx, freeit); \ | 177 | 116k | } |
pkcs11c.c:SFTKCipher_AESKeyWrap_DestroyContext Line | Count | Source | 174 | 1.36k | { \ | 175 | 1.36k | ctxtype *ctx = vctx; \ | 176 | 1.36k | mmm##_DestroyContext(ctx, freeit); \ | 177 | 1.36k | } |
|
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 | 277k | { |
209 | 277k | PORT_Free(data); |
210 | 277k | } |
211 | | |
212 | | static void |
213 | | sftk_ZSpace(void *data, PRBool freeit) |
214 | 5.31k | { |
215 | 5.31k | size_t len = *(size_t *)data; |
216 | 5.31k | PORT_ZFree(data, len); |
217 | 5.31k | } |
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 | 2 | { |
226 | 2 | unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae }; |
227 | 2 | unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 }; |
228 | 2 | unsigned char enc_src[8]; |
229 | 2 | unsigned char enc_dest[8]; |
230 | 2 | unsigned int leng, i; |
231 | 2 | DESContext *descx; |
232 | 2 | SECStatus rv; |
233 | 2 | CK_RV crv = CKR_OK; |
234 | | |
235 | | /* zero the parity bits */ |
236 | 18 | for (i = 0; i < 8; i++) { |
237 | 16 | enc_src[i] = cdmfkey[i] & 0xfe; |
238 | 16 | } |
239 | | |
240 | | /* encrypt with key 1 */ |
241 | 2 | descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE); |
242 | 2 | if (descx == NULL) { |
243 | 0 | crv = CKR_HOST_MEMORY; |
244 | 0 | goto done; |
245 | 0 | } |
246 | 2 | rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8); |
247 | 2 | DES_DestroyContext(descx, PR_TRUE); |
248 | 2 | 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 | 18 | for (i = 0; i < 8; i++) { |
255 | 16 | if (i & 1) { |
256 | 8 | enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe; |
257 | 8 | } else { |
258 | 8 | enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e; |
259 | 8 | } |
260 | 16 | } |
261 | | |
262 | | /* encrypt with key 2 */ |
263 | 2 | descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE); |
264 | 2 | if (descx == NULL) { |
265 | 0 | crv = CKR_HOST_MEMORY; |
266 | 0 | goto done; |
267 | 0 | } |
268 | 2 | rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8); |
269 | 2 | DES_DestroyContext(descx, PR_TRUE); |
270 | 2 | 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 | 2 | sftk_FormatDESKey(deskey, 8); |
277 | 2 | done: |
278 | 2 | PORT_Memset(enc_src, 0, sizeof enc_src); |
279 | 2 | PORT_Memset(enc_dest, 0, sizeof enc_dest); |
280 | 2 | return crv; |
281 | 2 | } |
282 | | |
283 | | /* NSC_DestroyObject destroys an object. */ |
284 | | CK_RV |
285 | | NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) |
286 | 1.58M | { |
287 | 1.58M | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
288 | 1.58M | SFTKSession *session; |
289 | 1.58M | SFTKObject *object; |
290 | 1.58M | SFTKFreeStatus status; |
291 | | |
292 | 1.58M | CHECK_FORK(); |
293 | | |
294 | 1.58M | 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.58M | session = sftk_SessionFromHandle(hSession); |
302 | 1.58M | if (session == NULL) { |
303 | 0 | return CKR_SESSION_HANDLE_INVALID; |
304 | 0 | } |
305 | | |
306 | 1.58M | object = sftk_ObjectFromHandle(hObject, session); |
307 | 1.58M | if (object == NULL) { |
308 | 1.72k | sftk_FreeSession(session); |
309 | 1.72k | return CKR_OBJECT_HANDLE_INVALID; |
310 | 1.72k | } |
311 | | |
312 | | /* don't destroy a private object if we aren't logged in */ |
313 | 1.58M | PR_Lock(slot->slotLock); |
314 | 1.58M | PRBool wouldNeedToLogIn = !slot->isLoggedIn && slot->needLogin; |
315 | 1.58M | PR_Unlock(slot->slotLock); |
316 | 1.58M | 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.58M | if (((session->info.flags & CKF_RW_SESSION) == 0) && |
325 | 1.58M | (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.58M | sftk_DeleteObject(session, object); |
332 | | |
333 | 1.58M | 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.58M | status = sftk_FreeObject(object); |
343 | | |
344 | 1.58M | return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR; |
345 | 1.58M | } |
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.31k | { |
353 | 5.31k | if (!params) { |
354 | 0 | return PR_FALSE; |
355 | 0 | } |
356 | 5.31k | if (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL || |
357 | 5.31k | sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) { |
358 | 3 | return PR_FALSE; |
359 | 3 | } |
360 | 5.31k | return PR_TRUE; |
361 | 5.31k | } |
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 | 12.9M | { |
393 | 12.9M | switch (type) { |
394 | 719k | case SFTK_ENCRYPT: |
395 | 1.33M | case SFTK_DECRYPT: |
396 | 1.51M | case SFTK_MESSAGE_ENCRYPT: |
397 | 1.70M | case SFTK_MESSAGE_DECRYPT: |
398 | 1.70M | return session->enc_context; |
399 | 9.10M | case SFTK_HASH: |
400 | 9.10M | return session->hash_context; |
401 | 1.99M | case SFTK_SIGN: |
402 | 1.99M | case SFTK_SIGN_RECOVER: |
403 | 2.06M | case SFTK_VERIFY: |
404 | 2.13M | case SFTK_VERIFY_RECOVER: |
405 | 2.13M | case SFTK_MESSAGE_SIGN: |
406 | 2.13M | case SFTK_MESSAGE_VERIFY: |
407 | 2.13M | return session->hash_context; |
408 | 12.9M | } |
409 | 0 | return NULL; |
410 | 12.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.59M | { |
419 | 3.59M | switch (type) { |
420 | 318k | case SFTK_ENCRYPT: |
421 | 600k | case SFTK_DECRYPT: |
422 | 678k | case SFTK_MESSAGE_ENCRYPT: |
423 | 762k | case SFTK_MESSAGE_DECRYPT: |
424 | 762k | session->enc_context = context; |
425 | 762k | break; |
426 | 1.95M | case SFTK_HASH: |
427 | 1.95M | session->hash_context = context; |
428 | 1.95M | break; |
429 | 822k | case SFTK_SIGN: |
430 | 822k | case SFTK_SIGN_RECOVER: |
431 | 844k | case SFTK_VERIFY: |
432 | 878k | case SFTK_VERIFY_RECOVER: |
433 | 878k | case SFTK_MESSAGE_SIGN: |
434 | 878k | case SFTK_MESSAGE_VERIFY: |
435 | 878k | session->hash_context = context; |
436 | 878k | break; |
437 | 3.59M | } |
438 | 3.59M | return; |
439 | 3.59M | } |
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.16M | { |
456 | 2.16M | SFTKSlot *slot = sftk_SlotFromSession(session); |
457 | 2.16M | PRLock *lock = SFTK_SESSION_LOCK(slot, session->handle); |
458 | 2.16M | CK_RV crv; |
459 | | |
460 | 2.16M | PR_Lock(lock); |
461 | 2.16M | if (sftk_ReturnContextByType(session, type) != NULL) { |
462 | 0 | crv = CKR_OPERATION_ACTIVE; |
463 | 2.16M | } else { |
464 | 2.16M | sftk_SetContextByType(session, type, context); |
465 | 2.16M | crv = CKR_OK; |
466 | 2.16M | } |
467 | 2.16M | PR_Unlock(lock); |
468 | 2.16M | return crv; |
469 | 2.16M | } |
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.43M | { |
480 | 1.43M | SFTKSlot *slot = sftk_SlotFromSession(session); |
481 | 1.43M | PRLock *lock = SFTK_SESSION_LOCK(slot, session->handle); |
482 | 1.43M | SFTKSessionContext *context; |
483 | | |
484 | 1.43M | PR_Lock(lock); |
485 | 1.43M | context = sftk_ReturnContextByType(session, type); |
486 | 1.43M | 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.43M | if (context) { |
491 | 1.26M | session->lastOpWasFIPS = context->isFIPS; |
492 | 1.26M | } |
493 | 1.43M | PR_Unlock(lock); |
494 | 1.43M | if (context) { |
495 | 1.26M | sftk_FreeContext(context); |
496 | 1.26M | } |
497 | 1.43M | } |
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 | 6.91M | { |
512 | 6.91M | SFTKSession *session; |
513 | 6.91M | SFTKSessionContext *context; |
514 | | |
515 | 6.91M | PORT_Assert(sessionPtr != NULL); |
516 | 6.91M | session = sftk_SessionFromHandle(handle); |
517 | 6.91M | if (session == NULL) |
518 | 0 | return CKR_SESSION_HANDLE_INVALID; |
519 | 6.91M | context = sftk_ReturnContextByType(session, type); |
520 | | /* make sure the context is valid */ |
521 | 6.91M | if ((context == NULL) || (context->type != type) || (needMulti && !(context->multi))) { |
522 | 198k | sftk_FreeSession(session); |
523 | 198k | return CKR_OPERATION_NOT_INITIALIZED; |
524 | 198k | } |
525 | 6.71M | *contextPtr = context; |
526 | 6.71M | *sessionPtr = session; |
527 | 6.71M | return CKR_OK; |
528 | 6.91M | } |
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.23M | { |
537 | 1.23M | sftk_UninstallContext(session, ctype); |
538 | 1.23M | } |
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.16M | { |
555 | 2.16M | SFTKObject *key = NULL; |
556 | 2.16M | SFTKAttribute *att; |
557 | 2.16M | SFTKSessionContext *context; |
558 | | |
559 | | /* We can only init if there is not current context active */ |
560 | 2.16M | if (sftk_ReturnContextByType(session, ctype) != NULL) { |
561 | 0 | return CKR_OPERATION_ACTIVE; |
562 | 0 | } |
563 | | |
564 | | /* find the key */ |
565 | 2.16M | if (keyPtr) { |
566 | 1.10M | key = sftk_ObjectFromHandle(hKey, session); |
567 | 1.10M | 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.10M | if (((key->objclass != CKO_SECRET_KEY) && |
573 | 164k | (key->objclass != pubKeyType)) || |
574 | 1.10M | !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.10M | att = sftk_FindAttribute(key, CKA_KEY_TYPE); |
580 | 1.10M | if (att == NULL) { |
581 | 0 | sftk_FreeObject(key); |
582 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
583 | 0 | } |
584 | 1.10M | PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE)); |
585 | 1.10M | 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.10M | PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE)); |
591 | 1.10M | sftk_FreeAttribute(att); |
592 | 1.10M | *keyPtr = key; |
593 | 1.10M | } |
594 | | |
595 | | /* allocate the context structure */ |
596 | 2.16M | context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext)); |
597 | 2.16M | if (context == NULL) { |
598 | 0 | if (key) |
599 | 0 | sftk_FreeObject(key); |
600 | 0 | return CKR_HOST_MEMORY; |
601 | 0 | } |
602 | 2.16M | context->type = ctype; |
603 | 2.16M | context->multi = PR_TRUE; |
604 | 2.16M | context->rsa = PR_FALSE; |
605 | 2.16M | context->cipherInfo = NULL; |
606 | 2.16M | context->hashInfo = NULL; |
607 | 2.16M | context->doPad = PR_FALSE; |
608 | 2.16M | context->padDataLength = 0; |
609 | 2.16M | context->key = key; |
610 | 2.16M | context->blockSize = 0; |
611 | 2.16M | context->maxLen = 0; |
612 | 2.16M | context->signature = NULL; |
613 | 2.16M | context->isFIPS = sftk_operationIsFIPS(session->slot, pMechanism, |
614 | 2.16M | operation, key, 0); |
615 | 2.16M | *contextPtr = context; |
616 | 2.16M | return CKR_OK; |
617 | 2.16M | } |
618 | | |
619 | | static int |
620 | | sftk_aes_mode(CK_MECHANISM_TYPE mechanism) |
621 | 116k | { |
622 | 116k | switch (mechanism) { |
623 | 483 | case CKM_AES_CBC_PAD: |
624 | 91.1k | case CKM_AES_CBC: |
625 | 91.1k | return NSS_AES_CBC; |
626 | 24.5k | case CKM_AES_ECB: |
627 | 24.5k | return NSS_AES; |
628 | 0 | case CKM_AES_CTS: |
629 | 0 | return NSS_AES_CTS; |
630 | 437 | case CKM_AES_CTR: |
631 | 437 | return NSS_AES_CTR; |
632 | 582 | case CKM_AES_GCM: |
633 | 582 | return NSS_AES_GCM; |
634 | 116k | } |
635 | 0 | return -1; |
636 | 116k | } |
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.2k | { |
689 | 15.2k | NSSLOWKEYPublicKey *key = ctx; |
690 | 15.2k | SECStatus rv = SECFailure; |
691 | | |
692 | 15.2k | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
693 | 15.2k | if (key->keyType != NSSLOWKEYRSAKey) { |
694 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
695 | 0 | return SECFailure; |
696 | 0 | } |
697 | | |
698 | 15.2k | rv = RSA_EncryptBlock(&key->u.rsa, output, outputLen, maxLen, input, |
699 | 15.2k | inputLen); |
700 | 15.2k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
701 | 0 | sftk_fatalError = PR_TRUE; |
702 | 0 | } |
703 | | |
704 | 15.2k | return rv; |
705 | 15.2k | } |
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 | 88.1k | { |
712 | 88.1k | NSSLOWKEYPrivateKey *key = ctx; |
713 | 88.1k | SECStatus rv = SECFailure; |
714 | | |
715 | 88.1k | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
716 | 88.1k | if (key->keyType != NSSLOWKEYRSAKey) { |
717 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
718 | 0 | return SECFailure; |
719 | 0 | } |
720 | | |
721 | 88.1k | rv = RSA_DecryptBlock(&key->u.rsa, output, outputLen, maxLen, input, |
722 | 88.1k | inputLen); |
723 | 88.1k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
724 | 0 | sftk_fatalError = PR_TRUE; |
725 | 0 | } |
726 | | |
727 | 88.1k | return rv; |
728 | 88.1k | } |
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 | 275 | { |
796 | 275 | SFTKChaCha20Poly1305Info *ctx; |
797 | | |
798 | 275 | if (params->ulNonceLen != sizeof(ctx->nonce)) { |
799 | 47 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
800 | 47 | return NULL; |
801 | 47 | } |
802 | | |
803 | 228 | ctx = PORT_New(SFTKChaCha20Poly1305Info); |
804 | 228 | if (ctx == NULL) { |
805 | 0 | return NULL; |
806 | 0 | } |
807 | | |
808 | 228 | if (ChaCha20Poly1305_InitContext(&ctx->freeblCtx, key, keyLen, |
809 | 228 | params->ulTagLen) != SECSuccess) { |
810 | 66 | PORT_Free(ctx); |
811 | 66 | return NULL; |
812 | 66 | } |
813 | | |
814 | 162 | PORT_Memcpy(ctx->nonce, params->pNonce, sizeof(ctx->nonce)); |
815 | | |
816 | | /* AAD data and length must both be null, or both non-null. */ |
817 | 162 | PORT_Assert((params->pAAD == NULL) == (params->ulAADLen == 0)); |
818 | | |
819 | 162 | 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 | 162 | } else { |
828 | 162 | ctx->adOverflow = NULL; |
829 | 162 | if (params->pAAD) { |
830 | 0 | PORT_Memcpy(ctx->ad, params->pAAD, params->ulAADLen); |
831 | 0 | } |
832 | 162 | } |
833 | 162 | ctx->adLen = params->ulAADLen; |
834 | | |
835 | 162 | return ctx; |
836 | 162 | } |
837 | | |
838 | | static void |
839 | | sftk_ChaCha20Poly1305_DestroyContext(void *vctx, |
840 | | PRBool freeit) |
841 | 162 | { |
842 | 162 | SFTKChaCha20Poly1305Info *ctx = vctx; |
843 | 162 | ChaCha20Poly1305_DestroyContext(&ctx->freeblCtx, PR_FALSE); |
844 | 162 | if (ctx->adOverflow != NULL) { |
845 | 0 | PORT_ZFree(ctx->adOverflow, ctx->adLen); |
846 | 0 | ctx->adOverflow = NULL; |
847 | 162 | } else { |
848 | 162 | PORT_Memset(ctx->ad, 0, ctx->adLen); |
849 | 162 | } |
850 | 162 | ctx->adLen = 0; |
851 | 162 | if (freeit) { |
852 | 162 | PORT_Free(ctx); |
853 | 162 | } |
854 | 162 | } |
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 | 77 | { |
862 | 77 | const SFTKChaCha20Poly1305Info *ctx = vctx; |
863 | 77 | const unsigned char *ad = ctx->adOverflow; |
864 | | |
865 | 77 | if (ad == NULL) { |
866 | 77 | ad = ctx->ad; |
867 | 77 | } |
868 | | |
869 | 77 | return ChaCha20Poly1305_Seal(&ctx->freeblCtx, output, outputLen, |
870 | 77 | maxOutputLen, input, inputLen, ctx->nonce, |
871 | 77 | sizeof(ctx->nonce), ad, ctx->adLen); |
872 | 77 | } |
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 | 85 | { |
880 | 85 | const SFTKChaCha20Poly1305Info *ctx = vctx; |
881 | 85 | const unsigned char *ad = ctx->adOverflow; |
882 | | |
883 | 85 | if (ad == NULL) { |
884 | 85 | ad = ctx->ad; |
885 | 85 | } |
886 | | |
887 | 85 | return ChaCha20Poly1305_Open(&ctx->freeblCtx, output, outputLen, |
888 | 85 | maxOutputLen, input, inputLen, ctx->nonce, |
889 | 85 | sizeof(ctx->nonce), ad, ctx->adLen); |
890 | 85 | } |
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 | 13.9k | { |
898 | 13.9k | if (maxOutputLen < inputLen) { |
899 | 0 | PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
900 | 0 | return SECFailure; |
901 | 0 | } |
902 | 13.9k | SFTKChaCha20CtrInfo *ctx = vctx; |
903 | 13.9k | ChaCha20_Xor(output, input, inputLen, ctx->key, |
904 | 13.9k | ctx->nonce, ctx->counter); |
905 | 13.9k | *outputLen = inputLen; |
906 | 13.9k | return SECSuccess; |
907 | 13.9k | } |
908 | | |
909 | | static void |
910 | | sftk_ChaCha20Ctr_DestroyContext(void *vctx, |
911 | | PRBool freeit) |
912 | 13.9k | { |
913 | 13.9k | SFTKChaCha20CtrInfo *ctx = vctx; |
914 | 13.9k | memset(ctx, 0, sizeof(SFTKChaCha20CtrInfo)); |
915 | 13.9k | if (freeit) { |
916 | 13.9k | PORT_Free(ctx); |
917 | 13.9k | } |
918 | 13.9k | } |
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 | 399k | { |
932 | 399k | SFTKSession *session; |
933 | 399k | SFTKObject *key; |
934 | 399k | SFTKSessionContext *context; |
935 | 399k | SFTKAttribute *att; |
936 | 399k | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
937 | 399k | CK_RC2_CBC_PARAMS *rc2_param; |
938 | 399k | unsigned effectiveKeyLength; |
939 | 399k | #endif |
940 | | #if NSS_SOFTOKEN_DOES_RC5 |
941 | | CK_RC5_CBC_PARAMS *rc5_param; |
942 | | SECItem rc5Key; |
943 | | #endif |
944 | 399k | CK_NSS_GCM_PARAMS nss_gcm_param; |
945 | 399k | void *aes_param; |
946 | 399k | CK_NSS_AEAD_PARAMS nss_aead_params; |
947 | 399k | CK_NSS_AEAD_PARAMS *nss_aead_params_ptr = NULL; |
948 | 399k | CK_KEY_TYPE key_type; |
949 | 399k | CK_RV crv = CKR_OK; |
950 | 399k | unsigned char newdeskey[24]; |
951 | 399k | PRBool useNewKey = PR_FALSE; |
952 | 399k | int t; |
953 | | |
954 | 399k | if (!pMechanism) { |
955 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
956 | 0 | } |
957 | | |
958 | 399k | crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage); |
959 | 399k | if (crv != CKR_OK) |
960 | 689 | return crv; |
961 | | |
962 | 398k | session = sftk_SessionFromHandle(hSession); |
963 | 398k | if (session == NULL) |
964 | 0 | return CKR_SESSION_HANDLE_INVALID; |
965 | | |
966 | 398k | crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key, |
967 | 398k | hKey, &key_type, |
968 | 398k | isEncrypt ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY, |
969 | 398k | keyUsage); |
970 | | |
971 | 398k | if (crv != CKR_OK) { |
972 | 0 | sftk_FreeSession(session); |
973 | 0 | return crv; |
974 | 0 | } |
975 | | |
976 | 398k | context->doPad = PR_FALSE; |
977 | 398k | switch (pMechanism->mechanism) { |
978 | 103k | case CKM_RSA_PKCS: |
979 | 103k | case CKM_RSA_X_509: |
980 | 103k | if (key_type != CKK_RSA) { |
981 | 5 | crv = CKR_KEY_TYPE_INCONSISTENT; |
982 | 5 | break; |
983 | 5 | } |
984 | 103k | context->multi = PR_FALSE; |
985 | 103k | context->rsa = PR_TRUE; |
986 | 103k | if (isEncrypt) { |
987 | 15.2k | NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); |
988 | 15.2k | if (pubKey == NULL) { |
989 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
990 | 0 | break; |
991 | 0 | } |
992 | 15.2k | context->maxLen = nsslowkey_PublicModulusLen(pubKey); |
993 | 15.2k | context->cipherInfo = (void *)pubKey; |
994 | 15.2k | context->update = pMechanism->mechanism == CKM_RSA_X_509 |
995 | 15.2k | ? sftk_RSAEncryptRaw |
996 | 15.2k | : sftk_RSAEncrypt; |
997 | 88.1k | } else { |
998 | 88.1k | NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key, CKK_RSA, &crv); |
999 | 88.1k | if (privKey == NULL) { |
1000 | 3 | crv = CKR_KEY_HANDLE_INVALID; |
1001 | 3 | break; |
1002 | 3 | } |
1003 | 88.1k | context->maxLen = nsslowkey_PrivateModulusLen(privKey); |
1004 | 88.1k | context->cipherInfo = (void *)privKey; |
1005 | 88.1k | context->update = pMechanism->mechanism == CKM_RSA_X_509 |
1006 | 88.1k | ? sftk_RSADecryptRaw |
1007 | 88.1k | : sftk_RSADecrypt; |
1008 | 88.1k | } |
1009 | 103k | context->destroy = sftk_Null; |
1010 | 103k | break; |
1011 | 6 | case CKM_RSA_PKCS_OAEP: |
1012 | 6 | if (key_type != CKK_RSA) { |
1013 | 6 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1014 | 6 | break; |
1015 | 6 | } |
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 | 5.77k | case CKM_RC2_CBC: |
1078 | 5.77k | context->blockSize = 8; |
1079 | 5.77k | if (key_type != CKK_RC2) { |
1080 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1081 | 0 | break; |
1082 | 0 | } |
1083 | 5.77k | att = sftk_FindAttribute(key, CKA_VALUE); |
1084 | 5.77k | if (att == NULL) { |
1085 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1086 | 0 | break; |
1087 | 0 | } |
1088 | | |
1089 | 5.77k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_CBC_PARAMS))) { |
1090 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1091 | 0 | break; |
1092 | 0 | } |
1093 | 5.77k | rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter; |
1094 | 5.77k | effectiveKeyLength = (rc2_param->ulEffectiveBits + 7) / 8; |
1095 | 5.77k | context->cipherInfo = |
1096 | 5.77k | RC2_CreateContext((unsigned char *)att->attrib.pValue, |
1097 | 5.77k | att->attrib.ulValueLen, rc2_param->iv, |
1098 | 5.77k | pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : NSS_RC2_CBC, effectiveKeyLength); |
1099 | 5.77k | sftk_FreeAttribute(att); |
1100 | 5.77k | if (context->cipherInfo == NULL) { |
1101 | 0 | crv = CKR_HOST_MEMORY; |
1102 | 0 | break; |
1103 | 0 | } |
1104 | 5.77k | context->update = isEncrypt ? SFTKCipher_RC2_Encrypt : SFTKCipher_RC2_Decrypt; |
1105 | 5.77k | context->destroy = SFTKCipher_RC2_DestroyContext; |
1106 | 5.77k | break; |
1107 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
1108 | | |
1109 | | #if NSS_SOFTOKEN_DOES_RC5 |
1110 | | case CKM_RC5_CBC_PAD: |
1111 | | context->doPad = PR_TRUE; |
1112 | | /* fall thru */ |
1113 | | case CKM_RC5_ECB: |
1114 | | case CKM_RC5_CBC: |
1115 | | if (key_type != CKK_RC5) { |
1116 | | crv = CKR_KEY_TYPE_INCONSISTENT; |
1117 | | break; |
1118 | | } |
1119 | | att = sftk_FindAttribute(key, CKA_VALUE); |
1120 | | if (att == NULL) { |
1121 | | crv = CKR_KEY_HANDLE_INVALID; |
1122 | | break; |
1123 | | } |
1124 | | |
1125 | | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_CBC_PARAMS))) { |
1126 | | crv = CKR_MECHANISM_PARAM_INVALID; |
1127 | | break; |
1128 | | } |
1129 | | rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter; |
1130 | | context->blockSize = rc5_param->ulWordsize * 2; |
1131 | | rc5Key.data = (unsigned char *)att->attrib.pValue; |
1132 | | rc5Key.len = att->attrib.ulValueLen; |
1133 | | context->cipherInfo = RC5_CreateContext(&rc5Key, rc5_param->ulRounds, |
1134 | | rc5_param->ulWordsize, rc5_param->pIv, |
1135 | | pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC); |
1136 | | sftk_FreeAttribute(att); |
1137 | | if (context->cipherInfo == NULL) { |
1138 | | crv = CKR_HOST_MEMORY; |
1139 | | break; |
1140 | | } |
1141 | | context->update = isEncrypt ? SFTKCipher_RC5_Encrypt : SFTKCipher_RC5_Decrypt; |
1142 | | context->destroy = SFTKCipher_RC5_DestroyContext; |
1143 | | break; |
1144 | | #endif |
1145 | 5.85k | case CKM_RC4: |
1146 | 5.85k | if (key_type != CKK_RC4) { |
1147 | 19 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1148 | 19 | break; |
1149 | 19 | } |
1150 | 5.83k | att = sftk_FindAttribute(key, CKA_VALUE); |
1151 | 5.83k | if (att == NULL) { |
1152 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1153 | 0 | break; |
1154 | 0 | } |
1155 | 5.83k | context->cipherInfo = |
1156 | 5.83k | RC4_CreateContext((unsigned char *)att->attrib.pValue, |
1157 | 5.83k | att->attrib.ulValueLen); |
1158 | 5.83k | sftk_FreeAttribute(att); |
1159 | 5.83k | if (context->cipherInfo == NULL) { |
1160 | 12 | crv = CKR_HOST_MEMORY; /* WRONG !!! */ |
1161 | 12 | break; |
1162 | 12 | } |
1163 | 5.82k | context->update = isEncrypt ? SFTKCipher_RC4_Encrypt : SFTKCipher_RC4_Decrypt; |
1164 | 5.82k | context->destroy = SFTKCipher_RC4_DestroyContext; |
1165 | 5.82k | break; |
1166 | 0 | case CKM_CDMF_CBC_PAD: |
1167 | 0 | context->doPad = PR_TRUE; |
1168 | | /* fall thru */ |
1169 | 0 | case CKM_CDMF_ECB: |
1170 | 2 | case CKM_CDMF_CBC: |
1171 | 2 | if (key_type != CKK_CDMF) { |
1172 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1173 | 0 | break; |
1174 | 0 | } |
1175 | 2 | t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC; |
1176 | 2 | goto finish_des; |
1177 | 92 | case CKM_DES_ECB: |
1178 | 92 | if (key_type != CKK_DES) { |
1179 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1180 | 0 | break; |
1181 | 0 | } |
1182 | 92 | t = NSS_DES; |
1183 | 92 | goto finish_des; |
1184 | 0 | case CKM_DES_CBC_PAD: |
1185 | 0 | context->doPad = PR_TRUE; |
1186 | | /* fall thru */ |
1187 | 11.5k | case CKM_DES_CBC: |
1188 | 11.5k | if (key_type != CKK_DES) { |
1189 | 6 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1190 | 6 | break; |
1191 | 6 | } |
1192 | 11.5k | t = NSS_DES_CBC; |
1193 | 11.5k | goto finish_des; |
1194 | 61.3k | case CKM_DES3_ECB: |
1195 | 61.3k | if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { |
1196 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1197 | 0 | break; |
1198 | 0 | } |
1199 | 61.3k | t = NSS_DES_EDE3; |
1200 | 61.3k | goto finish_des; |
1201 | 0 | case CKM_DES3_CBC_PAD: |
1202 | 0 | context->doPad = PR_TRUE; |
1203 | | /* fall thru */ |
1204 | 29.7k | case CKM_DES3_CBC: |
1205 | 29.7k | if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { |
1206 | 2 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1207 | 2 | break; |
1208 | 2 | } |
1209 | 29.7k | t = NSS_DES_EDE3_CBC; |
1210 | 102k | finish_des: |
1211 | 102k | if ((t != NSS_DES && t != NSS_DES_EDE3) && (pMechanism->pParameter == NULL || |
1212 | 41.3k | pMechanism->ulParameterLen < 8)) { |
1213 | 7 | crv = CKR_DOMAIN_PARAMS_INVALID; |
1214 | 7 | break; |
1215 | 7 | } |
1216 | 102k | context->blockSize = 8; |
1217 | 102k | att = sftk_FindAttribute(key, CKA_VALUE); |
1218 | 102k | if (att == NULL) { |
1219 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1220 | 0 | break; |
1221 | 0 | } |
1222 | 102k | if (key_type == CKK_DES2 && |
1223 | 7 | (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) { |
1224 | | /* extend DES2 key to DES3 key. */ |
1225 | 7 | memcpy(newdeskey, att->attrib.pValue, 16); |
1226 | 7 | memcpy(newdeskey + 16, newdeskey, 8); |
1227 | 7 | useNewKey = PR_TRUE; |
1228 | 102k | } else if (key_type == CKK_CDMF) { |
1229 | 2 | crv = sftk_cdmf2des((unsigned char *)att->attrib.pValue, newdeskey); |
1230 | 2 | if (crv != CKR_OK) { |
1231 | 0 | sftk_FreeAttribute(att); |
1232 | 0 | break; |
1233 | 0 | } |
1234 | 2 | useNewKey = PR_TRUE; |
1235 | 2 | } |
1236 | 102k | context->cipherInfo = DES_CreateContext( |
1237 | 102k | useNewKey ? newdeskey : (unsigned char *)att->attrib.pValue, |
1238 | 102k | (unsigned char *)pMechanism->pParameter, t, isEncrypt); |
1239 | 102k | if (useNewKey) |
1240 | 9 | memset(newdeskey, 0, sizeof newdeskey); |
1241 | 102k | sftk_FreeAttribute(att); |
1242 | 102k | if (context->cipherInfo == NULL) { |
1243 | 0 | crv = CKR_HOST_MEMORY; |
1244 | 0 | break; |
1245 | 0 | } |
1246 | 102k | context->update = isEncrypt ? SFTKCipher_DES_Encrypt : SFTKCipher_DES_Decrypt; |
1247 | 102k | context->destroy = SFTKCipher_DES_DestroyContext; |
1248 | 102k | break; |
1249 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
1250 | 0 | case CKM_SEED_CBC_PAD: |
1251 | 0 | context->doPad = PR_TRUE; |
1252 | | /* fall thru */ |
1253 | 14.7k | case CKM_SEED_CBC: |
1254 | 14.7k | if (!pMechanism->pParameter || |
1255 | 14.7k | pMechanism->ulParameterLen != 16) { |
1256 | 10 | crv = CKR_MECHANISM_PARAM_INVALID; |
1257 | 10 | break; |
1258 | 10 | } |
1259 | | /* fall thru */ |
1260 | 15.0k | case CKM_SEED_ECB: |
1261 | 15.0k | context->blockSize = 16; |
1262 | 15.0k | if (key_type != CKK_SEED) { |
1263 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1264 | 0 | break; |
1265 | 0 | } |
1266 | 15.0k | att = sftk_FindAttribute(key, CKA_VALUE); |
1267 | 15.0k | if (att == NULL) { |
1268 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1269 | 0 | break; |
1270 | 0 | } |
1271 | 15.0k | context->cipherInfo = SEED_CreateContext( |
1272 | 15.0k | (unsigned char *)att->attrib.pValue, |
1273 | 15.0k | (unsigned char *)pMechanism->pParameter, |
1274 | 15.0k | pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC, |
1275 | 15.0k | isEncrypt); |
1276 | 15.0k | sftk_FreeAttribute(att); |
1277 | 15.0k | if (context->cipherInfo == NULL) { |
1278 | 0 | crv = CKR_HOST_MEMORY; |
1279 | 0 | break; |
1280 | 0 | } |
1281 | 15.0k | context->update = isEncrypt ? SFTKCipher_SEED_Encrypt : SFTKCipher_SEED_Decrypt; |
1282 | 15.0k | context->destroy = SFTKCipher_SEED_DestroyContext; |
1283 | 15.0k | break; |
1284 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
1285 | 0 | case CKM_CAMELLIA_CBC_PAD: |
1286 | 0 | context->doPad = PR_TRUE; |
1287 | | /* fall thru */ |
1288 | 32.6k | case CKM_CAMELLIA_CBC: |
1289 | 32.6k | if (!pMechanism->pParameter || |
1290 | 32.6k | pMechanism->ulParameterLen != 16) { |
1291 | 3 | crv = CKR_MECHANISM_PARAM_INVALID; |
1292 | 3 | break; |
1293 | 3 | } |
1294 | | /* fall thru */ |
1295 | 32.9k | case CKM_CAMELLIA_ECB: |
1296 | 32.9k | context->blockSize = 16; |
1297 | 32.9k | if (key_type != CKK_CAMELLIA) { |
1298 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1299 | 0 | break; |
1300 | 0 | } |
1301 | 32.9k | att = sftk_FindAttribute(key, CKA_VALUE); |
1302 | 32.9k | if (att == NULL) { |
1303 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1304 | 0 | break; |
1305 | 0 | } |
1306 | 32.9k | context->cipherInfo = Camellia_CreateContext( |
1307 | 32.9k | (unsigned char *)att->attrib.pValue, |
1308 | 32.9k | (unsigned char *)pMechanism->pParameter, |
1309 | 32.9k | pMechanism->mechanism == |
1310 | 32.9k | CKM_CAMELLIA_ECB |
1311 | 32.9k | ? NSS_CAMELLIA |
1312 | 32.9k | : NSS_CAMELLIA_CBC, |
1313 | 32.9k | isEncrypt, att->attrib.ulValueLen); |
1314 | 32.9k | sftk_FreeAttribute(att); |
1315 | 32.9k | if (context->cipherInfo == NULL) { |
1316 | 6 | crv = CKR_HOST_MEMORY; |
1317 | 6 | break; |
1318 | 6 | } |
1319 | 32.9k | context->update = isEncrypt ? SFTKCipher_Camellia_Encrypt : SFTKCipher_Camellia_Decrypt; |
1320 | 32.9k | context->destroy = SFTKCipher_Camellia_DestroyContext; |
1321 | 32.9k | break; |
1322 | | |
1323 | 483 | case CKM_AES_CBC_PAD: |
1324 | 483 | context->doPad = PR_TRUE; |
1325 | | /* fall thru */ |
1326 | 25.0k | case CKM_AES_ECB: |
1327 | 115k | case CKM_AES_CBC: |
1328 | 115k | context->blockSize = 16; |
1329 | 115k | case CKM_AES_CTS: |
1330 | 116k | case CKM_AES_CTR: |
1331 | 116k | case CKM_AES_GCM: |
1332 | 116k | aes_param = pMechanism->pParameter; |
1333 | | /* |
1334 | | * Due to a mismatch between the documentation and the header |
1335 | | * file, two different definitions for CK_GCM_PARAMS exist. |
1336 | | * The header file is normative according to Oasis, but NSS used |
1337 | | * the documentation. In PKCS #11 v3.0, this was reconciled in |
1338 | | * favor of the header file definition. To maintain binary |
1339 | | * compatibility, NSS now defines CK_GCM_PARAMS_V3 as the official |
1340 | | * version v3 (V2.4 header file) and CK_NSS_GCM_PARAMS as the |
1341 | | * legacy (V2.4 documentation, NSS version). CK_GCM_PARAMS |
1342 | | * is defined as CK_GCM_PARAMS_V3 if NSS_PKCS11_2_0_COMPAT is not |
1343 | | * defined and CK_NSS_GCM_PARAMS if it is. Internally |
1344 | | * softoken continues to use the legacy version. The code below |
1345 | | * automatically detects which parameter was passed in and |
1346 | | * converts CK_GCM_PARAMS_V3 to the CK_NSS_GCM_PARAMS (legacy |
1347 | | * version) on the fly. NSS proper will eventually start |
1348 | | * using the CK_GCM_PARAMS_V3 version and fall back to the |
1349 | | * CK_NSS_GCM_PARAMS if the CK_GCM_PARAMS_V3 version fails with |
1350 | | * CKR_MECHANISM_PARAM_INVALID. |
1351 | | */ |
1352 | 116k | if (pMechanism->mechanism == CKM_AES_GCM) { |
1353 | 595 | if (!aes_param) { |
1354 | 2 | crv = CKR_MECHANISM_PARAM_INVALID; |
1355 | 2 | break; |
1356 | 2 | } |
1357 | 593 | if (pMechanism->ulParameterLen == sizeof(CK_GCM_PARAMS_V3)) { |
1358 | | /* convert the true V3 parameters into the old NSS parameters */ |
1359 | 0 | CK_GCM_PARAMS_V3 *gcm_params = (CK_GCM_PARAMS_V3 *)aes_param; |
1360 | 0 | if (gcm_params->ulIvLen * 8 != gcm_params->ulIvBits) { |
1361 | | /* only support byte aligned IV lengths */ |
1362 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1363 | 0 | break; |
1364 | 0 | } |
1365 | 0 | aes_param = (void *)&nss_gcm_param; |
1366 | 0 | nss_gcm_param.pIv = gcm_params->pIv; |
1367 | 0 | nss_gcm_param.ulIvLen = gcm_params->ulIvLen; |
1368 | 0 | nss_gcm_param.pAAD = gcm_params->pAAD; |
1369 | 0 | nss_gcm_param.ulAADLen = gcm_params->ulAADLen; |
1370 | 0 | nss_gcm_param.ulTagBits = gcm_params->ulTagBits; |
1371 | 593 | } else if (pMechanism->ulParameterLen != sizeof(CK_NSS_GCM_PARAMS)) { |
1372 | | /* neither old nor new style params, must be invalid */ |
1373 | 11 | crv = CKR_MECHANISM_PARAM_INVALID; |
1374 | 11 | break; |
1375 | 11 | } |
1376 | 116k | } else if ((pMechanism->mechanism == CKM_AES_CTR && BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CTR_PARAMS))) || |
1377 | 116k | ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CTS) && BAD_PARAM_CAST(pMechanism, AES_BLOCK_SIZE))) { |
1378 | 15 | crv = CKR_MECHANISM_PARAM_INVALID; |
1379 | 15 | break; |
1380 | 15 | } |
1381 | | |
1382 | 116k | if (pMechanism->mechanism == CKM_AES_GCM) { |
1383 | 582 | context->multi = PR_FALSE; |
1384 | 582 | } |
1385 | 116k | if (key_type != CKK_AES) { |
1386 | 30 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1387 | 30 | break; |
1388 | 30 | } |
1389 | 116k | att = sftk_FindAttribute(key, CKA_VALUE); |
1390 | 116k | if (att == NULL) { |
1391 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1392 | 0 | break; |
1393 | 0 | } |
1394 | 116k | context->cipherInfo = AES_CreateContext( |
1395 | 116k | (unsigned char *)att->attrib.pValue, |
1396 | 116k | (unsigned char *)aes_param, |
1397 | 116k | sftk_aes_mode(pMechanism->mechanism), |
1398 | 116k | isEncrypt, att->attrib.ulValueLen, 16); |
1399 | 116k | sftk_FreeAttribute(att); |
1400 | 116k | if (context->cipherInfo == NULL) { |
1401 | 102 | crv = CKR_HOST_MEMORY; |
1402 | 102 | break; |
1403 | 102 | } |
1404 | 116k | context->update = isEncrypt ? SFTKCipher_AES_Encrypt : SFTKCipher_AES_Decrypt; |
1405 | 116k | context->destroy = SFTKCipher_AES_DestroyContext; |
1406 | 116k | break; |
1407 | | |
1408 | 275 | case CKM_NSS_CHACHA20_POLY1305: |
1409 | 275 | case CKM_CHACHA20_POLY1305: |
1410 | 275 | if (pMechanism->mechanism == CKM_NSS_CHACHA20_POLY1305) { |
1411 | 275 | if (key_type != CKK_NSS_CHACHA20) { |
1412 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1413 | 0 | break; |
1414 | 0 | } |
1415 | 275 | if ((pMechanism->pParameter == NULL) || |
1416 | 275 | (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS))) { |
1417 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1418 | 0 | break; |
1419 | 0 | } |
1420 | 275 | nss_aead_params_ptr = (CK_NSS_AEAD_PARAMS *)pMechanism->pParameter; |
1421 | 275 | } else { |
1422 | 0 | CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR chacha_poly_params; |
1423 | 0 | if (key_type != CKK_CHACHA20) { |
1424 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1425 | 0 | break; |
1426 | 0 | } |
1427 | 0 | if ((pMechanism->pParameter == NULL) || |
1428 | 0 | (pMechanism->ulParameterLen != |
1429 | 0 | sizeof(CK_SALSA20_CHACHA20_POLY1305_PARAMS))) { |
1430 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1431 | 0 | break; |
1432 | 0 | } |
1433 | 0 | chacha_poly_params = (CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR) |
1434 | 0 | pMechanism->pParameter; |
1435 | 0 | nss_aead_params_ptr = &nss_aead_params; |
1436 | 0 | nss_aead_params.pNonce = chacha_poly_params->pNonce; |
1437 | 0 | nss_aead_params.ulNonceLen = chacha_poly_params->ulNonceLen; |
1438 | 0 | nss_aead_params.pAAD = chacha_poly_params->pAAD; |
1439 | 0 | nss_aead_params.ulAADLen = chacha_poly_params->ulAADLen; |
1440 | 0 | nss_aead_params.ulTagLen = 16; /* Poly1305 is always 16 */ |
1441 | 0 | } |
1442 | | |
1443 | 275 | context->multi = PR_FALSE; |
1444 | 275 | att = sftk_FindAttribute(key, CKA_VALUE); |
1445 | 275 | if (att == NULL) { |
1446 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1447 | 0 | break; |
1448 | 0 | } |
1449 | 275 | context->cipherInfo = sftk_ChaCha20Poly1305_CreateContext( |
1450 | 275 | (unsigned char *)att->attrib.pValue, att->attrib.ulValueLen, |
1451 | 275 | nss_aead_params_ptr); |
1452 | 275 | sftk_FreeAttribute(att); |
1453 | 275 | if (context->cipherInfo == NULL) { |
1454 | 113 | crv = sftk_MapCryptError(PORT_GetError()); |
1455 | 113 | break; |
1456 | 113 | } |
1457 | 162 | context->update = isEncrypt ? sftk_ChaCha20Poly1305_Encrypt : sftk_ChaCha20Poly1305_Decrypt; |
1458 | 162 | context->destroy = sftk_ChaCha20Poly1305_DestroyContext; |
1459 | 162 | break; |
1460 | | |
1461 | 13.9k | case CKM_NSS_CHACHA20_CTR: /* old NSS private version */ |
1462 | 13.9k | case CKM_CHACHA20: /* PKCS #11 v3 version */ |
1463 | 13.9k | { |
1464 | 13.9k | unsigned char *counter; |
1465 | 13.9k | unsigned char *nonce; |
1466 | 13.9k | unsigned long counter_len; |
1467 | 13.9k | unsigned long nonce_len; |
1468 | 13.9k | context->multi = PR_FALSE; |
1469 | 13.9k | if (pMechanism->mechanism == CKM_NSS_CHACHA20_CTR) { |
1470 | 13.9k | if (key_type != CKK_NSS_CHACHA20) { |
1471 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1472 | 0 | break; |
1473 | 0 | } |
1474 | 13.9k | if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) { |
1475 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1476 | 0 | break; |
1477 | 0 | } |
1478 | 13.9k | counter_len = 4; |
1479 | 13.9k | counter = pMechanism->pParameter; |
1480 | 13.9k | nonce = counter + 4; |
1481 | 13.9k | nonce_len = 12; |
1482 | 13.9k | } else { |
1483 | 0 | CK_CHACHA20_PARAMS_PTR chacha20_param_ptr; |
1484 | 0 | if (key_type != CKK_CHACHA20) { |
1485 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1486 | 0 | break; |
1487 | 0 | } |
1488 | 0 | if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != sizeof(CK_CHACHA20_PARAMS)) { |
1489 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1490 | 0 | break; |
1491 | 0 | } |
1492 | 0 | chacha20_param_ptr = (CK_CHACHA20_PARAMS_PTR)pMechanism->pParameter; |
1493 | 0 | if ((chacha20_param_ptr->blockCounterBits != 32) && |
1494 | 0 | (chacha20_param_ptr->blockCounterBits != 64)) { |
1495 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1496 | 0 | break; |
1497 | 0 | } |
1498 | 0 | counter_len = chacha20_param_ptr->blockCounterBits / PR_BITS_PER_BYTE; |
1499 | 0 | counter = chacha20_param_ptr->pBlockCounter; |
1500 | 0 | nonce = chacha20_param_ptr->pNonce; |
1501 | 0 | nonce_len = chacha20_param_ptr->ulNonceBits / PR_BITS_PER_BYTE; |
1502 | 0 | } |
1503 | | |
1504 | 13.9k | att = sftk_FindAttribute(key, CKA_VALUE); |
1505 | 13.9k | if (att == NULL) { |
1506 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1507 | 0 | break; |
1508 | 0 | } |
1509 | 13.9k | SFTKChaCha20CtrInfo *ctx = PORT_ZNew(SFTKChaCha20CtrInfo); |
1510 | 13.9k | if (!ctx) { |
1511 | 0 | sftk_FreeAttribute(att); |
1512 | 0 | crv = CKR_HOST_MEMORY; |
1513 | 0 | break; |
1514 | 0 | } |
1515 | 13.9k | if (att->attrib.ulValueLen != sizeof(ctx->key)) { |
1516 | 0 | sftk_FreeAttribute(att); |
1517 | 0 | PORT_Free(ctx); |
1518 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1519 | 0 | break; |
1520 | 0 | } |
1521 | 13.9k | memcpy(ctx->key, att->attrib.pValue, att->attrib.ulValueLen); |
1522 | 13.9k | sftk_FreeAttribute(att); |
1523 | | |
1524 | | /* make sure we don't overflow our parameters */ |
1525 | 13.9k | if ((sizeof(ctx->counter) < counter_len) || |
1526 | 13.9k | (sizeof(ctx->nonce) < nonce_len)) { |
1527 | 0 | PORT_Free(ctx); |
1528 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1529 | 0 | break; |
1530 | 0 | } |
1531 | | |
1532 | | /* The counter is little endian. */ |
1533 | 13.9k | int i = 0; |
1534 | 69.9k | for (; i < counter_len; ++i) { |
1535 | 55.9k | ctx->counter |= (PRUint32)counter[i] << (i * 8); |
1536 | 55.9k | } |
1537 | 13.9k | memcpy(ctx->nonce, nonce, nonce_len); |
1538 | 13.9k | context->cipherInfo = ctx; |
1539 | 13.9k | context->update = sftk_ChaCha20Ctr; |
1540 | 13.9k | context->destroy = sftk_ChaCha20Ctr_DestroyContext; |
1541 | 13.9k | break; |
1542 | 13.9k | } |
1543 | | |
1544 | 0 | case CKM_NSS_AES_KEY_WRAP_PAD: |
1545 | 0 | case CKM_AES_KEY_WRAP_PAD: |
1546 | 0 | context->doPad = PR_TRUE; |
1547 | | /* fall thru */ |
1548 | 0 | case CKM_NSS_AES_KEY_WRAP: |
1549 | 1.37k | case CKM_AES_KEY_WRAP: |
1550 | 1.37k | context->blockSize = 8; |
1551 | 1.37k | case CKM_AES_KEY_WRAP_KWP: |
1552 | 1.37k | context->multi = PR_FALSE; |
1553 | 1.37k | if (key_type != CKK_AES) { |
1554 | 14 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1555 | 14 | break; |
1556 | 14 | } |
1557 | 1.36k | att = sftk_FindAttribute(key, CKA_VALUE); |
1558 | 1.36k | if (att == NULL) { |
1559 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1560 | 0 | break; |
1561 | 0 | } |
1562 | 1.36k | context->cipherInfo = AESKeyWrap_CreateContext( |
1563 | 1.36k | (unsigned char *)att->attrib.pValue, |
1564 | 1.36k | (unsigned char *)pMechanism->pParameter, |
1565 | 1.36k | isEncrypt, att->attrib.ulValueLen); |
1566 | 1.36k | sftk_FreeAttribute(att); |
1567 | 1.36k | if (context->cipherInfo == NULL) { |
1568 | 0 | crv = CKR_HOST_MEMORY; |
1569 | 0 | break; |
1570 | 0 | } |
1571 | 1.36k | if (pMechanism->mechanism == CKM_AES_KEY_WRAP_KWP) { |
1572 | 0 | context->update = isEncrypt ? SFTKCipher_AESKeyWrap_EncryptKWP |
1573 | 0 | : SFTKCipher_AESKeyWrap_DecryptKWP; |
1574 | 1.36k | } else { |
1575 | 1.36k | context->update = isEncrypt ? SFTKCipher_AESKeyWrap_Encrypt |
1576 | 1.36k | : SFTKCipher_AESKeyWrap_Decrypt; |
1577 | 1.36k | } |
1578 | 1.36k | context->destroy = SFTKCipher_AESKeyWrap_DestroyContext; |
1579 | 1.36k | break; |
1580 | | |
1581 | 0 | default: |
1582 | 0 | crv = CKR_MECHANISM_INVALID; |
1583 | 0 | break; |
1584 | 398k | } |
1585 | | |
1586 | 398k | if (crv != CKR_OK) { |
1587 | 366 | sftk_FreeContext(context); |
1588 | 366 | sftk_FreeSession(session); |
1589 | 366 | return crv; |
1590 | 366 | } |
1591 | 397k | crv = sftk_InstallContext(session, contextType, context); |
1592 | 397k | if (crv != CKR_OK) { |
1593 | 0 | sftk_FreeContext(context); |
1594 | 0 | } |
1595 | 397k | sftk_FreeSession(session); |
1596 | 397k | return crv; |
1597 | 398k | } |
1598 | | |
1599 | | /* NSC_EncryptInit initializes an encryption operation. */ |
1600 | | CK_RV |
1601 | | NSC_EncryptInit(CK_SESSION_HANDLE hSession, |
1602 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
1603 | 129k | { |
1604 | 129k | CHECK_FORK(); |
1605 | 129k | return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT, |
1606 | 129k | SFTK_ENCRYPT, PR_TRUE); |
1607 | 129k | } |
1608 | | |
1609 | | /* NSC_EncryptUpdate continues a multiple-part encryption operation. */ |
1610 | | CK_RV |
1611 | | NSC_EncryptUpdate(CK_SESSION_HANDLE hSession, |
1612 | | CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
1613 | | CK_ULONG_PTR pulEncryptedPartLen) |
1614 | 4.24k | { |
1615 | 4.24k | SFTKSession *session; |
1616 | 4.24k | SFTKSessionContext *context; |
1617 | 4.24k | unsigned int outlen, i; |
1618 | 4.24k | unsigned int padoutlen = 0; |
1619 | 4.24k | unsigned int maxout = *pulEncryptedPartLen; |
1620 | 4.24k | CK_RV crv; |
1621 | 4.24k | SECStatus rv; |
1622 | | |
1623 | 4.24k | CHECK_FORK(); |
1624 | | |
1625 | | /* Hold the session reference for the duration of the context deref; |
1626 | | * see comment on NSC_DigestUpdate. */ |
1627 | 4.24k | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, &session); |
1628 | 4.24k | if (crv != CKR_OK) |
1629 | 0 | return crv; |
1630 | | |
1631 | 4.24k | if (!pEncryptedPart) { |
1632 | 0 | if (context->doPad) { |
1633 | 0 | CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength; |
1634 | 0 | CK_ULONG blocksToSend = totalDataAvailable / context->blockSize; |
1635 | |
|
1636 | 0 | *pulEncryptedPartLen = blocksToSend * context->blockSize; |
1637 | 0 | goto finish; |
1638 | 0 | } |
1639 | 0 | *pulEncryptedPartLen = ulPartLen; |
1640 | 0 | goto finish; |
1641 | 0 | } |
1642 | | |
1643 | | /* do padding */ |
1644 | 4.24k | if (context->doPad) { |
1645 | | /* deal with previous buffered data */ |
1646 | 483 | if (context->padDataLength != 0) { |
1647 | | /* fill in the padded to a full block size */ |
1648 | 0 | for (i = context->padDataLength; |
1649 | 0 | (ulPartLen != 0) && i < context->blockSize; i++) { |
1650 | 0 | context->padBuf[i] = *pPart++; |
1651 | 0 | ulPartLen--; |
1652 | 0 | context->padDataLength++; |
1653 | 0 | } |
1654 | | |
1655 | | /* not enough data to encrypt yet? then return */ |
1656 | 0 | if (context->padDataLength != context->blockSize) { |
1657 | 0 | *pulEncryptedPartLen = 0; |
1658 | 0 | goto finish; |
1659 | 0 | } |
1660 | | /* encrypt the current padded data */ |
1661 | 0 | rv = (*context->update)(context->cipherInfo, pEncryptedPart, |
1662 | 0 | &padoutlen, maxout, context->padBuf, |
1663 | 0 | context->blockSize); |
1664 | 0 | if (rv != SECSuccess) { |
1665 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
1666 | 0 | goto finish; |
1667 | 0 | } |
1668 | 0 | pEncryptedPart += padoutlen; |
1669 | 0 | maxout -= padoutlen; |
1670 | 0 | } |
1671 | | /* save the residual */ |
1672 | 483 | context->padDataLength = ulPartLen % context->blockSize; |
1673 | 483 | if (context->padDataLength) { |
1674 | 483 | PORT_Memcpy(context->padBuf, |
1675 | 483 | &pPart[ulPartLen - context->padDataLength], |
1676 | 483 | context->padDataLength); |
1677 | 483 | ulPartLen -= context->padDataLength; |
1678 | 483 | } |
1679 | | /* if we've exhausted our new buffer, we're done */ |
1680 | 483 | if (ulPartLen == 0) { |
1681 | 0 | *pulEncryptedPartLen = padoutlen; |
1682 | 0 | goto finish; |
1683 | 0 | } |
1684 | 483 | } |
1685 | | |
1686 | | /* do it: NOTE: this assumes buf size in is >= buf size out! */ |
1687 | 4.24k | rv = (*context->update)(context->cipherInfo, pEncryptedPart, |
1688 | 4.24k | &outlen, maxout, pPart, ulPartLen); |
1689 | 4.24k | if (rv != SECSuccess) { |
1690 | 42 | crv = sftk_MapCryptError(PORT_GetError()); |
1691 | 42 | goto finish; |
1692 | 42 | } |
1693 | 4.20k | *pulEncryptedPartLen = (CK_ULONG)(outlen + padoutlen); |
1694 | 4.24k | finish: |
1695 | 4.24k | sftk_FreeSession(session); |
1696 | 4.24k | return crv; |
1697 | 4.20k | } |
1698 | | |
1699 | | /* NSC_EncryptFinal finishes a multiple-part encryption operation. */ |
1700 | | CK_RV |
1701 | | NSC_EncryptFinal(CK_SESSION_HANDLE hSession, |
1702 | | CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) |
1703 | 620 | { |
1704 | 620 | SFTKSession *session; |
1705 | 620 | SFTKSessionContext *context; |
1706 | 620 | unsigned int outlen, i; |
1707 | 620 | unsigned int maxout = *pulLastEncryptedPartLen; |
1708 | 620 | CK_RV crv; |
1709 | 620 | SECStatus rv = SECSuccess; |
1710 | 620 | PRBool contextFinished = PR_TRUE; |
1711 | | |
1712 | 620 | CHECK_FORK(); |
1713 | | |
1714 | | /* make sure we're legal */ |
1715 | 620 | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, &session); |
1716 | 620 | if (crv != CKR_OK) |
1717 | 0 | return crv; |
1718 | | |
1719 | 620 | *pulLastEncryptedPartLen = 0; |
1720 | 620 | if (!pLastEncryptedPart) { |
1721 | | /* caller is checking the amount of remaining data */ |
1722 | 0 | if (context->blockSize > 0 && context->doPad) { |
1723 | 0 | *pulLastEncryptedPartLen = context->blockSize; |
1724 | 0 | contextFinished = PR_FALSE; /* still have padding to go */ |
1725 | 0 | } |
1726 | 0 | goto finish; |
1727 | 0 | } |
1728 | | |
1729 | | /* do padding */ |
1730 | 620 | if (context->doPad) { |
1731 | 483 | unsigned char padbyte = (unsigned char)(context->blockSize - context->padDataLength); |
1732 | | /* fill out rest of pad buffer with pad magic*/ |
1733 | 4.36k | for (i = context->padDataLength; i < context->blockSize; i++) { |
1734 | 3.88k | context->padBuf[i] = padbyte; |
1735 | 3.88k | } |
1736 | 483 | rv = (*context->update)(context->cipherInfo, pLastEncryptedPart, |
1737 | 483 | &outlen, maxout, context->padBuf, context->blockSize); |
1738 | 483 | if (rv == SECSuccess) |
1739 | 483 | *pulLastEncryptedPartLen = (CK_ULONG)outlen; |
1740 | 483 | } |
1741 | | |
1742 | 620 | finish: |
1743 | 620 | if (contextFinished) |
1744 | 620 | sftk_TerminateOp(session, SFTK_ENCRYPT); |
1745 | 620 | sftk_FreeSession(session); |
1746 | 620 | return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
1747 | 620 | } |
1748 | | |
1749 | | /* NSC_Encrypt encrypts single-part data. */ |
1750 | | CK_RV |
1751 | | NSC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
1752 | | CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, |
1753 | | CK_ULONG_PTR pulEncryptedDataLen) |
1754 | 113k | { |
1755 | 113k | SFTKSession *session; |
1756 | 113k | SFTKSessionContext *context; |
1757 | 113k | unsigned int outlen; |
1758 | 113k | unsigned int maxoutlen = *pulEncryptedDataLen; |
1759 | 113k | CK_RV crv; |
1760 | 113k | CK_RV crv2; |
1761 | 113k | SECStatus rv = SECSuccess; |
1762 | 113k | SECItem pText; |
1763 | | |
1764 | 113k | pText.type = siBuffer; |
1765 | 113k | pText.data = pData; |
1766 | 113k | pText.len = ulDataLen; |
1767 | | |
1768 | 113k | CHECK_FORK(); |
1769 | | |
1770 | | /* make sure we're legal */ |
1771 | 113k | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, &session); |
1772 | 113k | if (crv != CKR_OK) |
1773 | 0 | return crv; |
1774 | | |
1775 | 113k | if (!pEncryptedData) { |
1776 | 0 | outlen = context->rsa ? context->maxLen : ulDataLen + 2 * context->blockSize; |
1777 | 0 | goto done; |
1778 | 0 | } |
1779 | | |
1780 | 113k | if (context->doPad) { |
1781 | 483 | if (context->multi) { |
1782 | 483 | CK_ULONG updateLen = maxoutlen; |
1783 | 483 | CK_ULONG finalLen; |
1784 | | /* padding is fairly complicated, have the update and final |
1785 | | * code deal with it */ |
1786 | 483 | sftk_FreeSession(session); |
1787 | 483 | crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData, |
1788 | 483 | &updateLen); |
1789 | 483 | if (crv != CKR_OK) { |
1790 | 0 | updateLen = 0; |
1791 | 0 | } |
1792 | 483 | maxoutlen -= updateLen; |
1793 | 483 | pEncryptedData += updateLen; |
1794 | 483 | finalLen = maxoutlen; |
1795 | 483 | crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen); |
1796 | 483 | if (crv == CKR_OK && crv2 == CKR_OK) { |
1797 | 483 | *pulEncryptedDataLen = updateLen + finalLen; |
1798 | 483 | } |
1799 | 483 | return crv == CKR_OK ? crv2 : crv; |
1800 | 483 | } |
1801 | | /* doPad without multi means that padding must be done on the first |
1802 | | ** and only update. There will be no final. |
1803 | | */ |
1804 | 0 | PORT_Assert(context->blockSize > 1); |
1805 | 0 | if (context->blockSize > 1) { |
1806 | 0 | CK_ULONG remainder = ulDataLen % context->blockSize; |
1807 | 0 | CK_ULONG padding = context->blockSize - remainder; |
1808 | 0 | pText.len += padding; |
1809 | 0 | pText.data = PORT_ZAlloc(pText.len); |
1810 | 0 | if (pText.data) { |
1811 | 0 | memcpy(pText.data, pData, ulDataLen); |
1812 | 0 | memset(pText.data + ulDataLen, padding, padding); |
1813 | 0 | } else { |
1814 | 0 | crv = CKR_HOST_MEMORY; |
1815 | 0 | goto fail; |
1816 | 0 | } |
1817 | 0 | } |
1818 | 0 | } |
1819 | | |
1820 | | /* do it: NOTE: this assumes buf size is big enough. */ |
1821 | 112k | rv = (*context->update)(context->cipherInfo, pEncryptedData, |
1822 | 112k | &outlen, maxoutlen, pText.data, pText.len); |
1823 | 112k | crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
1824 | 112k | if (pText.data != pData) |
1825 | 0 | PORT_ZFree(pText.data, pText.len); |
1826 | 112k | fail: |
1827 | 112k | sftk_TerminateOp(session, SFTK_ENCRYPT); |
1828 | 112k | done: |
1829 | 112k | sftk_FreeSession(session); |
1830 | 112k | if (crv == CKR_OK) { |
1831 | 112k | *pulEncryptedDataLen = (CK_ULONG)outlen; |
1832 | 112k | } |
1833 | 112k | return crv; |
1834 | 112k | } |
1835 | | |
1836 | | /* |
1837 | | ************** Crypto Functions: Decrypt ************************ |
1838 | | */ |
1839 | | |
1840 | | /* NSC_DecryptInit initializes a decryption operation. */ |
1841 | | CK_RV |
1842 | | NSC_DecryptInit(CK_SESSION_HANDLE hSession, |
1843 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
1844 | 146k | { |
1845 | 146k | CHECK_FORK(); |
1846 | 146k | return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT, |
1847 | 146k | SFTK_DECRYPT, PR_FALSE); |
1848 | 146k | } |
1849 | | |
1850 | | /* NSC_DecryptUpdate continues a multiple-part decryption operation. */ |
1851 | | CK_RV |
1852 | | NSC_DecryptUpdate(CK_SESSION_HANDLE hSession, |
1853 | | CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, |
1854 | | CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) |
1855 | 49.4k | { |
1856 | 49.4k | SFTKSession *session; |
1857 | 49.4k | SFTKSessionContext *context; |
1858 | 49.4k | unsigned int padoutlen = 0; |
1859 | 49.4k | unsigned int outlen; |
1860 | 49.4k | unsigned int maxout = *pulPartLen; |
1861 | 49.4k | CK_RV crv; |
1862 | 49.4k | SECStatus rv; |
1863 | | |
1864 | 49.4k | CHECK_FORK(); |
1865 | | |
1866 | | /* Hold the session reference for the duration of the context deref; |
1867 | | * see comment on NSC_DigestUpdate. */ |
1868 | 49.4k | crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, &session); |
1869 | 49.4k | if (crv != CKR_OK) |
1870 | 335 | return crv; |
1871 | | |
1872 | | /* this can only happen on an NSS programming error */ |
1873 | 49.1k | PORT_Assert((context->padDataLength == 0) || context->padDataLength == context->blockSize); |
1874 | | |
1875 | 49.1k | if (context->doPad) { |
1876 | | /* Check the data length for block ciphers. If we are padding, |
1877 | | * then we must be using a block cipher. In the non-padding case |
1878 | | * the error will be returned by the underlying decryption |
1879 | | * function when we do the actual decrypt. We need to do the |
1880 | | * check here to avoid returning a negative length to the caller |
1881 | | * or reading before the beginning of the pEncryptedPart buffer. |
1882 | | */ |
1883 | 0 | if ((ulEncryptedPartLen == 0) || |
1884 | 0 | (ulEncryptedPartLen % context->blockSize) != 0) { |
1885 | 0 | crv = CKR_ENCRYPTED_DATA_LEN_RANGE; |
1886 | 0 | goto finish; |
1887 | 0 | } |
1888 | 0 | } |
1889 | | |
1890 | 49.1k | if (!pPart) { |
1891 | 0 | if (context->doPad) { |
1892 | 0 | *pulPartLen = |
1893 | 0 | ulEncryptedPartLen + context->padDataLength - context->blockSize; |
1894 | 0 | goto finish; |
1895 | 0 | } |
1896 | | /* for stream ciphers there is are no constraints on ulEncryptedPartLen. |
1897 | | * for block ciphers, it must be a multiple of blockSize. The error is |
1898 | | * detected when this function is called again do decrypt the output. |
1899 | | */ |
1900 | 0 | *pulPartLen = ulEncryptedPartLen; |
1901 | 0 | goto finish; |
1902 | 0 | } |
1903 | | |
1904 | 49.1k | if (context->doPad) { |
1905 | | /* first decrypt our saved buffer */ |
1906 | 0 | if (context->padDataLength != 0) { |
1907 | 0 | rv = (*context->update)(context->cipherInfo, pPart, &padoutlen, |
1908 | 0 | maxout, context->padBuf, context->blockSize); |
1909 | 0 | if (rv != SECSuccess) { |
1910 | 0 | crv = sftk_MapDecryptError(PORT_GetError()); |
1911 | 0 | goto finish; |
1912 | 0 | } |
1913 | 0 | pPart += padoutlen; |
1914 | 0 | maxout -= padoutlen; |
1915 | 0 | } |
1916 | | /* now save the final block for the next decrypt or the final */ |
1917 | 0 | PORT_Memcpy(context->padBuf, &pEncryptedPart[ulEncryptedPartLen - context->blockSize], |
1918 | 0 | context->blockSize); |
1919 | 0 | context->padDataLength = context->blockSize; |
1920 | 0 | ulEncryptedPartLen -= context->padDataLength; |
1921 | 0 | } |
1922 | | |
1923 | | /* do it: NOTE: this assumes buf size in is >= buf size out! */ |
1924 | 49.1k | rv = (*context->update)(context->cipherInfo, pPart, &outlen, |
1925 | 49.1k | maxout, pEncryptedPart, ulEncryptedPartLen); |
1926 | 49.1k | if (rv != SECSuccess) { |
1927 | 63 | crv = sftk_MapDecryptError(PORT_GetError()); |
1928 | 63 | goto finish; |
1929 | 63 | } |
1930 | 49.0k | *pulPartLen = (CK_ULONG)(outlen + padoutlen); |
1931 | 49.1k | finish: |
1932 | 49.1k | sftk_FreeSession(session); |
1933 | 49.1k | return crv; |
1934 | 49.0k | } |
1935 | | |
1936 | | /* NSC_DecryptFinal finishes a multiple-part decryption operation. */ |
1937 | | CK_RV |
1938 | | NSC_DecryptFinal(CK_SESSION_HANDLE hSession, |
1939 | | CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) |
1940 | 37 | { |
1941 | 37 | SFTKSession *session; |
1942 | 37 | SFTKSessionContext *context; |
1943 | 37 | unsigned int outlen; |
1944 | 37 | unsigned int maxout = *pulLastPartLen; |
1945 | 37 | CK_RV crv; |
1946 | 37 | SECStatus rv = SECSuccess; |
1947 | | |
1948 | 37 | CHECK_FORK(); |
1949 | | |
1950 | | /* make sure we're legal */ |
1951 | 37 | crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, &session); |
1952 | 37 | if (crv != CKR_OK) |
1953 | 0 | return crv; |
1954 | | |
1955 | 37 | *pulLastPartLen = 0; |
1956 | 37 | if (!pLastPart) { |
1957 | | /* caller is checking the amount of remaining data */ |
1958 | 0 | if (context->padDataLength > 0) { |
1959 | 0 | *pulLastPartLen = context->padDataLength; |
1960 | 0 | } |
1961 | 0 | goto finish; |
1962 | 0 | } |
1963 | | |
1964 | 37 | if (context->doPad) { |
1965 | | /* decrypt our saved buffer */ |
1966 | 0 | if (context->padDataLength != 0) { |
1967 | | /* this assumes that pLastPart is big enough to hold the *whole* |
1968 | | * buffer!!! */ |
1969 | 0 | rv = (*context->update)(context->cipherInfo, pLastPart, &outlen, |
1970 | 0 | maxout, context->padBuf, context->blockSize); |
1971 | 0 | if (rv != SECSuccess) { |
1972 | 0 | crv = sftk_MapDecryptError(PORT_GetError()); |
1973 | 0 | } else { |
1974 | 0 | unsigned int padSize = 0; |
1975 | 0 | crv = sftk_CheckCBCPadding(pLastPart, outlen, |
1976 | 0 | context->blockSize, &padSize); |
1977 | | /* Update pulLastPartLen, in constant time, if crv is OK */ |
1978 | 0 | *pulLastPartLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulLastPartLen); |
1979 | 0 | } |
1980 | 0 | } |
1981 | 0 | } |
1982 | | |
1983 | 37 | sftk_TerminateOp(session, SFTK_DECRYPT); |
1984 | 37 | finish: |
1985 | 37 | sftk_FreeSession(session); |
1986 | 37 | return crv; |
1987 | 37 | } |
1988 | | |
1989 | | /* NSC_Decrypt decrypts encrypted data in a single part. */ |
1990 | | CK_RV |
1991 | | NSC_Decrypt(CK_SESSION_HANDLE hSession, |
1992 | | CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, |
1993 | | CK_ULONG_PTR pulDataLen) |
1994 | 89.1k | { |
1995 | 89.1k | SFTKSession *session; |
1996 | 89.1k | SFTKSessionContext *context; |
1997 | 89.1k | unsigned int outlen; |
1998 | 89.1k | unsigned int maxoutlen = *pulDataLen; |
1999 | 89.1k | CK_RV crv; |
2000 | 89.1k | CK_RV crv2; |
2001 | 89.1k | SECStatus rv = SECSuccess; |
2002 | | |
2003 | 89.1k | CHECK_FORK(); |
2004 | | |
2005 | | /* make sure we're legal */ |
2006 | 89.1k | crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_FALSE, &session); |
2007 | 89.1k | if (crv != CKR_OK) |
2008 | 0 | return crv; |
2009 | | |
2010 | 89.1k | if (!pData) { |
2011 | 0 | *pulDataLen = (CK_ULONG)(ulEncryptedDataLen + context->blockSize); |
2012 | 0 | goto done; |
2013 | 0 | } |
2014 | | |
2015 | 89.1k | if (context->doPad && context->multi) { |
2016 | 0 | CK_ULONG updateLen = maxoutlen; |
2017 | 0 | CK_ULONG finalLen; |
2018 | | /* padding is fairly complicated, have the update and final |
2019 | | * code deal with it */ |
2020 | 0 | sftk_FreeSession(session); |
2021 | 0 | crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, |
2022 | 0 | pData, &updateLen); |
2023 | 0 | if (crv == CKR_OK) { |
2024 | 0 | maxoutlen -= updateLen; |
2025 | 0 | pData += updateLen; |
2026 | 0 | } |
2027 | 0 | finalLen = maxoutlen; |
2028 | 0 | crv2 = NSC_DecryptFinal(hSession, pData, &finalLen); |
2029 | 0 | if (crv == CKR_OK) { |
2030 | 0 | *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv2), updateLen + finalLen, *pulDataLen); |
2031 | 0 | return crv2; |
2032 | 0 | } else { |
2033 | 0 | return crv; |
2034 | 0 | } |
2035 | 0 | } |
2036 | | |
2037 | 89.1k | rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, |
2038 | 89.1k | pEncryptedData, ulEncryptedDataLen); |
2039 | | /* XXX need to do MUCH better error mapping than this. */ |
2040 | 89.1k | crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError()); |
2041 | 89.1k | if (rv == SECSuccess) { |
2042 | 4.85k | if (context->doPad) { |
2043 | 0 | unsigned int padSize = 0; |
2044 | 0 | crv = sftk_CheckCBCPadding(pData, outlen, context->blockSize, |
2045 | 0 | &padSize); |
2046 | | /* Update pulDataLen, in constant time, if crv is OK */ |
2047 | 0 | *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulDataLen); |
2048 | 4.85k | } else { |
2049 | 4.85k | *pulDataLen = (CK_ULONG)outlen; |
2050 | 4.85k | } |
2051 | 4.85k | } |
2052 | 89.1k | sftk_TerminateOp(session, SFTK_DECRYPT); |
2053 | 89.1k | done: |
2054 | 89.1k | sftk_FreeSession(session); |
2055 | 89.1k | return crv; |
2056 | 89.1k | } |
2057 | | |
2058 | | /* |
2059 | | ************** Crypto Functions: Digest (HASH) ************************ |
2060 | | */ |
2061 | | |
2062 | | /* NSC_DigestInit initializes a message-digesting operation. */ |
2063 | | CK_RV |
2064 | | NSC_DigestInit(CK_SESSION_HANDLE hSession, |
2065 | | CK_MECHANISM_PTR pMechanism) |
2066 | 1.05M | { |
2067 | 1.05M | SFTKSession *session; |
2068 | 1.05M | SFTKSessionContext *context; |
2069 | 1.05M | CK_RV crv = CKR_OK; |
2070 | | |
2071 | 1.05M | CHECK_FORK(); |
2072 | | |
2073 | 1.05M | session = sftk_SessionFromHandle(hSession); |
2074 | 1.05M | if (session == NULL) |
2075 | 0 | return CKR_SESSION_HANDLE_INVALID; |
2076 | 1.05M | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_HASH, |
2077 | 1.05M | NULL, 0, NULL, 0, CKA_DIGEST); |
2078 | 1.05M | if (crv != CKR_OK) { |
2079 | 0 | sftk_FreeSession(session); |
2080 | 0 | return crv; |
2081 | 0 | } |
2082 | | |
2083 | 1.05M | #define INIT_MECH(mmm) \ |
2084 | 1.05M | case CKM_##mmm: { \ |
2085 | 1.05M | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ |
2086 | 1.05M | context->cipherInfo = (void *)mmm##_ctx; \ |
2087 | 1.05M | context->cipherInfoLen = mmm##_FlattenSize(mmm##_ctx); \ |
2088 | 1.05M | context->currentMech = CKM_##mmm; \ |
2089 | 1.05M | context->hashUpdate = SFTKHash_##mmm##_Update; \ |
2090 | 1.05M | context->end = SFTKHash_##mmm##_End; \ |
2091 | 1.05M | context->destroy = SFTKHash_##mmm##_DestroyContext; \ |
2092 | 1.05M | context->maxLen = mmm##_LENGTH; \ |
2093 | 1.05M | if (mmm##_ctx) \ |
2094 | 1.05M | mmm##_Begin(mmm##_ctx); \ |
2095 | 1.05M | else \ |
2096 | 1.05M | crv = CKR_HOST_MEMORY; \ |
2097 | 1.05M | break; \ |
2098 | 1.05M | } |
2099 | | |
2100 | 1.05M | switch (pMechanism->mechanism) { |
2101 | 276 | INIT_MECH(MD2) |
2102 | 137k | INIT_MECH(MD5) |
2103 | 360k | INIT_MECH(SHA1) |
2104 | 225k | INIT_MECH(SHA224) |
2105 | 170k | INIT_MECH(SHA256) |
2106 | 71.7k | INIT_MECH(SHA384) |
2107 | 61.4k | INIT_MECH(SHA512) |
2108 | 7.09k | INIT_MECH(SHA3_224) |
2109 | 12.8k | INIT_MECH(SHA3_256) |
2110 | 9.85k | INIT_MECH(SHA3_384) |
2111 | 1.87k | INIT_MECH(SHA3_512) |
2112 | | |
2113 | 0 | default: |
2114 | 0 | crv = CKR_MECHANISM_INVALID; |
2115 | 0 | break; |
2116 | 1.05M | } |
2117 | | |
2118 | 1.05M | if (crv != CKR_OK) { |
2119 | 0 | sftk_FreeContext(context); |
2120 | 0 | sftk_FreeSession(session); |
2121 | 0 | return crv; |
2122 | 0 | } |
2123 | 1.05M | crv = sftk_InstallContext(session, SFTK_HASH, context); |
2124 | 1.05M | if (crv != CKR_OK) { |
2125 | 0 | sftk_FreeContext(context); |
2126 | 0 | } |
2127 | 1.05M | sftk_FreeSession(session); |
2128 | 1.05M | return crv; |
2129 | 1.05M | } |
2130 | | |
2131 | | /* NSC_Digest digests data in a single part. */ |
2132 | | CK_RV |
2133 | | NSC_Digest(CK_SESSION_HANDLE hSession, |
2134 | | CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, |
2135 | | CK_ULONG_PTR pulDigestLen) |
2136 | 0 | { |
2137 | 0 | SFTKSession *session; |
2138 | 0 | SFTKSessionContext *context; |
2139 | 0 | unsigned int digestLen; |
2140 | 0 | unsigned int maxout = *pulDigestLen; |
2141 | 0 | CK_RV crv; |
2142 | |
|
2143 | 0 | CHECK_FORK(); |
2144 | | |
2145 | | /* make sure we're legal */ |
2146 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_FALSE, &session); |
2147 | 0 | if (crv != CKR_OK) |
2148 | 0 | return crv; |
2149 | | |
2150 | 0 | if (pDigest == NULL) { |
2151 | 0 | *pulDigestLen = context->maxLen; |
2152 | 0 | goto finish; |
2153 | 0 | } |
2154 | | |
2155 | 0 | #if (ULONG_MAX > UINT_MAX) |
2156 | | /* The context->hashUpdate function takes an unsigned int for its data |
2157 | | * length argument, but NSC_Digest takes an unsigned long. */ |
2158 | 0 | while (ulDataLen > UINT_MAX) { |
2159 | 0 | (*context->hashUpdate)(context->cipherInfo, pData, UINT_MAX); |
2160 | 0 | pData += UINT_MAX; |
2161 | 0 | ulDataLen -= UINT_MAX; |
2162 | 0 | } |
2163 | 0 | #endif |
2164 | 0 | (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen); |
2165 | | |
2166 | | /* NOTE: this assumes buf size is bigenough for the algorithm */ |
2167 | 0 | (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout); |
2168 | 0 | *pulDigestLen = digestLen; |
2169 | |
|
2170 | 0 | sftk_TerminateOp(session, SFTK_HASH); |
2171 | 0 | finish: |
2172 | 0 | sftk_FreeSession(session); |
2173 | 0 | return CKR_OK; |
2174 | 0 | } |
2175 | | |
2176 | | /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */ |
2177 | | CK_RV |
2178 | | NSC_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
2179 | | CK_ULONG ulPartLen) |
2180 | 4.80M | { |
2181 | 4.80M | SFTKSession *session; |
2182 | 4.80M | SFTKSessionContext *context; |
2183 | 4.80M | CK_RV crv; |
2184 | | |
2185 | 4.80M | CHECK_FORK(); |
2186 | | |
2187 | | /* Hold the session reference for the duration of the context deref: |
2188 | | * without it, a concurrent NSC_CloseSession could drive refCount to 0 |
2189 | | * inside sftk_GetContext, destroying the session (and freeing the |
2190 | | * context) before we touch context->hashUpdate. */ |
2191 | 4.80M | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); |
2192 | 4.80M | if (crv != CKR_OK) |
2193 | 0 | return crv; |
2194 | | |
2195 | 4.80M | #if (ULONG_MAX > UINT_MAX) |
2196 | | /* The context->hashUpdate function takes an unsigned int for its data |
2197 | | * length argument, but NSC_DigestUpdate takes an unsigned long. */ |
2198 | 4.80M | while (ulPartLen > UINT_MAX) { |
2199 | 0 | (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX); |
2200 | 0 | pPart += UINT_MAX; |
2201 | 0 | ulPartLen -= UINT_MAX; |
2202 | 0 | } |
2203 | 4.80M | #endif |
2204 | 4.80M | (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen); |
2205 | | |
2206 | 4.80M | sftk_FreeSession(session); |
2207 | 4.80M | return CKR_OK; |
2208 | 4.80M | } |
2209 | | |
2210 | | /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */ |
2211 | | CK_RV |
2212 | | NSC_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, |
2213 | | CK_ULONG_PTR pulDigestLen) |
2214 | 868k | { |
2215 | 868k | SFTKSession *session; |
2216 | 868k | SFTKSessionContext *context; |
2217 | 868k | unsigned int maxout = *pulDigestLen; |
2218 | 868k | unsigned int digestLen; |
2219 | 868k | CK_RV crv; |
2220 | | |
2221 | 868k | CHECK_FORK(); |
2222 | | |
2223 | | /* make sure we're legal */ |
2224 | 868k | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); |
2225 | 868k | if (crv != CKR_OK) |
2226 | 170k | return crv; |
2227 | | |
2228 | 697k | if (pDigest != NULL) { |
2229 | 697k | (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout); |
2230 | 697k | *pulDigestLen = digestLen; |
2231 | 697k | sftk_TerminateOp(session, SFTK_HASH); |
2232 | 697k | } else { |
2233 | 0 | *pulDigestLen = context->maxLen; |
2234 | 0 | } |
2235 | | |
2236 | 697k | sftk_FreeSession(session); |
2237 | 697k | return CKR_OK; |
2238 | 868k | } |
2239 | | |
2240 | | /* |
2241 | | * these helper functions are used by Generic Macing and Signing functions |
2242 | | * that use hashes as part of their operations. |
2243 | | */ |
2244 | | #define DOSUB(mmm) \ |
2245 | | static CK_RV \ |
2246 | | sftk_doSub##mmm(SFTKSessionContext *context) \ |
2247 | 5.97k | { \ |
2248 | 5.97k | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ |
2249 | 5.97k | context->hashInfo = (void *)mmm##_ctx; \ |
2250 | 5.97k | context->hashUpdate = SFTKHash_##mmm##_Update; \ |
2251 | 5.97k | context->end = SFTKHash_##mmm##_End; \ |
2252 | 5.97k | context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \ |
2253 | 5.97k | if (!context->hashInfo) { \ |
2254 | 0 | return CKR_HOST_MEMORY; \ |
2255 | 0 | } \ |
2256 | 5.97k | mmm##_Begin(mmm##_ctx); \ |
2257 | 5.97k | return CKR_OK; \ |
2258 | 5.97k | } Unexecuted instantiation: pkcs11c.c:sftk_doSubMD5 Unexecuted instantiation: pkcs11c.c:sftk_doSubMD2 Line | Count | Source | 2247 | 8 | { \ | 2248 | 8 | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ | 2249 | 8 | context->hashInfo = (void *)mmm##_ctx; \ | 2250 | 8 | context->hashUpdate = SFTKHash_##mmm##_Update; \ | 2251 | 8 | context->end = SFTKHash_##mmm##_End; \ | 2252 | 8 | context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \ | 2253 | 8 | if (!context->hashInfo) { \ | 2254 | 0 | return CKR_HOST_MEMORY; \ | 2255 | 0 | } \ | 2256 | 8 | mmm##_Begin(mmm##_ctx); \ | 2257 | 8 | return CKR_OK; \ | 2258 | 8 | } |
pkcs11c.c:sftk_doSubSHA224 Line | Count | Source | 2247 | 6 | { \ | 2248 | 6 | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ | 2249 | 6 | context->hashInfo = (void *)mmm##_ctx; \ | 2250 | 6 | context->hashUpdate = SFTKHash_##mmm##_Update; \ | 2251 | 6 | context->end = SFTKHash_##mmm##_End; \ | 2252 | 6 | context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \ | 2253 | 6 | if (!context->hashInfo) { \ | 2254 | 0 | return CKR_HOST_MEMORY; \ | 2255 | 0 | } \ | 2256 | 6 | mmm##_Begin(mmm##_ctx); \ | 2257 | 6 | return CKR_OK; \ | 2258 | 6 | } |
pkcs11c.c:sftk_doSubSHA256 Line | Count | Source | 2247 | 4.93k | { \ | 2248 | 4.93k | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ | 2249 | 4.93k | context->hashInfo = (void *)mmm##_ctx; \ | 2250 | 4.93k | context->hashUpdate = SFTKHash_##mmm##_Update; \ | 2251 | 4.93k | context->end = SFTKHash_##mmm##_End; \ | 2252 | 4.93k | context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \ | 2253 | 4.93k | if (!context->hashInfo) { \ | 2254 | 0 | return CKR_HOST_MEMORY; \ | 2255 | 0 | } \ | 2256 | 4.93k | mmm##_Begin(mmm##_ctx); \ | 2257 | 4.93k | return CKR_OK; \ | 2258 | 4.93k | } |
pkcs11c.c:sftk_doSubSHA384 Line | Count | Source | 2247 | 476 | { \ | 2248 | 476 | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ | 2249 | 476 | context->hashInfo = (void *)mmm##_ctx; \ | 2250 | 476 | context->hashUpdate = SFTKHash_##mmm##_Update; \ | 2251 | 476 | context->end = SFTKHash_##mmm##_End; \ | 2252 | 476 | context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \ | 2253 | 476 | if (!context->hashInfo) { \ | 2254 | 0 | return CKR_HOST_MEMORY; \ | 2255 | 0 | } \ | 2256 | 476 | mmm##_Begin(mmm##_ctx); \ | 2257 | 476 | return CKR_OK; \ | 2258 | 476 | } |
pkcs11c.c:sftk_doSubSHA512 Line | Count | Source | 2247 | 549 | { \ | 2248 | 549 | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ | 2249 | 549 | context->hashInfo = (void *)mmm##_ctx; \ | 2250 | 549 | context->hashUpdate = SFTKHash_##mmm##_Update; \ | 2251 | 549 | context->end = SFTKHash_##mmm##_End; \ | 2252 | 549 | context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \ | 2253 | 549 | if (!context->hashInfo) { \ | 2254 | 0 | return CKR_HOST_MEMORY; \ | 2255 | 0 | } \ | 2256 | 549 | mmm##_Begin(mmm##_ctx); \ | 2257 | 549 | return CKR_OK; \ | 2258 | 549 | } |
|
2259 | | |
2260 | | DOSUB(MD2) |
2261 | | DOSUB(MD5) |
2262 | | DOSUB(SHA1) |
2263 | | DOSUB(SHA224) |
2264 | | DOSUB(SHA256) |
2265 | | DOSUB(SHA384) |
2266 | | DOSUB(SHA512) |
2267 | | |
2268 | | static SECStatus |
2269 | | sftk_SignCopy( |
2270 | | void *copyLen, |
2271 | | unsigned char *out, unsigned int *outLength, |
2272 | | unsigned int maxLength, |
2273 | | const unsigned char *hashResult, |
2274 | | unsigned int hashResultLength) |
2275 | 65.9k | { |
2276 | 65.9k | unsigned int toCopy = *(CK_ULONG *)copyLen; |
2277 | 65.9k | if (toCopy > maxLength) { |
2278 | 0 | toCopy = maxLength; |
2279 | 0 | } |
2280 | 65.9k | if (toCopy > hashResultLength) { |
2281 | 0 | toCopy = hashResultLength; |
2282 | 0 | } |
2283 | 65.9k | memcpy(out, hashResult, toCopy); |
2284 | 65.9k | if (outLength) { |
2285 | 65.9k | *outLength = toCopy; |
2286 | 65.9k | } |
2287 | 65.9k | return SECSuccess; |
2288 | 65.9k | } |
2289 | | |
2290 | | /* Verify is just a compare for HMAC */ |
2291 | | static SECStatus |
2292 | | sftk_HMACCmp(void *copyLen, const unsigned char *sig, unsigned int sigLen, |
2293 | | const unsigned char *hash, unsigned int hashLen) |
2294 | 0 | { |
2295 | 0 | if (NSS_SecureMemcmp(sig, hash, *(CK_ULONG *)copyLen) == 0) { |
2296 | 0 | return SECSuccess; |
2297 | 0 | } |
2298 | | |
2299 | 0 | PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
2300 | 0 | return SECFailure; |
2301 | 0 | } |
2302 | | |
2303 | | /* |
2304 | | * common HMAC + CMAC initialization routine |
2305 | | */ |
2306 | | static CK_RV |
2307 | | sftk_doMACInit(CK_MECHANISM_TYPE mech, SFTKSessionContext *session, |
2308 | | SFTKObject *key, CK_ULONG mac_size) |
2309 | 252k | { |
2310 | 252k | CK_RV crv; |
2311 | 252k | sftk_MACCtx *context; |
2312 | 252k | CK_ULONG *intpointer; |
2313 | 252k | PRBool isFIPS = sftk_isFIPS(key->slot->slotID); |
2314 | | |
2315 | | /* Set up the initial context. */ |
2316 | 252k | crv = sftk_MAC_Create(mech, key, &context); |
2317 | 252k | if (crv != CKR_OK) { |
2318 | 0 | return crv; |
2319 | 0 | } |
2320 | | |
2321 | 252k | session->hashInfo = context; |
2322 | 252k | session->multi = PR_TRUE; |
2323 | | |
2324 | | /* Required by FIPS 198 Section 4. Delay this check until after the MAC |
2325 | | * has been initialized to steal the output size of the MAC. */ |
2326 | 252k | if (isFIPS && (mac_size < 4 || mac_size < context->mac_size / 2)) { |
2327 | 0 | sftk_MAC_DestroyContext(context, PR_TRUE); |
2328 | 0 | return CKR_BUFFER_TOO_SMALL; |
2329 | 0 | } |
2330 | | |
2331 | | /* Configure our helper functions appropriately. Note that these casts |
2332 | | * ignore the return values. */ |
2333 | 252k | session->hashUpdate = SFTKHash_sftk_MAC_Update; |
2334 | 252k | session->end = SFTKHash_sftk_MAC_End; |
2335 | 252k | session->hashdestroy = SFTKHash_sftk_MAC_DestroyContext; |
2336 | | |
2337 | 252k | intpointer = PORT_New(CK_ULONG); |
2338 | 252k | if (intpointer == NULL) { |
2339 | 0 | sftk_MAC_DestroyContext(context, PR_TRUE); |
2340 | 0 | return CKR_HOST_MEMORY; |
2341 | 0 | } |
2342 | 252k | *intpointer = mac_size; |
2343 | 252k | session->cipherInfo = intpointer; |
2344 | | |
2345 | | /* Since we're only "hashing", copy the result from session->end to the |
2346 | | * caller using sftk_SignCopy. */ |
2347 | 252k | session->update = sftk_SignCopy; |
2348 | 252k | session->verify = sftk_HMACCmp; |
2349 | 252k | session->destroy = sftk_Space; |
2350 | | |
2351 | 252k | session->maxLen = context->mac_size; |
2352 | | |
2353 | 252k | return CKR_OK; |
2354 | 252k | } |
2355 | | |
2356 | | /* |
2357 | | * SSL Macing support. SSL Macs are inited, then update with the base |
2358 | | * hashing algorithm, then finalized in sign and verify |
2359 | | */ |
2360 | | |
2361 | | /* |
2362 | | * FROM SSL: |
2363 | | * 60 bytes is 3 times the maximum length MAC size that is supported. |
2364 | | * We probably should have one copy of this table. We still need this table |
2365 | | * in ssl to 'sign' the handshake hashes. |
2366 | | */ |
2367 | | static unsigned char ssl_pad_1[60] = { |
2368 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2369 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2370 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2371 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2372 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2373 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2374 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2375 | | 0x36, 0x36, 0x36, 0x36 |
2376 | | }; |
2377 | | static unsigned char ssl_pad_2[60] = { |
2378 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2379 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2380 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2381 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2382 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2383 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2384 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2385 | | 0x5c, 0x5c, 0x5c, 0x5c |
2386 | | }; |
2387 | | |
2388 | | static SECStatus |
2389 | | sftk_SSLMACSign(void *ctx, unsigned char *sig, unsigned int *sigLen, |
2390 | | unsigned int maxLen, const unsigned char *hash, unsigned int hashLen) |
2391 | 0 | { |
2392 | 0 | SFTKSSLMACInfo *info = ctx; |
2393 | 0 | unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; |
2394 | 0 | unsigned int out; |
2395 | |
|
2396 | 0 | info->begin(info->hashContext); |
2397 | 0 | info->update(info->hashContext, info->key, info->keySize); |
2398 | 0 | info->update(info->hashContext, ssl_pad_2, info->padSize); |
2399 | 0 | info->update(info->hashContext, hash, hashLen); |
2400 | 0 | info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH); |
2401 | 0 | PORT_Memcpy(sig, tmpBuf, info->macSize); |
2402 | 0 | PORT_Memset(tmpBuf, 0, info->macSize); |
2403 | 0 | *sigLen = info->macSize; |
2404 | 0 | return SECSuccess; |
2405 | 0 | } |
2406 | | |
2407 | | static SECStatus |
2408 | | sftk_SSLMACVerify(void *ctx, const unsigned char *sig, unsigned int sigLen, |
2409 | | const unsigned char *hash, unsigned int hashLen) |
2410 | 0 | { |
2411 | 0 | SFTKSSLMACInfo *info = ctx; |
2412 | 0 | unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; |
2413 | 0 | unsigned int out; |
2414 | 0 | int cmp; |
2415 | |
|
2416 | 0 | info->begin(info->hashContext); |
2417 | 0 | info->update(info->hashContext, info->key, info->keySize); |
2418 | 0 | info->update(info->hashContext, ssl_pad_2, info->padSize); |
2419 | 0 | info->update(info->hashContext, hash, hashLen); |
2420 | 0 | info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH); |
2421 | 0 | cmp = NSS_SecureMemcmp(sig, tmpBuf, info->macSize); |
2422 | 0 | PORT_Memset(tmpBuf, 0, info->macSize); |
2423 | 0 | return (cmp == 0) ? SECSuccess : SECFailure; |
2424 | 0 | } |
2425 | | |
2426 | | /* |
2427 | | * common HMAC initalization routine |
2428 | | */ |
2429 | | static CK_RV |
2430 | | sftk_doSSLMACInit(SFTKSessionContext *context, SECOidTag oid, |
2431 | | SFTKObject *key, CK_ULONG mac_size) |
2432 | 0 | { |
2433 | 0 | SFTKAttribute *keyval; |
2434 | 0 | SFTKBegin begin; |
2435 | 0 | int padSize; |
2436 | 0 | SFTKSSLMACInfo *sslmacinfo; |
2437 | 0 | CK_RV crv = CKR_MECHANISM_INVALID; |
2438 | |
|
2439 | 0 | if (oid == SEC_OID_SHA1) { |
2440 | 0 | crv = sftk_doSubSHA1(context); |
2441 | 0 | if (crv != CKR_OK) |
2442 | 0 | return crv; |
2443 | 0 | begin = SFTKHash_SHA1_Begin; |
2444 | 0 | padSize = 40; |
2445 | 0 | } else { |
2446 | 0 | crv = sftk_doSubMD5(context); |
2447 | 0 | if (crv != CKR_OK) |
2448 | 0 | return crv; |
2449 | 0 | begin = SFTKHash_MD5_Begin; |
2450 | 0 | padSize = 48; |
2451 | 0 | } |
2452 | 0 | context->multi = PR_TRUE; |
2453 | |
|
2454 | 0 | keyval = sftk_FindAttribute(key, CKA_VALUE); |
2455 | 0 | if (keyval == NULL) |
2456 | 0 | return CKR_KEY_SIZE_RANGE; |
2457 | | |
2458 | 0 | context->hashUpdate(context->hashInfo, keyval->attrib.pValue, |
2459 | 0 | keyval->attrib.ulValueLen); |
2460 | 0 | context->hashUpdate(context->hashInfo, ssl_pad_1, padSize); |
2461 | 0 | sslmacinfo = (SFTKSSLMACInfo *)PORT_Alloc(sizeof(SFTKSSLMACInfo)); |
2462 | 0 | if (sslmacinfo == NULL) { |
2463 | 0 | sftk_FreeAttribute(keyval); |
2464 | 0 | return CKR_HOST_MEMORY; |
2465 | 0 | } |
2466 | 0 | sslmacinfo->size = sizeof(SFTKSSLMACInfo); |
2467 | 0 | sslmacinfo->macSize = mac_size; |
2468 | 0 | sslmacinfo->hashContext = context->hashInfo; |
2469 | 0 | PORT_Memcpy(sslmacinfo->key, keyval->attrib.pValue, |
2470 | 0 | keyval->attrib.ulValueLen); |
2471 | 0 | sslmacinfo->keySize = keyval->attrib.ulValueLen; |
2472 | 0 | sslmacinfo->begin = begin; |
2473 | 0 | sslmacinfo->end = context->end; |
2474 | 0 | sslmacinfo->update = context->hashUpdate; |
2475 | 0 | sslmacinfo->padSize = padSize; |
2476 | 0 | sftk_FreeAttribute(keyval); |
2477 | 0 | context->cipherInfo = (void *)sslmacinfo; |
2478 | 0 | context->destroy = sftk_ZSpace; |
2479 | 0 | context->update = sftk_SSLMACSign; |
2480 | 0 | context->verify = sftk_SSLMACVerify; |
2481 | 0 | context->maxLen = mac_size; |
2482 | 0 | return CKR_OK; |
2483 | 0 | } |
2484 | | |
2485 | | /* |
2486 | | ************** Crypto Functions: Sign ************************ |
2487 | | */ |
2488 | | |
2489 | | /** |
2490 | | * Check if We're using CBCMacing and initialize the session context if we are. |
2491 | | * @param contextType SFTK_SIGN or SFTK_VERIFY |
2492 | | * @param keyUsage check whether key allows this usage |
2493 | | */ |
2494 | | static CK_RV |
2495 | | sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
2496 | | CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage, |
2497 | | SFTKContextType contextType) |
2498 | | |
2499 | 526k | { |
2500 | 526k | CK_MECHANISM cbc_mechanism; |
2501 | 526k | CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE; |
2502 | 526k | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
2503 | 526k | CK_RC2_CBC_PARAMS rc2_params; |
2504 | 526k | #endif |
2505 | | #if NSS_SOFTOKEN_DOES_RC5 |
2506 | | CK_RC5_CBC_PARAMS rc5_params; |
2507 | | CK_RC5_MAC_GENERAL_PARAMS *rc5_mac; |
2508 | | #endif |
2509 | 526k | unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE]; |
2510 | 526k | unsigned char k2[SFTK_MAX_BLOCK_SIZE]; |
2511 | 526k | unsigned char k3[SFTK_MAX_BLOCK_SIZE]; |
2512 | 526k | SFTKSession *session; |
2513 | 526k | SFTKSessionContext *context; |
2514 | 526k | CK_RV crv; |
2515 | 526k | unsigned int blockSize; |
2516 | 526k | PRBool isXCBC = PR_FALSE; |
2517 | | |
2518 | 526k | if (!pMechanism) { |
2519 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
2520 | 0 | } |
2521 | | |
2522 | 526k | switch (pMechanism->mechanism) { |
2523 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
2524 | 0 | case CKM_RC2_MAC_GENERAL: |
2525 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_MAC_GENERAL_PARAMS))) { |
2526 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
2527 | 0 | } |
2528 | 0 | mac_bytes = |
2529 | 0 | ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; |
2530 | | /* fall through */ |
2531 | 0 | case CKM_RC2_MAC: |
2532 | | /* this works because ulEffectiveBits is in the same place in both the |
2533 | | * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */ |
2534 | 0 | rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *) |
2535 | 0 | pMechanism->pParameter) |
2536 | 0 | ->ulEffectiveBits; |
2537 | 0 | PORT_Memset(rc2_params.iv, 0, sizeof(rc2_params.iv)); |
2538 | 0 | cbc_mechanism.mechanism = CKM_RC2_CBC; |
2539 | 0 | cbc_mechanism.pParameter = &rc2_params; |
2540 | 0 | cbc_mechanism.ulParameterLen = sizeof(rc2_params); |
2541 | 0 | blockSize = 8; |
2542 | 0 | break; |
2543 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
2544 | | |
2545 | | #if NSS_SOFTOKEN_DOES_RC5 |
2546 | | case CKM_RC5_MAC_GENERAL: |
2547 | | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) { |
2548 | | return CKR_MECHANISM_PARAM_INVALID; |
2549 | | } |
2550 | | mac_bytes = |
2551 | | ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; |
2552 | | /* fall through */ |
2553 | | case CKM_RC5_MAC: |
2554 | | /* this works because ulEffectiveBits is in the same place in both the |
2555 | | * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */ |
2556 | | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) { |
2557 | | return CKR_MECHANISM_PARAM_INVALID; |
2558 | | } |
2559 | | rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter; |
2560 | | rc5_params.ulWordsize = rc5_mac->ulWordsize; |
2561 | | rc5_params.ulRounds = rc5_mac->ulRounds; |
2562 | | rc5_params.pIv = ivBlock; |
2563 | | if ((blockSize = rc5_mac->ulWordsize * 2) > SFTK_MAX_BLOCK_SIZE) |
2564 | | return CKR_MECHANISM_PARAM_INVALID; |
2565 | | rc5_params.ulIvLen = blockSize; |
2566 | | PORT_Memset(ivBlock, 0, blockSize); |
2567 | | cbc_mechanism.mechanism = CKM_RC5_CBC; |
2568 | | cbc_mechanism.pParameter = &rc5_params; |
2569 | | cbc_mechanism.ulParameterLen = sizeof(rc5_params); |
2570 | | break; |
2571 | | #endif |
2572 | | /* add cast and idea later */ |
2573 | 0 | case CKM_DES_MAC_GENERAL: |
2574 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2575 | | /* fall through */ |
2576 | 0 | case CKM_DES_MAC: |
2577 | 0 | blockSize = 8; |
2578 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2579 | 0 | cbc_mechanism.mechanism = CKM_DES_CBC; |
2580 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2581 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2582 | 0 | break; |
2583 | 0 | case CKM_DES3_MAC_GENERAL: |
2584 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2585 | | /* fall through */ |
2586 | 0 | case CKM_DES3_MAC: |
2587 | 0 | blockSize = 8; |
2588 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2589 | 0 | cbc_mechanism.mechanism = CKM_DES3_CBC; |
2590 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2591 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2592 | 0 | break; |
2593 | 0 | case CKM_CDMF_MAC_GENERAL: |
2594 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2595 | | /* fall through */ |
2596 | 0 | case CKM_CDMF_MAC: |
2597 | 0 | blockSize = 8; |
2598 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2599 | 0 | cbc_mechanism.mechanism = CKM_CDMF_CBC; |
2600 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2601 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2602 | 0 | break; |
2603 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
2604 | 0 | case CKM_SEED_MAC_GENERAL: |
2605 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2606 | | /* fall through */ |
2607 | 0 | case CKM_SEED_MAC: |
2608 | 0 | blockSize = 16; |
2609 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2610 | 0 | cbc_mechanism.mechanism = CKM_SEED_CBC; |
2611 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2612 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2613 | 0 | break; |
2614 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
2615 | 0 | case CKM_CAMELLIA_MAC_GENERAL: |
2616 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2617 | | /* fall through */ |
2618 | 0 | case CKM_CAMELLIA_MAC: |
2619 | 0 | blockSize = 16; |
2620 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2621 | 0 | cbc_mechanism.mechanism = CKM_CAMELLIA_CBC; |
2622 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2623 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2624 | 0 | break; |
2625 | 0 | case CKM_AES_MAC_GENERAL: |
2626 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2627 | | /* fall through */ |
2628 | 0 | case CKM_AES_MAC: |
2629 | 0 | blockSize = 16; |
2630 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2631 | 0 | cbc_mechanism.mechanism = CKM_AES_CBC; |
2632 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2633 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2634 | 0 | break; |
2635 | 0 | case CKM_AES_XCBC_MAC_96: |
2636 | 0 | case CKM_AES_XCBC_MAC: |
2637 | | /* The only difference between CKM_AES_XCBC_MAC |
2638 | | * and CKM_AES_XCBC_MAC_96 is the size of the returned mac. */ |
2639 | 0 | mac_bytes = pMechanism->mechanism == CKM_AES_XCBC_MAC_96 ? 12 : 16; |
2640 | 0 | blockSize = 16; |
2641 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2642 | 0 | cbc_mechanism.mechanism = CKM_AES_CBC; |
2643 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2644 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2645 | | /* is XCBC requires extra processing at the end of the operation */ |
2646 | 0 | isXCBC = PR_TRUE; |
2647 | | /* The input key is used to generate k1, k2, and k3. k2 and k3 |
2648 | | * are used at the end in the pad step. k1 replaces the input |
2649 | | * key in the aes cbc mac */ |
2650 | 0 | crv = sftk_aes_xcbc_new_keys(hSession, hKey, &hKey, k2, k3); |
2651 | 0 | if (crv != CKR_OK) { |
2652 | 0 | return crv; |
2653 | 0 | } |
2654 | 0 | break; |
2655 | 526k | default: |
2656 | 526k | return CKR_FUNCTION_NOT_SUPPORTED; |
2657 | 526k | } |
2658 | | |
2659 | | /* if MAC size is externally supplied, it should be checked. |
2660 | | */ |
2661 | 0 | if (mac_bytes == SFTK_INVALID_MAC_SIZE) |
2662 | 0 | mac_bytes = blockSize >> 1; |
2663 | 0 | else { |
2664 | 0 | if (mac_bytes > blockSize) { |
2665 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
2666 | 0 | goto fail; |
2667 | 0 | } |
2668 | 0 | } |
2669 | | |
2670 | 0 | crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey, |
2671 | 0 | CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */ |
2672 | 0 | keyUsage, contextType, PR_TRUE); |
2673 | 0 | if (crv != CKR_OK) |
2674 | 0 | goto fail; |
2675 | | /* Hold the session reference for the duration of the context writes; |
2676 | | * see comment on NSC_DigestUpdate. */ |
2677 | 0 | crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, &session); |
2678 | | |
2679 | | /* this shouldn't happen! */ |
2680 | 0 | PORT_Assert(crv == CKR_OK); |
2681 | 0 | if (crv != CKR_OK) |
2682 | 0 | goto fail; |
2683 | 0 | context->blockSize = blockSize; |
2684 | 0 | context->macSize = mac_bytes; |
2685 | 0 | context->isXCBC = isXCBC; |
2686 | 0 | if (isXCBC) { |
2687 | | /* save the xcbc specific parameters */ |
2688 | 0 | PORT_Memcpy(context->k2, k2, blockSize); |
2689 | 0 | PORT_Memcpy(context->k3, k3, blockSize); |
2690 | 0 | PORT_Memset(k2, 0, blockSize); |
2691 | 0 | PORT_Memset(k3, 0, blockSize); |
2692 | | /* get rid of the temp key now that the context has been created */ |
2693 | 0 | NSC_DestroyObject(hSession, hKey); |
2694 | 0 | } |
2695 | 0 | sftk_FreeSession(session); |
2696 | 0 | return CKR_OK; |
2697 | 0 | fail: |
2698 | 0 | if (isXCBC) { |
2699 | 0 | PORT_Memset(k2, 0, blockSize); |
2700 | 0 | PORT_Memset(k3, 0, blockSize); |
2701 | 0 | NSC_DestroyObject(hSession, hKey); /* get rid of our temp key */ |
2702 | 0 | } |
2703 | 0 | return crv; |
2704 | 0 | } |
2705 | | |
2706 | | /* |
2707 | | * encode RSA PKCS #1 Signature data before signing... |
2708 | | */ |
2709 | | static SECStatus |
2710 | | sftk_RSAHashSign(void *ctx, unsigned char *sig, |
2711 | | unsigned int *sigLen, unsigned int maxLen, |
2712 | | const unsigned char *hash, unsigned int hashLen) |
2713 | 0 | { |
2714 | 0 | SFTKHashSignInfo *info = ctx; |
2715 | 0 | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
2716 | 0 | if (info->key->keyType != NSSLOWKEYRSAKey) { |
2717 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2718 | 0 | return SECFailure; |
2719 | 0 | } |
2720 | | |
2721 | 0 | return RSA_HashSign(info->hashOid, info->key, sig, sigLen, maxLen, |
2722 | 0 | hash, hashLen); |
2723 | 0 | } |
2724 | | |
2725 | | /* XXX Old template; want to expunge it eventually. */ |
2726 | | static DERTemplate SECAlgorithmIDTemplate[] = { |
2727 | | { DER_SEQUENCE, |
2728 | | 0, NULL, sizeof(SECAlgorithmID) }, |
2729 | | { DER_OBJECT_ID, |
2730 | | offsetof(SECAlgorithmID, algorithm) }, |
2731 | | { DER_OPTIONAL | DER_ANY, |
2732 | | offsetof(SECAlgorithmID, parameters) }, |
2733 | | { 0 } |
2734 | | }; |
2735 | | |
2736 | | /* |
2737 | | * XXX OLD Template. Once all uses have been switched over to new one, |
2738 | | * remove this. |
2739 | | */ |
2740 | | static DERTemplate SGNDigestInfoTemplate[] = { |
2741 | | { DER_SEQUENCE, |
2742 | | 0, NULL, sizeof(SGNDigestInfo) }, |
2743 | | { DER_INLINE, |
2744 | | offsetof(SGNDigestInfo, digestAlgorithm), |
2745 | | SECAlgorithmIDTemplate }, |
2746 | | { DER_OCTET_STRING, |
2747 | | offsetof(SGNDigestInfo, digest) }, |
2748 | | { 0 } |
2749 | | }; |
2750 | | |
2751 | | /* |
2752 | | * encode RSA PKCS #1 Signature data before signing... |
2753 | | */ |
2754 | | SECStatus |
2755 | | RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, |
2756 | | unsigned char *sig, unsigned int *sigLen, unsigned int maxLen, |
2757 | | const unsigned char *hash, unsigned int hashLen) |
2758 | 0 | { |
2759 | 0 | SECStatus rv = SECFailure; |
2760 | 0 | SECItem digder; |
2761 | 0 | PLArenaPool *arena = NULL; |
2762 | 0 | SGNDigestInfo *di = NULL; |
2763 | |
|
2764 | 0 | digder.data = NULL; |
2765 | |
|
2766 | 0 | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
2767 | 0 | if (!arena) { |
2768 | 0 | goto loser; |
2769 | 0 | } |
2770 | | |
2771 | | /* Construct digest info */ |
2772 | 0 | di = SGN_CreateDigestInfo(hashOid, hash, hashLen); |
2773 | 0 | if (!di) { |
2774 | 0 | goto loser; |
2775 | 0 | } |
2776 | | |
2777 | | /* Der encode the digest as a DigestInfo */ |
2778 | 0 | rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di); |
2779 | 0 | if (rv != SECSuccess) { |
2780 | 0 | goto loser; |
2781 | 0 | } |
2782 | | |
2783 | | /* |
2784 | | ** Encrypt signature after constructing appropriate PKCS#1 signature |
2785 | | ** block |
2786 | | */ |
2787 | 0 | rv = RSA_Sign(&key->u.rsa, sig, sigLen, maxLen, digder.data, |
2788 | 0 | digder.len); |
2789 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2790 | 0 | sftk_fatalError = PR_TRUE; |
2791 | 0 | } |
2792 | |
|
2793 | 0 | loser: |
2794 | 0 | SGN_DestroyDigestInfo(di); |
2795 | 0 | if (arena != NULL) { |
2796 | 0 | PORT_FreeArena(arena, PR_TRUE); |
2797 | 0 | } |
2798 | 0 | return rv; |
2799 | 0 | } |
2800 | | |
2801 | | static SECStatus |
2802 | | sftk_RSASign(void *ctx, unsigned char *output, |
2803 | | unsigned int *outputLen, unsigned int maxOutputLen, |
2804 | | const unsigned char *input, unsigned int inputLen) |
2805 | 21.0k | { |
2806 | 21.0k | NSSLOWKEYPrivateKey *key = ctx; |
2807 | 21.0k | SECStatus rv = SECFailure; |
2808 | | |
2809 | 21.0k | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
2810 | 21.0k | if (key->keyType != NSSLOWKEYRSAKey) { |
2811 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2812 | 0 | return SECFailure; |
2813 | 0 | } |
2814 | | |
2815 | 21.0k | rv = RSA_Sign(&key->u.rsa, output, outputLen, maxOutputLen, input, |
2816 | 21.0k | inputLen); |
2817 | 21.0k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2818 | 0 | sftk_fatalError = PR_TRUE; |
2819 | 0 | } |
2820 | 21.0k | return rv; |
2821 | 21.0k | } |
2822 | | |
2823 | | static SECStatus |
2824 | | sftk_RSASignRaw(void *ctx, unsigned char *output, |
2825 | | unsigned int *outputLen, unsigned int maxOutputLen, |
2826 | | const unsigned char *input, unsigned int inputLen) |
2827 | 0 | { |
2828 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
2829 | 0 | SECStatus rv = SECFailure; |
2830 | |
|
2831 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
2832 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
2833 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2834 | 0 | return SECFailure; |
2835 | 0 | } |
2836 | | |
2837 | 0 | rv = RSA_SignRaw(&key->u.rsa, output, outputLen, maxOutputLen, input, |
2838 | 0 | inputLen); |
2839 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2840 | 0 | sftk_fatalError = PR_TRUE; |
2841 | 0 | } |
2842 | 0 | return rv; |
2843 | 0 | } |
2844 | | |
2845 | | static SECStatus |
2846 | | sftk_RSASignPSS(void *ctx, unsigned char *sig, |
2847 | | unsigned int *sigLen, unsigned int maxLen, |
2848 | | const unsigned char *hash, unsigned int hashLen) |
2849 | 2.87k | { |
2850 | 2.87k | SFTKPSSSignInfo *info = ctx; |
2851 | 2.87k | SECStatus rv = SECFailure; |
2852 | 2.87k | HASH_HashType hashAlg; |
2853 | 2.87k | HASH_HashType maskHashAlg; |
2854 | 2.87k | CK_RSA_PKCS_PSS_PARAMS *params = &info->params; |
2855 | | |
2856 | 2.87k | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
2857 | 2.87k | if (info->key->keyType != NSSLOWKEYRSAKey) { |
2858 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2859 | 0 | return SECFailure; |
2860 | 0 | } |
2861 | | |
2862 | 2.87k | hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg); |
2863 | 2.87k | maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf); |
2864 | | |
2865 | 2.87k | rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL, |
2866 | 2.87k | params->sLen, sig, sigLen, maxLen, hash, hashLen); |
2867 | 2.87k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2868 | 0 | sftk_fatalError = PR_TRUE; |
2869 | 0 | } |
2870 | 2.87k | return rv; |
2871 | 2.87k | } |
2872 | | |
2873 | | #ifndef NSS_DISABLE_DSA |
2874 | | static SECStatus |
2875 | | nsc_DSA_Verify_Stub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen, |
2876 | | const unsigned char *dataBuf, unsigned int dataLen) |
2877 | 4.67k | { |
2878 | 4.67k | NSSLOWKEYPublicKey *key = ctx; |
2879 | 4.67k | SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen }; |
2880 | 4.67k | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2881 | 4.67k | return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest); |
2882 | 4.67k | } |
2883 | | |
2884 | | static SECStatus |
2885 | | nsc_DSA_Sign_Stub(void *ctx, unsigned char *sigBuf, |
2886 | | unsigned int *sigLen, unsigned int maxSigLen, |
2887 | | const unsigned char *dataBuf, unsigned int dataLen) |
2888 | 0 | { |
2889 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
2890 | 0 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen }; |
2891 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2892 | 0 | SECStatus rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest); |
2893 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2894 | 0 | sftk_fatalError = PR_TRUE; |
2895 | 0 | } |
2896 | 0 | *sigLen = signature.len; |
2897 | 0 | return rv; |
2898 | 0 | } |
2899 | | #endif |
2900 | | |
2901 | | static SECStatus |
2902 | | nsc_ECDSAVerifyStub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen, |
2903 | | const unsigned char *dataBuf, unsigned int dataLen) |
2904 | 592 | { |
2905 | 592 | NSSLOWKEYPublicKey *key = ctx; |
2906 | 592 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen }; |
2907 | 592 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2908 | 592 | return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest); |
2909 | 592 | } |
2910 | | |
2911 | | static SECStatus |
2912 | | nsc_ECDSASignStub(void *ctx, unsigned char *sigBuf, |
2913 | | unsigned int *sigLen, unsigned int maxSigLen, |
2914 | | const unsigned char *dataBuf, unsigned int dataLen) |
2915 | 8.74k | { |
2916 | 8.74k | NSSLOWKEYPrivateKey *key = ctx; |
2917 | 8.74k | SECItem signature = { siBuffer, sigBuf, maxSigLen }; |
2918 | 8.74k | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2919 | | |
2920 | 8.74k | SECStatus rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest); |
2921 | 8.74k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2922 | 0 | sftk_fatalError = PR_TRUE; |
2923 | 0 | } |
2924 | 8.74k | *sigLen = signature.len; |
2925 | 8.74k | return rv; |
2926 | 8.74k | } |
2927 | | |
2928 | | static SECStatus |
2929 | | nsc_EDDSAVerifyStub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen, |
2930 | | const unsigned char *dataBuf, unsigned int dataLen) |
2931 | 0 | { |
2932 | 0 | NSSLOWKEYPublicKey *key = ctx; |
2933 | 0 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen }; |
2934 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2935 | 0 | return ED_VerifyMessage(&(key->u.ec), &signature, &digest); |
2936 | 0 | } |
2937 | | |
2938 | | static SECStatus |
2939 | | nsc_EDDSASignStub(void *ctx, unsigned char *sigBuf, |
2940 | | unsigned int *sigLen, unsigned int maxSigLen, |
2941 | | const unsigned char *dataBuf, unsigned int dataLen) |
2942 | 0 | { |
2943 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
2944 | 0 | SECItem signature = { siBuffer, sigBuf, maxSigLen }; |
2945 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2946 | |
|
2947 | 0 | SECStatus rv = ED_SignMessage(&(key->u.ec), &signature, &digest); |
2948 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2949 | 0 | sftk_fatalError = PR_TRUE; |
2950 | 0 | } |
2951 | 0 | *sigLen = signature.len; |
2952 | 0 | return rv; |
2953 | 0 | } |
2954 | | |
2955 | | void |
2956 | | sftk_MLDSASignUpdate(void *info, const unsigned char *data, unsigned int len) |
2957 | 0 | { |
2958 | 0 | MLDSAContext *ctptr = (MLDSAContext *)info; |
2959 | 0 | const SECItem inData = { siBuffer, (unsigned char *)data, len }; |
2960 | 0 | (void)MLDSA_SignUpdate(ctptr, &inData); |
2961 | 0 | } |
2962 | | |
2963 | | void |
2964 | | sftk_MLDSAVerifyUpdate(void *info, const unsigned char *data, unsigned int len) |
2965 | 0 | { |
2966 | 0 | MLDSAContext *ctptr = (MLDSAContext *)info; |
2967 | 0 | const SECItem inData = { siBuffer, (unsigned char *)data, len }; |
2968 | 0 | (void)MLDSA_VerifyUpdate(ctptr, &inData); |
2969 | 0 | } |
2970 | | |
2971 | | SECStatus |
2972 | | sftk_MLDSASignFinal(void *info, unsigned char *sig, unsigned int *sigLen, |
2973 | | unsigned int maxLen, const unsigned char *data, |
2974 | | unsigned int len) |
2975 | 0 | { |
2976 | 0 | MLDSAContext *ctptr = (MLDSAContext *)info; |
2977 | 0 | SECItem sigOut = { siBuffer, sig, maxLen }; |
2978 | 0 | SECStatus rv; |
2979 | |
|
2980 | 0 | if (len != 0) { |
2981 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2982 | 0 | return SECFailure; |
2983 | 0 | } |
2984 | | |
2985 | 0 | rv = MLDSA_SignFinal(ctptr, &sigOut); |
2986 | 0 | *sigLen = sigOut.len; |
2987 | 0 | return rv; |
2988 | 0 | } |
2989 | | |
2990 | | SECStatus |
2991 | | sftk_MLDSAVerifyFinal(void *info, const unsigned char *sig, unsigned int sigLen, |
2992 | | const unsigned char *data, unsigned int len) |
2993 | 0 | { |
2994 | 0 | MLDSAContext *ctptr = (MLDSAContext *)info; |
2995 | 0 | const SECItem sigIn = { siBuffer, (unsigned char *)sig, sigLen }; |
2996 | |
|
2997 | 0 | if (len != 0) { |
2998 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2999 | 0 | return SECFailure; |
3000 | 0 | } |
3001 | | |
3002 | 0 | return MLDSA_VerifyFinal(ctptr, &sigIn); |
3003 | 0 | } |
3004 | | |
3005 | | unsigned int |
3006 | | sftk_MLDSAGetSigLen(CK_ML_DSA_PARAMETER_SET_TYPE paramSet) |
3007 | 0 | { |
3008 | 0 | switch (paramSet) { |
3009 | 0 | case CKP_ML_DSA_44: |
3010 | 0 | return ML_DSA_44_SIGNATURE_LEN; |
3011 | 0 | case CKP_ML_DSA_65: |
3012 | 0 | return ML_DSA_65_SIGNATURE_LEN; |
3013 | 0 | case CKP_ML_DSA_87: |
3014 | 0 | return ML_DSA_87_SIGNATURE_LEN; |
3015 | 0 | } |
3016 | | /* this is a programming error if we get a valid DSA key with an unknown |
3017 | | * parmaSet */ |
3018 | 0 | PORT_Assert(/* unknown param set */ 0); |
3019 | 0 | return 0; |
3020 | 0 | } |
3021 | | |
3022 | | /* NSC_SignInit setups up the signing operations. There are three basic |
3023 | | * types of signing: |
3024 | | * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied |
3025 | | * to data in a single Sign operation (which often looks a lot like an |
3026 | | * encrypt, with data coming in and data going out). |
3027 | | * (2) Hash based signing, where we continually hash the data, then apply |
3028 | | * some sort of signature to the end. |
3029 | | * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key, |
3030 | | * and only the final block is part of the mac. |
3031 | | * |
3032 | | * For case number 3, we initialize a context much like the Encryption Context |
3033 | | * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and |
3034 | | * C_Final by the following method... if it's not multi-part, and it's doesn't |
3035 | | * have a hash context, it must be a block Encryption CBC MAC. |
3036 | | * |
3037 | | * For case number 2, we initialize a hash structure, as well as make it |
3038 | | * multi-part. Updates are simple calls to the hash update function. Final |
3039 | | * calls the hashend, then passes the result to the 'update' function (which |
3040 | | * operates as a final signature function). In some hash based MAC'ing (as |
3041 | | * opposed to hash base signatures), the update function is can be simply a |
3042 | | * copy (as is the case with HMAC). |
3043 | | */ |
3044 | | CK_RV |
3045 | | NSC_SignInit(CK_SESSION_HANDLE hSession, |
3046 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
3047 | 516k | { |
3048 | 516k | SFTKSession *session; |
3049 | 516k | SFTKObject *key; |
3050 | 516k | SFTKSessionContext *context; |
3051 | 516k | CK_KEY_TYPE key_type; |
3052 | 516k | CK_RV crv = CKR_OK; |
3053 | 516k | NSSLOWKEYPrivateKey *privKey; |
3054 | 516k | SFTKHashSignInfo *info = NULL; |
3055 | 516k | SFTKPSSSignInfo *pinfo = NULL; |
3056 | | |
3057 | 516k | CHECK_FORK(); |
3058 | | |
3059 | | /* Block Cipher MACing Algorithms use a different Context init method..*/ |
3060 | 516k | crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN); |
3061 | 516k | if (crv != CKR_FUNCTION_NOT_SUPPORTED) |
3062 | 0 | return crv; |
3063 | | |
3064 | | /* we're not using a block cipher mac */ |
3065 | 516k | session = sftk_SessionFromHandle(hSession); |
3066 | 516k | if (session == NULL) |
3067 | 0 | return CKR_SESSION_HANDLE_INVALID; |
3068 | 516k | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_SIGN, &key, |
3069 | 516k | hKey, &key_type, CKO_PRIVATE_KEY, CKA_SIGN); |
3070 | 516k | if (crv != CKR_OK) { |
3071 | 0 | sftk_FreeSession(session); |
3072 | 0 | return crv; |
3073 | 0 | } |
3074 | | |
3075 | 516k | context->multi = PR_FALSE; |
3076 | | |
3077 | 516k | #define INIT_RSA_SIGN_MECH(mmm) \ |
3078 | 516k | case CKM_##mmm##_RSA_PKCS: \ |
3079 | 0 | context->multi = PR_TRUE; \ |
3080 | 0 | crv = sftk_doSub##mmm(context); \ |
3081 | 0 | if (crv != CKR_OK) \ |
3082 | 0 | break; \ |
3083 | 0 | context->update = sftk_RSAHashSign; \ |
3084 | 0 | info = PORT_New(SFTKHashSignInfo); \ |
3085 | 0 | if (info == NULL) { \ |
3086 | 0 | crv = CKR_HOST_MEMORY; \ |
3087 | 0 | break; \ |
3088 | 0 | } \ |
3089 | 0 | info->hashOid = SEC_OID_##mmm; \ |
3090 | 0 | goto finish_rsa; |
3091 | | |
3092 | 516k | switch (pMechanism->mechanism) { |
3093 | 0 | INIT_RSA_SIGN_MECH(MD5) |
3094 | 0 | INIT_RSA_SIGN_MECH(MD2) |
3095 | 0 | INIT_RSA_SIGN_MECH(SHA1) |
3096 | 0 | INIT_RSA_SIGN_MECH(SHA224) |
3097 | 0 | INIT_RSA_SIGN_MECH(SHA256) |
3098 | 0 | INIT_RSA_SIGN_MECH(SHA384) |
3099 | 0 | INIT_RSA_SIGN_MECH(SHA512) |
3100 | | |
3101 | 21.0k | case CKM_RSA_PKCS: |
3102 | 21.0k | context->update = sftk_RSASign; |
3103 | 21.0k | goto finish_rsa; |
3104 | 0 | case CKM_RSA_X_509: |
3105 | 0 | context->update = sftk_RSASignRaw; |
3106 | 21.0k | finish_rsa: |
3107 | 21.0k | if (key_type != CKK_RSA) { |
3108 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3109 | 0 | break; |
3110 | 0 | } |
3111 | 21.0k | context->rsa = PR_TRUE; |
3112 | 21.0k | privKey = sftk_GetPrivKey(key, CKK_RSA, &crv); |
3113 | 21.0k | if (privKey == NULL) { |
3114 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3115 | 0 | break; |
3116 | 0 | } |
3117 | | /* OK, info is allocated only if we're doing hash and sign mechanism. |
3118 | | * It's necessary to be able to set the correct OID in the final |
3119 | | * signature. |
3120 | | */ |
3121 | 21.0k | if (info) { |
3122 | 0 | info->key = privKey; |
3123 | 0 | context->cipherInfo = info; |
3124 | 0 | context->destroy = sftk_Space; |
3125 | 21.0k | } else { |
3126 | 21.0k | context->cipherInfo = privKey; |
3127 | 21.0k | context->destroy = sftk_Null; |
3128 | 21.0k | } |
3129 | 21.0k | context->maxLen = nsslowkey_PrivateModulusLen(privKey); |
3130 | 21.0k | break; |
3131 | | |
3132 | 0 | #define INIT_RSA_PSS_SIG_MECH(mmm) \ |
3133 | 1.98k | case CKM_##mmm##_RSA_PKCS_PSS: \ |
3134 | 1.98k | context->multi = PR_TRUE; \ |
3135 | 1.98k | crv = sftk_doSub##mmm(context); \ |
3136 | 1.98k | if (crv != CKR_OK) \ |
3137 | 1.98k | break; \ |
3138 | 1.98k | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) { \ |
3139 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; \ |
3140 | 0 | break; \ |
3141 | 0 | } \ |
3142 | 1.98k | if (((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)->hashAlg != CKM_##mmm) { \ |
3143 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; \ |
3144 | 0 | break; \ |
3145 | 0 | } \ |
3146 | 1.98k | goto finish_rsa_pss; |
3147 | 0 | INIT_RSA_PSS_SIG_MECH(SHA1) |
3148 | 0 | INIT_RSA_PSS_SIG_MECH(SHA224) |
3149 | 2.75k | INIT_RSA_PSS_SIG_MECH(SHA256) |
3150 | 1.34k | INIT_RSA_PSS_SIG_MECH(SHA384) |
3151 | 1.60k | INIT_RSA_PSS_SIG_MECH(SHA512) |
3152 | 968 | case CKM_RSA_PKCS_PSS: |
3153 | 2.87k | finish_rsa_pss: |
3154 | 2.87k | if (key_type != CKK_RSA) { |
3155 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3156 | 0 | break; |
3157 | 0 | } |
3158 | 2.87k | context->rsa = PR_TRUE; |
3159 | 2.87k | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || |
3160 | 2.87k | !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) { |
3161 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3162 | 0 | break; |
3163 | 0 | } |
3164 | 2.87k | pinfo = PORT_New(SFTKPSSSignInfo); |
3165 | 2.87k | if (pinfo == NULL) { |
3166 | 0 | crv = CKR_HOST_MEMORY; |
3167 | 0 | break; |
3168 | 0 | } |
3169 | 2.87k | pinfo->size = sizeof(SFTKPSSSignInfo); |
3170 | 2.87k | pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter; |
3171 | 2.87k | pinfo->key = sftk_GetPrivKey(key, CKK_RSA, &crv); |
3172 | 2.87k | if (pinfo->key == NULL) { |
3173 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3174 | 0 | break; |
3175 | 0 | } |
3176 | 2.87k | context->cipherInfo = pinfo; |
3177 | 2.87k | context->destroy = sftk_ZSpace; |
3178 | 2.87k | context->update = sftk_RSASignPSS; |
3179 | 2.87k | context->maxLen = nsslowkey_PrivateModulusLen(pinfo->key); |
3180 | 2.87k | break; |
3181 | | |
3182 | 0 | #ifndef NSS_DISABLE_DSA |
3183 | 0 | #define INIT_DSA_SIG_MECH(mmm) \ |
3184 | 1.28k | case CKM_DSA_##mmm: \ |
3185 | 1.28k | context->multi = PR_TRUE; \ |
3186 | 1.28k | crv = sftk_doSub##mmm(context); \ |
3187 | 1.28k | if (crv != CKR_OK) \ |
3188 | 1.28k | break; \ |
3189 | 1.28k | goto finish_dsa; |
3190 | 0 | INIT_DSA_SIG_MECH(SHA1) |
3191 | 0 | INIT_DSA_SIG_MECH(SHA224) |
3192 | 0 | INIT_DSA_SIG_MECH(SHA256) |
3193 | 0 | INIT_DSA_SIG_MECH(SHA384) |
3194 | 0 | INIT_DSA_SIG_MECH(SHA512) |
3195 | 0 | case CKM_DSA: |
3196 | 0 | finish_dsa: |
3197 | 0 | if (key_type != CKK_DSA) { |
3198 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3199 | 0 | break; |
3200 | 0 | } |
3201 | 0 | privKey = sftk_GetPrivKey(key, CKK_DSA, &crv); |
3202 | 0 | if (privKey == NULL) { |
3203 | 0 | break; |
3204 | 0 | } |
3205 | 0 | context->cipherInfo = privKey; |
3206 | 0 | context->update = nsc_DSA_Sign_Stub; |
3207 | 0 | context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey; |
3208 | 0 | context->maxLen = DSA_MAX_SIGNATURE_LEN; |
3209 | |
|
3210 | 0 | break; |
3211 | 0 | #endif |
3212 | 0 | case CKM_ML_DSA: { |
3213 | | /* set our defaults */ |
3214 | 0 | CK_HEDGE_TYPE hedgeType = CKH_HEDGE_PREFERRED; |
3215 | 0 | SECItem signCtx = { siBuffer, NULL, 0 }; |
3216 | 0 | MLDSAContext *ctptr = NULL; |
3217 | 0 | SECStatus rv; |
3218 | | |
3219 | | /* make sure we have the right key type */ |
3220 | 0 | if (key_type != CKK_ML_DSA) { |
3221 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3222 | 0 | break; |
3223 | 0 | } |
3224 | | /* fill in our parameters from the mechanism parameters if |
3225 | | * supplied */ |
3226 | 0 | if (pMechanism->ulParameterLen != 0) { |
3227 | 0 | CK_SIGN_ADDITIONAL_CONTEXT *param; |
3228 | 0 | if (pMechanism->ulParameterLen != |
3229 | 0 | sizeof(CK_SIGN_ADDITIONAL_CONTEXT)) { |
3230 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3231 | 0 | break; |
3232 | 0 | } |
3233 | 0 | param = (CK_SIGN_ADDITIONAL_CONTEXT *)pMechanism->pParameter; |
3234 | 0 | hedgeType = param->hedgeVariant; |
3235 | 0 | signCtx.data = param->pContext; |
3236 | 0 | signCtx.len = param->ulContextLen; |
3237 | 0 | } |
3238 | | /* fetch the key */ |
3239 | 0 | privKey = sftk_GetPrivKey(key, key_type, &crv); |
3240 | 0 | if (privKey == NULL) { |
3241 | 0 | crv = CKR_HOST_MEMORY; |
3242 | 0 | break; |
3243 | 0 | } |
3244 | | /* now initialize it the signature */ |
3245 | 0 | rv = MLDSA_SignInit(&privKey->u.mldsa, hedgeType, &signCtx, &ctptr); |
3246 | 0 | if (rv != SECSuccess) { |
3247 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
3248 | 0 | if (privKey != key->objectInfo) { |
3249 | 0 | nsslowkey_DestroyPrivateKey(privKey); |
3250 | 0 | } |
3251 | 0 | break; |
3252 | 0 | } |
3253 | | /* set up our cipher info. MLDSA is only a combined hash/sign |
3254 | | * so the hash update is our sign update, the hash end is a null |
3255 | | * function returning a zero length value, and the final gets our |
3256 | | * signature based on the context. Both the cipher context and the |
3257 | | * hash Info is the same. The MLDSA_SignFinal frees the context, |
3258 | | * so we don't have to */ |
3259 | 0 | context->multi = PR_TRUE; |
3260 | 0 | context->cipherInfo = ctptr; |
3261 | 0 | context->hashInfo = ctptr; |
3262 | 0 | context->hashUpdate = sftk_MLDSASignUpdate; |
3263 | 0 | context->end = sftk_NullHashEnd; |
3264 | 0 | context->hashdestroy = sftk_Null; |
3265 | 0 | context->destroy = sftk_Null; |
3266 | 0 | context->update = sftk_MLDSASignFinal; |
3267 | 0 | context->maxLen = sftk_MLDSAGetSigLen(privKey->u.mldsa.paramSet); |
3268 | 0 | if (privKey != key->objectInfo) { |
3269 | 0 | nsslowkey_DestroyPrivateKey(privKey); |
3270 | 0 | } |
3271 | 0 | break; |
3272 | 0 | } |
3273 | | |
3274 | 0 | #define INIT_ECDSA_SIG_MECH(mmm) \ |
3275 | 1.08k | case CKM_ECDSA_##mmm: \ |
3276 | 1.08k | context->multi = PR_TRUE; \ |
3277 | 1.08k | crv = sftk_doSub##mmm(context); \ |
3278 | 1.08k | if (crv != CKR_OK) \ |
3279 | 1.08k | break; \ |
3280 | 1.08k | goto finish_ecdsa; |
3281 | 0 | INIT_ECDSA_SIG_MECH(SHA1) |
3282 | 0 | INIT_ECDSA_SIG_MECH(SHA224) |
3283 | 847 | INIT_ECDSA_SIG_MECH(SHA256) |
3284 | 847 | INIT_ECDSA_SIG_MECH(SHA384) |
3285 | 0 | INIT_ECDSA_SIG_MECH(SHA512) |
3286 | 7.89k | case CKM_ECDSA: |
3287 | 8.74k | finish_ecdsa: |
3288 | 8.74k | if (key_type != CKK_EC) { |
3289 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3290 | 0 | break; |
3291 | 0 | } |
3292 | 8.74k | privKey = sftk_GetPrivKey(key, CKK_EC, &crv); |
3293 | 8.74k | if (privKey == NULL) { |
3294 | 0 | crv = CKR_HOST_MEMORY; |
3295 | 0 | break; |
3296 | 0 | } |
3297 | 8.74k | context->cipherInfo = privKey; |
3298 | 8.74k | context->update = nsc_ECDSASignStub; |
3299 | 8.74k | context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey; |
3300 | 8.74k | context->maxLen = MAX_ECKEY_LEN * 2; |
3301 | | |
3302 | 8.74k | break; |
3303 | | |
3304 | 0 | case CKM_EDDSA: |
3305 | 0 | if (key_type != CKK_EC_EDWARDS) { |
3306 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3307 | 0 | break; |
3308 | 0 | } |
3309 | | |
3310 | 0 | if (pMechanism->pParameter) { |
3311 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3312 | 0 | break; |
3313 | 0 | } |
3314 | | |
3315 | 0 | privKey = sftk_GetPrivKey(key, CKK_EC_EDWARDS, &crv); |
3316 | 0 | if (privKey == NULL) { |
3317 | 0 | crv = CKR_HOST_MEMORY; |
3318 | 0 | break; |
3319 | 0 | } |
3320 | 0 | context->cipherInfo = privKey; |
3321 | 0 | context->update = nsc_EDDSASignStub; |
3322 | 0 | context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey; |
3323 | 0 | context->maxLen = MAX_ECKEY_LEN * 2; |
3324 | |
|
3325 | 0 | break; |
3326 | | |
3327 | 0 | #define INIT_HMAC_MECH(mmm) \ |
3328 | 0 | case CKM_##mmm##_HMAC_GENERAL: \ |
3329 | 0 | PORT_Assert(pMechanism->pParameter); \ |
3330 | 0 | if (!pMechanism->pParameter) { \ |
3331 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; \ |
3332 | 0 | break; \ |
3333 | 0 | } \ |
3334 | 0 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, \ |
3335 | 0 | *(CK_ULONG *)pMechanism->pParameter); \ |
3336 | 0 | break; \ |
3337 | 252k | case CKM_##mmm##_HMAC: \ |
3338 | 252k | crv = sftk_doMACInit(pMechanism->mechanism, context, key, \ |
3339 | 252k | mmm##_LENGTH); \ |
3340 | 252k | break; |
3341 | | |
3342 | 0 | INIT_HMAC_MECH(MD2) |
3343 | 0 | INIT_HMAC_MECH(MD5) |
3344 | 0 | INIT_HMAC_MECH(SHA1) |
3345 | 0 | INIT_HMAC_MECH(SHA224) |
3346 | 0 | INIT_HMAC_MECH(SHA256) |
3347 | 0 | INIT_HMAC_MECH(SHA384) |
3348 | 0 | INIT_HMAC_MECH(SHA512) |
3349 | 0 | INIT_HMAC_MECH(SHA3_224) |
3350 | 0 | INIT_HMAC_MECH(SHA3_256) |
3351 | 0 | INIT_HMAC_MECH(SHA3_384) |
3352 | 0 | INIT_HMAC_MECH(SHA3_512) |
3353 | | |
3354 | 0 | case CKM_AES_CMAC_GENERAL: |
3355 | 0 | PORT_Assert(pMechanism->pParameter); |
3356 | 0 | if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { |
3357 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3358 | 0 | break; |
3359 | 0 | } |
3360 | 0 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, *(CK_ULONG *)pMechanism->pParameter); |
3361 | 0 | break; |
3362 | 54 | case CKM_AES_CMAC: |
3363 | 54 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, AES_BLOCK_SIZE); |
3364 | 54 | break; |
3365 | 0 | case CKM_SSL3_MD5_MAC: |
3366 | 0 | PORT_Assert(pMechanism->pParameter); |
3367 | 0 | if (!pMechanism->pParameter) { |
3368 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3369 | 0 | break; |
3370 | 0 | } |
3371 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key, |
3372 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
3373 | 0 | break; |
3374 | 0 | case CKM_SSL3_SHA1_MAC: |
3375 | 0 | PORT_Assert(pMechanism->pParameter); |
3376 | 0 | if (!pMechanism->pParameter) { |
3377 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3378 | 0 | break; |
3379 | 0 | } |
3380 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key, |
3381 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
3382 | 0 | break; |
3383 | 0 | case CKM_TLS_PRF_GENERAL: |
3384 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); |
3385 | 0 | break; |
3386 | 208k | case CKM_TLS_MAC: { |
3387 | 208k | CK_TLS_MAC_PARAMS *tls12_mac_params; |
3388 | 208k | HASH_HashType tlsPrfHash; |
3389 | 208k | const char *label; |
3390 | | |
3391 | 208k | if (pMechanism->ulParameterLen != sizeof(CK_TLS_MAC_PARAMS)) { |
3392 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3393 | 0 | break; |
3394 | 0 | } |
3395 | 208k | tls12_mac_params = (CK_TLS_MAC_PARAMS *)pMechanism->pParameter; |
3396 | 208k | if (tls12_mac_params->prfHashMechanism == CKM_TLS_PRF) { |
3397 | | /* The TLS 1.0 and 1.1 PRF */ |
3398 | 82.4k | tlsPrfHash = HASH_AlgNULL; |
3399 | 82.4k | if (tls12_mac_params->ulMacLength != 12) { |
3400 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3401 | 0 | break; |
3402 | 0 | } |
3403 | 125k | } else { |
3404 | | /* The hash function for the TLS 1.2 PRF */ |
3405 | 125k | tlsPrfHash = |
3406 | 125k | sftk_GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism); |
3407 | 125k | if (tlsPrfHash == HASH_AlgNULL || |
3408 | 125k | tls12_mac_params->ulMacLength < 12) { |
3409 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3410 | 0 | break; |
3411 | 0 | } |
3412 | 125k | } |
3413 | 208k | if (tls12_mac_params->ulServerOrClient == 1) { |
3414 | 100k | label = "server finished"; |
3415 | 107k | } else if (tls12_mac_params->ulServerOrClient == 2) { |
3416 | 107k | label = "client finished"; |
3417 | 107k | } else { |
3418 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3419 | 0 | break; |
3420 | 0 | } |
3421 | 208k | crv = sftk_TLSPRFInit(context, key, key_type, tlsPrfHash, |
3422 | 208k | tls12_mac_params->ulMacLength); |
3423 | 208k | if (crv == CKR_OK) { |
3424 | 208k | context->hashUpdate(context->hashInfo, (unsigned char *)label, 15); |
3425 | 208k | } |
3426 | 208k | break; |
3427 | 208k | } |
3428 | 0 | case CKM_NSS_TLS_PRF_GENERAL_SHA256: |
3429 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); |
3430 | 0 | break; |
3431 | | |
3432 | 22.7k | case CKM_NSS_HMAC_CONSTANT_TIME: { |
3433 | 22.7k | sftk_MACConstantTimeCtx *ctx = |
3434 | 22.7k | sftk_HMACConstantTime_New(pMechanism, key); |
3435 | 22.7k | CK_ULONG *intpointer; |
3436 | | |
3437 | 22.7k | if (ctx == NULL) { |
3438 | 0 | crv = CKR_ARGUMENTS_BAD; |
3439 | 0 | break; |
3440 | 0 | } |
3441 | 22.7k | intpointer = PORT_New(CK_ULONG); |
3442 | 22.7k | if (intpointer == NULL) { |
3443 | 0 | PORT_Free(ctx); |
3444 | 0 | crv = CKR_HOST_MEMORY; |
3445 | 0 | break; |
3446 | 0 | } |
3447 | 22.7k | *intpointer = ctx->hash->length; |
3448 | | |
3449 | 22.7k | context->cipherInfo = intpointer; |
3450 | 22.7k | context->hashInfo = ctx; |
3451 | 22.7k | context->currentMech = pMechanism->mechanism; |
3452 | 22.7k | context->hashUpdate = sftk_HMACConstantTime_Update; |
3453 | 22.7k | context->hashdestroy = sftk_MACConstantTime_DestroyContext; |
3454 | 22.7k | context->end = sftk_MACConstantTime_EndHash; |
3455 | 22.7k | context->update = sftk_SignCopy; |
3456 | 22.7k | context->destroy = sftk_Space; |
3457 | 22.7k | context->maxLen = 64; |
3458 | 22.7k | context->multi = PR_TRUE; |
3459 | 22.7k | break; |
3460 | 22.7k | } |
3461 | | |
3462 | 0 | case CKM_NSS_SSL3_MAC_CONSTANT_TIME: { |
3463 | 0 | sftk_MACConstantTimeCtx *ctx = |
3464 | 0 | sftk_SSLv3MACConstantTime_New(pMechanism, key); |
3465 | 0 | CK_ULONG *intpointer; |
3466 | |
|
3467 | 0 | if (ctx == NULL) { |
3468 | 0 | crv = CKR_ARGUMENTS_BAD; |
3469 | 0 | break; |
3470 | 0 | } |
3471 | 0 | intpointer = PORT_New(CK_ULONG); |
3472 | 0 | if (intpointer == NULL) { |
3473 | 0 | PORT_Free(ctx); |
3474 | 0 | crv = CKR_HOST_MEMORY; |
3475 | 0 | break; |
3476 | 0 | } |
3477 | 0 | *intpointer = ctx->hash->length; |
3478 | |
|
3479 | 0 | context->cipherInfo = intpointer; |
3480 | 0 | context->hashInfo = ctx; |
3481 | 0 | context->currentMech = pMechanism->mechanism; |
3482 | 0 | context->hashUpdate = sftk_SSLv3MACConstantTime_Update; |
3483 | 0 | context->hashdestroy = sftk_MACConstantTime_DestroyContext; |
3484 | 0 | context->end = sftk_MACConstantTime_EndHash; |
3485 | 0 | context->update = sftk_SignCopy; |
3486 | 0 | context->destroy = sftk_Space; |
3487 | 0 | context->maxLen = 64; |
3488 | 0 | context->multi = PR_TRUE; |
3489 | 0 | break; |
3490 | 0 | } |
3491 | | |
3492 | 36 | default: |
3493 | 36 | crv = CKR_MECHANISM_INVALID; |
3494 | 36 | break; |
3495 | 516k | } |
3496 | | |
3497 | 516k | if (crv != CKR_OK) { |
3498 | 36 | if (info) |
3499 | 0 | PORT_Free(info); |
3500 | 36 | if (pinfo) |
3501 | 0 | PORT_ZFree(pinfo, pinfo->size); |
3502 | 36 | sftk_FreeContext(context); |
3503 | 36 | sftk_FreeSession(session); |
3504 | 36 | return crv; |
3505 | 36 | } |
3506 | | /* At this point info/pinfo (if allocated) are linked into |
3507 | | * context->cipherInfo and will be freed via sftk_FreeContext. */ |
3508 | 516k | crv = sftk_InstallContext(session, SFTK_SIGN, context); |
3509 | 516k | if (crv != CKR_OK) { |
3510 | 0 | sftk_FreeContext(context); |
3511 | 0 | } |
3512 | 516k | sftk_FreeSession(session); |
3513 | 516k | return crv; |
3514 | 516k | } |
3515 | | |
3516 | | /** MAC one block of data by block cipher |
3517 | | */ |
3518 | | static CK_RV |
3519 | | sftk_MACBlock(SFTKSessionContext *ctx, void *blk) |
3520 | 0 | { |
3521 | 0 | unsigned int outlen; |
3522 | 0 | return (SECSuccess == (ctx->update)(ctx->cipherInfo, ctx->macBuf, &outlen, |
3523 | 0 | SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize)) |
3524 | 0 | ? CKR_OK |
3525 | 0 | : sftk_MapCryptError(PORT_GetError()); |
3526 | 0 | } |
3527 | | |
3528 | | /** MAC last (incomplete) block of data by block cipher |
3529 | | * |
3530 | | * Call once, then terminate MACing operation. |
3531 | | */ |
3532 | | static CK_RV |
3533 | | sftk_MACFinal(SFTKSessionContext *ctx) |
3534 | 0 | { |
3535 | 0 | unsigned int padLen = ctx->padDataLength; |
3536 | | /* pad and proceed the residual */ |
3537 | 0 | if (ctx->isXCBC) { |
3538 | 0 | CK_RV crv = sftk_xcbc_mac_pad(ctx->padBuf, padLen, ctx->blockSize, |
3539 | 0 | ctx->k2, ctx->k3); |
3540 | 0 | if (crv != CKR_OK) |
3541 | 0 | return crv; |
3542 | 0 | return sftk_MACBlock(ctx, ctx->padBuf); |
3543 | 0 | } |
3544 | 0 | if (padLen) { |
3545 | | /* shd clr ctx->padLen to make sftk_MACFinal idempotent */ |
3546 | 0 | PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen); |
3547 | 0 | return sftk_MACBlock(ctx, ctx->padBuf); |
3548 | 0 | } else |
3549 | 0 | return CKR_OK; |
3550 | 0 | } |
3551 | | |
3552 | | /** The common implementation for {Sign,Verify}Update. (S/V only vary in their |
3553 | | * setup and final operations). |
3554 | | * |
3555 | | * A call which results in an error terminates the operation [PKCS#11,v2.11] |
3556 | | */ |
3557 | | static CK_RV |
3558 | | sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
3559 | | CK_ULONG ulPartLen, SFTKContextType type) |
3560 | 304k | { |
3561 | 304k | SFTKSession *session; |
3562 | 304k | SFTKSessionContext *context; |
3563 | 304k | CK_RV crv; |
3564 | | |
3565 | | /* make sure we're legal */ |
3566 | 304k | crv = sftk_GetContext(hSession, &context, type, PR_TRUE, &session); |
3567 | 304k | if (crv != CKR_OK) |
3568 | 0 | return crv; |
3569 | | |
3570 | 304k | if (context->hashInfo) { |
3571 | 304k | #if (ULONG_MAX > UINT_MAX) |
3572 | 304k | while (ulPartLen > UINT_MAX) { |
3573 | 0 | (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX); |
3574 | 0 | pPart += UINT_MAX; |
3575 | 0 | ulPartLen -= UINT_MAX; |
3576 | 0 | } |
3577 | 304k | #endif |
3578 | 304k | (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen); |
3579 | 304k | } else { |
3580 | | /* must be block cipher MACing */ |
3581 | |
|
3582 | 0 | unsigned int blkSize = context->blockSize; |
3583 | 0 | unsigned char *residual = /* free room in context->padBuf */ |
3584 | 0 | context->padBuf + context->padDataLength; |
3585 | 0 | unsigned int minInput = /* min input for MACing at least one block */ |
3586 | 0 | blkSize - context->padDataLength; |
3587 | | |
3588 | | /* not enough data even for one block */ |
3589 | 0 | if (ulPartLen <= minInput) { |
3590 | 0 | PORT_Memcpy(residual, pPart, ulPartLen); |
3591 | 0 | context->padDataLength += ulPartLen; |
3592 | 0 | goto cleanup; |
3593 | 0 | } |
3594 | | /* MACing residual */ |
3595 | 0 | if (context->padDataLength) { |
3596 | 0 | PORT_Memcpy(residual, pPart, minInput); |
3597 | 0 | ulPartLen -= minInput; |
3598 | 0 | pPart += minInput; |
3599 | 0 | if (CKR_OK != (crv = sftk_MACBlock(context, context->padBuf))) |
3600 | 0 | goto terminate; |
3601 | 0 | } |
3602 | | /* MACing full blocks */ |
3603 | 0 | while (ulPartLen > blkSize) { |
3604 | 0 | if (CKR_OK != (crv = sftk_MACBlock(context, pPart))) |
3605 | 0 | goto terminate; |
3606 | 0 | ulPartLen -= blkSize; |
3607 | 0 | pPart += blkSize; |
3608 | 0 | } |
3609 | | /* save the residual */ |
3610 | 0 | if ((context->padDataLength = ulPartLen)) |
3611 | 0 | PORT_Memcpy(context->padBuf, pPart, ulPartLen); |
3612 | 0 | } /* blk cipher MACing */ |
3613 | | |
3614 | 304k | goto cleanup; |
3615 | | |
3616 | 304k | terminate: |
3617 | 0 | sftk_TerminateOp(session, type); |
3618 | 304k | cleanup: |
3619 | 304k | sftk_FreeSession(session); |
3620 | 304k | return crv; |
3621 | 0 | } |
3622 | | |
3623 | | /* NSC_SignUpdate continues a multiple-part signature operation, |
3624 | | * where the signature is (will be) an appendix to the data, |
3625 | | * and plaintext cannot be recovered from the signature |
3626 | | * |
3627 | | * A call which results in an error terminates the operation [PKCS#11,v2.11] |
3628 | | */ |
3629 | | CK_RV |
3630 | | NSC_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
3631 | | CK_ULONG ulPartLen) |
3632 | 301k | { |
3633 | 301k | CHECK_FORK(); |
3634 | 301k | return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN); |
3635 | 301k | } |
3636 | | |
3637 | | struct SFTK_SESSION_FLAGS { |
3638 | | CK_FLAGS flag; |
3639 | | SFTKContextType type; |
3640 | | }; |
3641 | | |
3642 | | const static struct SFTK_SESSION_FLAGS sftk_session_flags[] = { |
3643 | | { CKF_ENCRYPT, SFTK_ENCRYPT }, |
3644 | | { CKF_DECRYPT, SFTK_DECRYPT }, |
3645 | | { CKF_DIGEST, SFTK_HASH }, |
3646 | | { CKF_SIGN, SFTK_SIGN }, |
3647 | | { CKF_SIGN_RECOVER, SFTK_SIGN_RECOVER }, |
3648 | | { CKF_VERIFY, SFTK_VERIFY }, |
3649 | | { CKF_VERIFY_RECOVER, SFTK_VERIFY_RECOVER }, |
3650 | | { CKF_MESSAGE_ENCRYPT, SFTK_MESSAGE_ENCRYPT }, |
3651 | | { CKF_MESSAGE_DECRYPT, SFTK_MESSAGE_DECRYPT }, |
3652 | | { CKF_MESSAGE_SIGN, SFTK_MESSAGE_SIGN }, |
3653 | | { CKF_MESSAGE_VERIFY, SFTK_MESSAGE_VERIFY }, |
3654 | | }; |
3655 | | const static int sftk_flag_count = PR_ARRAY_SIZE(sftk_session_flags); |
3656 | | |
3657 | | /* |
3658 | | * Cancel one or more operations running on the existing session. |
3659 | | */ |
3660 | | CK_RV |
3661 | | NSC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags) |
3662 | 0 | { |
3663 | 0 | SFTKSession *session; |
3664 | 0 | SFTKSessionContext *context; |
3665 | 0 | CK_RV gcrv = CKR_OK; |
3666 | 0 | CK_RV crv; |
3667 | 0 | int i; |
3668 | |
|
3669 | 0 | for (i = 0; i < sftk_flag_count; i++) { |
3670 | 0 | if (flags & sftk_session_flags[i].flag) { |
3671 | 0 | flags &= ~sftk_session_flags[i].flag; |
3672 | 0 | crv = sftk_GetContext(hSession, &context, sftk_session_flags[i].type, PR_TRUE, &session); |
3673 | 0 | if (crv != CKR_OK) { |
3674 | 0 | gcrv = CKR_OPERATION_CANCEL_FAILED; |
3675 | 0 | continue; |
3676 | 0 | } |
3677 | 0 | sftk_TerminateOp(session, sftk_session_flags[i].type); |
3678 | 0 | } |
3679 | 0 | } |
3680 | 0 | if (flags & CKF_FIND_OBJECTS) { |
3681 | 0 | flags &= ~CKF_FIND_OBJECTS; |
3682 | 0 | crv = NSC_FindObjectsFinal(hSession); |
3683 | 0 | if (crv != CKR_OK) { |
3684 | 0 | gcrv = CKR_OPERATION_CANCEL_FAILED; |
3685 | 0 | } |
3686 | 0 | } |
3687 | 0 | if (flags) { |
3688 | 0 | gcrv = CKR_OPERATION_CANCEL_FAILED; |
3689 | 0 | } |
3690 | 0 | return gcrv; |
3691 | 0 | } |
3692 | | |
3693 | | /* NSC_SignFinal finishes a multiple-part signature operation, |
3694 | | * returning the signature. */ |
3695 | | CK_RV |
3696 | | NSC_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, |
3697 | | CK_ULONG_PTR pulSignatureLen) |
3698 | 304k | { |
3699 | 304k | SFTKSession *session; |
3700 | 304k | SFTKSessionContext *context; |
3701 | 304k | unsigned int outlen = 0; |
3702 | 304k | unsigned int maxoutlen = *pulSignatureLen; |
3703 | 304k | CK_RV crv; |
3704 | | |
3705 | 304k | CHECK_FORK(); |
3706 | | |
3707 | | /* make sure we're legal */ |
3708 | 304k | crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_TRUE, &session); |
3709 | 304k | if (crv != CKR_OK) |
3710 | 27.8k | return crv; |
3711 | | |
3712 | 276k | if (context->hashInfo) { |
3713 | 276k | unsigned int digestLen; |
3714 | 276k | unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; |
3715 | | |
3716 | 276k | if (!pSignature) { |
3717 | 0 | outlen = context->maxLen; |
3718 | 0 | goto finish; |
3719 | 0 | } |
3720 | 276k | (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); |
3721 | 276k | if (SECSuccess != (context->update)(context->cipherInfo, pSignature, |
3722 | 276k | &outlen, maxoutlen, tmpbuf, digestLen)) |
3723 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
3724 | | /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate. |
3725 | | * Keeping "too small" CK_RV intact is a standard violation, but allows |
3726 | | * application read EXACT signature length */ |
3727 | 276k | PORT_Memset(tmpbuf, 0, sizeof tmpbuf); |
3728 | 276k | } else { |
3729 | | /* must be block cipher MACing */ |
3730 | 0 | outlen = context->macSize; |
3731 | | /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/ |
3732 | 0 | if (!pSignature || maxoutlen < outlen) { |
3733 | 0 | if (pSignature) |
3734 | 0 | crv = CKR_BUFFER_TOO_SMALL; |
3735 | 0 | goto finish; |
3736 | 0 | } |
3737 | 0 | if (CKR_OK == (crv = sftk_MACFinal(context))) |
3738 | 0 | PORT_Memcpy(pSignature, context->macBuf, outlen); |
3739 | 0 | } |
3740 | | |
3741 | 276k | sftk_TerminateOp(session, SFTK_SIGN); |
3742 | 276k | finish: |
3743 | 276k | *pulSignatureLen = outlen; |
3744 | 276k | sftk_FreeSession(session); |
3745 | 276k | return crv; |
3746 | 276k | } |
3747 | | |
3748 | | /* NSC_Sign signs (encrypts with private key) data in a single part, |
3749 | | * where the signature is (will be) an appendix to the data, |
3750 | | * and plaintext cannot be recovered from the signature */ |
3751 | | CK_RV |
3752 | | NSC_Sign(CK_SESSION_HANDLE hSession, |
3753 | | CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, |
3754 | | CK_ULONG_PTR pulSignatureLen) |
3755 | 52.7k | { |
3756 | 52.7k | SFTKSession *session; |
3757 | 52.7k | SFTKSessionContext *context; |
3758 | 52.7k | CK_RV crv; |
3759 | | |
3760 | 52.7k | CHECK_FORK(); |
3761 | | |
3762 | | /* make sure we're legal */ |
3763 | 52.7k | crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_FALSE, &session); |
3764 | 52.7k | if (crv != CKR_OK) |
3765 | 0 | return crv; |
3766 | | |
3767 | 52.7k | if (!pSignature) { |
3768 | | /* see also how C_SignUpdate implements this */ |
3769 | 0 | *pulSignatureLen = (!context->multi || context->hashInfo) |
3770 | 0 | ? context->maxLen |
3771 | 0 | : context->macSize; /* must be block cipher MACing */ |
3772 | 0 | goto finish; |
3773 | 0 | } |
3774 | | |
3775 | | /* multi part Signing are completely implemented by SignUpdate and |
3776 | | * sign Final */ |
3777 | 52.7k | if (context->multi) { |
3778 | | /* SignFinal can't follow failed SignUpdate */ |
3779 | 22.7k | if (CKR_OK == (crv = NSC_SignUpdate(hSession, pData, ulDataLen))) |
3780 | 22.7k | crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen); |
3781 | 29.9k | } else { |
3782 | | /* single-part PKC signature (e.g. CKM_ECDSA) */ |
3783 | 29.9k | unsigned int outlen; |
3784 | 29.9k | unsigned int maxoutlen = *pulSignatureLen; |
3785 | 29.9k | if (SECSuccess != (*context->update)(context->cipherInfo, pSignature, |
3786 | 29.9k | &outlen, maxoutlen, pData, ulDataLen)) |
3787 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
3788 | 29.9k | *pulSignatureLen = (CK_ULONG)outlen; |
3789 | | /* "too small" here is certainly continuable */ |
3790 | 29.9k | if (crv != CKR_BUFFER_TOO_SMALL) |
3791 | 29.9k | sftk_TerminateOp(session, SFTK_SIGN); |
3792 | 29.9k | } /* single-part */ |
3793 | | |
3794 | 52.7k | finish: |
3795 | 52.7k | sftk_FreeSession(session); |
3796 | 52.7k | return crv; |
3797 | 52.7k | } |
3798 | | |
3799 | | /* |
3800 | | ************** Crypto Functions: Sign Recover ************************ |
3801 | | */ |
3802 | | /* NSC_SignRecoverInit initializes a signature operation, |
3803 | | * where the (digest) data can be recovered from the signature. |
3804 | | * E.g. encryption with the user's private key */ |
3805 | | CK_RV |
3806 | | NSC_SignRecoverInit(CK_SESSION_HANDLE hSession, |
3807 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
3808 | 0 | { |
3809 | 0 | CHECK_FORK(); |
3810 | |
|
3811 | 0 | switch (pMechanism->mechanism) { |
3812 | 0 | case CKM_RSA_PKCS: |
3813 | 0 | case CKM_RSA_X_509: |
3814 | 0 | return NSC_SignInit(hSession, pMechanism, hKey); |
3815 | 0 | default: |
3816 | 0 | break; |
3817 | 0 | } |
3818 | 0 | return CKR_MECHANISM_INVALID; |
3819 | 0 | } |
3820 | | |
3821 | | /* NSC_SignRecover signs data in a single operation |
3822 | | * where the (digest) data can be recovered from the signature. |
3823 | | * E.g. encryption with the user's private key */ |
3824 | | CK_RV |
3825 | | NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
3826 | | CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) |
3827 | 0 | { |
3828 | 0 | CHECK_FORK(); |
3829 | |
|
3830 | 0 | return NSC_Sign(hSession, pData, ulDataLen, pSignature, pulSignatureLen); |
3831 | 0 | } |
3832 | | |
3833 | | /* |
3834 | | ************** Crypto Functions: verify ************************ |
3835 | | */ |
3836 | | |
3837 | | /* Handle RSA Signature formatting */ |
3838 | | static SECStatus |
3839 | | sftk_hashCheckSign(void *ctx, const unsigned char *sig, |
3840 | | unsigned int sigLen, const unsigned char *digest, |
3841 | | unsigned int digestLen) |
3842 | 1.63k | { |
3843 | 1.63k | SFTKHashVerifyInfo *info = ctx; |
3844 | 1.63k | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
3845 | 1.63k | if (info->key->keyType != NSSLOWKEYRSAKey) { |
3846 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3847 | 0 | return SECFailure; |
3848 | 0 | } |
3849 | | |
3850 | 1.63k | return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, digest, |
3851 | 1.63k | digestLen); |
3852 | 1.63k | } |
3853 | | |
3854 | | SECStatus |
3855 | | RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key, |
3856 | | const unsigned char *sig, unsigned int sigLen, |
3857 | | const unsigned char *digestData, unsigned int digestLen) |
3858 | 1.63k | { |
3859 | 1.63k | unsigned char *pkcs1DigestInfoData; |
3860 | 1.63k | SECItem pkcs1DigestInfo; |
3861 | 1.63k | SECItem digest; |
3862 | 1.63k | unsigned int bufferSize; |
3863 | 1.63k | SECStatus rv; |
3864 | | |
3865 | | /* pkcs1DigestInfo.data must be less than key->u.rsa.modulus.len */ |
3866 | 1.63k | bufferSize = key->u.rsa.modulus.len; |
3867 | 1.63k | pkcs1DigestInfoData = PORT_ZAlloc(bufferSize); |
3868 | 1.63k | if (!pkcs1DigestInfoData) { |
3869 | 0 | PORT_SetError(SEC_ERROR_NO_MEMORY); |
3870 | 0 | return SECFailure; |
3871 | 0 | } |
3872 | | |
3873 | 1.63k | pkcs1DigestInfo.data = pkcs1DigestInfoData; |
3874 | 1.63k | pkcs1DigestInfo.len = bufferSize; |
3875 | | |
3876 | | /* decrypt the block */ |
3877 | 1.63k | rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data, |
3878 | 1.63k | &pkcs1DigestInfo.len, pkcs1DigestInfo.len, |
3879 | 1.63k | sig, sigLen); |
3880 | 1.63k | if (rv != SECSuccess) { |
3881 | 1.57k | PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
3882 | 1.57k | } else { |
3883 | 57 | digest.data = (PRUint8 *)digestData; |
3884 | 57 | digest.len = digestLen; |
3885 | 57 | rv = _SGN_VerifyPKCS1DigestInfo( |
3886 | 57 | digestOid, &digest, &pkcs1DigestInfo, |
3887 | 57 | PR_FALSE /*XXX: unsafeAllowMissingParameters*/); |
3888 | 57 | } |
3889 | | |
3890 | 1.63k | PORT_ZFree(pkcs1DigestInfoData, bufferSize); |
3891 | 1.63k | return rv; |
3892 | 1.63k | } |
3893 | | |
3894 | | static SECStatus |
3895 | | sftk_RSACheckSign(void *ctx, const unsigned char *sig, |
3896 | | unsigned int sigLen, const unsigned char *digest, |
3897 | | unsigned int digestLen) |
3898 | 1.28k | { |
3899 | 1.28k | NSSLOWKEYPublicKey *key = ctx; |
3900 | 1.28k | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
3901 | 1.28k | if (key->keyType != NSSLOWKEYRSAKey) { |
3902 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3903 | 0 | return SECFailure; |
3904 | 0 | } |
3905 | | |
3906 | 1.28k | return RSA_CheckSign(&key->u.rsa, sig, sigLen, digest, digestLen); |
3907 | 1.28k | } |
3908 | | |
3909 | | static SECStatus |
3910 | | sftk_RSACheckSignRaw(void *ctx, const unsigned char *sig, |
3911 | | unsigned int sigLen, const unsigned char *digest, |
3912 | | unsigned int digestLen) |
3913 | 0 | { |
3914 | 0 | NSSLOWKEYPublicKey *key = ctx; |
3915 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
3916 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
3917 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3918 | 0 | return SECFailure; |
3919 | 0 | } |
3920 | | |
3921 | 0 | return RSA_CheckSignRaw(&key->u.rsa, sig, sigLen, digest, digestLen); |
3922 | 0 | } |
3923 | | |
3924 | | static SECStatus |
3925 | | sftk_RSACheckSignPSS(void *ctx, const unsigned char *sig, |
3926 | | unsigned int sigLen, const unsigned char *digest, |
3927 | | unsigned int digestLen) |
3928 | 2.44k | { |
3929 | 2.44k | SFTKPSSVerifyInfo *info = ctx; |
3930 | 2.44k | HASH_HashType hashAlg; |
3931 | 2.44k | HASH_HashType maskHashAlg; |
3932 | 2.44k | CK_RSA_PKCS_PSS_PARAMS *params = &info->params; |
3933 | | |
3934 | 2.44k | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
3935 | 2.44k | if (info->key->keyType != NSSLOWKEYRSAKey) { |
3936 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3937 | 0 | return SECFailure; |
3938 | 0 | } |
3939 | | |
3940 | 2.44k | hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg); |
3941 | 2.44k | maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf); |
3942 | | |
3943 | 2.44k | return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, |
3944 | 2.44k | params->sLen, sig, sigLen, digest, digestLen); |
3945 | 2.44k | } |
3946 | | |
3947 | | /* NSC_VerifyInit initializes a verification operation, |
3948 | | * where the signature is an appendix to the data, |
3949 | | * and plaintext cannot be recovered from the signature (e.g. DSA) */ |
3950 | | CK_RV |
3951 | | NSC_VerifyInit(CK_SESSION_HANDLE hSession, |
3952 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
3953 | 10.6k | { |
3954 | 10.6k | SFTKSession *session; |
3955 | 10.6k | SFTKObject *key; |
3956 | 10.6k | SFTKSessionContext *context; |
3957 | 10.6k | CK_KEY_TYPE key_type; |
3958 | 10.6k | CK_RV crv = CKR_OK; |
3959 | 10.6k | NSSLOWKEYPublicKey *pubKey; |
3960 | 10.6k | SFTKHashVerifyInfo *info = NULL; |
3961 | 10.6k | SFTKPSSVerifyInfo *pinfo = NULL; |
3962 | | |
3963 | 10.6k | CHECK_FORK(); |
3964 | | |
3965 | | /* Block Cipher MACing Algorithms use a different Context init method..*/ |
3966 | 10.6k | crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY); |
3967 | 10.6k | if (crv != CKR_FUNCTION_NOT_SUPPORTED) |
3968 | 0 | return crv; |
3969 | | |
3970 | 10.6k | session = sftk_SessionFromHandle(hSession); |
3971 | 10.6k | if (session == NULL) |
3972 | 0 | return CKR_SESSION_HANDLE_INVALID; |
3973 | 10.6k | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY, &key, |
3974 | 10.6k | hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY); |
3975 | 10.6k | if (crv != CKR_OK) { |
3976 | 0 | sftk_FreeSession(session); |
3977 | 0 | return crv; |
3978 | 0 | } |
3979 | | |
3980 | 10.6k | context->multi = PR_FALSE; |
3981 | | |
3982 | 10.6k | #define INIT_RSA_VFY_MECH(mmm) \ |
3983 | 10.6k | case CKM_##mmm##_RSA_PKCS: \ |
3984 | 1.63k | context->multi = PR_TRUE; \ |
3985 | 1.63k | crv = sftk_doSub##mmm(context); \ |
3986 | 1.63k | if (crv != CKR_OK) \ |
3987 | 1.63k | break; \ |
3988 | 1.63k | context->verify = sftk_hashCheckSign; \ |
3989 | 1.63k | info = PORT_New(SFTKHashVerifyInfo); \ |
3990 | 1.63k | if (info == NULL) { \ |
3991 | 0 | crv = CKR_HOST_MEMORY; \ |
3992 | 0 | break; \ |
3993 | 0 | } \ |
3994 | 1.63k | info->hashOid = SEC_OID_##mmm; \ |
3995 | 1.63k | goto finish_rsa; |
3996 | | |
3997 | 10.6k | switch (pMechanism->mechanism) { |
3998 | 0 | INIT_RSA_VFY_MECH(MD5) |
3999 | 0 | INIT_RSA_VFY_MECH(MD2) |
4000 | 6 | INIT_RSA_VFY_MECH(SHA1) |
4001 | 2 | INIT_RSA_VFY_MECH(SHA224) |
4002 | 3.25k | INIT_RSA_VFY_MECH(SHA256) |
4003 | 2 | INIT_RSA_VFY_MECH(SHA384) |
4004 | 2 | INIT_RSA_VFY_MECH(SHA512) |
4005 | | |
4006 | 1.28k | case CKM_RSA_PKCS: |
4007 | 1.28k | context->verify = sftk_RSACheckSign; |
4008 | 1.28k | goto finish_rsa; |
4009 | 0 | case CKM_RSA_X_509: |
4010 | 0 | context->verify = sftk_RSACheckSignRaw; |
4011 | 2.91k | finish_rsa: |
4012 | 2.91k | if (key_type != CKK_RSA) { |
4013 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4014 | 0 | break; |
4015 | 0 | } |
4016 | 2.91k | context->rsa = PR_TRUE; |
4017 | 2.91k | pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); |
4018 | 2.91k | if (pubKey == NULL) { |
4019 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4020 | 0 | break; |
4021 | 0 | } |
4022 | 2.91k | if (info) { |
4023 | 1.63k | info->key = pubKey; |
4024 | 1.63k | context->cipherInfo = info; |
4025 | 1.63k | context->destroy = sftk_Space; |
4026 | 1.63k | } else { |
4027 | 1.28k | context->cipherInfo = pubKey; |
4028 | 1.28k | context->destroy = sftk_Null; |
4029 | 1.28k | } |
4030 | 2.91k | break; |
4031 | | |
4032 | 15 | INIT_RSA_PSS_SIG_MECH(SHA1) |
4033 | 9 | INIT_RSA_PSS_SIG_MECH(SHA224) |
4034 | 117 | INIT_RSA_PSS_SIG_MECH(SHA256) |
4035 | 72 | INIT_RSA_PSS_SIG_MECH(SHA384) |
4036 | 33 | INIT_RSA_PSS_SIG_MECH(SHA512) |
4037 | 2.36k | case CKM_RSA_PKCS_PSS: |
4038 | 2.44k | finish_rsa_pss: |
4039 | 2.44k | if (key_type != CKK_RSA) { |
4040 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4041 | 0 | break; |
4042 | 0 | } |
4043 | 2.44k | context->rsa = PR_TRUE; |
4044 | 2.44k | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || |
4045 | 2.44k | !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) { |
4046 | 3 | crv = CKR_MECHANISM_PARAM_INVALID; |
4047 | 3 | break; |
4048 | 3 | } |
4049 | 2.44k | pinfo = PORT_New(SFTKPSSVerifyInfo); |
4050 | 2.44k | if (pinfo == NULL) { |
4051 | 0 | crv = CKR_HOST_MEMORY; |
4052 | 0 | break; |
4053 | 0 | } |
4054 | 2.44k | pinfo->size = sizeof(SFTKPSSVerifyInfo); |
4055 | 2.44k | pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter; |
4056 | 2.44k | pinfo->key = sftk_GetPubKey(key, CKK_RSA, &crv); |
4057 | 2.44k | if (pinfo->key == NULL) { |
4058 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4059 | 0 | break; |
4060 | 0 | } |
4061 | 2.44k | context->cipherInfo = pinfo; |
4062 | 2.44k | context->destroy = sftk_ZSpace; |
4063 | 2.44k | context->verify = sftk_RSACheckSignPSS; |
4064 | 2.44k | break; |
4065 | | |
4066 | 0 | #ifndef NSS_DISABLE_DSA |
4067 | 0 | INIT_DSA_SIG_MECH(SHA1) |
4068 | 1 | INIT_DSA_SIG_MECH(SHA224) |
4069 | 1.28k | INIT_DSA_SIG_MECH(SHA256) |
4070 | 1.28k | INIT_DSA_SIG_MECH(SHA384) |
4071 | 0 | INIT_DSA_SIG_MECH(SHA512) |
4072 | 3.38k | case CKM_DSA: |
4073 | 4.67k | finish_dsa: |
4074 | 4.67k | if (key_type != CKK_DSA) { |
4075 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4076 | 0 | break; |
4077 | 0 | } |
4078 | 4.67k | pubKey = sftk_GetPubKey(key, CKK_DSA, &crv); |
4079 | 4.67k | if (pubKey == NULL) { |
4080 | 0 | break; |
4081 | 0 | } |
4082 | 4.67k | context->cipherInfo = pubKey; |
4083 | 4.67k | context->verify = nsc_DSA_Verify_Stub; |
4084 | 4.67k | context->destroy = sftk_Null; |
4085 | 4.67k | break; |
4086 | 0 | #endif |
4087 | 0 | case CKM_ML_DSA: { |
4088 | | /* set our defaults */ |
4089 | 0 | SECItem signCtx = { siBuffer, NULL, 0 }; |
4090 | 0 | MLDSAContext *ctptr = NULL; |
4091 | 0 | SECStatus rv; |
4092 | | |
4093 | | /* make sure we have the right key type */ |
4094 | 0 | if (key_type != CKK_ML_DSA) { |
4095 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4096 | 0 | break; |
4097 | 0 | } |
4098 | | /* fill in our parameters from the mechanism parameters if |
4099 | | * supplied */ |
4100 | 0 | if (pMechanism->ulParameterLen != 0) { |
4101 | 0 | CK_SIGN_ADDITIONAL_CONTEXT *param; |
4102 | 0 | if (pMechanism->ulParameterLen != |
4103 | 0 | sizeof(CK_SIGN_ADDITIONAL_CONTEXT)) { |
4104 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
4105 | 0 | break; |
4106 | 0 | } |
4107 | 0 | param = (CK_SIGN_ADDITIONAL_CONTEXT *)pMechanism->pParameter; |
4108 | 0 | signCtx.data = param->pContext; |
4109 | 0 | signCtx.len = param->ulContextLen; |
4110 | 0 | } |
4111 | | /* fetch the key */ |
4112 | 0 | pubKey = sftk_GetPubKey(key, key_type, &crv); |
4113 | 0 | if (pubKey == NULL) { |
4114 | | /* crv already set */ |
4115 | 0 | break; |
4116 | 0 | } |
4117 | | /* now initialize it the signature */ |
4118 | 0 | rv = MLDSA_VerifyInit(&(pubKey->u.mldsa), &signCtx, &ctptr); |
4119 | 0 | if (rv != SECSuccess) { |
4120 | 0 | crv = sftk_MapVerifyError(PORT_GetError()); |
4121 | 0 | break; |
4122 | 0 | } |
4123 | | /* set up our cipher info. MLDSA is only a combined hash/sign |
4124 | | * so the hash update is our sign update, the hash end is a null |
4125 | | * function returning a zero length value, and the final gets our |
4126 | | * signature based on the context. Both the cipher context and the |
4127 | | * hash Info is the same. The MLDSA_VerifyFinal frees the context, |
4128 | | * so we don't have to */ |
4129 | 0 | context->multi = PR_TRUE; |
4130 | 0 | context->cipherInfo = ctptr; |
4131 | 0 | context->hashInfo = ctptr; |
4132 | 0 | context->hashUpdate = sftk_MLDSAVerifyUpdate; |
4133 | 0 | context->end = sftk_NullHashEnd; |
4134 | 0 | context->hashdestroy = sftk_Null; |
4135 | 0 | context->destroy = sftk_Null; |
4136 | 0 | context->verify = sftk_MLDSAVerifyFinal; |
4137 | 0 | context->maxLen = sftk_MLDSAGetSigLen(pubKey->u.mldsa.paramSet); |
4138 | 0 | break; |
4139 | 0 | } |
4140 | | |
4141 | 0 | INIT_ECDSA_SIG_MECH(SHA1) |
4142 | 1 | INIT_ECDSA_SIG_MECH(SHA224) |
4143 | 228 | INIT_ECDSA_SIG_MECH(SHA256) |
4144 | 228 | INIT_ECDSA_SIG_MECH(SHA384) |
4145 | 3 | INIT_ECDSA_SIG_MECH(SHA512) |
4146 | 359 | case CKM_ECDSA: |
4147 | 592 | finish_ecdsa: |
4148 | 592 | if (key_type != CKK_EC) { |
4149 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4150 | 0 | break; |
4151 | 0 | } |
4152 | 592 | pubKey = sftk_GetPubKey(key, CKK_EC, &crv); |
4153 | 592 | if (pubKey == NULL) { |
4154 | 0 | crv = CKR_HOST_MEMORY; |
4155 | 0 | break; |
4156 | 0 | } |
4157 | 592 | context->cipherInfo = pubKey; |
4158 | 592 | context->verify = nsc_ECDSAVerifyStub; |
4159 | 592 | context->destroy = sftk_Null; |
4160 | 592 | break; |
4161 | | |
4162 | 0 | INIT_HMAC_MECH(MD2) |
4163 | 0 | INIT_HMAC_MECH(MD5) |
4164 | 0 | INIT_HMAC_MECH(SHA1) |
4165 | 0 | INIT_HMAC_MECH(SHA224) |
4166 | 0 | INIT_HMAC_MECH(SHA256) |
4167 | 0 | INIT_HMAC_MECH(SHA384) |
4168 | 0 | INIT_HMAC_MECH(SHA512) |
4169 | 0 | INIT_HMAC_MECH(SHA3_224) |
4170 | 0 | INIT_HMAC_MECH(SHA3_256) |
4171 | 0 | INIT_HMAC_MECH(SHA3_384) |
4172 | 0 | INIT_HMAC_MECH(SHA3_512) |
4173 | | |
4174 | 0 | case CKM_EDDSA: |
4175 | 0 | if (key_type != CKK_EC_EDWARDS) { |
4176 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4177 | 0 | break; |
4178 | 0 | } |
4179 | 0 | pubKey = sftk_GetPubKey(key, CKK_EC_EDWARDS, &crv); |
4180 | 0 | if (pubKey == NULL) { |
4181 | 0 | crv = CKR_HOST_MEMORY; |
4182 | 0 | break; |
4183 | 0 | } |
4184 | | |
4185 | 0 | if (pMechanism->pParameter) { |
4186 | 0 | crv = CKR_FUNCTION_NOT_SUPPORTED; |
4187 | 0 | break; |
4188 | 0 | } |
4189 | | |
4190 | 0 | context->cipherInfo = pubKey; |
4191 | 0 | context->verify = nsc_EDDSAVerifyStub; |
4192 | 0 | context->destroy = sftk_Null; |
4193 | 0 | break; |
4194 | | |
4195 | 0 | case CKM_SSL3_MD5_MAC: |
4196 | 0 | PORT_Assert(pMechanism->pParameter); |
4197 | 0 | if (!pMechanism->pParameter) { |
4198 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
4199 | 0 | break; |
4200 | 0 | } |
4201 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key, |
4202 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
4203 | 0 | break; |
4204 | 0 | case CKM_SSL3_SHA1_MAC: |
4205 | 0 | PORT_Assert(pMechanism->pParameter); |
4206 | 0 | if (!pMechanism->pParameter) { |
4207 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
4208 | 0 | break; |
4209 | 0 | } |
4210 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key, |
4211 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
4212 | 0 | break; |
4213 | 0 | case CKM_TLS_PRF_GENERAL: |
4214 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); |
4215 | 0 | break; |
4216 | 0 | case CKM_NSS_TLS_PRF_GENERAL_SHA256: |
4217 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); |
4218 | 0 | break; |
4219 | | |
4220 | 0 | default: |
4221 | 0 | crv = CKR_MECHANISM_INVALID; |
4222 | 0 | break; |
4223 | 10.6k | } |
4224 | | |
4225 | 10.6k | if (crv != CKR_OK) { |
4226 | 3 | if (info) |
4227 | 0 | PORT_Free(info); |
4228 | 3 | if (pinfo) |
4229 | 0 | PORT_ZFree(pinfo, pinfo->size); |
4230 | 3 | sftk_FreeContext(context); |
4231 | 3 | sftk_FreeSession(session); |
4232 | 3 | return crv; |
4233 | 3 | } |
4234 | | /* At this point info/pinfo (if allocated) are linked into |
4235 | | * context->cipherInfo and will be freed via sftk_FreeContext. */ |
4236 | 10.6k | crv = sftk_InstallContext(session, SFTK_VERIFY, context); |
4237 | 10.6k | if (crv != CKR_OK) { |
4238 | 0 | sftk_FreeContext(context); |
4239 | 0 | } |
4240 | 10.6k | sftk_FreeSession(session); |
4241 | 10.6k | return crv; |
4242 | 10.6k | } |
4243 | | |
4244 | | /* NSC_Verify verifies a signature in a single-part operation, |
4245 | | * where the signature is an appendix to the data, |
4246 | | * and plaintext cannot be recovered from the signature */ |
4247 | | CK_RV |
4248 | | NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
4249 | | CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) |
4250 | 10.6k | { |
4251 | 10.6k | SFTKSession *session; |
4252 | 10.6k | SFTKSessionContext *context; |
4253 | 10.6k | CK_RV crv; |
4254 | | |
4255 | 10.6k | CHECK_FORK(); |
4256 | | |
4257 | | /* make sure we're legal */ |
4258 | 10.6k | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session); |
4259 | 10.6k | if (crv != CKR_OK) |
4260 | 0 | return crv; |
4261 | | |
4262 | | /* multi part Verifying are completely implemented by VerifyUpdate and |
4263 | | * VerifyFinal */ |
4264 | 10.6k | if (context->multi) { |
4265 | | /* VerifyFinal can't follow failed VerifyUpdate */ |
4266 | 3.22k | if (CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen))) |
4267 | 3.22k | crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen); |
4268 | 7.39k | } else { |
4269 | 7.39k | if (SECSuccess != (*context->verify)(context->cipherInfo, pSignature, |
4270 | 7.39k | ulSignatureLen, pData, ulDataLen)) |
4271 | 7.34k | crv = sftk_MapCryptError(PORT_GetError()); |
4272 | | |
4273 | 7.39k | sftk_TerminateOp(session, SFTK_VERIFY); |
4274 | 7.39k | } |
4275 | 10.6k | sftk_FreeSession(session); |
4276 | 10.6k | return crv; |
4277 | 10.6k | } |
4278 | | |
4279 | | /* NSC_VerifyUpdate continues a multiple-part verification operation, |
4280 | | * where the signature is an appendix to the data, |
4281 | | * and plaintext cannot be recovered from the signature |
4282 | | * |
4283 | | * A call which results in an error terminates the operation [PKCS#11,v2.11] |
4284 | | */ |
4285 | | CK_RV |
4286 | | NSC_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
4287 | | CK_ULONG ulPartLen) |
4288 | 3.22k | { |
4289 | 3.22k | CHECK_FORK(); |
4290 | 3.22k | return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY); |
4291 | 3.22k | } |
4292 | | |
4293 | | /* NSC_VerifyFinal finishes a multiple-part verification operation, |
4294 | | * checking the signature. */ |
4295 | | CK_RV |
4296 | | NSC_VerifyFinal(CK_SESSION_HANDLE hSession, |
4297 | | CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) |
4298 | 3.22k | { |
4299 | 3.22k | SFTKSession *session; |
4300 | 3.22k | SFTKSessionContext *context; |
4301 | 3.22k | CK_RV crv; |
4302 | | |
4303 | 3.22k | CHECK_FORK(); |
4304 | | |
4305 | 3.22k | if (!pSignature) |
4306 | 0 | return CKR_ARGUMENTS_BAD; |
4307 | | |
4308 | | /* make sure we're legal */ |
4309 | 3.22k | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session); |
4310 | 3.22k | if (crv != CKR_OK) |
4311 | 0 | return crv; |
4312 | | |
4313 | 3.22k | if (context->hashInfo) { |
4314 | 3.22k | unsigned int digestLen; |
4315 | 3.22k | unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; |
4316 | | |
4317 | 3.22k | (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); |
4318 | 3.22k | if (SECSuccess != (context->verify)(context->cipherInfo, pSignature, |
4319 | 3.22k | ulSignatureLen, tmpbuf, digestLen)) |
4320 | 2.60k | crv = sftk_MapCryptError(PORT_GetError()); |
4321 | 3.22k | PORT_Memset(tmpbuf, 0, sizeof tmpbuf); |
4322 | 3.22k | } else if (ulSignatureLen != context->macSize) { |
4323 | | /* must be block cipher MACing */ |
4324 | 0 | crv = CKR_SIGNATURE_LEN_RANGE; |
4325 | 0 | } else if (CKR_OK == (crv = sftk_MACFinal(context))) { |
4326 | 0 | if (NSS_SecureMemcmp(pSignature, context->macBuf, ulSignatureLen)) |
4327 | 0 | crv = CKR_SIGNATURE_INVALID; |
4328 | 0 | } |
4329 | | |
4330 | 3.22k | sftk_TerminateOp(session, SFTK_VERIFY); |
4331 | 3.22k | sftk_FreeSession(session); |
4332 | 3.22k | return crv; |
4333 | 3.22k | } |
4334 | | |
4335 | | /* |
4336 | | ************** Crypto Functions: Verify Signature ************************ |
4337 | | * some algorithms need the signature at the beginning of the verification, |
4338 | | * VerifySignature provides such and API. For algorithms that don't need |
4339 | | * the signature first, we stash the signature and just pass it to |
4340 | | * NSC_VerifyXXX. |
4341 | | */ |
4342 | | CK_RV |
4343 | | NSC_VerifySignatureInit(CK_SESSION_HANDLE hSession, |
4344 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, |
4345 | | CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) |
4346 | 10.6k | { |
4347 | 10.6k | SFTKSession *session; |
4348 | 10.6k | SFTKSessionContext *context; |
4349 | 10.6k | CK_RV crv; |
4350 | 10.6k | SECItem tmpItem; |
4351 | | |
4352 | 10.6k | crv = NSC_VerifyInit(hSession, pMechanism, hKey); |
4353 | 10.6k | if (crv != CKR_OK) { |
4354 | 3 | return crv; |
4355 | 3 | } |
4356 | | |
4357 | 10.6k | CHECK_FORK(); |
4358 | | |
4359 | 10.6k | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session); |
4360 | 10.6k | if (crv != CKR_OK) |
4361 | 0 | return crv; |
4362 | | |
4363 | 10.6k | tmpItem.type = siBuffer; |
4364 | 10.6k | tmpItem.data = pSignature; |
4365 | 10.6k | tmpItem.len = ulSignatureLen; |
4366 | 10.6k | context->signature = SECITEM_DupItem(&tmpItem); |
4367 | 10.6k | if (!context->signature) { |
4368 | 0 | sftk_TerminateOp(session, SFTK_VERIFY); |
4369 | 0 | sftk_FreeSession(session); |
4370 | 0 | return CKR_HOST_MEMORY; |
4371 | 0 | } |
4372 | 10.6k | sftk_FreeSession(session); |
4373 | 10.6k | return CKR_OK; |
4374 | 10.6k | } |
4375 | | |
4376 | | CK_RV |
4377 | | NSC_VerifySignature(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
4378 | | CK_ULONG ulDataLen) |
4379 | 10.6k | { |
4380 | 10.6k | SFTKSession *session; |
4381 | 10.6k | SFTKSessionContext *context; |
4382 | 10.6k | CK_RV crv; |
4383 | | |
4384 | 10.6k | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session); |
4385 | 10.6k | if (crv != CKR_OK) |
4386 | 0 | return crv; |
4387 | | |
4388 | | /* make sure we're legal */ |
4389 | 10.6k | if (!context->signature) { |
4390 | 0 | sftk_FreeSession(session); |
4391 | 0 | return CKR_OPERATION_NOT_INITIALIZED; |
4392 | 0 | } |
4393 | 10.6k | crv = NSC_Verify(hSession, pData, ulDataLen, |
4394 | 10.6k | context->signature->data, context->signature->len); |
4395 | | /* we free the signature here because the context is part of the session and has |
4396 | | * a lifetime tied to the session. So we want to hold our reference to the |
4397 | | * session so it doesn't go away on us */ |
4398 | 10.6k | sftk_FreeSession(session); |
4399 | 10.6k | return crv; |
4400 | 10.6k | } |
4401 | | |
4402 | | CK_RV |
4403 | | NSC_VerifySignatureUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
4404 | | CK_ULONG ulPartLen) |
4405 | 0 | { |
4406 | 0 | SFTKSession *session; |
4407 | 0 | SFTKSessionContext *context; |
4408 | 0 | CK_RV crv; |
4409 | | |
4410 | | /* make sure we're legal */ |
4411 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session); |
4412 | 0 | if (crv != CKR_OK) |
4413 | 0 | return crv; |
4414 | | |
4415 | | /* like verify above, we bother keeping the session to make sure the context |
4416 | | * doesn't go way on use. there's little chance that it will since that application |
4417 | | * must protect against multiple threads calling the same same session at the same |
4418 | | * time (nss has session locks for this), but there are a couple of corner cases, |
4419 | | * (like close all sessions, or shutting down the whole module. Also if the |
4420 | | * application breaks the contract, we want to just fail rather than crash */ |
4421 | 0 | if (!context->signature) { |
4422 | 0 | sftk_FreeSession(session); |
4423 | 0 | return CKR_OPERATION_NOT_INITIALIZED; |
4424 | 0 | } |
4425 | 0 | sftk_FreeSession(session); |
4426 | 0 | return NSC_VerifyUpdate(hSession, pPart, ulPartLen); |
4427 | 0 | } |
4428 | | |
4429 | | CK_RV |
4430 | | NSC_VerifySignatureFinal(CK_SESSION_HANDLE hSession) |
4431 | 0 | { |
4432 | 0 | SFTKSession *session; |
4433 | 0 | SFTKSessionContext *context; |
4434 | 0 | CK_RV crv; |
4435 | | |
4436 | | /* make sure we're legal */ |
4437 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session); |
4438 | 0 | if (crv != CKR_OK) |
4439 | 0 | return crv; |
4440 | | |
4441 | 0 | if (!context->signature) { |
4442 | 0 | sftk_FreeSession(session); |
4443 | 0 | return CKR_OPERATION_NOT_INITIALIZED; |
4444 | 0 | } |
4445 | 0 | crv = NSC_VerifyFinal(hSession, context->signature->data, |
4446 | 0 | context->signature->len); |
4447 | | /* see comment in NSC_VerifySignature() */ |
4448 | 0 | sftk_FreeSession(session); |
4449 | 0 | return crv; |
4450 | 0 | } |
4451 | | |
4452 | | /* |
4453 | | ************** Crypto Functions: Verify Recover ************************ |
4454 | | */ |
4455 | | static SECStatus |
4456 | | sftk_RSACheckSignRecover(void *ctx, unsigned char *data, |
4457 | | unsigned int *dataLen, unsigned int maxDataLen, |
4458 | | const unsigned char *sig, unsigned int sigLen) |
4459 | 17.3k | { |
4460 | 17.3k | NSSLOWKEYPublicKey *key = ctx; |
4461 | 17.3k | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
4462 | 17.3k | if (key->keyType != NSSLOWKEYRSAKey) { |
4463 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
4464 | 0 | return SECFailure; |
4465 | 0 | } |
4466 | | |
4467 | 17.3k | return RSA_CheckSignRecover(&key->u.rsa, data, dataLen, maxDataLen, |
4468 | 17.3k | sig, sigLen); |
4469 | 17.3k | } |
4470 | | |
4471 | | static SECStatus |
4472 | | sftk_RSACheckSignRecoverRaw(void *ctx, unsigned char *data, |
4473 | | unsigned int *dataLen, unsigned int maxDataLen, |
4474 | | const unsigned char *sig, unsigned int sigLen) |
4475 | 0 | { |
4476 | 0 | NSSLOWKEYPublicKey *key = ctx; |
4477 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
4478 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
4479 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
4480 | 0 | return SECFailure; |
4481 | 0 | } |
4482 | | |
4483 | 0 | return RSA_CheckSignRecoverRaw(&key->u.rsa, data, dataLen, maxDataLen, |
4484 | 0 | sig, sigLen); |
4485 | 0 | } |
4486 | | |
4487 | | /* NSC_VerifyRecoverInit initializes a signature verification operation, |
4488 | | * where the data is recovered from the signature. |
4489 | | * E.g. Decryption with the user's public key */ |
4490 | | CK_RV |
4491 | | NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, |
4492 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
4493 | 17.3k | { |
4494 | 17.3k | SFTKSession *session; |
4495 | 17.3k | SFTKObject *key; |
4496 | 17.3k | SFTKSessionContext *context; |
4497 | 17.3k | CK_KEY_TYPE key_type; |
4498 | 17.3k | CK_RV crv = CKR_OK; |
4499 | 17.3k | NSSLOWKEYPublicKey *pubKey; |
4500 | | |
4501 | 17.3k | CHECK_FORK(); |
4502 | | |
4503 | 17.3k | session = sftk_SessionFromHandle(hSession); |
4504 | 17.3k | if (session == NULL) |
4505 | 0 | return CKR_SESSION_HANDLE_INVALID; |
4506 | 17.3k | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY_RECOVER, |
4507 | 17.3k | &key, hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY_RECOVER); |
4508 | 17.3k | if (crv != CKR_OK) { |
4509 | 0 | sftk_FreeSession(session); |
4510 | 0 | return crv; |
4511 | 0 | } |
4512 | | |
4513 | 17.3k | context->multi = PR_TRUE; |
4514 | | |
4515 | 17.3k | switch (pMechanism->mechanism) { |
4516 | 17.3k | case CKM_RSA_PKCS: |
4517 | 17.3k | case CKM_RSA_X_509: |
4518 | 17.3k | if (key_type != CKK_RSA) { |
4519 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4520 | 0 | break; |
4521 | 0 | } |
4522 | 17.3k | context->multi = PR_FALSE; |
4523 | 17.3k | context->rsa = PR_TRUE; |
4524 | 17.3k | pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); |
4525 | 17.3k | if (pubKey == NULL) { |
4526 | 0 | break; |
4527 | 0 | } |
4528 | 17.3k | context->cipherInfo = pubKey; |
4529 | 17.3k | context->update = pMechanism->mechanism == CKM_RSA_X_509 |
4530 | 17.3k | ? sftk_RSACheckSignRecoverRaw |
4531 | 17.3k | : sftk_RSACheckSignRecover; |
4532 | 17.3k | context->destroy = sftk_Null; |
4533 | 17.3k | break; |
4534 | 0 | default: |
4535 | 0 | crv = CKR_MECHANISM_INVALID; |
4536 | 0 | break; |
4537 | 17.3k | } |
4538 | | |
4539 | 17.3k | if (crv != CKR_OK) { |
4540 | 0 | PORT_Free(context); |
4541 | 0 | sftk_FreeSession(session); |
4542 | 0 | return crv; |
4543 | 0 | } |
4544 | 17.3k | crv = sftk_InstallContext(session, SFTK_VERIFY_RECOVER, context); |
4545 | 17.3k | if (crv != CKR_OK) { |
4546 | 0 | sftk_FreeContext(context); |
4547 | 0 | } |
4548 | 17.3k | sftk_FreeSession(session); |
4549 | 17.3k | return crv; |
4550 | 17.3k | } |
4551 | | |
4552 | | /* NSC_VerifyRecover verifies a signature in a single-part operation, |
4553 | | * where the data is recovered from the signature. |
4554 | | * E.g. Decryption with the user's public key */ |
4555 | | CK_RV |
4556 | | NSC_VerifyRecover(CK_SESSION_HANDLE hSession, |
4557 | | CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, |
4558 | | CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) |
4559 | 17.3k | { |
4560 | 17.3k | SFTKSession *session; |
4561 | 17.3k | SFTKSessionContext *context; |
4562 | 17.3k | unsigned int outlen; |
4563 | 17.3k | unsigned int maxoutlen = *pulDataLen; |
4564 | 17.3k | CK_RV crv; |
4565 | 17.3k | SECStatus rv; |
4566 | | |
4567 | 17.3k | CHECK_FORK(); |
4568 | | |
4569 | | /* make sure we're legal */ |
4570 | 17.3k | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY_RECOVER, |
4571 | 17.3k | PR_FALSE, &session); |
4572 | 17.3k | if (crv != CKR_OK) |
4573 | 0 | return crv; |
4574 | 17.3k | if (pData == NULL) { |
4575 | | /* to return the actual size, we need to do the decrypt, just return |
4576 | | * the max size, which is the size of the input signature. */ |
4577 | 0 | *pulDataLen = ulSignatureLen; |
4578 | 0 | rv = SECSuccess; |
4579 | 0 | goto finish; |
4580 | 0 | } |
4581 | | |
4582 | 17.3k | rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, |
4583 | 17.3k | pSignature, ulSignatureLen); |
4584 | 17.3k | *pulDataLen = (CK_ULONG)outlen; |
4585 | | |
4586 | 17.3k | sftk_TerminateOp(session, SFTK_VERIFY_RECOVER); |
4587 | 17.3k | finish: |
4588 | 17.3k | sftk_FreeSession(session); |
4589 | 17.3k | return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError()); |
4590 | 17.3k | } |
4591 | | |
4592 | | /* |
4593 | | **************************** Random Functions: ************************ |
4594 | | */ |
4595 | | |
4596 | | /* NSC_SeedRandom mixes additional seed material into the token's random number |
4597 | | * generator. */ |
4598 | | CK_RV |
4599 | | NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, |
4600 | | CK_ULONG ulSeedLen) |
4601 | 0 | { |
4602 | 0 | SECStatus rv; |
4603 | |
|
4604 | 0 | CHECK_FORK(); |
4605 | |
|
4606 | 0 | rv = RNG_RandomUpdate(pSeed, ulSeedLen); |
4607 | 0 | return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
4608 | 0 | } |
4609 | | |
4610 | | /* NSC_GenerateRandom generates random data. */ |
4611 | | CK_RV |
4612 | | NSC_GenerateRandom(CK_SESSION_HANDLE hSession, |
4613 | | CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) |
4614 | 373k | { |
4615 | 373k | SECStatus rv; |
4616 | | |
4617 | 373k | CHECK_FORK(); |
4618 | | |
4619 | 373k | rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen); |
4620 | | /* |
4621 | | * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't |
4622 | | * seeded with enough entropy. |
4623 | | */ |
4624 | 373k | return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
4625 | 373k | } |
4626 | | |
4627 | | /* |
4628 | | **************************** Key Functions: ************************ |
4629 | | */ |
4630 | | |
4631 | | /* |
4632 | | * generate a password based encryption key. This code uses |
4633 | | * PKCS5 to do the work. |
4634 | | */ |
4635 | | static CK_RV |
4636 | | nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism, |
4637 | | void *buf, CK_ULONG *key_length, PRBool faulty3DES) |
4638 | 6.63k | { |
4639 | 6.63k | SECItem *pbe_key = NULL, iv, pwitem; |
4640 | 6.63k | CK_PBE_PARAMS *pbe_params = NULL; |
4641 | 6.63k | CK_PKCS5_PBKD2_PARAMS2 *pbkd2_params = NULL; |
4642 | | |
4643 | 6.63k | *key_length = 0; |
4644 | 6.63k | iv.data = NULL; |
4645 | 6.63k | iv.len = 0; |
4646 | | |
4647 | 6.63k | if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { |
4648 | 5.99k | pbkd2_params = (CK_PKCS5_PBKD2_PARAMS2 *)pMechanism->pParameter; |
4649 | 5.99k | if (!pMechanism->pParameter) { |
4650 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4651 | 0 | } |
4652 | | |
4653 | 5.99k | #ifdef SOFTOKEN_USE_PKCS5_PBKD2_PARAMS2_ONLY |
4654 | 5.99k | if (pMechanism->ulParameterLen < sizeof(CK_PKCS5_PBKD2_PARAMS2)) { |
4655 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4656 | 0 | } |
4657 | 5.99k | pwitem.len = pbkd2_params->ulPasswordLen; |
4658 | | #else |
4659 | | int v2; |
4660 | | if (pMechanism->ulParameterLen < PR_MIN(sizeof(CK_PKCS5_PBKD2_PARAMS), |
4661 | | sizeof(CK_PKCS5_PBKD2_PARAMS2))) { |
4662 | | return CKR_MECHANISM_PARAM_INVALID; |
4663 | | } |
4664 | | |
4665 | | if (sizeof(CK_PKCS5_PBKD2_PARAMS2) != sizeof(CK_PKCS5_PBKD2_PARAMS)) { |
4666 | | if (pMechanism->ulParameterLen == sizeof(CK_PKCS5_PBKD2_PARAMS)) { |
4667 | | v2 = 0; |
4668 | | } else if (pMechanism->ulParameterLen == sizeof(CK_PKCS5_PBKD2_PARAMS2)) { |
4669 | | v2 = 1; |
4670 | | } else { |
4671 | | return CKR_MECHANISM_PARAM_INVALID; |
4672 | | } |
4673 | | } else { |
4674 | | /* it's unlikely that the password will be longer than 8192 bytes, if so it is |
4675 | | * most likely a pointer => CK_PKCS5_PBKD2_PARAMS */ |
4676 | | v2 = pbkd2_params->ulPasswordLen <= CK_PKCS5_PBKD2_PARAMS_PTR_BOUNDARY; |
4677 | | } |
4678 | | pwitem.len = v2 ? pbkd2_params->ulPasswordLen : *((CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter)->ulPasswordLen; |
4679 | | #endif |
4680 | 5.99k | pwitem.data = (unsigned char *)pbkd2_params->pPassword; |
4681 | 5.99k | } else { |
4682 | 646 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) { |
4683 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4684 | 0 | } |
4685 | 646 | pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
4686 | 646 | pwitem.data = (unsigned char *)pbe_params->pPassword; |
4687 | 646 | pwitem.len = pbe_params->ulPasswordLen; |
4688 | 646 | } |
4689 | 6.63k | pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES); |
4690 | 6.63k | if (pbe_key == NULL) { |
4691 | 489 | return CKR_HOST_MEMORY; |
4692 | 489 | } |
4693 | | |
4694 | 6.14k | PORT_Memcpy(buf, pbe_key->data, pbe_key->len); |
4695 | 6.14k | *key_length = pbe_key->len; |
4696 | 6.14k | SECITEM_ZfreeItem(pbe_key, PR_TRUE); |
4697 | 6.14k | pbe_key = NULL; |
4698 | | |
4699 | 6.14k | if (iv.data) { |
4700 | 406 | if (pbe_params && pbe_params->pInitVector != NULL) { |
4701 | 406 | PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len); |
4702 | 406 | } |
4703 | 406 | PORT_Free(iv.data); |
4704 | 406 | } |
4705 | | |
4706 | 6.14k | return CKR_OK; |
4707 | 6.63k | } |
4708 | | |
4709 | | /* |
4710 | | * this is coded for "full" support. These selections will be limitted to |
4711 | | * the official subset by freebl. |
4712 | | */ |
4713 | | static unsigned int |
4714 | | sftk_GetSubPrimeFromPrime(unsigned int primeBits) |
4715 | 0 | { |
4716 | 0 | if (primeBits <= 1024) { |
4717 | 0 | return 160; |
4718 | 0 | } else if (primeBits <= 2048) { |
4719 | 0 | return 224; |
4720 | 0 | } else if (primeBits <= 3072) { |
4721 | 0 | return 256; |
4722 | 0 | } else if (primeBits <= 7680) { |
4723 | 0 | return 384; |
4724 | 0 | } else { |
4725 | 0 | return 512; |
4726 | 0 | } |
4727 | 0 | } |
4728 | | |
4729 | | static CK_RV |
4730 | | nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key) |
4731 | 0 | { |
4732 | 0 | SFTKAttribute *attribute; |
4733 | 0 | CK_ULONG counter; |
4734 | 0 | unsigned int seedBits = 0; |
4735 | 0 | unsigned int subprimeBits = 0; |
4736 | 0 | unsigned int primeBits; |
4737 | 0 | unsigned int j = 8; /* default to 1024 bits */ |
4738 | 0 | CK_RV crv = CKR_OK; |
4739 | 0 | PQGParams *params = NULL; |
4740 | 0 | PQGVerify *vfy = NULL; |
4741 | 0 | SECStatus rv; |
4742 | |
|
4743 | 0 | attribute = sftk_FindAttribute(key, CKA_PRIME_BITS); |
4744 | 0 | if (attribute == NULL) { |
4745 | 0 | attribute = sftk_FindAttribute(key, CKA_PRIME); |
4746 | 0 | if (attribute == NULL) { |
4747 | 0 | return CKR_TEMPLATE_INCOMPLETE; |
4748 | 0 | } else { |
4749 | 0 | primeBits = attribute->attrib.ulValueLen; |
4750 | 0 | sftk_FreeAttribute(attribute); |
4751 | 0 | } |
4752 | 0 | } else { |
4753 | 0 | primeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; |
4754 | 0 | sftk_FreeAttribute(attribute); |
4755 | 0 | } |
4756 | 0 | if (primeBits < 1024) { |
4757 | 0 | j = PQG_PBITS_TO_INDEX(primeBits); |
4758 | 0 | if (j == (unsigned int)-1) { |
4759 | 0 | return CKR_ATTRIBUTE_VALUE_INVALID; |
4760 | 0 | } |
4761 | 0 | } |
4762 | | |
4763 | 0 | attribute = sftk_FindAttribute(key, CKA_NSS_PQG_SEED_BITS); |
4764 | 0 | if (attribute != NULL) { |
4765 | 0 | seedBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; |
4766 | 0 | sftk_FreeAttribute(attribute); |
4767 | 0 | } |
4768 | |
|
4769 | 0 | attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS); |
4770 | 0 | if (attribute != NULL) { |
4771 | 0 | subprimeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; |
4772 | 0 | sftk_FreeAttribute(attribute); |
4773 | 0 | } |
4774 | | |
4775 | | /* if P and Q are supplied, we want to generate a new G */ |
4776 | 0 | attribute = sftk_FindAttribute(key, CKA_PRIME); |
4777 | 0 | if (attribute != NULL) { |
4778 | 0 | PLArenaPool *arena; |
4779 | |
|
4780 | 0 | sftk_FreeAttribute(attribute); |
4781 | 0 | arena = PORT_NewArena(1024); |
4782 | 0 | if (arena == NULL) { |
4783 | 0 | crv = CKR_HOST_MEMORY; |
4784 | 0 | goto loser; |
4785 | 0 | } |
4786 | 0 | params = PORT_ArenaAlloc(arena, sizeof(*params)); |
4787 | 0 | if (params == NULL) { |
4788 | 0 | crv = CKR_HOST_MEMORY; |
4789 | 0 | goto loser; |
4790 | 0 | } |
4791 | 0 | params->arena = arena; |
4792 | 0 | crv = sftk_Attribute2SSecItem(arena, ¶ms->prime, key, CKA_PRIME); |
4793 | 0 | if (crv != CKR_OK) { |
4794 | 0 | goto loser; |
4795 | 0 | } |
4796 | 0 | crv = sftk_Attribute2SSecItem(arena, ¶ms->subPrime, |
4797 | 0 | key, CKA_SUBPRIME); |
4798 | 0 | if (crv != CKR_OK) { |
4799 | 0 | goto loser; |
4800 | 0 | } |
4801 | | |
4802 | 0 | arena = PORT_NewArena(1024); |
4803 | 0 | if (arena == NULL) { |
4804 | 0 | crv = CKR_HOST_MEMORY; |
4805 | 0 | goto loser; |
4806 | 0 | } |
4807 | 0 | vfy = PORT_ArenaAlloc(arena, sizeof(*vfy)); |
4808 | 0 | if (vfy == NULL) { |
4809 | 0 | crv = CKR_HOST_MEMORY; |
4810 | 0 | goto loser; |
4811 | 0 | } |
4812 | 0 | vfy->arena = arena; |
4813 | 0 | crv = sftk_Attribute2SSecItem(arena, &vfy->seed, key, CKA_NSS_PQG_SEED); |
4814 | 0 | if (crv != CKR_OK) { |
4815 | 0 | goto loser; |
4816 | 0 | } |
4817 | 0 | crv = sftk_Attribute2SSecItem(arena, &vfy->h, key, CKA_NSS_PQG_H); |
4818 | 0 | if (crv != CKR_OK) { |
4819 | 0 | goto loser; |
4820 | 0 | } |
4821 | 0 | sftk_DeleteAttributeType(key, CKA_PRIME); |
4822 | 0 | sftk_DeleteAttributeType(key, CKA_SUBPRIME); |
4823 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED); |
4824 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_PQG_H); |
4825 | 0 | } |
4826 | | |
4827 | 0 | sftk_DeleteAttributeType(key, CKA_PRIME_BITS); |
4828 | 0 | sftk_DeleteAttributeType(key, CKA_SUBPRIME_BITS); |
4829 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED_BITS); |
4830 | | |
4831 | | /* use the old PQG interface if we have old input data */ |
4832 | 0 | if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) { |
4833 | 0 | if (seedBits == 0) { |
4834 | 0 | rv = PQG_ParamGen(j, ¶ms, &vfy); |
4835 | 0 | } else { |
4836 | 0 | rv = PQG_ParamGenSeedLen(j, seedBits / 8, ¶ms, &vfy); |
4837 | 0 | } |
4838 | 0 | } else { |
4839 | 0 | if (subprimeBits == 0) { |
4840 | 0 | subprimeBits = sftk_GetSubPrimeFromPrime(primeBits); |
4841 | 0 | } |
4842 | 0 | if (seedBits == 0) { |
4843 | 0 | seedBits = primeBits; |
4844 | 0 | } |
4845 | 0 | rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits / 8, ¶ms, &vfy); |
4846 | 0 | } |
4847 | |
|
4848 | 0 | if (rv != SECSuccess) { |
4849 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
4850 | 0 | sftk_fatalError = PR_TRUE; |
4851 | 0 | } |
4852 | 0 | return sftk_MapCryptError(PORT_GetError()); |
4853 | 0 | } |
4854 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME, |
4855 | 0 | params->prime.data, params->prime.len); |
4856 | 0 | if (crv != CKR_OK) |
4857 | 0 | goto loser; |
4858 | 0 | crv = sftk_AddAttributeType(key, CKA_SUBPRIME, |
4859 | 0 | params->subPrime.data, params->subPrime.len); |
4860 | 0 | if (crv != CKR_OK) |
4861 | 0 | goto loser; |
4862 | 0 | crv = sftk_AddAttributeType(key, CKA_BASE, |
4863 | 0 | params->base.data, params->base.len); |
4864 | 0 | if (crv != CKR_OK) |
4865 | 0 | goto loser; |
4866 | 0 | counter = vfy->counter; |
4867 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_PQG_COUNTER, |
4868 | 0 | &counter, sizeof(counter)); |
4869 | 0 | if (crv != CKR_OK) |
4870 | 0 | goto loser; |
4871 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_PQG_SEED, |
4872 | 0 | vfy->seed.data, vfy->seed.len); |
4873 | 0 | if (crv != CKR_OK) |
4874 | 0 | goto loser; |
4875 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_PQG_H, |
4876 | 0 | vfy->h.data, vfy->h.len); |
4877 | 0 | if (crv != CKR_OK) |
4878 | 0 | goto loser; |
4879 | | |
4880 | 0 | loser: |
4881 | 0 | if (params) { |
4882 | 0 | PQG_DestroyParams(params); |
4883 | 0 | } |
4884 | |
|
4885 | 0 | if (vfy) { |
4886 | 0 | PQG_DestroyVerify(vfy); |
4887 | 0 | } |
4888 | 0 | return crv; |
4889 | 0 | } |
4890 | | |
4891 | | static CK_RV |
4892 | | nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type, |
4893 | | CK_ULONG *key_length) |
4894 | 39.0k | { |
4895 | 39.0k | CK_RV crv = CKR_OK; |
4896 | | |
4897 | 39.0k | switch (mechanism) { |
4898 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
4899 | 0 | case CKM_RC2_KEY_GEN: |
4900 | 0 | *key_type = CKK_RC2; |
4901 | 0 | if (*key_length == 0) |
4902 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4903 | 0 | break; |
4904 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
4905 | | #if NSS_SOFTOKEN_DOES_RC5 |
4906 | | case CKM_RC5_KEY_GEN: |
4907 | | *key_type = CKK_RC5; |
4908 | | if (*key_length == 0) |
4909 | | crv = CKR_TEMPLATE_INCOMPLETE; |
4910 | | break; |
4911 | | #endif |
4912 | 0 | case CKM_RC4_KEY_GEN: |
4913 | 0 | *key_type = CKK_RC4; |
4914 | 0 | if (*key_length == 0) |
4915 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4916 | 0 | break; |
4917 | 1.55k | case CKM_GENERIC_SECRET_KEY_GEN: |
4918 | 1.55k | *key_type = CKK_GENERIC_SECRET; |
4919 | 1.55k | if (*key_length == 0) |
4920 | 7 | crv = CKR_TEMPLATE_INCOMPLETE; |
4921 | 1.55k | break; |
4922 | 0 | case CKM_CDMF_KEY_GEN: |
4923 | 0 | *key_type = CKK_CDMF; |
4924 | 0 | *key_length = 8; |
4925 | 0 | break; |
4926 | 0 | case CKM_DES_KEY_GEN: |
4927 | 0 | *key_type = CKK_DES; |
4928 | 0 | *key_length = 8; |
4929 | 0 | break; |
4930 | 0 | case CKM_DES2_KEY_GEN: |
4931 | 0 | *key_type = CKK_DES2; |
4932 | 0 | *key_length = 16; |
4933 | 0 | break; |
4934 | 5.18k | case CKM_DES3_KEY_GEN: |
4935 | 5.18k | *key_type = CKK_DES3; |
4936 | 5.18k | *key_length = 24; |
4937 | 5.18k | break; |
4938 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
4939 | 0 | case CKM_SEED_KEY_GEN: |
4940 | 0 | *key_type = CKK_SEED; |
4941 | 0 | *key_length = 16; |
4942 | 0 | break; |
4943 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
4944 | 0 | case CKM_CAMELLIA_KEY_GEN: |
4945 | 0 | *key_type = CKK_CAMELLIA; |
4946 | 0 | if (*key_length == 0) |
4947 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4948 | 0 | break; |
4949 | 6 | case CKM_AES_KEY_GEN: |
4950 | 6 | *key_type = CKK_AES; |
4951 | 6 | if (*key_length == 0) |
4952 | 2 | crv = CKR_TEMPLATE_INCOMPLETE; |
4953 | 6 | break; |
4954 | 32.3k | case CKM_NSS_CHACHA20_KEY_GEN: |
4955 | 32.3k | *key_type = CKK_NSS_CHACHA20; |
4956 | 32.3k | *key_length = 32; |
4957 | 32.3k | break; |
4958 | 0 | case CKM_CHACHA20_KEY_GEN: |
4959 | 0 | *key_type = CKK_CHACHA20; |
4960 | 0 | *key_length = 32; |
4961 | 0 | break; |
4962 | 0 | case CKM_HKDF_KEY_GEN: |
4963 | 0 | *key_type = CKK_HKDF; |
4964 | 0 | if (*key_length == 0) |
4965 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4966 | 0 | break; |
4967 | 0 | default: |
4968 | 0 | PORT_Assert(0); |
4969 | 0 | crv = CKR_MECHANISM_INVALID; |
4970 | 0 | break; |
4971 | 39.0k | } |
4972 | | |
4973 | 39.0k | return crv; |
4974 | 39.0k | } |
4975 | | |
4976 | | CK_RV |
4977 | | nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe) |
4978 | 181 | { |
4979 | 181 | SECItem salt; |
4980 | 181 | CK_PBE_PARAMS *pbe_params = NULL; |
4981 | 181 | NSSPKCS5PBEParameter *params; |
4982 | 181 | PLArenaPool *arena = NULL; |
4983 | 181 | SECStatus rv; |
4984 | | |
4985 | 181 | *pbe = NULL; |
4986 | | |
4987 | 181 | arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); |
4988 | 181 | if (arena == NULL) { |
4989 | 0 | return CKR_HOST_MEMORY; |
4990 | 0 | } |
4991 | | |
4992 | 181 | params = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena, |
4993 | 181 | sizeof(NSSPKCS5PBEParameter)); |
4994 | 181 | if (params == NULL) { |
4995 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4996 | 0 | return CKR_HOST_MEMORY; |
4997 | 0 | } |
4998 | 181 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) { |
4999 | 0 | PORT_FreeArena(arena, PR_TRUE); |
5000 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
5001 | 0 | } |
5002 | | |
5003 | 181 | params->poolp = arena; |
5004 | 181 | params->ivLen = 0; |
5005 | 181 | params->pbeType = NSSPKCS5_PKCS12_V2; |
5006 | 181 | params->hashType = HASH_AlgSHA1; |
5007 | 181 | params->encAlg = SEC_OID_SHA1; /* any invalid value */ |
5008 | 181 | params->is2KeyDES = PR_FALSE; |
5009 | 181 | params->keyID = pbeBitGenIntegrityKey; |
5010 | 181 | pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
5011 | 181 | params->iter = pbe_params->ulIteration; |
5012 | | |
5013 | 181 | salt.data = (unsigned char *)pbe_params->pSalt; |
5014 | 181 | salt.len = (unsigned int)pbe_params->ulSaltLen; |
5015 | 181 | salt.type = siBuffer; |
5016 | 181 | rv = SECITEM_CopyItem(arena, ¶ms->salt, &salt); |
5017 | 181 | if (rv != SECSuccess) { |
5018 | 0 | PORT_FreeArena(arena, PR_TRUE); |
5019 | 0 | return CKR_HOST_MEMORY; |
5020 | 0 | } |
5021 | 181 | switch (pMechanism->mechanism) { |
5022 | 3 | case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN: |
5023 | 3 | case CKM_PBA_SHA1_WITH_SHA1_HMAC: |
5024 | 3 | params->hashType = HASH_AlgSHA1; |
5025 | 3 | params->keyLen = 20; |
5026 | 3 | break; |
5027 | 0 | case CKM_NSS_PBE_MD5_HMAC_KEY_GEN: |
5028 | 0 | params->hashType = HASH_AlgMD5; |
5029 | 0 | params->keyLen = 16; |
5030 | 0 | break; |
5031 | 0 | case CKM_NSS_PBE_MD2_HMAC_KEY_GEN: |
5032 | 0 | params->hashType = HASH_AlgMD2; |
5033 | 0 | params->keyLen = 16; |
5034 | 0 | break; |
5035 | 15 | case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN: |
5036 | 15 | params->hashType = HASH_AlgSHA224; |
5037 | 15 | params->keyLen = 28; |
5038 | 15 | break; |
5039 | 51 | case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN: |
5040 | 51 | params->hashType = HASH_AlgSHA256; |
5041 | 51 | params->keyLen = 32; |
5042 | 51 | break; |
5043 | 74 | case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN: |
5044 | 74 | params->hashType = HASH_AlgSHA384; |
5045 | 74 | params->keyLen = 48; |
5046 | 74 | break; |
5047 | 38 | case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN: |
5048 | 38 | params->hashType = HASH_AlgSHA512; |
5049 | 38 | params->keyLen = 64; |
5050 | 38 | break; |
5051 | 0 | default: |
5052 | 0 | PORT_FreeArena(arena, PR_TRUE); |
5053 | 0 | return CKR_MECHANISM_INVALID; |
5054 | 181 | } |
5055 | 181 | *pbe = params; |
5056 | 181 | return CKR_OK; |
5057 | 181 | } |
5058 | | |
5059 | | /* maybe this should be table driven? */ |
5060 | | static CK_RV |
5061 | | nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe, |
5062 | | CK_KEY_TYPE *key_type, CK_ULONG *key_length) |
5063 | 7.75k | { |
5064 | 7.75k | CK_RV crv = CKR_OK; |
5065 | 7.75k | SECOidData *oid; |
5066 | 7.75k | CK_PBE_PARAMS *pbe_params = NULL; |
5067 | 7.75k | NSSPKCS5PBEParameter *params = NULL; |
5068 | 7.75k | HASH_HashType hashType = HASH_AlgSHA1; |
5069 | 7.75k | CK_PKCS5_PBKD2_PARAMS2 *pbkd2_params = NULL; |
5070 | 7.75k | SECItem salt; |
5071 | 7.75k | CK_ULONG iteration = 0; |
5072 | | |
5073 | 7.75k | *pbe = NULL; |
5074 | | |
5075 | 7.75k | oid = SECOID_FindOIDByMechanism(pMechanism->mechanism); |
5076 | 7.75k | if (oid == NULL) { |
5077 | 0 | return CKR_MECHANISM_INVALID; |
5078 | 0 | } |
5079 | | |
5080 | 7.75k | if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { |
5081 | 7.28k | if (pMechanism->ulParameterLen < PR_MIN(sizeof(CK_PKCS5_PBKD2_PARAMS2), |
5082 | 7.28k | sizeof(CK_PKCS5_PBKD2_PARAMS))) { |
5083 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
5084 | 0 | } |
5085 | 7.28k | pbkd2_params = (CK_PKCS5_PBKD2_PARAMS2 *)pMechanism->pParameter; |
5086 | 7.28k | switch (pbkd2_params->prf) { |
5087 | 299 | case CKP_PKCS5_PBKD2_HMAC_SHA1: |
5088 | 299 | hashType = HASH_AlgSHA1; |
5089 | 299 | break; |
5090 | 209 | case CKP_PKCS5_PBKD2_HMAC_SHA224: |
5091 | 209 | hashType = HASH_AlgSHA224; |
5092 | 209 | break; |
5093 | 5.54k | case CKP_PKCS5_PBKD2_HMAC_SHA256: |
5094 | 5.54k | hashType = HASH_AlgSHA256; |
5095 | 5.54k | break; |
5096 | 144 | case CKP_PKCS5_PBKD2_HMAC_SHA384: |
5097 | 144 | hashType = HASH_AlgSHA384; |
5098 | 144 | break; |
5099 | 1.09k | case CKP_PKCS5_PBKD2_HMAC_SHA512: |
5100 | 1.09k | hashType = HASH_AlgSHA512; |
5101 | 1.09k | break; |
5102 | 0 | default: |
5103 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
5104 | 7.28k | } |
5105 | 7.28k | if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) { |
5106 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
5107 | 0 | } |
5108 | 7.28k | salt.data = (unsigned char *)pbkd2_params->pSaltSourceData; |
5109 | 7.28k | salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen; |
5110 | 7.28k | iteration = pbkd2_params->iterations; |
5111 | 7.28k | } else { |
5112 | 465 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) { |
5113 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
5114 | 0 | } |
5115 | 465 | pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
5116 | 465 | salt.data = (unsigned char *)pbe_params->pSalt; |
5117 | 465 | salt.len = (unsigned int)pbe_params->ulSaltLen; |
5118 | 465 | iteration = pbe_params->ulIteration; |
5119 | 465 | } |
5120 | 7.75k | params = nsspkcs5_NewParam(oid->offset, hashType, &salt, iteration); |
5121 | 7.75k | if (params == NULL) { |
5122 | 0 | return CKR_MECHANISM_INVALID; |
5123 | 0 | } |
5124 | | |
5125 | 7.75k | switch (params->encAlg) { |
5126 | 252 | case SEC_OID_DES_CBC: |
5127 | 252 | *key_type = CKK_DES; |
5128 | 252 | *key_length = params->keyLen; |
5129 | 252 | break; |
5130 | 136 | case SEC_OID_DES_EDE3_CBC: |
5131 | 136 | *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3; |
5132 | 136 | *key_length = params->keyLen; |
5133 | 136 | break; |
5134 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
5135 | 50 | case SEC_OID_RC2_CBC: |
5136 | 50 | *key_type = CKK_RC2; |
5137 | 50 | *key_length = params->keyLen; |
5138 | 50 | break; |
5139 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
5140 | 27 | case SEC_OID_RC4: |
5141 | 27 | *key_type = CKK_RC4; |
5142 | 27 | *key_length = params->keyLen; |
5143 | 27 | break; |
5144 | 7.28k | case SEC_OID_PKCS5_PBKDF2: |
5145 | | /* key type must already be set */ |
5146 | 7.28k | if (*key_type == CKK_INVALID_KEY_TYPE) { |
5147 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5148 | 0 | break; |
5149 | 0 | } |
5150 | | /* PBKDF2 needs to calculate the key length from the other parameters |
5151 | | */ |
5152 | 7.28k | if (*key_length == 0) { |
5153 | 1.14k | *key_length = sftk_MapKeySize(*key_type); |
5154 | 1.14k | } |
5155 | 7.28k | if (*key_length == 0) { |
5156 | 1.14k | crv = CKR_TEMPLATE_INCOMPLETE; |
5157 | 1.14k | break; |
5158 | 1.14k | } |
5159 | 6.14k | params->keyLen = *key_length; |
5160 | 6.14k | break; |
5161 | 0 | default: |
5162 | 0 | crv = CKR_MECHANISM_INVALID; |
5163 | 0 | break; |
5164 | 7.75k | } |
5165 | 7.75k | if (crv == CKR_OK) { |
5166 | 6.61k | *pbe = params; |
5167 | 6.61k | } else { |
5168 | 1.14k | nsspkcs5_DestroyPBEParameter(params); |
5169 | 1.14k | } |
5170 | 7.75k | return crv; |
5171 | 7.75k | } |
5172 | | |
5173 | | /* NSC_GenerateKey generates a secret key, creating a new key object. */ |
5174 | | CK_RV |
5175 | | NSC_GenerateKey(CK_SESSION_HANDLE hSession, |
5176 | | CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, |
5177 | | CK_OBJECT_HANDLE_PTR phKey) |
5178 | 108k | { |
5179 | 108k | SFTKObject *key; |
5180 | 108k | SFTKSession *session; |
5181 | 108k | PRBool checkWeak = PR_FALSE; |
5182 | 108k | CK_ULONG key_length = 0; |
5183 | 108k | CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE; |
5184 | 108k | CK_OBJECT_CLASS objclass = CKO_SECRET_KEY; |
5185 | 108k | CK_RV crv = CKR_OK; |
5186 | 108k | CK_BBOOL cktrue = CK_TRUE; |
5187 | 108k | NSSPKCS5PBEParameter *pbe_param = NULL; |
5188 | 108k | int i; |
5189 | 108k | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
5190 | 108k | unsigned char buf[MAX_KEY_LEN]; |
5191 | 108k | enum { nsc_pbe, |
5192 | 108k | nsc_ssl, |
5193 | 108k | nsc_bulk, |
5194 | 108k | nsc_param, |
5195 | 108k | nsc_jpake } key_gen_type; |
5196 | 108k | SSL3RSAPreMasterSecret *rsa_pms; |
5197 | 108k | CK_VERSION *version; |
5198 | | /* in very old versions of NSS, there were implementation errors with key |
5199 | | * generation methods. We want to beable to read these, but not |
5200 | | * produce them any more. The affected algorithm was 3DES. |
5201 | | */ |
5202 | 108k | PRBool faultyPBE3DES = PR_FALSE; |
5203 | 108k | HASH_HashType hashType = HASH_AlgNULL; |
5204 | | |
5205 | 108k | CHECK_FORK(); |
5206 | | |
5207 | 108k | if (!slot) { |
5208 | 0 | return CKR_SESSION_HANDLE_INVALID; |
5209 | 0 | } |
5210 | | /* |
5211 | | * now lets create an object to hang the attributes off of |
5212 | | */ |
5213 | 108k | key = sftk_NewObject(slot); /* fill in the handle later */ |
5214 | 108k | if (key == NULL) { |
5215 | 0 | return CKR_HOST_MEMORY; |
5216 | 0 | } |
5217 | | |
5218 | | /* |
5219 | | * load the template values into the object |
5220 | | */ |
5221 | 396k | for (i = 0; i < (int)ulCount; i++) { |
5222 | 287k | if (pTemplate[i].type == CKA_VALUE_LEN) { |
5223 | 40.0k | key_length = *(CK_ULONG *)pTemplate[i].pValue; |
5224 | 40.0k | continue; |
5225 | 40.0k | } |
5226 | | /* some algorithms need keytype specified */ |
5227 | 247k | if (pTemplate[i].type == CKA_KEY_TYPE) { |
5228 | 7.28k | key_type = *(CK_ULONG *)pTemplate[i].pValue; |
5229 | 7.28k | continue; |
5230 | 7.28k | } |
5231 | | |
5232 | 240k | crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); |
5233 | 240k | if (crv != CKR_OK) { |
5234 | 0 | break; |
5235 | 0 | } |
5236 | 240k | } |
5237 | 108k | if (crv != CKR_OK) { |
5238 | 0 | goto loser; |
5239 | 0 | } |
5240 | | |
5241 | | /* make sure we don't have any class, key_type, or value fields */ |
5242 | 108k | sftk_DeleteAttributeType(key, CKA_CLASS); |
5243 | 108k | sftk_DeleteAttributeType(key, CKA_KEY_TYPE); |
5244 | 108k | sftk_DeleteAttributeType(key, CKA_VALUE); |
5245 | | |
5246 | | /* Now Set up the parameters to generate the key (based on mechanism) */ |
5247 | 108k | key_gen_type = nsc_bulk; /* bulk key by default */ |
5248 | 108k | switch (pMechanism->mechanism) { |
5249 | 0 | case CKM_CDMF_KEY_GEN: |
5250 | 0 | case CKM_DES_KEY_GEN: |
5251 | 0 | case CKM_DES2_KEY_GEN: |
5252 | 5.18k | case CKM_DES3_KEY_GEN: |
5253 | 5.18k | checkWeak = PR_TRUE; |
5254 | | /* fall through */ |
5255 | 5.18k | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
5256 | 5.18k | case CKM_RC2_KEY_GEN: |
5257 | 5.18k | #endif |
5258 | 5.18k | case CKM_RC4_KEY_GEN: |
5259 | 6.74k | case CKM_GENERIC_SECRET_KEY_GEN: |
5260 | 6.74k | #ifndef NSS_DISABLE_DEPRECATED_SEED |
5261 | 6.74k | case CKM_SEED_KEY_GEN: |
5262 | 6.74k | #endif |
5263 | 6.74k | case CKM_CAMELLIA_KEY_GEN: |
5264 | 6.75k | case CKM_AES_KEY_GEN: |
5265 | 39.0k | case CKM_NSS_CHACHA20_KEY_GEN: |
5266 | 39.0k | case CKM_CHACHA20_KEY_GEN: |
5267 | | #if NSS_SOFTOKEN_DOES_RC5 |
5268 | | case CKM_RC5_KEY_GEN: |
5269 | | #endif |
5270 | 39.0k | crv = nsc_SetupBulkKeyGen(pMechanism->mechanism, &key_type, &key_length); |
5271 | 39.0k | break; |
5272 | 61.5k | case CKM_SSL3_PRE_MASTER_KEY_GEN: |
5273 | 61.5k | key_type = CKK_GENERIC_SECRET; |
5274 | 61.5k | key_length = 48; |
5275 | 61.5k | key_gen_type = nsc_ssl; |
5276 | 61.5k | break; |
5277 | 0 | case CKM_PBA_SHA1_WITH_SHA1_HMAC: |
5278 | 3 | case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN: |
5279 | 3 | case CKM_NSS_PBE_MD5_HMAC_KEY_GEN: |
5280 | 3 | case CKM_NSS_PBE_MD2_HMAC_KEY_GEN: |
5281 | 18 | case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN: |
5282 | 69 | case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN: |
5283 | 143 | case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN: |
5284 | 181 | case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN: |
5285 | 181 | key_gen_type = nsc_pbe; |
5286 | 181 | key_type = CKK_GENERIC_SECRET; |
5287 | 181 | crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param); |
5288 | 181 | break; |
5289 | 0 | case CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC: |
5290 | 0 | faultyPBE3DES = PR_TRUE; |
5291 | | /* fall through */ |
5292 | 0 | case CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC: |
5293 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
5294 | 0 | case CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC: |
5295 | 0 | case CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC: |
5296 | 8 | case CKM_PBE_SHA1_RC2_128_CBC: |
5297 | 50 | case CKM_PBE_SHA1_RC2_40_CBC: |
5298 | 50 | #endif |
5299 | 78 | case CKM_NSS_PBE_SHA1_DES_CBC: |
5300 | 78 | case CKM_NSS_PBE_SHA1_40_BIT_RC4: |
5301 | 78 | case CKM_NSS_PBE_SHA1_128_BIT_RC4: |
5302 | 200 | case CKM_PBE_SHA1_DES3_EDE_CBC: |
5303 | 214 | case CKM_PBE_SHA1_DES2_EDE_CBC: |
5304 | 231 | case CKM_PBE_SHA1_RC4_128: |
5305 | 241 | case CKM_PBE_SHA1_RC4_40: |
5306 | 310 | case CKM_PBE_MD5_DES_CBC: |
5307 | 465 | case CKM_PBE_MD2_DES_CBC: |
5308 | 7.75k | case CKM_PKCS5_PBKD2: |
5309 | 7.75k | key_gen_type = nsc_pbe; |
5310 | 7.75k | crv = nsc_SetupPBEKeyGen(pMechanism, &pbe_param, &key_type, &key_length); |
5311 | 7.75k | break; |
5312 | | /*#ifndef NSS_DISABLE_DSA */ |
5313 | | /* some applications use CKM_DSA_PARAMETER_GEN for weak DH keys... |
5314 | | * most notably tests and even ssl... continue to allow it for now */ |
5315 | 0 | case CKM_DSA_PARAMETER_GEN: |
5316 | 0 | key_gen_type = nsc_param; |
5317 | 0 | key_type = CKK_DSA; |
5318 | 0 | objclass = CKO_DOMAIN_PARAMETERS; |
5319 | 0 | crv = CKR_OK; |
5320 | 0 | break; |
5321 | | /* #endif */ |
5322 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA1: |
5323 | 0 | hashType = HASH_AlgSHA1; |
5324 | 0 | goto jpake1; |
5325 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA256: |
5326 | 0 | hashType = HASH_AlgSHA256; |
5327 | 0 | goto jpake1; |
5328 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA384: |
5329 | 0 | hashType = HASH_AlgSHA384; |
5330 | 0 | goto jpake1; |
5331 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA512: |
5332 | 0 | hashType = HASH_AlgSHA512; |
5333 | 0 | goto jpake1; |
5334 | 0 | jpake1: |
5335 | 0 | key_gen_type = nsc_jpake; |
5336 | 0 | key_type = CKK_NSS_JPAKE_ROUND1; |
5337 | 0 | objclass = CKO_PRIVATE_KEY; |
5338 | 0 | if (pMechanism->pParameter == NULL || |
5339 | 0 | pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) { |
5340 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
5341 | 0 | break; |
5342 | 0 | } |
5343 | 0 | if (sftk_isTrue(key, CKA_TOKEN)) { |
5344 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
5345 | 0 | break; |
5346 | 0 | } |
5347 | 0 | crv = CKR_OK; |
5348 | 0 | break; |
5349 | 8 | default: |
5350 | 8 | crv = CKR_MECHANISM_INVALID; |
5351 | 8 | break; |
5352 | 108k | } |
5353 | | |
5354 | | /* make sure we aren't going to overflow the buffer */ |
5355 | 108k | if (sizeof(buf) < key_length) { |
5356 | | /* someone is getting pretty optimistic about how big their key can |
5357 | | * be... */ |
5358 | 158 | crv = CKR_TEMPLATE_INCONSISTENT; |
5359 | 158 | } |
5360 | | |
5361 | 108k | if (crv != CKR_OK) { |
5362 | 1.31k | if (pbe_param) { |
5363 | 158 | nsspkcs5_DestroyPBEParameter(pbe_param); |
5364 | 158 | } |
5365 | 1.31k | goto loser; |
5366 | 1.31k | } |
5367 | | |
5368 | | /* if there was no error, |
5369 | | * key_type *MUST* be set in the switch statement above */ |
5370 | 107k | PORT_Assert(key_type != CKK_INVALID_KEY_TYPE); |
5371 | | |
5372 | | /* |
5373 | | * now to the actual key gen. |
5374 | | */ |
5375 | 107k | switch (key_gen_type) { |
5376 | 6.63k | case nsc_pbe: |
5377 | 6.63k | crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length, |
5378 | 6.63k | faultyPBE3DES); |
5379 | 6.63k | nsspkcs5_DestroyPBEParameter(pbe_param); |
5380 | 6.63k | break; |
5381 | 61.5k | case nsc_ssl: |
5382 | 61.5k | rsa_pms = (SSL3RSAPreMasterSecret *)buf; |
5383 | 61.5k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_VERSION))) { |
5384 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
5385 | 0 | goto loser; |
5386 | 0 | } |
5387 | 61.5k | version = (CK_VERSION *)pMechanism->pParameter; |
5388 | 61.5k | rsa_pms->client_version[0] = version->major; |
5389 | 61.5k | rsa_pms->client_version[1] = version->minor; |
5390 | 61.5k | crv = |
5391 | 61.5k | NSC_GenerateRandom(0, &rsa_pms->random[0], sizeof(rsa_pms->random)); |
5392 | 61.5k | break; |
5393 | 39.0k | case nsc_bulk: |
5394 | | /* get the key, check for weak keys and repeat if found */ |
5395 | 39.0k | do { |
5396 | 39.0k | crv = NSC_GenerateRandom(0, buf, key_length); |
5397 | 39.0k | } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf, key_type)); |
5398 | 39.0k | break; |
5399 | 0 | case nsc_param: |
5400 | | /* generate parameters */ |
5401 | 0 | *buf = 0; |
5402 | 0 | crv = nsc_parameter_gen(key_type, key); |
5403 | 0 | break; |
5404 | 0 | case nsc_jpake: |
5405 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_NSS_JPAKERound1Params))) { |
5406 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
5407 | 0 | goto loser; |
5408 | 0 | } |
5409 | 0 | crv = jpake_Round1(hashType, |
5410 | 0 | (CK_NSS_JPAKERound1Params *)pMechanism->pParameter, |
5411 | 0 | key); |
5412 | 0 | break; |
5413 | 107k | } |
5414 | | |
5415 | 107k | if (crv != CKR_OK) { |
5416 | 489 | goto loser; |
5417 | 489 | } |
5418 | | |
5419 | | /* Add the class, key_type, and value */ |
5420 | 106k | crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS)); |
5421 | 106k | if (crv != CKR_OK) { |
5422 | 0 | goto loser; |
5423 | 0 | } |
5424 | 106k | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE)); |
5425 | 106k | if (crv != CKR_OK) { |
5426 | 0 | goto loser; |
5427 | 0 | } |
5428 | 106k | if (key_length != 0) { |
5429 | 106k | crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length); |
5430 | 106k | if (crv != CKR_OK) { |
5431 | 0 | goto loser; |
5432 | 0 | } |
5433 | 106k | } |
5434 | | |
5435 | | /* get the session */ |
5436 | 106k | session = sftk_SessionFromHandle(hSession); |
5437 | 106k | if (session == NULL) { |
5438 | 0 | crv = CKR_SESSION_HANDLE_INVALID; |
5439 | 0 | goto loser; |
5440 | 0 | } |
5441 | | |
5442 | | /* |
5443 | | * handle the base object stuff |
5444 | | */ |
5445 | 106k | crv = sftk_handleObject(key, session); |
5446 | | /* we need to do this check at the end, so we can check the generated key |
5447 | | * length against fips requirements */ |
5448 | 106k | sftk_setFIPS(key, sftk_operationIsFIPS(slot, pMechanism, CKA_NSS_GENERATE, |
5449 | 106k | key, 0)); |
5450 | 106k | session->lastOpWasFIPS = sftk_hasFIPS(key); |
5451 | 106k | sftk_FreeSession(session); |
5452 | 106k | if (crv != CKR_OK) { |
5453 | 107 | goto loser; |
5454 | 107 | } |
5455 | 106k | if (sftk_isTrue(key, CKA_SENSITIVE)) { |
5456 | 0 | crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL)); |
5457 | 0 | } |
5458 | 106k | if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) { |
5459 | 0 | crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL)); |
5460 | 0 | } |
5461 | 106k | if (crv != CKR_OK) { |
5462 | 0 | NSC_DestroyObject(hSession, key->handle); |
5463 | 0 | goto loser; |
5464 | 0 | } |
5465 | 106k | *phKey = key->handle; |
5466 | 108k | loser: |
5467 | 108k | PORT_Memset(buf, 0, sizeof buf); |
5468 | 108k | sftk_FreeObject(key); |
5469 | 108k | return crv; |
5470 | 106k | } |
5471 | | |
5472 | | /* takes raw sessions and key handles and determines if the keys |
5473 | | * have the same value. */ |
5474 | | PRBool |
5475 | | sftk_compareKeysEqual(CK_SESSION_HANDLE hSession, |
5476 | | CK_OBJECT_HANDLE key1, CK_OBJECT_HANDLE key2) |
5477 | 0 | { |
5478 | 0 | PRBool result = PR_FALSE; |
5479 | 0 | SFTKSession *session; |
5480 | 0 | SFTKObject *key1obj = NULL; |
5481 | 0 | SFTKObject *key2obj = NULL; |
5482 | 0 | SFTKAttribute *att1 = NULL; |
5483 | 0 | SFTKAttribute *att2 = NULL; |
5484 | | |
5485 | | /* fetch the pkcs11 objects from the handles */ |
5486 | 0 | session = sftk_SessionFromHandle(hSession); |
5487 | 0 | if (session == NULL) { |
5488 | 0 | return PR_FALSE; |
5489 | 0 | } |
5490 | | |
5491 | 0 | key1obj = sftk_ObjectFromHandle(key1, session); |
5492 | 0 | key2obj = sftk_ObjectFromHandle(key2, session); |
5493 | 0 | sftk_FreeSession(session); |
5494 | 0 | if ((key1obj == NULL) || (key2obj == NULL)) { |
5495 | 0 | goto loser; |
5496 | 0 | } |
5497 | | /* fetch the value attributes */ |
5498 | 0 | att1 = sftk_FindAttribute(key1obj, CKA_VALUE); |
5499 | 0 | if (att1 == NULL) { |
5500 | 0 | goto loser; |
5501 | 0 | } |
5502 | 0 | att2 = sftk_FindAttribute(key2obj, CKA_VALUE); |
5503 | 0 | if (att2 == NULL) { |
5504 | 0 | goto loser; |
5505 | 0 | } |
5506 | | /* make sure that they are equal */ |
5507 | 0 | if (att1->attrib.ulValueLen != att2->attrib.ulValueLen) { |
5508 | 0 | goto loser; |
5509 | 0 | } |
5510 | 0 | if (PORT_Memcmp(att1->attrib.pValue, att2->attrib.pValue, |
5511 | 0 | att1->attrib.ulValueLen) != 0) { |
5512 | 0 | goto loser; |
5513 | 0 | } |
5514 | 0 | result = PR_TRUE; |
5515 | 0 | loser: |
5516 | 0 | if (att1) { |
5517 | 0 | sftk_FreeAttribute(att1); |
5518 | 0 | } |
5519 | 0 | if (att2) { |
5520 | 0 | sftk_FreeAttribute(att2); |
5521 | 0 | } |
5522 | 0 | if (key1obj) { |
5523 | 0 | sftk_FreeObject(key1obj); |
5524 | 0 | } |
5525 | 0 | if (key2obj) { |
5526 | 0 | sftk_FreeObject(key2obj); |
5527 | 0 | } |
5528 | 0 | return result; |
5529 | 0 | } |
5530 | | |
5531 | 0 | #define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ |
5532 | | |
5533 | | /* |
5534 | | * FIPS 140-3 pairwise consistency check utilized to validate key pair. |
5535 | | * |
5536 | | * This function returns |
5537 | | * CKR_OK if pairwise consistency check passed |
5538 | | * CKR_GENERAL_ERROR if pairwise consistency check failed |
5539 | | * other error codes if paiswise consistency check could not be |
5540 | | * performed, for example, CKR_HOST_MEMORY. |
5541 | | */ |
5542 | | static CK_RV |
5543 | | sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, SFTKSlot *slot, |
5544 | | SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType) |
5545 | 29.7k | { |
5546 | | /* |
5547 | | * Key type Mechanism type |
5548 | | * -------------------------------- |
5549 | | * For encrypt/decrypt: CKK_RSA => CKM_RSA_PKCS_OAEP |
5550 | | * others => CKM_INVALID_MECHANISM |
5551 | | * |
5552 | | * For sign/verify: CKK_RSA => CKM_SHA256_RSA_PKCS_PSS |
5553 | | * CKK_DSA => CKM_DSA_SHA256 |
5554 | | * CKK_EC => CKM_ECDSA_SHA256 |
5555 | | * CKK_ML_DSA => CKM_ML_DSA |
5556 | | * others => CKM_INVALID_MECHANISM |
5557 | | * |
5558 | | * None of these mechanisms has a parameter. |
5559 | | * |
5560 | | * For derive CKK_DH => CKM_DH_PKCS_DERIVE |
5561 | | * CKK_EC => CKM_ECDH1_DERIVE |
5562 | | * CKK_EC_MONTGOMERY => CKM_ECDH1_DERIVE |
5563 | | * others => CKM_INVALID_MECHANISM |
5564 | | * |
5565 | | * For KEM mechanisms: |
5566 | | * CKK_NSS_KYBER => don't |
5567 | | * CKK_NSS_ML_KEM => don't |
5568 | | * CKK_ML_KEM => CM_ML_KEM |
5569 | | * |
5570 | | * The parameters for these mechanisms is the public key. |
5571 | | */ |
5572 | 29.7k | CK_MECHANISM mech = { 0, NULL, 0 }; |
5573 | | |
5574 | 29.7k | CK_ULONG modulusLen = 0; |
5575 | 29.7k | #ifndef NSS_DISABLE_DSA |
5576 | 29.7k | CK_ULONG subPrimeLen = 0; |
5577 | 29.7k | #endif |
5578 | 29.7k | PRBool isEncryptable = PR_FALSE; |
5579 | 29.7k | PRBool canSignVerify = PR_FALSE; |
5580 | 29.7k | PRBool isDerivable = PR_FALSE; |
5581 | 29.7k | PRBool isKEM = PR_FALSE; |
5582 | 29.7k | CK_RV crv; |
5583 | | |
5584 | | /* Variables used for Encrypt/Decrypt functions. */ |
5585 | 29.7k | unsigned char *known_message = (unsigned char *)"Known Crypto Message"; |
5586 | 29.7k | unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH]; |
5587 | 29.7k | CK_ULONG bytes_decrypted; |
5588 | 29.7k | unsigned char *ciphertext; |
5589 | 29.7k | unsigned char *text_compared; |
5590 | 29.7k | CK_ULONG bytes_encrypted; |
5591 | 29.7k | CK_ULONG bytes_compared; |
5592 | | |
5593 | | /* Variables used for Signature/Verification functions. */ |
5594 | 29.7k | unsigned char *signature; |
5595 | 29.7k | CK_ULONG signature_length; |
5596 | 29.7k | SFTKAttribute *attribute; |
5597 | | |
5598 | 29.7k | switch (keyType) { |
5599 | 0 | case CKK_RSA: |
5600 | | /* Get modulus length of private key. */ |
5601 | 0 | attribute = sftk_FindAttribute(privateKey, CKA_MODULUS); |
5602 | 0 | if (attribute == NULL) { |
5603 | 0 | return CKR_DEVICE_ERROR; |
5604 | 0 | } |
5605 | 0 | modulusLen = attribute->attrib.ulValueLen; |
5606 | 0 | if (*(unsigned char *)attribute->attrib.pValue == 0) { |
5607 | 0 | modulusLen--; |
5608 | 0 | } |
5609 | 0 | sftk_FreeAttribute(attribute); |
5610 | 0 | #if RSA_MIN_MODULUS_BITS < 1023 |
5611 | | /* if we allow weak RSA keys, and this is a weak RSA key and |
5612 | | * we aren't in FIPS mode, skip the tests, These keys are |
5613 | | * factorable anyway, the pairwise test doen't matter. */ |
5614 | 0 | if ((modulusLen < 1023) && !sftk_isFIPS(slot->slotID)) { |
5615 | 0 | return CKR_OK; |
5616 | 0 | } |
5617 | 0 | #endif |
5618 | 0 | break; |
5619 | 0 | #ifndef NSS_DISABLE_DSA |
5620 | 0 | case CKK_DSA: |
5621 | | /* Get subprime length of private key. */ |
5622 | 0 | attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME); |
5623 | 0 | if (attribute == NULL) { |
5624 | 0 | return CKR_DEVICE_ERROR; |
5625 | 0 | } |
5626 | 0 | subPrimeLen = attribute->attrib.ulValueLen; |
5627 | 0 | if (subPrimeLen > 1 && |
5628 | 0 | *(unsigned char *)attribute->attrib.pValue == 0) { |
5629 | 0 | subPrimeLen--; |
5630 | 0 | } |
5631 | 0 | sftk_FreeAttribute(attribute); |
5632 | 0 | break; |
5633 | 0 | #endif |
5634 | 0 | case CKK_NSS_KYBER: |
5635 | 13.7k | case CKK_NSS_ML_KEM: |
5636 | | /* these aren't FIPS. we use them to generate keys without a |
5637 | | * pairwise consistency check */ |
5638 | 13.7k | return CKR_OK; |
5639 | 29.7k | } |
5640 | | |
5641 | | /**************************************************/ |
5642 | | /* Pairwise Consistency Check of Encrypt/Decrypt. */ |
5643 | | /**************************************************/ |
5644 | | |
5645 | 15.9k | isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT); |
5646 | | |
5647 | | /* |
5648 | | * If the decryption attribute is set, attempt to encrypt |
5649 | | * with the public key and decrypt with the private key. |
5650 | | */ |
5651 | 15.9k | if (isEncryptable) { |
5652 | 0 | if (keyType != CKK_RSA) { |
5653 | 0 | return CKR_DEVICE_ERROR; |
5654 | 0 | } |
5655 | 0 | bytes_encrypted = modulusLen; |
5656 | 0 | mech.mechanism = CKM_RSA_PKCS_OAEP; |
5657 | 0 | CK_RSA_PKCS_OAEP_PARAMS oaepParams; |
5658 | 0 | oaepParams.hashAlg = CKM_SHA256; |
5659 | 0 | oaepParams.mgf = CKG_MGF1_SHA256; |
5660 | 0 | oaepParams.source = CKZ_DATA_SPECIFIED; |
5661 | 0 | oaepParams.pSourceData = NULL; |
5662 | 0 | oaepParams.ulSourceDataLen = 0; |
5663 | 0 | mech.pParameter = &oaepParams; |
5664 | 0 | mech.ulParameterLen = sizeof(oaepParams); |
5665 | | |
5666 | | /* Allocate space for ciphertext. */ |
5667 | 0 | ciphertext = (unsigned char *)PORT_ZAlloc(bytes_encrypted); |
5668 | 0 | if (ciphertext == NULL) { |
5669 | 0 | return CKR_HOST_MEMORY; |
5670 | 0 | } |
5671 | | |
5672 | | /* Prepare for encryption using the public key. */ |
5673 | 0 | crv = NSC_EncryptInit(hSession, &mech, publicKey->handle); |
5674 | 0 | if (crv != CKR_OK) { |
5675 | 0 | PORT_Free(ciphertext); |
5676 | 0 | return crv; |
5677 | 0 | } |
5678 | | |
5679 | | /* Encrypt using the public key. */ |
5680 | 0 | crv = NSC_Encrypt(hSession, |
5681 | 0 | known_message, |
5682 | 0 | PAIRWISE_MESSAGE_LENGTH, |
5683 | 0 | ciphertext, |
5684 | 0 | &bytes_encrypted); |
5685 | 0 | if (crv != CKR_OK) { |
5686 | 0 | PORT_Free(ciphertext); |
5687 | 0 | return crv; |
5688 | 0 | } |
5689 | | |
5690 | | /* Always use the smaller of these two values . . . */ |
5691 | 0 | bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH); |
5692 | | |
5693 | | /* |
5694 | | * If there was a failure, the plaintext |
5695 | | * goes at the end, therefore . . . |
5696 | | */ |
5697 | 0 | text_compared = ciphertext + bytes_encrypted - bytes_compared; |
5698 | | |
5699 | | /* |
5700 | | * Check to ensure that ciphertext does |
5701 | | * NOT EQUAL known input message text |
5702 | | * per FIPS PUB 140-2 directive. |
5703 | | */ |
5704 | 0 | if (PORT_Memcmp(text_compared, known_message, |
5705 | 0 | bytes_compared) == 0) { |
5706 | | /* Set error to Invalid PRIVATE Key. */ |
5707 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
5708 | 0 | PORT_Free(ciphertext); |
5709 | 0 | return CKR_GENERAL_ERROR; |
5710 | 0 | } |
5711 | | |
5712 | | /* Prepare for decryption using the private key. */ |
5713 | 0 | crv = NSC_DecryptInit(hSession, &mech, privateKey->handle); |
5714 | 0 | if (crv != CKR_OK) { |
5715 | 0 | PORT_Free(ciphertext); |
5716 | 0 | return crv; |
5717 | 0 | } |
5718 | | |
5719 | 0 | memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH); |
5720 | | |
5721 | | /* |
5722 | | * Initialize bytes decrypted to be the |
5723 | | * expected PAIRWISE_MESSAGE_LENGTH. |
5724 | | */ |
5725 | 0 | bytes_decrypted = PAIRWISE_MESSAGE_LENGTH; |
5726 | | |
5727 | | /* |
5728 | | * Decrypt using the private key. |
5729 | | * NOTE: No need to reset the |
5730 | | * value of bytes_encrypted. |
5731 | | */ |
5732 | 0 | crv = NSC_Decrypt(hSession, |
5733 | 0 | ciphertext, |
5734 | 0 | bytes_encrypted, |
5735 | 0 | plaintext, |
5736 | 0 | &bytes_decrypted); |
5737 | | |
5738 | | /* Finished with ciphertext; free it. */ |
5739 | 0 | PORT_Free(ciphertext); |
5740 | |
|
5741 | 0 | if (crv != CKR_OK) { |
5742 | 0 | return crv; |
5743 | 0 | } |
5744 | | |
5745 | | /* |
5746 | | * Check to ensure that the output plaintext |
5747 | | * does EQUAL known input message text. |
5748 | | */ |
5749 | 0 | if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) || |
5750 | 0 | (PORT_Memcmp(plaintext, known_message, |
5751 | 0 | PAIRWISE_MESSAGE_LENGTH) != 0)) { |
5752 | | /* Set error to Bad PUBLIC Key. */ |
5753 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); |
5754 | 0 | return CKR_GENERAL_ERROR; |
5755 | 0 | } |
5756 | 0 | } |
5757 | | |
5758 | | /**********************************************/ |
5759 | | /* Pairwise Consistency Check of Sign/Verify. */ |
5760 | | /**********************************************/ |
5761 | | |
5762 | 15.9k | canSignVerify = sftk_isTrue(privateKey, CKA_SIGN); |
5763 | | /* Unfortunately CKA_SIGN is always true in lg dbs. We have to check the |
5764 | | * actual curve to determine if we can do sign/verify. */ |
5765 | 15.9k | if (canSignVerify && keyType == CKK_EC) { |
5766 | 3.33k | NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(privateKey, CKK_EC, &crv); |
5767 | 3.33k | if (privKey && privKey->u.ec.ecParams.name == ECCurve25519) { |
5768 | 3.33k | canSignVerify = PR_FALSE; |
5769 | 3.33k | } |
5770 | 3.33k | } |
5771 | | |
5772 | 15.9k | if (canSignVerify) { |
5773 | 0 | CK_RSA_PKCS_PSS_PARAMS pssParams; |
5774 | | /* Determine length of signature. */ |
5775 | 0 | switch (keyType) { |
5776 | 0 | case CKK_RSA: |
5777 | 0 | signature_length = modulusLen; |
5778 | 0 | mech.mechanism = CKM_SHA256_RSA_PKCS_PSS; |
5779 | 0 | pssParams.hashAlg = CKM_SHA256; |
5780 | 0 | pssParams.mgf = CKG_MGF1_SHA256; |
5781 | 0 | pssParams.sLen = 0; |
5782 | 0 | mech.pParameter = &pssParams; |
5783 | 0 | mech.ulParameterLen = sizeof(pssParams); |
5784 | 0 | break; |
5785 | 0 | #ifndef NSS_DISABLE_DSA |
5786 | 0 | case CKK_DSA: |
5787 | 0 | signature_length = DSA_MAX_SIGNATURE_LEN; |
5788 | 0 | mech.mechanism = CKM_DSA_SHA256; |
5789 | 0 | break; |
5790 | 0 | #endif |
5791 | 0 | case CKK_EC: |
5792 | 0 | signature_length = MAX_ECKEY_LEN * 2; |
5793 | 0 | mech.mechanism = CKM_ECDSA_SHA256; |
5794 | 0 | break; |
5795 | 0 | case CKK_ML_DSA: |
5796 | 0 | signature_length = MAX_ML_DSA_SIGNATURE_LEN; |
5797 | 0 | mech.mechanism = CKM_ML_DSA; |
5798 | 0 | break; |
5799 | 0 | case CKK_EC_EDWARDS: |
5800 | 0 | signature_length = ED25519_SIGN_LEN; |
5801 | 0 | mech.mechanism = CKM_EDDSA; |
5802 | 0 | break; |
5803 | 0 | default: |
5804 | 0 | return CKR_DEVICE_ERROR; |
5805 | 0 | } |
5806 | | |
5807 | | /* Allocate space for signature data. */ |
5808 | 0 | signature = (unsigned char *)PORT_ZAlloc(signature_length); |
5809 | 0 | if (signature == NULL) { |
5810 | 0 | return CKR_HOST_MEMORY; |
5811 | 0 | } |
5812 | | |
5813 | | /* Sign the known hash using the private key. */ |
5814 | 0 | crv = NSC_SignInit(hSession, &mech, privateKey->handle); |
5815 | 0 | if (crv != CKR_OK) { |
5816 | 0 | PORT_Free(signature); |
5817 | 0 | return crv; |
5818 | 0 | } |
5819 | | |
5820 | 0 | crv = NSC_Sign(hSession, |
5821 | 0 | known_message, |
5822 | 0 | PAIRWISE_MESSAGE_LENGTH, |
5823 | 0 | signature, |
5824 | 0 | &signature_length); |
5825 | 0 | if (crv != CKR_OK) { |
5826 | 0 | PORT_Free(signature); |
5827 | 0 | return crv; |
5828 | 0 | } |
5829 | | |
5830 | | /* detect trivial signing transforms */ |
5831 | 0 | if ((signature_length >= PAIRWISE_MESSAGE_LENGTH) && |
5832 | 0 | (PORT_Memcmp(known_message, signature + (signature_length - PAIRWISE_MESSAGE_LENGTH), PAIRWISE_MESSAGE_LENGTH) == 0)) { |
5833 | 0 | PORT_Free(signature); |
5834 | 0 | return CKR_GENERAL_ERROR; |
5835 | 0 | } |
5836 | | |
5837 | | /* Verify the known hash using the public key. */ |
5838 | 0 | crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); |
5839 | 0 | if (crv != CKR_OK) { |
5840 | 0 | PORT_Free(signature); |
5841 | 0 | return crv; |
5842 | 0 | } |
5843 | | |
5844 | 0 | crv = NSC_Verify(hSession, |
5845 | 0 | known_message, |
5846 | 0 | PAIRWISE_MESSAGE_LENGTH, |
5847 | 0 | signature, |
5848 | 0 | signature_length); |
5849 | | |
5850 | | /* Free signature data. */ |
5851 | 0 | PORT_Free(signature); |
5852 | |
|
5853 | 0 | if ((crv == CKR_SIGNATURE_LEN_RANGE) || |
5854 | 0 | (crv == CKR_SIGNATURE_INVALID)) { |
5855 | 0 | return CKR_GENERAL_ERROR; |
5856 | 0 | } |
5857 | 0 | if (crv != CKR_OK) { |
5858 | 0 | return crv; |
5859 | 0 | } |
5860 | 0 | } |
5861 | | |
5862 | | /**********************************************/ |
5863 | | /* Pairwise Consistency Check for Derivation */ |
5864 | | /**********************************************/ |
5865 | | |
5866 | 15.9k | isDerivable = sftk_isTrue(privateKey, CKA_DERIVE); |
5867 | | |
5868 | 15.9k | if (isDerivable) { |
5869 | 15.9k | SFTKAttribute *pubAttribute = NULL; |
5870 | 15.9k | PRBool isFIPS = sftk_isFIPS(slot->slotID); |
5871 | 15.9k | NSSLOWKEYPrivateKey *lowPrivKey = NULL; |
5872 | 15.9k | ECPrivateKey *ecPriv = NULL; |
5873 | 15.9k | SECItem *lowPubValue = NULL; |
5874 | 15.9k | SECItem item = { siBuffer, NULL, 0 }; |
5875 | 15.9k | SECStatus rv; |
5876 | | |
5877 | 15.9k | crv = CKR_OK; /*paranoia, already get's set before we drop to the end */ |
5878 | | |
5879 | | /* FIPS 140-3 requires we verify that the resulting key is a valid key |
5880 | | * by recalculating the public can an compare it to our own public |
5881 | | * key. */ |
5882 | 15.9k | lowPrivKey = sftk_GetPrivKey(privateKey, keyType, &crv); |
5883 | 15.9k | if (lowPrivKey == NULL) { |
5884 | 0 | return sftk_MapCryptError(PORT_GetError()); |
5885 | 0 | } |
5886 | | /* recalculate the public key from the private key */ |
5887 | 15.9k | switch (keyType) { |
5888 | 7.44k | case CKK_DH: |
5889 | 7.44k | rv = DH_Derive(&lowPrivKey->u.dh.base, &lowPrivKey->u.dh.prime, |
5890 | 7.44k | &lowPrivKey->u.dh.privateValue, &item, 0); |
5891 | 7.44k | if (rv != SECSuccess) { |
5892 | 0 | return CKR_GENERAL_ERROR; |
5893 | 0 | } |
5894 | 7.44k | lowPubValue = SECITEM_DupItem(&item); |
5895 | 7.44k | SECITEM_ZfreeItem(&item, PR_FALSE); |
5896 | 7.44k | pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE); |
5897 | 7.44k | break; |
5898 | 0 | case CKK_EC_MONTGOMERY: |
5899 | 8.51k | case CKK_EC: |
5900 | 8.51k | rv = EC_NewKeyFromSeed(&lowPrivKey->u.ec.ecParams, &ecPriv, |
5901 | 8.51k | lowPrivKey->u.ec.privateValue.data, |
5902 | 8.51k | lowPrivKey->u.ec.privateValue.len); |
5903 | 8.51k | if (rv != SECSuccess) { |
5904 | 0 | return CKR_GENERAL_ERROR; |
5905 | 0 | } |
5906 | | /* make sure it has the same encoding */ |
5907 | 8.51k | if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") || |
5908 | 8.51k | lowPrivKey->u.ec.ecParams.type != ec_params_named) { |
5909 | 3.33k | lowPubValue = SECITEM_DupItem(&ecPriv->publicValue); |
5910 | 5.18k | } else { |
5911 | 5.18k | lowPubValue = SEC_ASN1EncodeItem(NULL, NULL, &ecPriv->publicValue, |
5912 | 5.18k | SEC_ASN1_GET(SEC_OctetStringTemplate)); |
5913 | 5.18k | } |
5914 | 8.51k | pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT); |
5915 | | /* clear out our generated private key */ |
5916 | 8.51k | PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); |
5917 | 8.51k | break; |
5918 | 0 | default: |
5919 | 0 | return CKR_DEVICE_ERROR; |
5920 | 15.9k | } |
5921 | | |
5922 | | /* now compare new public key with our already generated key */ |
5923 | 15.9k | if ((pubAttribute == NULL) || (lowPubValue == NULL) || |
5924 | 15.9k | (pubAttribute->attrib.ulValueLen != lowPubValue->len) || |
5925 | 15.9k | (PORT_Memcmp(pubAttribute->attrib.pValue, lowPubValue->data, |
5926 | 15.9k | lowPubValue->len) != 0)) { |
5927 | 0 | if (pubAttribute) |
5928 | 0 | sftk_FreeAttribute(pubAttribute); |
5929 | 0 | if (lowPubValue) |
5930 | 0 | SECITEM_ZfreeItem(lowPubValue, PR_TRUE); |
5931 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); |
5932 | 0 | return CKR_GENERAL_ERROR; |
5933 | 0 | } |
5934 | 15.9k | SECITEM_ZfreeItem(lowPubValue, PR_TRUE); |
5935 | | |
5936 | | /* FIPS requires full validation, but in fipx mode NSC_Derive |
5937 | | * only does partial validation with approved primes, now handle |
5938 | | * full validation */ |
5939 | 15.9k | if (isFIPS && keyType == CKK_DH) { |
5940 | 0 | SECItem pubKey = { siBuffer, pubAttribute->attrib.pValue, |
5941 | 0 | pubAttribute->attrib.ulValueLen }; |
5942 | 0 | SECItem base = { siBuffer, NULL, 0 }; |
5943 | 0 | SECItem prime = { siBuffer, NULL, 0 }; |
5944 | 0 | SECItem subPrime = { siBuffer, NULL, 0 }; |
5945 | 0 | SECItem generator = { siBuffer, NULL, 0 }; |
5946 | 0 | const SECItem *subPrimePtr = &subPrime; |
5947 | |
|
5948 | 0 | crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME); |
5949 | 0 | if (crv != CKR_OK) { |
5950 | 0 | goto done; |
5951 | 0 | } |
5952 | 0 | crv = sftk_Attribute2SecItem(NULL, &base, privateKey, CKA_BASE); |
5953 | 0 | if (crv != CKR_OK) { |
5954 | 0 | goto done; |
5955 | 0 | } |
5956 | | /* we ignore the return code an only look at the length */ |
5957 | | /* do we have a known prime ? */ |
5958 | 0 | subPrimePtr = sftk_VerifyDH_Prime(&prime, &generator, isFIPS); |
5959 | 0 | if (subPrimePtr == NULL) { |
5960 | 0 | if (subPrime.len == 0) { |
5961 | | /* if not a known prime, subprime must be supplied */ |
5962 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5963 | 0 | goto done; |
5964 | 0 | } else { |
5965 | | /* not a known prime, check for primality of prime |
5966 | | * and subPrime */ |
5967 | 0 | if (!KEA_PrimeCheck(&prime)) { |
5968 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5969 | 0 | goto done; |
5970 | 0 | } |
5971 | 0 | if (!KEA_PrimeCheck(&subPrime)) { |
5972 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5973 | 0 | goto done; |
5974 | 0 | } |
5975 | | /* if we aren't using a defined group, make sure base is in the |
5976 | | * subgroup. If it's not, then our key could fail or succeed sometimes. |
5977 | | * This makes the failure reliable */ |
5978 | 0 | if (!KEA_Verify(&base, &prime, &subPrime)) { |
5979 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5980 | 0 | } |
5981 | 0 | } |
5982 | 0 | subPrimePtr = &subPrime; |
5983 | 0 | } else { |
5984 | | /* we're using a known group, make sure we are using the known generator for that group */ |
5985 | 0 | if (SECITEM_CompareItem(&generator, &base) != 0) { |
5986 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5987 | 0 | goto done; |
5988 | 0 | } |
5989 | 0 | if (subPrime.len != 0) { |
5990 | | /* we have a known prime and a supplied subPrime, |
5991 | | * make sure the subPrime matches the subPrime for |
5992 | | * the known Prime */ |
5993 | 0 | if (SECITEM_CompareItem(subPrimePtr, &subPrime) != 0) { |
5994 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5995 | 0 | goto done; |
5996 | 0 | } |
5997 | 0 | } |
5998 | 0 | } |
5999 | 0 | if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) { |
6000 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
6001 | 0 | } |
6002 | 0 | done: |
6003 | 0 | SECITEM_ZfreeItem(&base, PR_FALSE); |
6004 | 0 | SECITEM_ZfreeItem(&subPrime, PR_FALSE); |
6005 | 0 | SECITEM_ZfreeItem(&prime, PR_FALSE); |
6006 | 0 | } |
6007 | | /* clean up before we return */ |
6008 | 15.9k | sftk_FreeAttribute(pubAttribute); |
6009 | 15.9k | if (crv != CKR_OK) { |
6010 | 0 | return crv; |
6011 | 0 | } |
6012 | 15.9k | } |
6013 | | |
6014 | 15.9k | isKEM = sftk_isTrue(privateKey, CKA_DECAPSULATE); |
6015 | 15.9k | if (isKEM) { |
6016 | 0 | unsigned char *cipher_text = NULL; |
6017 | 0 | CK_ULONG cipher_text_length = 0; |
6018 | 0 | CK_OBJECT_HANDLE key1 = CK_INVALID_HANDLE; |
6019 | 0 | CK_OBJECT_HANDLE key2 = CK_INVALID_HANDLE; |
6020 | 0 | CK_KEY_TYPE genClass = CKO_SECRET_KEY; |
6021 | 0 | CK_ATTRIBUTE template = { CKA_CLASS, NULL, 0 }; |
6022 | |
|
6023 | 0 | template.pValue = &genClass; |
6024 | 0 | template.ulValueLen = sizeof(genClass); |
6025 | 0 | crv = CKR_OK; |
6026 | 0 | switch (keyType) { |
6027 | 0 | case CKK_ML_KEM: |
6028 | 0 | cipher_text_length = MAX_ML_KEM_CIPHER_LENGTH; |
6029 | 0 | mech.mechanism = CKM_ML_KEM; |
6030 | 0 | break; |
6031 | 0 | default: |
6032 | 0 | return CKR_DEVICE_ERROR; |
6033 | 0 | } |
6034 | | /* Allocate space for kem cipher text. */ |
6035 | 0 | cipher_text = (unsigned char *)PORT_ZAlloc(cipher_text_length); |
6036 | 0 | if (cipher_text == NULL) { |
6037 | 0 | return CKR_HOST_MEMORY; |
6038 | 0 | } |
6039 | 0 | crv = NSC_Encapsulate(hSession, &mech, publicKey->handle, &template, 1, |
6040 | 0 | &key1, cipher_text, &cipher_text_length); |
6041 | 0 | if (crv != CKR_OK) { |
6042 | 0 | goto kem_done; |
6043 | 0 | } |
6044 | 0 | crv = NSC_Decapsulate(hSession, &mech, privateKey->handle, |
6045 | 0 | cipher_text, cipher_text_length, &template, 1, |
6046 | 0 | &key2); |
6047 | 0 | if (crv != CKR_OK) { |
6048 | 0 | goto kem_done; |
6049 | 0 | } |
6050 | 0 | if (!sftk_compareKeysEqual(hSession, key1, key2)) { |
6051 | 0 | crv = CKR_GENERAL_ERROR; |
6052 | 0 | goto kem_done; |
6053 | 0 | } |
6054 | 0 | kem_done: |
6055 | | /* PORT_Free already checks for NULL */ |
6056 | 0 | PORT_Free(cipher_text); |
6057 | 0 | if (key1 != CK_INVALID_HANDLE) { |
6058 | 0 | NSC_DestroyObject(hSession, key1); |
6059 | 0 | } |
6060 | 0 | if (key2 != CK_INVALID_HANDLE) { |
6061 | 0 | NSC_DestroyObject(hSession, key2); |
6062 | 0 | } |
6063 | 0 | if (crv != CKR_OK) { |
6064 | 0 | return crv; |
6065 | 0 | } |
6066 | 0 | } |
6067 | | |
6068 | 15.9k | return CKR_OK; |
6069 | 15.9k | } |
6070 | | |
6071 | | /* NSC_GenerateKeyPair generates a public-key/private-key pair, |
6072 | | * creating new key objects. */ |
6073 | | CK_RV |
6074 | | NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession, |
6075 | | CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, |
6076 | | CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, |
6077 | | CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, |
6078 | | CK_OBJECT_HANDLE_PTR phPrivateKey) |
6079 | 106k | { |
6080 | 106k | SFTKObject *publicKey, *privateKey; |
6081 | 106k | SFTKSession *session; |
6082 | 106k | CK_KEY_TYPE key_type; |
6083 | 106k | CK_RV crv = CKR_OK; |
6084 | 106k | CK_BBOOL cktrue = CK_TRUE; |
6085 | 106k | SECStatus rv; |
6086 | 106k | CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; |
6087 | 106k | CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; |
6088 | 106k | int i; |
6089 | 106k | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
6090 | 106k | unsigned int bitSize; |
6091 | | |
6092 | | /* RSA */ |
6093 | 106k | int public_modulus_bits = 0; |
6094 | 106k | SECItem pubExp; |
6095 | 106k | RSAPrivateKey *rsaPriv; |
6096 | | |
6097 | 106k | DHParams dhParam; |
6098 | 106k | #ifndef NSS_DISABLE_DSA |
6099 | | /* DSA */ |
6100 | 106k | PQGParams pqgParam; |
6101 | 106k | DSAPrivateKey *dsaPriv; |
6102 | 106k | #endif |
6103 | 106k | MLDSAPrivateKey mldsaPriv; |
6104 | 106k | MLDSAPublicKey mldsaPub; |
6105 | | |
6106 | | /* Diffie Hellman */ |
6107 | 106k | DHPrivateKey *dhPriv; |
6108 | | |
6109 | | /* Elliptic Curve Cryptography */ |
6110 | 106k | SECItem ecEncodedParams; /* DER Encoded parameters */ |
6111 | 106k | ECPrivateKey *ecPriv; |
6112 | 106k | ECParams *ecParams; |
6113 | | |
6114 | | /* parameter set, mostly pq keys */ |
6115 | 106k | CK_ULONG genParamSet = 0; |
6116 | | |
6117 | 106k | CHECK_FORK(); |
6118 | | |
6119 | 106k | if (!slot) { |
6120 | 0 | return CKR_SESSION_HANDLE_INVALID; |
6121 | 0 | } |
6122 | | /* |
6123 | | * now lets create an object to hang the attributes off of |
6124 | | */ |
6125 | 106k | publicKey = sftk_NewObject(slot); /* fill in the handle later */ |
6126 | 106k | if (publicKey == NULL) { |
6127 | 0 | return CKR_HOST_MEMORY; |
6128 | 0 | } |
6129 | | |
6130 | | /* |
6131 | | * load the template values into the publicKey |
6132 | | */ |
6133 | 870k | for (i = 0; i < (int)ulPublicKeyAttributeCount; i++) { |
6134 | 764k | if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) { |
6135 | 0 | public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue; |
6136 | 0 | continue; |
6137 | 0 | } |
6138 | | |
6139 | 764k | if ((pPublicKeyTemplate[i].type == CKA_PARAMETER_SET) || |
6140 | 750k | (pPublicKeyTemplate[i].type == CKA_NSS_PARAMETER_SET)) { |
6141 | 13.7k | genParamSet = *(CK_ULONG *)pPublicKeyTemplate[i].pValue; |
6142 | 13.7k | continue; |
6143 | 13.7k | } |
6144 | | |
6145 | 750k | crv = sftk_AddAttributeType(publicKey, |
6146 | 750k | sftk_attr_expand(&pPublicKeyTemplate[i])); |
6147 | 750k | if (crv != CKR_OK) |
6148 | 0 | break; |
6149 | 750k | } |
6150 | | |
6151 | 106k | if (crv != CKR_OK) { |
6152 | 0 | sftk_FreeObject(publicKey); |
6153 | 0 | return CKR_HOST_MEMORY; |
6154 | 0 | } |
6155 | | |
6156 | 106k | privateKey = sftk_NewObject(slot); /* fill in the handle later */ |
6157 | 106k | if (privateKey == NULL) { |
6158 | 0 | sftk_FreeObject(publicKey); |
6159 | 0 | return CKR_HOST_MEMORY; |
6160 | 0 | } |
6161 | | /* |
6162 | | * now load the private key template |
6163 | | */ |
6164 | 862k | for (i = 0; i < (int)ulPrivateKeyAttributeCount; i++) { |
6165 | 756k | if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) { |
6166 | 0 | continue; |
6167 | 0 | } |
6168 | | |
6169 | 756k | crv = sftk_AddAttributeType(privateKey, |
6170 | 756k | sftk_attr_expand(&pPrivateKeyTemplate[i])); |
6171 | 756k | if (crv != CKR_OK) |
6172 | 0 | break; |
6173 | 756k | } |
6174 | | |
6175 | 106k | if (crv != CKR_OK) { |
6176 | 0 | sftk_FreeObject(publicKey); |
6177 | 0 | sftk_FreeObject(privateKey); |
6178 | 0 | return CKR_HOST_MEMORY; |
6179 | 0 | } |
6180 | 106k | sftk_DeleteAttributeType(privateKey, CKA_CLASS); |
6181 | 106k | sftk_DeleteAttributeType(privateKey, CKA_KEY_TYPE); |
6182 | 106k | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
6183 | 106k | sftk_DeleteAttributeType(publicKey, CKA_CLASS); |
6184 | 106k | sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE); |
6185 | 106k | sftk_DeleteAttributeType(publicKey, CKA_VALUE); |
6186 | | |
6187 | | /* Now Set up the parameters to generate the key (based on mechanism) */ |
6188 | 106k | switch (pMechanism->mechanism) { |
6189 | 0 | case CKM_RSA_PKCS_KEY_PAIR_GEN: |
6190 | | /* format the keys */ |
6191 | 0 | sftk_DeleteAttributeType(publicKey, CKA_MODULUS); |
6192 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6193 | 0 | sftk_DeleteAttributeType(privateKey, CKA_MODULUS); |
6194 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIVATE_EXPONENT); |
6195 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PUBLIC_EXPONENT); |
6196 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME_1); |
6197 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME_2); |
6198 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_1); |
6199 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_2); |
6200 | 0 | sftk_DeleteAttributeType(privateKey, CKA_COEFFICIENT); |
6201 | 0 | key_type = CKK_RSA; |
6202 | 0 | if (public_modulus_bits == 0) { |
6203 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6204 | 0 | break; |
6205 | 0 | } |
6206 | 0 | if (public_modulus_bits < RSA_MIN_MODULUS_BITS) { |
6207 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
6208 | 0 | break; |
6209 | 0 | } |
6210 | 0 | if (public_modulus_bits % 2 != 0) { |
6211 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
6212 | 0 | break; |
6213 | 0 | } |
6214 | | |
6215 | | /* extract the exponent */ |
6216 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pubExp, publicKey, CKA_PUBLIC_EXPONENT); |
6217 | 0 | if (crv != CKR_OK) |
6218 | 0 | break; |
6219 | 0 | bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len); |
6220 | 0 | if (bitSize < 2) { |
6221 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
6222 | 0 | SECITEM_ZfreeItem(&pubExp, PR_FALSE); |
6223 | 0 | break; |
6224 | 0 | } |
6225 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PUBLIC_EXPONENT, |
6226 | 0 | sftk_item_expand(&pubExp)); |
6227 | 0 | if (crv != CKR_OK) { |
6228 | 0 | SECITEM_ZfreeItem(&pubExp, PR_FALSE); |
6229 | 0 | break; |
6230 | 0 | } |
6231 | | |
6232 | 0 | rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp); |
6233 | 0 | SECITEM_ZfreeItem(&pubExp, PR_FALSE); |
6234 | 0 | if (rsaPriv == NULL) { |
6235 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
6236 | 0 | sftk_fatalError = PR_TRUE; |
6237 | 0 | } |
6238 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6239 | 0 | break; |
6240 | 0 | } |
6241 | | /* now fill in the RSA dependent paramenters in the public key */ |
6242 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_MODULUS, |
6243 | 0 | sftk_item_expand(&rsaPriv->modulus)); |
6244 | 0 | if (crv != CKR_OK) |
6245 | 0 | goto kpg_done; |
6246 | | /* now fill in the RSA dependent paramenters in the private key */ |
6247 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6248 | 0 | sftk_item_expand(&rsaPriv->modulus)); |
6249 | 0 | if (crv != CKR_OK) |
6250 | 0 | goto kpg_done; |
6251 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_MODULUS, |
6252 | 0 | sftk_item_expand(&rsaPriv->modulus)); |
6253 | 0 | if (crv != CKR_OK) |
6254 | 0 | goto kpg_done; |
6255 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIVATE_EXPONENT, |
6256 | 0 | sftk_item_expand(&rsaPriv->privateExponent)); |
6257 | 0 | if (crv != CKR_OK) |
6258 | 0 | goto kpg_done; |
6259 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME_1, |
6260 | 0 | sftk_item_expand(&rsaPriv->prime1)); |
6261 | 0 | if (crv != CKR_OK) |
6262 | 0 | goto kpg_done; |
6263 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME_2, |
6264 | 0 | sftk_item_expand(&rsaPriv->prime2)); |
6265 | 0 | if (crv != CKR_OK) |
6266 | 0 | goto kpg_done; |
6267 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_1, |
6268 | 0 | sftk_item_expand(&rsaPriv->exponent1)); |
6269 | 0 | if (crv != CKR_OK) |
6270 | 0 | goto kpg_done; |
6271 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_2, |
6272 | 0 | sftk_item_expand(&rsaPriv->exponent2)); |
6273 | 0 | if (crv != CKR_OK) |
6274 | 0 | goto kpg_done; |
6275 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_COEFFICIENT, |
6276 | 0 | sftk_item_expand(&rsaPriv->coefficient)); |
6277 | 0 | kpg_done: |
6278 | | /* Should zeroize the contents first, since this func doesn't. */ |
6279 | 0 | PORT_FreeArena(rsaPriv->arena, PR_TRUE); |
6280 | 0 | break; |
6281 | 0 | #ifndef NSS_DISABLE_DSA |
6282 | 0 | case CKM_DSA_KEY_PAIR_GEN: |
6283 | 0 | sftk_DeleteAttributeType(publicKey, CKA_VALUE); |
6284 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6285 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME); |
6286 | 0 | sftk_DeleteAttributeType(privateKey, CKA_SUBPRIME); |
6287 | 0 | sftk_DeleteAttributeType(privateKey, CKA_BASE); |
6288 | 0 | key_type = CKK_DSA; |
6289 | | |
6290 | | /* extract the necessary parameters and copy them to the private key */ |
6291 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pqgParam.prime, publicKey, CKA_PRIME); |
6292 | 0 | if (crv != CKR_OK) |
6293 | 0 | break; |
6294 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pqgParam.subPrime, publicKey, |
6295 | 0 | CKA_SUBPRIME); |
6296 | 0 | if (crv != CKR_OK) { |
6297 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6298 | 0 | break; |
6299 | 0 | } |
6300 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pqgParam.base, publicKey, CKA_BASE); |
6301 | 0 | if (crv != CKR_OK) { |
6302 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6303 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6304 | 0 | break; |
6305 | 0 | } |
6306 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME, |
6307 | 0 | sftk_item_expand(&pqgParam.prime)); |
6308 | 0 | if (crv != CKR_OK) { |
6309 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6310 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6311 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6312 | 0 | break; |
6313 | 0 | } |
6314 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_SUBPRIME, |
6315 | 0 | sftk_item_expand(&pqgParam.subPrime)); |
6316 | 0 | if (crv != CKR_OK) { |
6317 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6318 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6319 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6320 | 0 | break; |
6321 | 0 | } |
6322 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_BASE, |
6323 | 0 | sftk_item_expand(&pqgParam.base)); |
6324 | 0 | if (crv != CKR_OK) { |
6325 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6326 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6327 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6328 | 0 | break; |
6329 | 0 | } |
6330 | | |
6331 | | /* |
6332 | | * these are checked by DSA_NewKey |
6333 | | */ |
6334 | 0 | bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data, |
6335 | 0 | pqgParam.subPrime.len); |
6336 | 0 | if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) { |
6337 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6338 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6339 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6340 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6341 | 0 | break; |
6342 | 0 | } |
6343 | 0 | bitSize = sftk_GetLengthInBits(pqgParam.prime.data, pqgParam.prime.len); |
6344 | 0 | if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) { |
6345 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6346 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6347 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6348 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6349 | 0 | break; |
6350 | 0 | } |
6351 | 0 | bitSize = sftk_GetLengthInBits(pqgParam.base.data, pqgParam.base.len); |
6352 | 0 | if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) { |
6353 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6354 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6355 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6356 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6357 | 0 | break; |
6358 | 0 | } |
6359 | | |
6360 | | /* Generate the key */ |
6361 | 0 | rv = DSA_NewKey(&pqgParam, &dsaPriv); |
6362 | |
|
6363 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6364 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6365 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6366 | |
|
6367 | 0 | if (rv != SECSuccess) { |
6368 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
6369 | 0 | sftk_fatalError = PR_TRUE; |
6370 | 0 | } |
6371 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6372 | 0 | break; |
6373 | 0 | } |
6374 | | |
6375 | | /* store the generated key into the attributes */ |
6376 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, |
6377 | 0 | sftk_item_expand(&dsaPriv->publicValue)); |
6378 | 0 | if (crv != CKR_OK) |
6379 | 0 | goto dsagn_done; |
6380 | | |
6381 | | /* now fill in the RSA dependent paramenters in the private key */ |
6382 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6383 | 0 | sftk_item_expand(&dsaPriv->publicValue)); |
6384 | 0 | if (crv != CKR_OK) |
6385 | 0 | goto dsagn_done; |
6386 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
6387 | 0 | sftk_item_expand(&dsaPriv->privateValue)); |
6388 | |
|
6389 | 0 | dsagn_done: |
6390 | | /* should zeroize, since this function doesn't. */ |
6391 | 0 | PORT_FreeArena(dsaPriv->params.arena, PR_TRUE); |
6392 | 0 | break; |
6393 | 0 | #endif |
6394 | 7.92k | case CKM_DH_PKCS_KEY_PAIR_GEN: |
6395 | 7.92k | sftk_DeleteAttributeType(privateKey, CKA_PRIME); |
6396 | 7.92k | sftk_DeleteAttributeType(privateKey, CKA_BASE); |
6397 | 7.92k | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
6398 | 7.92k | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6399 | 7.92k | key_type = CKK_DH; |
6400 | | |
6401 | | /* extract the necessary parameters and copy them to private keys */ |
6402 | 7.92k | crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey, |
6403 | 7.92k | CKA_PRIME); |
6404 | 7.92k | if (crv != CKR_OK) |
6405 | 0 | break; |
6406 | 7.92k | crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE); |
6407 | 7.92k | if (crv != CKR_OK) { |
6408 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
6409 | 0 | break; |
6410 | 0 | } |
6411 | 7.92k | crv = sftk_AddAttributeType(privateKey, CKA_PRIME, |
6412 | 7.92k | sftk_item_expand(&dhParam.prime)); |
6413 | 7.92k | if (crv != CKR_OK) { |
6414 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
6415 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
6416 | 0 | break; |
6417 | 0 | } |
6418 | 7.92k | crv = sftk_AddAttributeType(privateKey, CKA_BASE, |
6419 | 7.92k | sftk_item_expand(&dhParam.base)); |
6420 | 7.92k | if (crv != CKR_OK) { |
6421 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
6422 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
6423 | 0 | break; |
6424 | 0 | } |
6425 | 7.92k | bitSize = sftk_GetLengthInBits(dhParam.prime.data, dhParam.prime.len); |
6426 | 7.92k | if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) { |
6427 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6428 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
6429 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
6430 | 0 | break; |
6431 | 0 | } |
6432 | 7.92k | bitSize = sftk_GetLengthInBits(dhParam.base.data, dhParam.base.len); |
6433 | 7.92k | if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) { |
6434 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6435 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
6436 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
6437 | 0 | break; |
6438 | 0 | } |
6439 | | |
6440 | 7.92k | rv = DH_NewKey(&dhParam, &dhPriv); |
6441 | 7.92k | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
6442 | 7.92k | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
6443 | 7.92k | if (rv != SECSuccess) { |
6444 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
6445 | 0 | sftk_fatalError = PR_TRUE; |
6446 | 0 | } |
6447 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6448 | 0 | break; |
6449 | 0 | } |
6450 | | |
6451 | 7.92k | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, |
6452 | 7.92k | sftk_item_expand(&dhPriv->publicValue)); |
6453 | 7.92k | if (crv != CKR_OK) |
6454 | 0 | goto dhgn_done; |
6455 | | |
6456 | 7.92k | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6457 | 7.92k | sftk_item_expand(&dhPriv->publicValue)); |
6458 | 7.92k | if (crv != CKR_OK) |
6459 | 0 | goto dhgn_done; |
6460 | | |
6461 | 7.92k | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
6462 | 7.92k | sftk_item_expand(&dhPriv->privateValue)); |
6463 | | |
6464 | 7.92k | dhgn_done: |
6465 | | /* should zeroize, since this function doesn't. */ |
6466 | 7.92k | PORT_FreeArena(dhPriv->arena, PR_TRUE); |
6467 | 7.92k | break; |
6468 | | |
6469 | 8.53k | case CKM_EC_KEY_PAIR_GEN: |
6470 | 84.3k | case CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN: |
6471 | 84.3k | sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS); |
6472 | 84.3k | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
6473 | 84.3k | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6474 | 84.3k | key_type = CKK_EC; |
6475 | | |
6476 | | /* extract the necessary parameters and copy them to private keys */ |
6477 | 84.3k | crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, |
6478 | 84.3k | CKA_EC_PARAMS); |
6479 | 84.3k | if (crv != CKR_OK) |
6480 | 0 | break; |
6481 | | |
6482 | 84.3k | crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS, |
6483 | 84.3k | sftk_item_expand(&ecEncodedParams)); |
6484 | 84.3k | if (crv != CKR_OK) { |
6485 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
6486 | 0 | break; |
6487 | 0 | } |
6488 | | |
6489 | | /* Decode ec params before calling EC_NewKey */ |
6490 | 84.3k | rv = EC_DecodeParams(&ecEncodedParams, &ecParams); |
6491 | 84.3k | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
6492 | 84.3k | if (rv != SECSuccess) { |
6493 | 420 | crv = sftk_MapCryptError(PORT_GetError()); |
6494 | 420 | break; |
6495 | 420 | } |
6496 | 83.9k | rv = EC_NewKey(ecParams, &ecPriv); |
6497 | 83.9k | if (rv != SECSuccess) { |
6498 | 339 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
6499 | 0 | sftk_fatalError = PR_TRUE; |
6500 | 0 | } |
6501 | 339 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
6502 | 339 | crv = sftk_MapCryptError(PORT_GetError()); |
6503 | 339 | break; |
6504 | 339 | } |
6505 | | |
6506 | 83.5k | if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") || |
6507 | 83.5k | ecParams->type != ec_params_named) { |
6508 | 19.2k | PORT_FreeArena(ecParams->arena, PR_TRUE); |
6509 | 19.2k | crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
6510 | 19.2k | sftk_item_expand(&ecPriv->publicValue)); |
6511 | 64.3k | } else { |
6512 | 64.3k | PORT_FreeArena(ecParams->arena, PR_TRUE); |
6513 | 64.3k | SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, |
6514 | 64.3k | &ecPriv->publicValue, |
6515 | 64.3k | SEC_ASN1_GET(SEC_OctetStringTemplate)); |
6516 | 64.3k | if (!pubValue) { |
6517 | 0 | crv = CKR_ARGUMENTS_BAD; |
6518 | 0 | goto ecgn_done; |
6519 | 0 | } |
6520 | 64.3k | crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
6521 | 64.3k | sftk_item_expand(pubValue)); |
6522 | 64.3k | SECITEM_ZfreeItem(pubValue, PR_TRUE); |
6523 | 64.3k | } |
6524 | 83.5k | if (crv != CKR_OK) |
6525 | 0 | goto ecgn_done; |
6526 | | |
6527 | 83.5k | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
6528 | 83.5k | sftk_item_expand(&ecPriv->privateValue)); |
6529 | 83.5k | if (crv != CKR_OK) |
6530 | 0 | goto ecgn_done; |
6531 | | |
6532 | 83.5k | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6533 | 83.5k | sftk_item_expand(&ecPriv->publicValue)); |
6534 | 83.5k | ecgn_done: |
6535 | | /* should zeroize, since this function doesn't. */ |
6536 | 83.5k | PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); |
6537 | 83.5k | break; |
6538 | | |
6539 | 0 | #ifndef NSS_DISABLE_KYBER |
6540 | 0 | case CKM_NSS_KYBER_KEY_PAIR_GEN: |
6541 | 0 | key_type = CKK_NSS_KYBER; |
6542 | 0 | goto do_ml_kem; |
6543 | 0 | #endif |
6544 | 13.7k | case CKM_NSS_ML_KEM_KEY_PAIR_GEN: |
6545 | 13.7k | key_type = CKK_NSS_ML_KEM; |
6546 | 13.7k | goto do_ml_kem; |
6547 | | |
6548 | 0 | case CKM_ML_KEM_KEY_PAIR_GEN: |
6549 | 0 | key_type = CKK_ML_KEM; |
6550 | |
|
6551 | 13.7k | do_ml_kem: |
6552 | 13.7k | sftk_DeleteAttributeType(publicKey, CKA_VALUE); |
6553 | 13.7k | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6554 | 13.7k | sftk_DeleteAttributeType(privateKey, CKA_SEED); |
6555 | 13.7k | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
6556 | 13.7k | SECItem privKey = { siBuffer, NULL, 0 }; |
6557 | 13.7k | SECItem pubKey = { siBuffer, NULL, 0 }; |
6558 | 13.7k | SECItem seed = { siBuffer, NULL, 0 }; |
6559 | 13.7k | unsigned char seedData[KYBER_KEYPAIR_COIN_BYTES]; |
6560 | | |
6561 | | /* generate the seed here so we can record it with |
6562 | | * the private key */ |
6563 | 13.7k | seed.data = seedData; |
6564 | 13.7k | seed.len = sizeof(seedData); |
6565 | 13.7k | rv = RNG_GenerateGlobalRandomBytes(seed.data, seed.len); |
6566 | 13.7k | if (rv != SECSuccess) { |
6567 | 0 | fprintf(stderr, "Generate bytes failed nbytes=%d err=%d\n", |
6568 | 0 | seed.len, PORT_GetError()); |
6569 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6570 | 0 | goto kyber_done; |
6571 | 0 | } |
6572 | | |
6573 | 13.7k | KyberParams kyberParams = sftk_kyber_PK11ParamToInternal(genParamSet); |
6574 | 13.7k | if (!sftk_kyber_AllocPrivKeyItem(kyberParams, &privKey)) { |
6575 | 0 | crv = CKR_HOST_MEMORY; |
6576 | 0 | goto kyber_done; |
6577 | 0 | } |
6578 | 13.7k | if (!sftk_kyber_AllocPubKeyItem(kyberParams, &pubKey)) { |
6579 | 0 | crv = CKR_HOST_MEMORY; |
6580 | 0 | goto kyber_done; |
6581 | 0 | } |
6582 | 13.7k | rv = Kyber_NewKey(kyberParams, &seed, &privKey, &pubKey); |
6583 | 13.7k | if (rv != SECSuccess) { |
6584 | 0 | fprintf(stderr, "Generate Kyber_NewKey failed nbytes=%d err=%d\n", |
6585 | 0 | seed.len, PORT_GetError()); |
6586 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6587 | 0 | goto kyber_done; |
6588 | 0 | } |
6589 | | |
6590 | 13.7k | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, sftk_item_expand(&pubKey)); |
6591 | 13.7k | if (crv != CKR_OK) { |
6592 | 0 | goto kyber_done; |
6593 | 0 | } |
6594 | 13.7k | crv = sftk_AddAttributeType(publicKey, CKA_PARAMETER_SET, |
6595 | 13.7k | &genParamSet, |
6596 | 13.7k | sizeof(CK_ML_KEM_PARAMETER_SET_TYPE)); |
6597 | 13.7k | if (crv != CKR_OK) { |
6598 | 0 | goto kyber_done; |
6599 | 0 | } |
6600 | 13.7k | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
6601 | 13.7k | sftk_item_expand(&privKey)); |
6602 | 13.7k | if (crv != CKR_OK) { |
6603 | 0 | goto kyber_done; |
6604 | 0 | } |
6605 | 13.7k | crv = sftk_AddAttributeType(privateKey, CKA_SEED, |
6606 | 13.7k | sftk_item_expand(&seed)); |
6607 | 13.7k | if (crv != CKR_OK) { |
6608 | 0 | goto kyber_done; |
6609 | 0 | } |
6610 | | /* pseudo attribute that says the seed came with the key |
6611 | | * so don't try to regenerate the key in handleObject. |
6612 | | * it will be removed before the object sees the light of |
6613 | | * day. */ |
6614 | 13.7k | crv = sftk_AddAttributeType(privateKey, CKA_NSS_SEED_OK, |
6615 | 13.7k | NULL, 0); |
6616 | 13.7k | if (crv != CKR_OK) { |
6617 | 0 | goto kyber_done; |
6618 | 0 | } |
6619 | 13.7k | crv = sftk_AddAttributeType(privateKey, CKA_PARAMETER_SET, |
6620 | 13.7k | &genParamSet, |
6621 | 13.7k | sizeof(CK_ML_KEM_PARAMETER_SET_TYPE)); |
6622 | 13.7k | if (crv != CKR_OK) { |
6623 | 0 | goto kyber_done; |
6624 | 0 | } |
6625 | 13.7k | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6626 | 13.7k | sftk_item_expand(&pubKey)); |
6627 | 13.7k | kyber_done: |
6628 | 13.7k | PORT_SafeZero(seed.data, seed.len); |
6629 | 13.7k | SECITEM_ZfreeItem(&privKey, PR_FALSE); |
6630 | 13.7k | SECITEM_FreeItem(&pubKey, PR_FALSE); |
6631 | 13.7k | break; |
6632 | | |
6633 | 0 | case CKM_ML_DSA_KEY_PAIR_GEN: |
6634 | 0 | sftk_DeleteAttributeType(publicKey, CKA_VALUE); |
6635 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6636 | 0 | sftk_DeleteAttributeType(privateKey, CKA_SEED); |
6637 | 0 | key_type = CKK_ML_DSA; |
6638 | | |
6639 | | /* |
6640 | | * the parameters are recognized by us |
6641 | | */ |
6642 | 0 | bitSize = sftk_MLDSAGetSigLen(genParamSet); |
6643 | 0 | if (bitSize == 0) { |
6644 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6645 | 0 | break; |
6646 | 0 | } |
6647 | | |
6648 | | /* Generate the key */ |
6649 | 0 | rv = MLDSA_NewKey(genParamSet, NULL, &mldsaPriv, &mldsaPub); |
6650 | |
|
6651 | 0 | if (rv != SECSuccess) { |
6652 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
6653 | 0 | sftk_fatalError = PR_TRUE; |
6654 | 0 | } |
6655 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6656 | 0 | break; |
6657 | 0 | } |
6658 | | |
6659 | | /* store the generated key into the attributes */ |
6660 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, |
6661 | 0 | mldsaPub.keyVal, mldsaPub.keyValLen); |
6662 | 0 | if (crv != CKR_OK) |
6663 | 0 | goto mldsagn_done; |
6664 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_PARAMETER_SET, |
6665 | 0 | &genParamSet, sizeof(CK_ML_DSA_PARAMETER_SET_TYPE)); |
6666 | 0 | if (crv != CKR_OK) { |
6667 | 0 | goto mldsagn_done; |
6668 | 0 | } |
6669 | | |
6670 | | /* now fill in the ML-DSA specfic paramenters in the private key */ |
6671 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6672 | 0 | mldsaPub.keyVal, mldsaPub.keyValLen); |
6673 | 0 | if (crv != CKR_OK) |
6674 | 0 | goto mldsagn_done; |
6675 | | |
6676 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
6677 | 0 | mldsaPriv.keyVal, |
6678 | 0 | mldsaPriv.keyValLen); |
6679 | 0 | if (crv != CKR_OK) |
6680 | 0 | goto mldsagn_done; |
6681 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PARAMETER_SET, |
6682 | 0 | &genParamSet, sizeof(CK_ML_DSA_PARAMETER_SET_TYPE)); |
6683 | 0 | if (crv != CKR_OK) { |
6684 | 0 | goto mldsagn_done; |
6685 | 0 | } |
6686 | | |
6687 | 0 | if (mldsaPriv.seedLen != 0) { |
6688 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_SEED, |
6689 | 0 | mldsaPriv.seed, mldsaPriv.seedLen); |
6690 | 0 | if (crv != CKR_OK) { |
6691 | 0 | goto mldsagn_done; |
6692 | 0 | } |
6693 | | /* pseudo attribute that says the seed came with the key |
6694 | | * so don't try to regenerate the key in handleObject. |
6695 | | * it will be removed before the object sees the light of |
6696 | | * day. */ |
6697 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_SEED_OK, |
6698 | 0 | NULL, 0); |
6699 | | /* it was either this or a comment 'fall through' which would |
6700 | | * be cryptic to some users */ |
6701 | 0 | if (crv != CKR_OK) { |
6702 | 0 | goto mldsagn_done; |
6703 | 0 | } |
6704 | 0 | } |
6705 | 0 | mldsagn_done: |
6706 | 0 | PORT_SafeZero(&mldsaPriv, sizeof(mldsaPriv)); |
6707 | 0 | PORT_SafeZero(&mldsaPub, sizeof(mldsaPub)); |
6708 | 0 | break; |
6709 | | |
6710 | 0 | case CKM_EC_MONTGOMERY_KEY_PAIR_GEN: |
6711 | 0 | case CKM_EC_EDWARDS_KEY_PAIR_GEN: |
6712 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS); |
6713 | 0 | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
6714 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6715 | 0 | key_type = (pMechanism->mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN) ? CKK_EC_EDWARDS : CKK_EC_MONTGOMERY; |
6716 | | |
6717 | | /* extract the necessary parameters and copy them to private keys */ |
6718 | 0 | crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, |
6719 | 0 | CKA_EC_PARAMS); |
6720 | 0 | if (crv != CKR_OK) { |
6721 | 0 | break; |
6722 | 0 | } |
6723 | | |
6724 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS, |
6725 | 0 | sftk_item_expand(&ecEncodedParams)); |
6726 | 0 | if (crv != CKR_OK) { |
6727 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
6728 | 0 | break; |
6729 | 0 | } |
6730 | | |
6731 | | /* Decode ec params before calling EC_NewKey */ |
6732 | 0 | rv = EC_DecodeParams(&ecEncodedParams, &ecParams); |
6733 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
6734 | 0 | if (rv != SECSuccess) { |
6735 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6736 | 0 | break; |
6737 | 0 | } |
6738 | | |
6739 | 0 | rv = EC_NewKey(ecParams, &ecPriv); |
6740 | 0 | if (rv != SECSuccess) { |
6741 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
6742 | 0 | sftk_fatalError = PR_TRUE; |
6743 | 0 | } |
6744 | 0 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
6745 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6746 | 0 | break; |
6747 | 0 | } |
6748 | 0 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
6749 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
6750 | 0 | sftk_item_expand(&ecPriv->publicValue)); |
6751 | 0 | if (crv != CKR_OK) |
6752 | 0 | goto edgn_done; |
6753 | | |
6754 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
6755 | 0 | sftk_item_expand(&ecPriv->privateValue)); |
6756 | 0 | if (crv != CKR_OK) |
6757 | 0 | goto edgn_done; |
6758 | | |
6759 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6760 | 0 | sftk_item_expand(&ecPriv->publicValue)); |
6761 | 0 | edgn_done: |
6762 | | /* should zeroize, since this function doesn't. */ |
6763 | 0 | PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); |
6764 | 0 | break; |
6765 | | |
6766 | 0 | default: |
6767 | 0 | crv = CKR_MECHANISM_INVALID; |
6768 | 106k | } |
6769 | | |
6770 | 106k | if (crv != CKR_OK) { |
6771 | 759 | sftk_FreeObject(privateKey); |
6772 | 759 | sftk_FreeObject(publicKey); |
6773 | 759 | return crv; |
6774 | 759 | } |
6775 | | |
6776 | | /* Add the class, key_type The loop lets us check errors blow out |
6777 | | * on errors and clean up at the bottom */ |
6778 | 105k | session = NULL; /* make pedtantic happy... session cannot leave the*/ |
6779 | | /* loop below NULL unless an error is set... */ |
6780 | 105k | do { |
6781 | 105k | crv = sftk_AddAttributeType(privateKey, CKA_CLASS, &privClass, |
6782 | 105k | sizeof(CK_OBJECT_CLASS)); |
6783 | 105k | if (crv != CKR_OK) |
6784 | 0 | break; |
6785 | 105k | crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &pubClass, |
6786 | 105k | sizeof(CK_OBJECT_CLASS)); |
6787 | 105k | if (crv != CKR_OK) |
6788 | 0 | break; |
6789 | 105k | crv = sftk_AddAttributeType(privateKey, CKA_KEY_TYPE, &key_type, |
6790 | 105k | sizeof(CK_KEY_TYPE)); |
6791 | 105k | if (crv != CKR_OK) |
6792 | 0 | break; |
6793 | 105k | crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &key_type, |
6794 | 105k | sizeof(CK_KEY_TYPE)); |
6795 | 105k | if (crv != CKR_OK) |
6796 | 0 | break; |
6797 | 105k | session = sftk_SessionFromHandle(hSession); |
6798 | 105k | if (session == NULL) |
6799 | 0 | crv = CKR_SESSION_HANDLE_INVALID; |
6800 | 105k | } while (0); |
6801 | | |
6802 | 105k | if (crv != CKR_OK) { |
6803 | 0 | sftk_FreeObject(privateKey); |
6804 | 0 | sftk_FreeObject(publicKey); |
6805 | 0 | return crv; |
6806 | 0 | } |
6807 | | |
6808 | | /* |
6809 | | * handle the base object cleanup for the public Key |
6810 | | */ |
6811 | 105k | crv = sftk_handleObject(privateKey, session); |
6812 | 105k | if (crv != CKR_OK) { |
6813 | 0 | sftk_FreeSession(session); |
6814 | 0 | sftk_FreeObject(privateKey); |
6815 | 0 | sftk_FreeObject(publicKey); |
6816 | 0 | return crv; |
6817 | 0 | } |
6818 | | |
6819 | | /* |
6820 | | * handle the base object cleanup for the private Key |
6821 | | * If we have any problems, we destroy the public Key we've |
6822 | | * created and linked. |
6823 | | */ |
6824 | 105k | crv = sftk_handleObject(publicKey, session); |
6825 | 105k | if (crv != CKR_OK) { |
6826 | 474 | sftk_FreeSession(session); |
6827 | 474 | sftk_FreeObject(publicKey); |
6828 | 474 | NSC_DestroyObject(hSession, privateKey->handle); |
6829 | 474 | sftk_FreeObject(privateKey); |
6830 | 474 | return crv; |
6831 | 474 | } |
6832 | 104k | if (sftk_isTrue(privateKey, CKA_SENSITIVE)) { |
6833 | 3.33k | crv = sftk_forceAttribute(privateKey, CKA_ALWAYS_SENSITIVE, |
6834 | 3.33k | &cktrue, sizeof(CK_BBOOL)); |
6835 | 3.33k | } |
6836 | 104k | if (crv == CKR_OK && sftk_isTrue(publicKey, CKA_SENSITIVE)) { |
6837 | 0 | crv = sftk_forceAttribute(publicKey, CKA_ALWAYS_SENSITIVE, |
6838 | 0 | &cktrue, sizeof(CK_BBOOL)); |
6839 | 0 | } |
6840 | 104k | if (crv == CKR_OK && !sftk_isTrue(privateKey, CKA_EXTRACTABLE)) { |
6841 | 0 | crv = sftk_forceAttribute(privateKey, CKA_NEVER_EXTRACTABLE, |
6842 | 0 | &cktrue, sizeof(CK_BBOOL)); |
6843 | 0 | } |
6844 | 104k | if (crv == CKR_OK && !sftk_isTrue(publicKey, CKA_EXTRACTABLE)) { |
6845 | 104k | crv = sftk_forceAttribute(publicKey, CKA_NEVER_EXTRACTABLE, |
6846 | 104k | &cktrue, sizeof(CK_BBOOL)); |
6847 | 104k | } |
6848 | | |
6849 | 104k | if (crv == CKR_OK && |
6850 | 104k | pMechanism->mechanism != CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN) { |
6851 | | /* Perform FIPS 140-2 pairwise consistency check. */ |
6852 | 29.7k | crv = sftk_PairwiseConsistencyCheck(hSession, slot, |
6853 | 29.7k | publicKey, privateKey, key_type); |
6854 | 29.7k | if (crv != CKR_OK) { |
6855 | 0 | if (sftk_audit_enabled) { |
6856 | 0 | char msg[128]; |
6857 | 0 | PR_snprintf(msg, sizeof msg, |
6858 | 0 | "C_GenerateKeyPair(hSession=0x%08lX, " |
6859 | 0 | "pMechanism->mechanism=0x%08lX)=0x%08lX " |
6860 | 0 | "self-test: pair-wise consistency test failed", |
6861 | 0 | (PRUint32)hSession, (PRUint32)pMechanism->mechanism, |
6862 | 0 | (PRUint32)crv); |
6863 | 0 | sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg); |
6864 | 0 | } |
6865 | 0 | } |
6866 | 29.7k | } |
6867 | | |
6868 | 104k | if (crv != CKR_OK) { |
6869 | 0 | sftk_FreeSession(session); |
6870 | 0 | NSC_DestroyObject(hSession, publicKey->handle); |
6871 | 0 | sftk_FreeObject(publicKey); |
6872 | 0 | NSC_DestroyObject(hSession, privateKey->handle); |
6873 | 0 | sftk_FreeObject(privateKey); |
6874 | 0 | return crv; |
6875 | 0 | } |
6876 | | /* we need to do this check at the end to make sure the generated key |
6877 | | * meets the key length requirements */ |
6878 | 104k | sftk_setFIPS(privateKey, sftk_operationIsFIPS(slot, pMechanism, |
6879 | 104k | CKA_NSS_GENERATE_KEY_PAIR, |
6880 | 104k | privateKey, 0)); |
6881 | 104k | session->lastOpWasFIPS = sftk_hasFIPS(privateKey); |
6882 | 104k | sftk_setFIPS(publicKey, session->lastOpWasFIPS); |
6883 | 104k | sftk_FreeSession(session); |
6884 | 104k | *phPrivateKey = privateKey->handle; |
6885 | 104k | *phPublicKey = publicKey->handle; |
6886 | 104k | sftk_FreeObject(publicKey); |
6887 | 104k | sftk_FreeObject(privateKey); |
6888 | | |
6889 | 104k | return CKR_OK; |
6890 | 104k | } |
6891 | | |
6892 | | static SECItem * |
6893 | | sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp) |
6894 | 0 | { |
6895 | 0 | NSSLOWKEYPrivateKey *lk = NULL; |
6896 | 0 | NSSLOWKEYPrivateKeyInfo *pki = NULL; |
6897 | 0 | SFTKAttribute *attribute = NULL; |
6898 | 0 | PLArenaPool *arena = NULL; |
6899 | 0 | SECOidTag algorithm = SEC_OID_UNKNOWN; |
6900 | 0 | void *dummy, *param = NULL; |
6901 | 0 | SECStatus rv = SECSuccess; |
6902 | 0 | SECItem *encodedKey = NULL; |
6903 | | #ifdef EC_DEBUG |
6904 | | SECItem *fordebug; |
6905 | | #endif |
6906 | 0 | int savelen; |
6907 | |
|
6908 | 0 | if (!key) { |
6909 | 0 | *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */ |
6910 | 0 | return NULL; |
6911 | 0 | } |
6912 | | |
6913 | 0 | attribute = sftk_FindAttribute(key, CKA_KEY_TYPE); |
6914 | 0 | if (!attribute) { |
6915 | 0 | *crvp = CKR_KEY_TYPE_INCONSISTENT; |
6916 | 0 | return NULL; |
6917 | 0 | } |
6918 | | |
6919 | 0 | lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp); |
6920 | 0 | sftk_FreeAttribute(attribute); |
6921 | 0 | if (!lk) { |
6922 | 0 | return NULL; |
6923 | 0 | } |
6924 | | |
6925 | 0 | arena = PORT_NewArena(2048); /* XXX different size? */ |
6926 | 0 | if (!arena) { |
6927 | 0 | *crvp = CKR_HOST_MEMORY; |
6928 | 0 | rv = SECFailure; |
6929 | 0 | goto loser; |
6930 | 0 | } |
6931 | | |
6932 | 0 | pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena, |
6933 | 0 | sizeof(NSSLOWKEYPrivateKeyInfo)); |
6934 | 0 | if (!pki) { |
6935 | 0 | *crvp = CKR_HOST_MEMORY; |
6936 | 0 | rv = SECFailure; |
6937 | 0 | goto loser; |
6938 | 0 | } |
6939 | 0 | pki->arena = arena; |
6940 | |
|
6941 | 0 | param = NULL; |
6942 | 0 | switch (lk->keyType) { |
6943 | 0 | case NSSLOWKEYRSAKey: |
6944 | 0 | prepare_low_rsa_priv_key_for_asn1(lk); |
6945 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6946 | 0 | nsslowkey_RSAPrivateKeyTemplate); |
6947 | | |
6948 | | /* determine RSA key type from the CKA_PUBLIC_KEY_INFO if present */ |
6949 | 0 | attribute = sftk_FindAttribute(key, CKA_PUBLIC_KEY_INFO); |
6950 | 0 | if (attribute) { |
6951 | 0 | NSSLOWKEYSubjectPublicKeyInfo *publicKeyInfo; |
6952 | 0 | SECItem spki; |
6953 | |
|
6954 | 0 | spki.data = attribute->attrib.pValue; |
6955 | 0 | spki.len = attribute->attrib.ulValueLen; |
6956 | |
|
6957 | 0 | publicKeyInfo = PORT_ArenaZAlloc(arena, |
6958 | 0 | sizeof(NSSLOWKEYSubjectPublicKeyInfo)); |
6959 | 0 | if (!publicKeyInfo) { |
6960 | 0 | sftk_FreeAttribute(attribute); |
6961 | 0 | *crvp = CKR_HOST_MEMORY; |
6962 | 0 | rv = SECFailure; |
6963 | 0 | goto loser; |
6964 | 0 | } |
6965 | 0 | rv = SEC_QuickDERDecodeItem(arena, publicKeyInfo, |
6966 | 0 | nsslowkey_SubjectPublicKeyInfoTemplate, |
6967 | 0 | &spki); |
6968 | 0 | if (rv != SECSuccess) { |
6969 | 0 | sftk_FreeAttribute(attribute); |
6970 | 0 | *crvp = CKR_KEY_TYPE_INCONSISTENT; |
6971 | 0 | goto loser; |
6972 | 0 | } |
6973 | 0 | algorithm = SECOID_GetAlgorithmTag(&publicKeyInfo->algorithm); |
6974 | 0 | if (algorithm != SEC_OID_PKCS1_RSA_ENCRYPTION && |
6975 | 0 | algorithm != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { |
6976 | 0 | sftk_FreeAttribute(attribute); |
6977 | 0 | rv = SECFailure; |
6978 | 0 | *crvp = CKR_KEY_TYPE_INCONSISTENT; |
6979 | 0 | goto loser; |
6980 | 0 | } |
6981 | 0 | param = SECITEM_DupItem(&publicKeyInfo->algorithm.parameters); |
6982 | 0 | if (!param) { |
6983 | 0 | sftk_FreeAttribute(attribute); |
6984 | 0 | rv = SECFailure; |
6985 | 0 | *crvp = CKR_HOST_MEMORY; |
6986 | 0 | goto loser; |
6987 | 0 | } |
6988 | 0 | sftk_FreeAttribute(attribute); |
6989 | 0 | } else { |
6990 | | /* default to PKCS #1 */ |
6991 | 0 | algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; |
6992 | 0 | } |
6993 | 0 | break; |
6994 | 0 | case NSSLOWKEYDSAKey: |
6995 | 0 | prepare_low_dsa_priv_key_export_for_asn1(lk); |
6996 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6997 | 0 | nsslowkey_DSAPrivateKeyExportTemplate); |
6998 | 0 | prepare_low_pqg_params_for_asn1(&lk->u.dsa.params); |
6999 | 0 | param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params), |
7000 | 0 | nsslowkey_PQGParamsTemplate); |
7001 | 0 | algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE; |
7002 | 0 | break; |
7003 | 0 | case NSSLOWKEYECKey: |
7004 | 0 | prepare_low_ec_priv_key_for_asn1(lk); |
7005 | | /* Public value is encoded as a bit string so adjust length |
7006 | | * to be in bits before ASN encoding and readjust |
7007 | | * immediately after. |
7008 | | * |
7009 | | * Since the SECG specification recommends not including the |
7010 | | * parameters as part of ECPrivateKey, we zero out the curveOID |
7011 | | * length before encoding and restore it later. |
7012 | | */ |
7013 | 0 | lk->u.ec.publicValue.len <<= 3; |
7014 | 0 | savelen = lk->u.ec.ecParams.curveOID.len; |
7015 | 0 | lk->u.ec.ecParams.curveOID.len = 0; |
7016 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
7017 | 0 | nsslowkey_ECPrivateKeyTemplate); |
7018 | 0 | lk->u.ec.ecParams.curveOID.len = savelen; |
7019 | 0 | lk->u.ec.publicValue.len >>= 3; |
7020 | |
|
7021 | | #ifdef EC_DEBUG |
7022 | | fordebug = &pki->privateKey; |
7023 | | SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType, |
7024 | | fordebug); |
7025 | | #endif |
7026 | |
|
7027 | 0 | param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding); |
7028 | |
|
7029 | 0 | algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY; |
7030 | 0 | break; |
7031 | 0 | case NSSLOWKEYMLKEMKey: { |
7032 | 0 | SECItem seed = { siBuffer, NULL, 0 }; |
7033 | 0 | SECItem rawKey = { siBuffer, NULL, 0 }; |
7034 | 0 | dummy = NULL; |
7035 | |
|
7036 | 0 | switch (lk->u.mlkem.mlkemParams) { |
7037 | 0 | case params_ml_kem768: |
7038 | 0 | case params_ml_kem768_test_mode: |
7039 | 0 | algorithm = SEC_OID_ML_KEM_768; |
7040 | 0 | break; |
7041 | 0 | case params_ml_kem1024: |
7042 | 0 | case params_ml_kem1024_test_mode: |
7043 | 0 | algorithm = SEC_OID_ML_KEM_1024; |
7044 | 0 | break; |
7045 | 0 | default: |
7046 | 0 | algorithm = SEC_OID_UNKNOWN; |
7047 | 0 | break; |
7048 | 0 | } |
7049 | 0 | if (algorithm == SEC_OID_UNKNOWN) { |
7050 | 0 | break; |
7051 | 0 | } |
7052 | | /* save the seed and key items before they are overwritten */ |
7053 | 0 | if (lk->u.mlkem.seed.len != 0) { |
7054 | 0 | seed = lk->u.mlkem.seed; |
7055 | 0 | } |
7056 | 0 | rawKey = lk->u.mlkem.key; |
7057 | 0 | if (lk == key->objectInfo) { |
7058 | | /* we have a cached key, and we are about to |
7059 | | * overwrite it, let's get a duplicate first */ |
7060 | 0 | lk = nsslowkey_CopyPrivateKey(lk); |
7061 | 0 | if (lk == NULL) { |
7062 | 0 | break; |
7063 | 0 | } |
7064 | 0 | } |
7065 | | /* this overwrites the mlkem data, but we don't need it any |
7066 | | * more because we are discarding lk once we encode. This |
7067 | | * allows us to use the same template for mlkem and mldsa |
7068 | | * (and presumably other pq algorithms, though mlfn and mlshl |
7069 | | * don't have additional seeds) */ |
7070 | 0 | lk->u.genpq.seedItem = seed; |
7071 | 0 | lk->u.genpq.keyItem = rawKey; |
7072 | 0 | if (seed.len) { |
7073 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
7074 | 0 | nsslowkey_PQBothSeedAndPrivateKeyTemplate); |
7075 | 0 | } else { |
7076 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
7077 | 0 | nsslowkey_PQPrivateKeyTemplate); |
7078 | 0 | } |
7079 | 0 | } break; |
7080 | 0 | case NSSLOWKEYMLDSAKey: { |
7081 | 0 | SECItem seed = { siBuffer, NULL, 0 }; |
7082 | 0 | SECItem keyVal = { siBuffer, NULL, 0 }; |
7083 | 0 | dummy = NULL; |
7084 | | |
7085 | | /* paramSet sets the algorithm */ |
7086 | 0 | switch (lk->u.mldsa.paramSet) { |
7087 | 0 | case CKP_ML_DSA_44: |
7088 | 0 | algorithm = SEC_OID_ML_DSA_44_PUBLIC_KEY; |
7089 | 0 | break; |
7090 | 0 | case CKP_ML_DSA_65: |
7091 | 0 | algorithm = SEC_OID_ML_DSA_65_PUBLIC_KEY; |
7092 | 0 | break; |
7093 | 0 | case CKP_ML_DSA_87: |
7094 | 0 | algorithm = SEC_OID_ML_DSA_87_PUBLIC_KEY; |
7095 | 0 | break; |
7096 | 0 | default: |
7097 | 0 | algorithm = SEC_OID_UNKNOWN; |
7098 | 0 | break; |
7099 | 0 | } |
7100 | 0 | if (algorithm == SEC_OID_UNKNOWN) { |
7101 | 0 | break; |
7102 | 0 | } |
7103 | | |
7104 | | /* if we have the seed, copy it */ |
7105 | 0 | if (lk->u.mldsa.seedLen != 0) { |
7106 | 0 | rv = SECITEM_MakeItem(arena, &seed, lk->u.mldsa.seed, |
7107 | 0 | lk->u.mldsa.seedLen); |
7108 | 0 | if (rv != SECSuccess) { |
7109 | 0 | break; |
7110 | 0 | } |
7111 | 0 | } |
7112 | 0 | rv = SECITEM_MakeItem(arena, &keyVal, lk->u.mldsa.keyVal, |
7113 | 0 | lk->u.mldsa.keyValLen); |
7114 | 0 | if (rv != SECSuccess) { |
7115 | 0 | break; |
7116 | 0 | } |
7117 | 0 | if (lk == key->objectInfo) { |
7118 | | /* we have a cached key, and we are about to |
7119 | | * overwrite it, let's get a duplicate first */ |
7120 | 0 | lk = nsslowkey_CopyPrivateKey(lk); |
7121 | 0 | if (lk == NULL) { |
7122 | 0 | break; |
7123 | 0 | } |
7124 | 0 | } |
7125 | | /* this overwrites the mldsa data, but we don't need it any |
7126 | | * more because we are discarding lk once we encode */ |
7127 | 0 | lk->u.genpq.seedItem = seed; |
7128 | 0 | lk->u.genpq.keyItem = keyVal; |
7129 | |
|
7130 | 0 | if (seed.len) { |
7131 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
7132 | 0 | nsslowkey_PQBothSeedAndPrivateKeyTemplate); |
7133 | 0 | } else { |
7134 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
7135 | 0 | nsslowkey_PQPrivateKeyTemplate); |
7136 | 0 | } |
7137 | 0 | } break; |
7138 | | |
7139 | 0 | case NSSLOWKEYDHKey: |
7140 | 0 | default: |
7141 | 0 | dummy = NULL; |
7142 | 0 | break; |
7143 | 0 | } |
7144 | | |
7145 | 0 | if (!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) { |
7146 | 0 | *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
7147 | 0 | rv = SECFailure; |
7148 | 0 | goto loser; |
7149 | 0 | } |
7150 | | |
7151 | 0 | rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, |
7152 | 0 | (SECItem *)param); |
7153 | 0 | if (rv != SECSuccess) { |
7154 | 0 | *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
7155 | 0 | rv = SECFailure; |
7156 | 0 | goto loser; |
7157 | 0 | } |
7158 | | |
7159 | 0 | dummy = SEC_ASN1EncodeInteger(arena, &pki->version, |
7160 | 0 | NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); |
7161 | 0 | if (!dummy) { |
7162 | 0 | *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
7163 | 0 | rv = SECFailure; |
7164 | 0 | goto loser; |
7165 | 0 | } |
7166 | | |
7167 | 0 | encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, |
7168 | 0 | nsslowkey_PrivateKeyInfoTemplate); |
7169 | 0 | *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR; |
7170 | |
|
7171 | | #ifdef EC_DEBUG |
7172 | | fordebug = encodedKey; |
7173 | | SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType, |
7174 | | fordebug); |
7175 | | #endif |
7176 | 0 | loser: |
7177 | 0 | if (arena) { |
7178 | 0 | PORT_FreeArena(arena, PR_TRUE); |
7179 | 0 | } |
7180 | |
|
7181 | 0 | if (lk && (lk != key->objectInfo)) { |
7182 | 0 | nsslowkey_DestroyPrivateKey(lk); |
7183 | 0 | } |
7184 | |
|
7185 | 0 | if (param) { |
7186 | 0 | SECITEM_ZfreeItem((SECItem *)param, PR_TRUE); |
7187 | 0 | } |
7188 | |
|
7189 | 0 | if (rv != SECSuccess) { |
7190 | 0 | return NULL; |
7191 | 0 | } |
7192 | | |
7193 | 0 | return encodedKey; |
7194 | 0 | } |
7195 | | |
7196 | | /* it doesn't matter yet, since we colapse error conditions in the |
7197 | | * level above, but we really should map those few key error differences */ |
7198 | | static CK_RV |
7199 | | sftk_mapWrap(CK_RV crv) |
7200 | 118k | { |
7201 | 118k | switch (crv) { |
7202 | 0 | case CKR_ENCRYPTED_DATA_INVALID: |
7203 | 0 | crv = CKR_WRAPPED_KEY_INVALID; |
7204 | 0 | break; |
7205 | 118k | } |
7206 | 118k | return crv; |
7207 | 118k | } |
7208 | | |
7209 | | /* NSC_WrapKey wraps (i.e., encrypts) a key. */ |
7210 | | CK_RV |
7211 | | NSC_WrapKey(CK_SESSION_HANDLE hSession, |
7212 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, |
7213 | | CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, |
7214 | | CK_ULONG_PTR pulWrappedKeyLen) |
7215 | 76.7k | { |
7216 | 76.7k | SFTKSession *session; |
7217 | 76.7k | SFTKAttribute *attribute; |
7218 | 76.7k | SFTKObject *key; |
7219 | 76.7k | CK_RV crv; |
7220 | | |
7221 | 76.7k | CHECK_FORK(); |
7222 | | |
7223 | 76.7k | session = sftk_SessionFromHandle(hSession); |
7224 | 76.7k | if (session == NULL) { |
7225 | 0 | return CKR_SESSION_HANDLE_INVALID; |
7226 | 0 | } |
7227 | | |
7228 | 76.7k | key = sftk_ObjectFromHandle(hKey, session); |
7229 | 76.7k | if (key == NULL) { |
7230 | 0 | sftk_FreeSession(session); |
7231 | 0 | return CKR_KEY_HANDLE_INVALID; |
7232 | 0 | } |
7233 | | |
7234 | 76.7k | switch (key->objclass) { |
7235 | 76.7k | case CKO_SECRET_KEY: { |
7236 | 76.7k | SFTKSessionContext *context = NULL; |
7237 | 76.7k | SECItem pText; |
7238 | | |
7239 | 76.7k | attribute = sftk_FindAttribute(key, CKA_VALUE); |
7240 | | |
7241 | 76.7k | if (attribute == NULL) { |
7242 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7243 | 0 | break; |
7244 | 0 | } |
7245 | 76.7k | crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, |
7246 | 76.7k | CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); |
7247 | 76.7k | if (crv != CKR_OK) { |
7248 | 39 | sftk_FreeAttribute(attribute); |
7249 | 39 | break; |
7250 | 39 | } |
7251 | | |
7252 | 76.6k | pText.type = siBuffer; |
7253 | 76.6k | pText.data = (unsigned char *)attribute->attrib.pValue; |
7254 | 76.6k | pText.len = attribute->attrib.ulValueLen; |
7255 | | |
7256 | | /* Find out if this is a block cipher. The context was just |
7257 | | * installed by sftk_CryptInit above, so we already hold a |
7258 | | * session reference and the context's type is SFTK_ENCRYPT |
7259 | | * by construction. */ |
7260 | 76.6k | context = sftk_ReturnContextByType(session, SFTK_ENCRYPT); |
7261 | 76.6k | if (!context) { |
7262 | 0 | sftk_FreeAttribute(attribute); |
7263 | 0 | crv = CKR_OPERATION_NOT_INITIALIZED; |
7264 | 0 | break; |
7265 | 0 | } |
7266 | 76.6k | if (context->blockSize > 1) { |
7267 | 61.3k | unsigned int remainder = pText.len % context->blockSize; |
7268 | 61.3k | if (!context->doPad && remainder) { |
7269 | | /* When wrapping secret keys with unpadded block ciphers, |
7270 | | ** the keys are zero padded, if necessary, to fill out |
7271 | | ** a full block. |
7272 | | */ |
7273 | 0 | pText.len += context->blockSize - remainder; |
7274 | 0 | pText.data = PORT_ZAlloc(pText.len); |
7275 | 0 | if (pText.data) |
7276 | 0 | memcpy(pText.data, attribute->attrib.pValue, |
7277 | 0 | attribute->attrib.ulValueLen); |
7278 | 0 | else { |
7279 | 0 | sftk_FreeAttribute(attribute); |
7280 | 0 | crv = CKR_HOST_MEMORY; |
7281 | 0 | break; |
7282 | 0 | } |
7283 | 0 | } |
7284 | 61.3k | } |
7285 | | |
7286 | 76.6k | crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data, |
7287 | 76.6k | pText.len, pWrappedKey, pulWrappedKeyLen); |
7288 | | /* always force a finalize, both on errors and when |
7289 | | * we are just getting the size */ |
7290 | 76.6k | if (crv != CKR_OK || pWrappedKey == NULL) { |
7291 | 0 | sftk_UninstallContext(session, SFTK_ENCRYPT); |
7292 | 0 | } |
7293 | | |
7294 | 76.6k | if (pText.data != (unsigned char *)attribute->attrib.pValue) |
7295 | 0 | PORT_ZFree(pText.data, pText.len); |
7296 | 76.6k | sftk_FreeAttribute(attribute); |
7297 | 76.6k | break; |
7298 | 76.6k | } |
7299 | | |
7300 | 0 | case CKO_PRIVATE_KEY: { |
7301 | 0 | SECItem *bpki = sftk_PackagePrivateKey(key, &crv); |
7302 | |
|
7303 | 0 | if (!bpki) { |
7304 | 0 | break; |
7305 | 0 | } |
7306 | | |
7307 | 0 | crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, |
7308 | 0 | CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); |
7309 | 0 | if (crv != CKR_OK) { |
7310 | 0 | SECITEM_ZfreeItem(bpki, PR_TRUE); |
7311 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7312 | 0 | break; |
7313 | 0 | } |
7314 | | |
7315 | 0 | crv = NSC_Encrypt(hSession, bpki->data, bpki->len, |
7316 | 0 | pWrappedKey, pulWrappedKeyLen); |
7317 | | /* always force a finalize */ |
7318 | 0 | if (crv != CKR_OK || pWrappedKey == NULL) { |
7319 | 0 | sftk_UninstallContext(session, SFTK_ENCRYPT); |
7320 | 0 | } |
7321 | 0 | SECITEM_ZfreeItem(bpki, PR_TRUE); |
7322 | 0 | break; |
7323 | 0 | } |
7324 | | |
7325 | 0 | default: |
7326 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7327 | 0 | break; |
7328 | 76.7k | } |
7329 | 76.7k | sftk_FreeObject(key); |
7330 | 76.7k | sftk_FreeSession(session); |
7331 | 76.7k | return sftk_mapWrap(crv); |
7332 | 76.7k | } |
7333 | | |
7334 | | /* |
7335 | | * import a pprivate key info into the desired slot |
7336 | | */ |
7337 | | static SECStatus |
7338 | | sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) |
7339 | 0 | { |
7340 | 0 | CK_BBOOL cktrue = CK_TRUE; |
7341 | 0 | CK_BBOOL ckfalse = CK_FALSE; |
7342 | 0 | CK_KEY_TYPE keyType = CKK_RSA; |
7343 | 0 | SECStatus rv = SECFailure; |
7344 | 0 | const SEC_ASN1Template *keyTemplate, *paramTemplate; |
7345 | 0 | void *paramDest = NULL; |
7346 | 0 | PLArenaPool *arena; |
7347 | 0 | NSSLOWKEYPrivateKey *lpk = NULL; |
7348 | 0 | NSSLOWKEYPrivateKeyInfo *pki = NULL; |
7349 | 0 | CK_RV crv = CKR_KEY_TYPE_INCONSISTENT; |
7350 | 0 | CK_ULONG paramSet = 0; |
7351 | |
|
7352 | 0 | arena = PORT_NewArena(2048); |
7353 | 0 | if (!arena) { |
7354 | 0 | return SECFailure; |
7355 | 0 | } |
7356 | | |
7357 | 0 | pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena, |
7358 | 0 | sizeof(NSSLOWKEYPrivateKeyInfo)); |
7359 | 0 | if (!pki) { |
7360 | 0 | PORT_FreeArena(arena, PR_FALSE); |
7361 | 0 | return SECFailure; |
7362 | 0 | } |
7363 | | |
7364 | 0 | if (SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) != SECSuccess) { |
7365 | 0 | PORT_FreeArena(arena, PR_TRUE); |
7366 | 0 | return SECFailure; |
7367 | 0 | } |
7368 | | |
7369 | 0 | lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena, |
7370 | 0 | sizeof(NSSLOWKEYPrivateKey)); |
7371 | 0 | if (lpk == NULL) { |
7372 | 0 | goto loser; |
7373 | 0 | } |
7374 | 0 | lpk->arena = arena; |
7375 | |
|
7376 | 0 | switch (SECOID_GetAlgorithmTag(&pki->algorithm)) { |
7377 | 0 | case SEC_OID_PKCS1_RSA_ENCRYPTION: |
7378 | 0 | case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: |
7379 | 0 | keyTemplate = nsslowkey_RSAPrivateKeyTemplate; |
7380 | 0 | paramTemplate = NULL; |
7381 | 0 | paramDest = NULL; |
7382 | 0 | lpk->keyType = NSSLOWKEYRSAKey; |
7383 | 0 | prepare_low_rsa_priv_key_for_asn1(lpk); |
7384 | 0 | break; |
7385 | 0 | case SEC_OID_ANSIX9_DSA_SIGNATURE: |
7386 | 0 | keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate; |
7387 | 0 | paramTemplate = nsslowkey_PQGParamsTemplate; |
7388 | 0 | paramDest = &(lpk->u.dsa.params); |
7389 | 0 | lpk->keyType = NSSLOWKEYDSAKey; |
7390 | 0 | prepare_low_dsa_priv_key_export_for_asn1(lpk); |
7391 | 0 | prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params); |
7392 | 0 | break; |
7393 | | /* case NSSLOWKEYDHKey: */ |
7394 | 0 | case SEC_OID_ANSIX962_EC_PUBLIC_KEY: |
7395 | 0 | keyTemplate = nsslowkey_ECPrivateKeyTemplate; |
7396 | 0 | paramTemplate = NULL; |
7397 | 0 | paramDest = &(lpk->u.ec.ecParams.DEREncoding); |
7398 | 0 | lpk->keyType = NSSLOWKEYECKey; |
7399 | 0 | prepare_low_ec_priv_key_for_asn1(lpk); |
7400 | 0 | prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams); |
7401 | 0 | break; |
7402 | 0 | case SEC_OID_ML_KEM_768: |
7403 | 0 | paramSet = CKP_ML_KEM_768; |
7404 | 0 | goto mlkem_next; |
7405 | 0 | case SEC_OID_ML_KEM_1024: |
7406 | 0 | paramSet = CKP_ML_KEM_1024; |
7407 | 0 | mlkem_next: |
7408 | 0 | lpk->keyType = NSSLOWKEYMLKEMKey; |
7409 | 0 | goto pq_next; |
7410 | 0 | case SEC_OID_ML_DSA_44_PUBLIC_KEY: |
7411 | 0 | paramSet = CKP_ML_DSA_44; |
7412 | 0 | goto mldsa_next; |
7413 | 0 | case SEC_OID_ML_DSA_65_PUBLIC_KEY: |
7414 | 0 | paramSet = CKP_ML_DSA_65; |
7415 | 0 | goto mldsa_next; |
7416 | 0 | case SEC_OID_ML_DSA_87_PUBLIC_KEY: |
7417 | 0 | paramSet = CKP_ML_DSA_87; |
7418 | 0 | mldsa_next: |
7419 | 0 | lpk->keyType = NSSLOWKEYMLDSAKey; |
7420 | 0 | pq_next: |
7421 | 0 | if (pki->privateKey.data == NULL || pki->privateKey.len == 0) { |
7422 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); |
7423 | 0 | goto loser; |
7424 | 0 | } |
7425 | 0 | switch (pki->privateKey.data[0]) { |
7426 | 0 | case SEC_ASN1_CONTEXT_SPECIFIC | 0: |
7427 | 0 | keyTemplate = nsslowkey_PQSeedTemplate; |
7428 | 0 | break; |
7429 | 0 | case SEC_ASN1_OCTET_STRING: |
7430 | 0 | keyTemplate = nsslowkey_PQPrivateKeyTemplate; |
7431 | 0 | break; |
7432 | 0 | case SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE: |
7433 | 0 | keyTemplate = nsslowkey_PQBothSeedAndPrivateKeyTemplate; |
7434 | 0 | break; |
7435 | 0 | default: |
7436 | 0 | keyTemplate = NULL; |
7437 | 0 | break; |
7438 | 0 | } |
7439 | | |
7440 | 0 | paramTemplate = NULL; |
7441 | 0 | paramDest = NULL; |
7442 | | /* genpq encodes ocect, not integer, so no need to prep it */ |
7443 | 0 | break; |
7444 | 0 | default: |
7445 | 0 | keyTemplate = NULL; |
7446 | 0 | paramTemplate = NULL; |
7447 | 0 | paramDest = NULL; |
7448 | 0 | break; |
7449 | 0 | } |
7450 | | |
7451 | 0 | if (!keyTemplate) { |
7452 | 0 | goto loser; |
7453 | 0 | } |
7454 | | |
7455 | | /* decode the private key and any algorithm parameters */ |
7456 | 0 | rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey); |
7457 | |
|
7458 | 0 | if (lpk->keyType == NSSLOWKEYECKey) { |
7459 | | /* convert length in bits to length in bytes */ |
7460 | 0 | lpk->u.ec.publicValue.len >>= 3; |
7461 | 0 | rv = SECITEM_CopyItem(arena, |
7462 | 0 | &(lpk->u.ec.ecParams.DEREncoding), |
7463 | 0 | &(pki->algorithm.parameters)); |
7464 | 0 | if (rv != SECSuccess) { |
7465 | 0 | goto loser; |
7466 | 0 | } |
7467 | 0 | } |
7468 | | |
7469 | 0 | if (rv != SECSuccess) { |
7470 | 0 | goto loser; |
7471 | 0 | } |
7472 | 0 | if (paramDest && paramTemplate) { |
7473 | 0 | rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate, |
7474 | 0 | &(pki->algorithm.parameters)); |
7475 | 0 | if (rv != SECSuccess) { |
7476 | 0 | goto loser; |
7477 | 0 | } |
7478 | 0 | } |
7479 | | |
7480 | 0 | rv = SECFailure; |
7481 | |
|
7482 | 0 | switch (lpk->keyType) { |
7483 | 0 | case NSSLOWKEYRSAKey: |
7484 | 0 | keyType = CKK_RSA; |
7485 | 0 | if (sftk_hasAttribute(key, CKA_NSS_DB)) { |
7486 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_DB); |
7487 | 0 | } |
7488 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
7489 | 0 | sizeof(keyType)); |
7490 | 0 | if (crv != CKR_OK) |
7491 | 0 | break; |
7492 | 0 | crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue, |
7493 | 0 | sizeof(CK_BBOOL)); |
7494 | 0 | if (crv != CKR_OK) |
7495 | 0 | break; |
7496 | 0 | crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue, |
7497 | 0 | sizeof(CK_BBOOL)); |
7498 | 0 | if (crv != CKR_OK) |
7499 | 0 | break; |
7500 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
7501 | 0 | sizeof(CK_BBOOL)); |
7502 | 0 | if (crv != CKR_OK) |
7503 | 0 | break; |
7504 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, |
7505 | 0 | sizeof(CK_BBOOL)); |
7506 | 0 | if (crv != CKR_OK) |
7507 | 0 | break; |
7508 | 0 | crv = sftk_AddAttributeType(key, CKA_MODULUS, |
7509 | 0 | sftk_item_expand(&lpk->u.rsa.modulus)); |
7510 | 0 | if (crv != CKR_OK) |
7511 | 0 | break; |
7512 | 0 | crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT, |
7513 | 0 | sftk_item_expand(&lpk->u.rsa.publicExponent)); |
7514 | 0 | if (crv != CKR_OK) |
7515 | 0 | break; |
7516 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT, |
7517 | 0 | sftk_item_expand(&lpk->u.rsa.privateExponent)); |
7518 | 0 | if (crv != CKR_OK) |
7519 | 0 | break; |
7520 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME_1, |
7521 | 0 | sftk_item_expand(&lpk->u.rsa.prime1)); |
7522 | 0 | if (crv != CKR_OK) |
7523 | 0 | break; |
7524 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME_2, |
7525 | 0 | sftk_item_expand(&lpk->u.rsa.prime2)); |
7526 | 0 | if (crv != CKR_OK) |
7527 | 0 | break; |
7528 | 0 | crv = sftk_AddAttributeType(key, CKA_EXPONENT_1, |
7529 | 0 | sftk_item_expand(&lpk->u.rsa.exponent1)); |
7530 | 0 | if (crv != CKR_OK) |
7531 | 0 | break; |
7532 | 0 | crv = sftk_AddAttributeType(key, CKA_EXPONENT_2, |
7533 | 0 | sftk_item_expand(&lpk->u.rsa.exponent2)); |
7534 | 0 | if (crv != CKR_OK) |
7535 | 0 | break; |
7536 | 0 | crv = sftk_AddAttributeType(key, CKA_COEFFICIENT, |
7537 | 0 | sftk_item_expand(&lpk->u.rsa.coefficient)); |
7538 | 0 | break; |
7539 | 0 | case NSSLOWKEYDSAKey: |
7540 | 0 | keyType = CKK_DSA; |
7541 | 0 | crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT; |
7542 | 0 | if (crv != CKR_OK) |
7543 | 0 | break; |
7544 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
7545 | 0 | sizeof(keyType)); |
7546 | 0 | if (crv != CKR_OK) |
7547 | 0 | break; |
7548 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
7549 | 0 | sizeof(CK_BBOOL)); |
7550 | 0 | if (crv != CKR_OK) |
7551 | 0 | break; |
7552 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &ckfalse, |
7553 | 0 | sizeof(CK_BBOOL)); |
7554 | 0 | if (crv != CKR_OK) |
7555 | 0 | break; |
7556 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME, |
7557 | 0 | sftk_item_expand(&lpk->u.dsa.params.prime)); |
7558 | 0 | if (crv != CKR_OK) |
7559 | 0 | break; |
7560 | 0 | crv = sftk_AddAttributeType(key, CKA_SUBPRIME, |
7561 | 0 | sftk_item_expand(&lpk->u.dsa.params.subPrime)); |
7562 | 0 | if (crv != CKR_OK) |
7563 | 0 | break; |
7564 | 0 | crv = sftk_AddAttributeType(key, CKA_BASE, |
7565 | 0 | sftk_item_expand(&lpk->u.dsa.params.base)); |
7566 | 0 | if (crv != CKR_OK) |
7567 | 0 | break; |
7568 | 0 | crv = sftk_AddAttributeType(key, CKA_VALUE, |
7569 | 0 | sftk_item_expand(&lpk->u.dsa.privateValue)); |
7570 | 0 | if (crv != CKR_OK) |
7571 | 0 | break; |
7572 | 0 | break; |
7573 | 0 | case NSSLOWKEYMLKEMKey: |
7574 | 0 | keyType = CKK_ML_KEM; |
7575 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
7576 | 0 | sizeof(keyType)); |
7577 | 0 | if (crv != CKR_OK) |
7578 | 0 | break; |
7579 | 0 | crv = sftk_AddAttributeType(key, CKA_DECAPSULATE, &cktrue, |
7580 | 0 | sizeof(CK_BBOOL)); |
7581 | 0 | if (crv != CKR_OK) |
7582 | 0 | break; |
7583 | 0 | crv = sftk_AddAttributeType(key, CKA_PARAMETER_SET, ¶mSet, |
7584 | 0 | sizeof(CK_ML_KEM_PARAMETER_SET_TYPE)); |
7585 | 0 | if (crv != CKR_OK) |
7586 | 0 | break; |
7587 | 0 | if (lpk->u.genpq.seedItem.len != 0) { |
7588 | 0 | crv = sftk_AddAttributeType(key, CKA_SEED, |
7589 | 0 | sftk_item_expand(&lpk->u.genpq.seedItem)); |
7590 | 0 | if (crv != CKR_OK) |
7591 | 0 | break; |
7592 | 0 | } |
7593 | | |
7594 | | /* if we were given just the seed, we'll regenerate the key |
7595 | | * from the seed in handleObject */ |
7596 | 0 | if (lpk->u.genpq.keyItem.len != 0) { |
7597 | 0 | crv = sftk_AddAttributeType(key, CKA_VALUE, |
7598 | 0 | sftk_item_expand(&lpk->u.genpq.keyItem)); |
7599 | | /* I know, this is redundant, but it would be too easy |
7600 | | * for someone to add another sftk_AddAttributeType after |
7601 | | * this without adding this check back because of the if */ |
7602 | 0 | if (crv != CKR_OK) |
7603 | 0 | break; |
7604 | 0 | } |
7605 | 0 | break; |
7606 | 0 | case NSSLOWKEYMLDSAKey: |
7607 | 0 | keyType = CKK_ML_DSA; |
7608 | 0 | crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT; |
7609 | 0 | if (crv != CKR_OK) |
7610 | 0 | break; |
7611 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
7612 | 0 | sizeof(keyType)); |
7613 | 0 | if (crv != CKR_OK) |
7614 | 0 | break; |
7615 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
7616 | 0 | sizeof(CK_BBOOL)); |
7617 | 0 | if (crv != CKR_OK) |
7618 | 0 | break; |
7619 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &ckfalse, |
7620 | 0 | sizeof(CK_BBOOL)); |
7621 | 0 | if (crv != CKR_OK) |
7622 | 0 | break; |
7623 | 0 | crv = sftk_AddAttributeType(key, CKA_PARAMETER_SET, ¶mSet, |
7624 | 0 | sizeof(CK_ML_DSA_PARAMETER_SET_TYPE)); |
7625 | 0 | if (crv != CKR_OK) |
7626 | 0 | break; |
7627 | 0 | if (lpk->u.genpq.seedItem.len != 0) { |
7628 | 0 | crv = sftk_AddAttributeType(key, CKA_SEED, |
7629 | 0 | sftk_item_expand(&lpk->u.genpq.seedItem)); |
7630 | 0 | if (crv != CKR_OK) |
7631 | 0 | break; |
7632 | 0 | } |
7633 | | |
7634 | | /* if we were given just the seed, we'll regenerate the key |
7635 | | * from the seed in handleObject */ |
7636 | 0 | if (lpk->u.genpq.keyItem.len != 0) { |
7637 | 0 | crv = sftk_AddAttributeType(key, CKA_VALUE, |
7638 | 0 | sftk_item_expand(&lpk->u.genpq.keyItem)); |
7639 | | /* I know, this is redundant, but it would be too easy |
7640 | | * for someone to add another sftk_AddAttributeType after |
7641 | | * this without adding this check back because of the if */ |
7642 | 0 | if (crv != CKR_OK) |
7643 | 0 | break; |
7644 | 0 | } |
7645 | 0 | break; |
7646 | | #ifdef notdef |
7647 | | case NSSLOWKEYDHKey: |
7648 | | template = dhTemplate; |
7649 | | templateCount = sizeof(dhTemplate) / sizeof(CK_ATTRIBUTE); |
7650 | | keyType = CKK_DH; |
7651 | | break; |
7652 | | #endif |
7653 | | /* what about fortezza??? */ |
7654 | 0 | case NSSLOWKEYECKey: |
7655 | 0 | keyType = CKK_EC; |
7656 | | /* if we weren't passed the CKA_NSS_DB, get it |
7657 | | * from the public key */ |
7658 | 0 | if (!sftk_hasAttribute(key, CKA_NSS_DB)) { |
7659 | 0 | if (lpk->u.ec.publicValue.len == 0) { |
7660 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7661 | 0 | goto loser; |
7662 | 0 | } |
7663 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_DB, |
7664 | 0 | sftk_item_expand(&lpk->u.ec.publicValue)); |
7665 | 0 | if (crv != CKR_OK) { |
7666 | 0 | goto loser; |
7667 | 0 | } |
7668 | 0 | } |
7669 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
7670 | 0 | sizeof(keyType)); |
7671 | 0 | if (crv != CKR_OK) |
7672 | 0 | break; |
7673 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
7674 | 0 | sizeof(CK_BBOOL)); |
7675 | 0 | if (crv != CKR_OK) |
7676 | 0 | break; |
7677 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &ckfalse, |
7678 | 0 | sizeof(CK_BBOOL)); |
7679 | 0 | if (crv != CKR_OK) |
7680 | 0 | break; |
7681 | 0 | crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue, |
7682 | 0 | sizeof(CK_BBOOL)); |
7683 | 0 | if (crv != CKR_OK) |
7684 | 0 | break; |
7685 | 0 | crv = sftk_AddAttributeType(key, CKA_EC_PARAMS, |
7686 | 0 | sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding)); |
7687 | 0 | if (crv != CKR_OK) |
7688 | 0 | break; |
7689 | 0 | crv = sftk_AddAttributeType(key, CKA_VALUE, |
7690 | 0 | sftk_item_expand(&lpk->u.ec.privateValue)); |
7691 | 0 | if (crv != CKR_OK) |
7692 | 0 | break; |
7693 | | /* XXX Do we need to decode the EC Params here ?? */ |
7694 | 0 | break; |
7695 | 0 | default: |
7696 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7697 | 0 | break; |
7698 | 0 | } |
7699 | | |
7700 | 0 | if (crv != CKR_OK) { |
7701 | 0 | goto loser; |
7702 | 0 | } |
7703 | | |
7704 | | /* For RSA-PSS, record the original algorithm parameters so |
7705 | | * they can be encrypted altoghether when wrapping */ |
7706 | 0 | if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { |
7707 | 0 | NSSLOWKEYSubjectPublicKeyInfo spki; |
7708 | 0 | NSSLOWKEYPublicKey pubk; |
7709 | 0 | SECItem *publicKeyInfo; |
7710 | |
|
7711 | 0 | memset(&spki, 0, sizeof(NSSLOWKEYSubjectPublicKeyInfo)); |
7712 | 0 | rv = SECOID_CopyAlgorithmID(arena, &spki.algorithm, &pki->algorithm); |
7713 | 0 | if (rv != SECSuccess) { |
7714 | 0 | crv = CKR_HOST_MEMORY; |
7715 | 0 | goto loser; |
7716 | 0 | } |
7717 | | |
7718 | 0 | prepare_low_rsa_pub_key_for_asn1(&pubk); |
7719 | |
|
7720 | 0 | rv = SECITEM_CopyItem(arena, &pubk.u.rsa.modulus, &lpk->u.rsa.modulus); |
7721 | 0 | if (rv != SECSuccess) { |
7722 | 0 | crv = CKR_HOST_MEMORY; |
7723 | 0 | goto loser; |
7724 | 0 | } |
7725 | 0 | rv = SECITEM_CopyItem(arena, &pubk.u.rsa.publicExponent, &lpk->u.rsa.publicExponent); |
7726 | 0 | if (rv != SECSuccess) { |
7727 | 0 | crv = CKR_HOST_MEMORY; |
7728 | 0 | goto loser; |
7729 | 0 | } |
7730 | 0 | pubk.u.rsa.needVerify = PR_FALSE; /* We're just encoding the key from the |
7731 | | * private key */ |
7732 | |
|
7733 | 0 | if (SEC_ASN1EncodeItem(arena, &spki.subjectPublicKey, |
7734 | 0 | &pubk, nsslowkey_RSAPublicKeyTemplate) == NULL) { |
7735 | 0 | crv = CKR_HOST_MEMORY; |
7736 | 0 | goto loser; |
7737 | 0 | } |
7738 | | |
7739 | 0 | publicKeyInfo = SEC_ASN1EncodeItem(arena, NULL, |
7740 | 0 | &spki, nsslowkey_SubjectPublicKeyInfoTemplate); |
7741 | 0 | if (!publicKeyInfo) { |
7742 | 0 | crv = CKR_HOST_MEMORY; |
7743 | 0 | goto loser; |
7744 | 0 | } |
7745 | 0 | crv = sftk_AddAttributeType(key, CKA_PUBLIC_KEY_INFO, |
7746 | 0 | sftk_item_expand(publicKeyInfo)); |
7747 | 0 | } |
7748 | | |
7749 | 0 | loser: |
7750 | 0 | if (lpk) { |
7751 | 0 | nsslowkey_DestroyPrivateKey(lpk); |
7752 | 0 | } |
7753 | |
|
7754 | 0 | if (crv != CKR_OK) { |
7755 | 0 | return SECFailure; |
7756 | 0 | } |
7757 | | |
7758 | 0 | return SECSuccess; |
7759 | 0 | } |
7760 | | |
7761 | | /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */ |
7762 | | CK_RV |
7763 | | NSC_UnwrapKey(CK_SESSION_HANDLE hSession, |
7764 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, |
7765 | | CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, |
7766 | | CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, |
7767 | | CK_OBJECT_HANDLE_PTR phKey) |
7768 | 46.0k | { |
7769 | 46.0k | SFTKObject *key = NULL; |
7770 | 46.0k | SFTKSession *session; |
7771 | 46.0k | CK_ULONG key_length = 0; |
7772 | 46.0k | unsigned char *buf = NULL; |
7773 | 46.0k | CK_RV crv = CKR_OK; |
7774 | 46.0k | int i; |
7775 | 46.0k | CK_ULONG bsize = ulWrappedKeyLen; |
7776 | 46.0k | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
7777 | 46.0k | SECItem bpki; |
7778 | 46.0k | CK_OBJECT_CLASS target_type = CKO_SECRET_KEY; |
7779 | | |
7780 | 46.0k | CHECK_FORK(); |
7781 | | |
7782 | 46.0k | if (!slot) { |
7783 | 0 | return CKR_SESSION_HANDLE_INVALID; |
7784 | 0 | } |
7785 | | /* |
7786 | | * now lets create an object to hang the attributes off of |
7787 | | */ |
7788 | 46.0k | key = sftk_NewObject(slot); /* fill in the handle later */ |
7789 | 46.0k | if (key == NULL) { |
7790 | 0 | return CKR_HOST_MEMORY; |
7791 | 0 | } |
7792 | | |
7793 | | /* |
7794 | | * load the template values into the object |
7795 | | */ |
7796 | 184k | for (i = 0; i < (int)ulAttributeCount; i++) { |
7797 | 138k | if (pTemplate[i].type == CKA_VALUE_LEN) { |
7798 | 0 | key_length = *(CK_ULONG *)pTemplate[i].pValue; |
7799 | 0 | continue; |
7800 | 0 | } |
7801 | 138k | if (pTemplate[i].type == CKA_CLASS) { |
7802 | 46.0k | target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; |
7803 | 46.0k | } |
7804 | 138k | crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); |
7805 | 138k | if (crv != CKR_OK) |
7806 | 0 | break; |
7807 | 138k | } |
7808 | 46.0k | if (crv != CKR_OK) { |
7809 | 0 | sftk_FreeObject(key); |
7810 | 0 | return crv; |
7811 | 0 | } |
7812 | | |
7813 | 46.0k | crv = sftk_CryptInit(hSession, pMechanism, hUnwrappingKey, CKA_UNWRAP, |
7814 | 46.0k | CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE); |
7815 | 46.0k | if (crv != CKR_OK) { |
7816 | 0 | sftk_FreeObject(key); |
7817 | 0 | return sftk_mapWrap(crv); |
7818 | 0 | } |
7819 | | |
7820 | | /* allocate the buffer to decrypt into |
7821 | | * this assumes the unwrapped key is never larger than the |
7822 | | * wrapped key. For all the mechanisms we support this is true */ |
7823 | 46.0k | buf = (unsigned char *)PORT_Alloc(ulWrappedKeyLen); |
7824 | 46.0k | bsize = ulWrappedKeyLen; |
7825 | | |
7826 | 46.0k | crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize); |
7827 | 46.0k | if (crv != CKR_OK) { |
7828 | 42.0k | sftk_FreeObject(key); |
7829 | 42.0k | PORT_Free(buf); |
7830 | 42.0k | return sftk_mapWrap(crv); |
7831 | 42.0k | } |
7832 | | |
7833 | 3.99k | switch (target_type) { |
7834 | 3.99k | case CKO_SECRET_KEY: |
7835 | 3.99k | if (!sftk_hasAttribute(key, CKA_KEY_TYPE)) { |
7836 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
7837 | 0 | break; |
7838 | 0 | } |
7839 | | |
7840 | 3.99k | if (key_length == 0 || key_length > bsize) { |
7841 | 3.99k | key_length = bsize; |
7842 | 3.99k | } |
7843 | 3.99k | if (key_length > MAX_KEY_LEN) { |
7844 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
7845 | 0 | break; |
7846 | 0 | } |
7847 | | |
7848 | | /* add the value */ |
7849 | 3.99k | crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length); |
7850 | 3.99k | break; |
7851 | 0 | case CKO_PRIVATE_KEY: |
7852 | 0 | bpki.data = (unsigned char *)buf; |
7853 | 0 | bpki.len = bsize; |
7854 | 0 | crv = CKR_OK; |
7855 | 0 | if (sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) { |
7856 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
7857 | 0 | } |
7858 | 0 | break; |
7859 | 0 | default: |
7860 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
7861 | 0 | break; |
7862 | 3.99k | } |
7863 | | |
7864 | 3.99k | PORT_ZFree(buf, bsize); |
7865 | 3.99k | if (crv != CKR_OK) { |
7866 | 0 | sftk_FreeObject(key); |
7867 | 0 | return crv; |
7868 | 0 | } |
7869 | | |
7870 | | /* get the session */ |
7871 | 3.99k | session = sftk_SessionFromHandle(hSession); |
7872 | 3.99k | if (session == NULL) { |
7873 | 0 | sftk_FreeObject(key); |
7874 | 0 | return CKR_SESSION_HANDLE_INVALID; |
7875 | 0 | } |
7876 | | |
7877 | | /* mark the key as FIPS if the previous operation was all FIPS */ |
7878 | 3.99k | sftk_setFIPS(key, session->lastOpWasFIPS); |
7879 | | /* |
7880 | | * handle the base object stuff |
7881 | | */ |
7882 | 3.99k | crv = sftk_handleObject(key, session); |
7883 | 3.99k | *phKey = key->handle; |
7884 | 3.99k | sftk_FreeSession(session); |
7885 | 3.99k | sftk_FreeObject(key); |
7886 | | |
7887 | 3.99k | return crv; |
7888 | 3.99k | } |
7889 | | |
7890 | | CK_RV |
7891 | | NSC_WrapKeyAuthenticated(CK_SESSION_HANDLE hSession, |
7892 | | CK_MECHANISM_PTR pMechanism, |
7893 | | CK_OBJECT_HANDLE hWrappingKey, |
7894 | | CK_OBJECT_HANDLE hKey, |
7895 | | CK_BYTE_PTR pAssociatedData, |
7896 | | CK_ULONG ulAssociatedDataLen, |
7897 | | CK_BYTE_PTR pWrappedKey, |
7898 | | CK_ULONG_PTR pulWrappedKeyLen) |
7899 | 0 | { |
7900 | 0 | CHECK_FORK(); |
7901 | |
|
7902 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
7903 | 0 | } |
7904 | | |
7905 | | CK_RV |
7906 | | NSC_UnwrapKeyAuthenticated(CK_SESSION_HANDLE hSession, |
7907 | | CK_MECHANISM_PTR pMechanism, |
7908 | | CK_OBJECT_HANDLE hUnwrappingKey, |
7909 | | CK_BYTE_PTR pWrappedKey, |
7910 | | CK_ULONG ulWrappedKeyLen, |
7911 | | CK_ATTRIBUTE_PTR pTemplate, |
7912 | | CK_ULONG ulAttributeCount, |
7913 | | CK_BYTE_PTR pAssociatedData, |
7914 | | CK_ULONG ulAssociatedDataLen, |
7915 | | CK_OBJECT_HANDLE_PTR phKey) |
7916 | 0 | { |
7917 | 0 | CHECK_FORK(); |
7918 | |
|
7919 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
7920 | 0 | } |
7921 | | |
7922 | | /* |
7923 | | * The SSL key gen mechanism create's lots of keys. This function handles the |
7924 | | * details of each of these key creation. |
7925 | | */ |
7926 | | static CK_RV |
7927 | | sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey, |
7928 | | PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize, |
7929 | | CK_OBJECT_HANDLE *keyHandle) |
7930 | 446k | { |
7931 | 446k | SFTKObject *key; |
7932 | 446k | SFTKSession *session; |
7933 | 446k | CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
7934 | 446k | CK_BBOOL cktrue = CK_TRUE; |
7935 | 446k | CK_BBOOL ckfalse = CK_FALSE; |
7936 | 446k | CK_RV crv = CKR_HOST_MEMORY; |
7937 | | |
7938 | | /* |
7939 | | * now lets create an object to hang the attributes off of |
7940 | | */ |
7941 | 446k | *keyHandle = CK_INVALID_HANDLE; |
7942 | 446k | key = sftk_NewObject(baseKey->slot); |
7943 | 446k | if (key == NULL) |
7944 | 0 | return CKR_HOST_MEMORY; |
7945 | 446k | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
7946 | 446k | PORT_Assert(sessKey); |
7947 | 446k | sessKey->wasDerived = PR_TRUE; |
7948 | | |
7949 | 446k | crv = sftk_CopyObject(key, baseKey); |
7950 | 446k | if (crv != CKR_OK) |
7951 | 0 | goto loser; |
7952 | 446k | if (isMacKey) { |
7953 | 237k | crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType)); |
7954 | 237k | if (crv != CKR_OK) |
7955 | 0 | goto loser; |
7956 | 237k | crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); |
7957 | 237k | if (crv != CKR_OK) |
7958 | 0 | goto loser; |
7959 | 237k | crv = sftk_forceAttribute(key, CKA_ENCRYPT, &ckfalse, sizeof(CK_BBOOL)); |
7960 | 237k | if (crv != CKR_OK) |
7961 | 0 | goto loser; |
7962 | 237k | crv = sftk_forceAttribute(key, CKA_DECRYPT, &ckfalse, sizeof(CK_BBOOL)); |
7963 | 237k | if (crv != CKR_OK) |
7964 | 0 | goto loser; |
7965 | 237k | crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); |
7966 | 237k | if (crv != CKR_OK) |
7967 | 0 | goto loser; |
7968 | 237k | crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); |
7969 | 237k | if (crv != CKR_OK) |
7970 | 0 | goto loser; |
7971 | 237k | crv = sftk_forceAttribute(key, CKA_WRAP, &ckfalse, sizeof(CK_BBOOL)); |
7972 | 237k | if (crv != CKR_OK) |
7973 | 0 | goto loser; |
7974 | 237k | crv = sftk_forceAttribute(key, CKA_UNWRAP, &ckfalse, sizeof(CK_BBOOL)); |
7975 | 237k | if (crv != CKR_OK) |
7976 | 0 | goto loser; |
7977 | 237k | } |
7978 | 446k | crv = sftk_forceAttribute(key, CKA_VALUE, keyBlock, keySize); |
7979 | 446k | if (crv != CKR_OK) |
7980 | 0 | goto loser; |
7981 | | |
7982 | | /* get the session */ |
7983 | 446k | crv = CKR_HOST_MEMORY; |
7984 | 446k | session = sftk_SessionFromHandle(hSession); |
7985 | 446k | if (session == NULL) { |
7986 | 0 | goto loser; |
7987 | 0 | } |
7988 | | |
7989 | 446k | crv = sftk_handleObject(key, session); |
7990 | 446k | sftk_FreeSession(session); |
7991 | 446k | *keyHandle = key->handle; |
7992 | 446k | loser: |
7993 | 446k | if (key) |
7994 | 446k | sftk_FreeObject(key); |
7995 | 446k | return crv; |
7996 | 446k | } |
7997 | | |
7998 | | /* |
7999 | | * if there is an error, we need to free the keys we already created in SSL |
8000 | | * This is the routine that will do it.. |
8001 | | */ |
8002 | | static void |
8003 | | sftk_freeSSLKeys(CK_SESSION_HANDLE session, |
8004 | | CK_SSL3_KEY_MAT_OUT *returnedMaterial) |
8005 | 0 | { |
8006 | 0 | if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) { |
8007 | 0 | NSC_DestroyObject(session, returnedMaterial->hClientMacSecret); |
8008 | 0 | } |
8009 | 0 | if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) { |
8010 | 0 | NSC_DestroyObject(session, returnedMaterial->hServerMacSecret); |
8011 | 0 | } |
8012 | 0 | if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) { |
8013 | 0 | NSC_DestroyObject(session, returnedMaterial->hClientKey); |
8014 | 0 | } |
8015 | 0 | if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) { |
8016 | 0 | NSC_DestroyObject(session, returnedMaterial->hServerKey); |
8017 | 0 | } |
8018 | 0 | } |
8019 | | |
8020 | | /* |
8021 | | * when deriving from sensitive and extractable keys, we need to preserve some |
8022 | | * of the semantics in the derived key. This helper routine maintains these |
8023 | | * semantics. |
8024 | | */ |
8025 | | static CK_RV |
8026 | | sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey, |
8027 | | PRBool canBeData) |
8028 | 620k | { |
8029 | 620k | PRBool hasSensitive; |
8030 | 620k | PRBool sensitive = PR_FALSE; |
8031 | 620k | CK_BBOOL bFalse = CK_FALSE; |
8032 | 620k | PRBool hasExtractable; |
8033 | 620k | PRBool extractable = PR_TRUE; |
8034 | 620k | CK_BBOOL bTrue = CK_TRUE; |
8035 | 620k | CK_RV crv = CKR_OK; |
8036 | 620k | SFTKAttribute *att; |
8037 | 620k | PRBool isData = PR_TRUE; |
8038 | | |
8039 | 620k | if (canBeData) { |
8040 | 494k | CK_OBJECT_CLASS objClass; |
8041 | | |
8042 | | /* if the target key is actually data, don't set the unexpected |
8043 | | * attributes */ |
8044 | 494k | crv = sftk_GetULongAttribute(destKey, CKA_CLASS, &objClass); |
8045 | 494k | if (crv != CKR_OK) { |
8046 | 0 | return crv; |
8047 | 0 | } |
8048 | 494k | if (objClass == CKO_DATA) { |
8049 | 145k | return CKR_OK; |
8050 | 145k | } |
8051 | | |
8052 | | /* if the base key is data, it doesn't have sensitive attributes, |
8053 | | * allow the destKey to get it's own */ |
8054 | 348k | crv = sftk_GetULongAttribute(baseKey, CKA_CLASS, &objClass); |
8055 | 348k | if (crv != CKR_OK) { |
8056 | 0 | return crv; |
8057 | 0 | } |
8058 | 348k | if (objClass == CKO_DATA) { |
8059 | 10.7k | isData = PR_TRUE; |
8060 | 10.7k | } |
8061 | 348k | } |
8062 | | |
8063 | 475k | hasSensitive = PR_FALSE; |
8064 | 475k | att = sftk_FindAttribute(destKey, CKA_SENSITIVE); |
8065 | 475k | if (att) { |
8066 | 0 | hasSensitive = PR_TRUE; |
8067 | 0 | sensitive = (PRBool) * (CK_BBOOL *)att->attrib.pValue; |
8068 | 0 | sftk_FreeAttribute(att); |
8069 | 0 | } |
8070 | | |
8071 | 475k | hasExtractable = PR_FALSE; |
8072 | 475k | att = sftk_FindAttribute(destKey, CKA_EXTRACTABLE); |
8073 | 475k | if (att) { |
8074 | 0 | hasExtractable = PR_TRUE; |
8075 | 0 | extractable = (PRBool) * (CK_BBOOL *)att->attrib.pValue; |
8076 | 0 | sftk_FreeAttribute(att); |
8077 | 0 | } |
8078 | | |
8079 | | /* don't make a key more accessible */ |
8080 | 475k | if (sftk_isTrue(baseKey, CKA_SENSITIVE) && hasSensitive && |
8081 | 0 | (sensitive == PR_FALSE)) { |
8082 | 0 | return CKR_KEY_FUNCTION_NOT_PERMITTED; |
8083 | 0 | } |
8084 | 475k | if (!sftk_isTrue(baseKey, CKA_EXTRACTABLE) && hasExtractable && |
8085 | 0 | (extractable == PR_TRUE)) { |
8086 | 0 | return CKR_KEY_FUNCTION_NOT_PERMITTED; |
8087 | 0 | } |
8088 | | |
8089 | | /* inherit parent's sensitivity */ |
8090 | 475k | if (!hasSensitive) { |
8091 | 475k | att = sftk_FindAttribute(baseKey, CKA_SENSITIVE); |
8092 | 475k | if (att != NULL) { |
8093 | 460k | crv = sftk_defaultAttribute(destKey, |
8094 | 460k | sftk_attr_expand(&att->attrib)); |
8095 | 460k | sftk_FreeAttribute(att); |
8096 | 460k | } else if (isData) { |
8097 | 14.1k | crv = sftk_defaultAttribute(destKey, CKA_SENSITIVE, |
8098 | 14.1k | &bFalse, sizeof(bFalse)); |
8099 | 14.1k | } else { |
8100 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
8101 | 0 | } |
8102 | 475k | if (crv != CKR_OK) |
8103 | 0 | return crv; |
8104 | 475k | } |
8105 | 475k | if (!hasExtractable) { |
8106 | 475k | att = sftk_FindAttribute(baseKey, CKA_EXTRACTABLE); |
8107 | 475k | if (att != NULL) { |
8108 | 460k | crv = sftk_defaultAttribute(destKey, |
8109 | 460k | sftk_attr_expand(&att->attrib)); |
8110 | 460k | sftk_FreeAttribute(att); |
8111 | 460k | } else if (isData) { |
8112 | 14.1k | crv = sftk_defaultAttribute(destKey, CKA_EXTRACTABLE, |
8113 | 14.1k | &bTrue, sizeof(bTrue)); |
8114 | 14.1k | } else { |
8115 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
8116 | 0 | } |
8117 | 475k | if (crv != CKR_OK) |
8118 | 0 | return crv; |
8119 | 475k | } |
8120 | | |
8121 | | /* we should inherit the parent's always extractable/ never sensitive info, |
8122 | | * but handleObject always forces this attributes, so we would need to do |
8123 | | * something special. */ |
8124 | 475k | return CKR_OK; |
8125 | 475k | } |
8126 | | |
8127 | | /* |
8128 | | * make known fixed PKCS #11 key types to their sizes in bytes |
8129 | | */ |
8130 | | unsigned long |
8131 | | sftk_MapKeySize(CK_KEY_TYPE keyType) |
8132 | 285k | { |
8133 | 285k | switch (keyType) { |
8134 | 2 | case CKK_CDMF: |
8135 | 2 | return 8; |
8136 | 12.7k | case CKK_DES: |
8137 | 12.7k | return 8; |
8138 | 255 | case CKK_DES2: |
8139 | 255 | return 16; |
8140 | 45.6k | case CKK_DES3: |
8141 | 45.6k | return 24; |
8142 | | /* IDEA and CAST need to be added */ |
8143 | 227k | default: |
8144 | 227k | break; |
8145 | 285k | } |
8146 | 227k | return 0; |
8147 | 285k | } |
8148 | | |
8149 | | /* Inputs: |
8150 | | * key_len: Length of derived key to be generated. |
8151 | | * SharedSecret: a shared secret that is the output of a key agreement primitive. |
8152 | | * SharedInfo: (Optional) some data shared by the entities computing the secret key. |
8153 | | * SharedInfoLen: the length in octets of SharedInfo |
8154 | | * Hash: The hash function to be used in the KDF |
8155 | | * HashLen: the length in octets of the output of Hash |
8156 | | * Output: |
8157 | | * key: Pointer to a buffer containing derived key, if return value is SECSuccess. |
8158 | | */ |
8159 | | static CK_RV |
8160 | | sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret, |
8161 | | CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, |
8162 | | SECStatus Hash(unsigned char *, const unsigned char *, PRUint32), |
8163 | | CK_ULONG HashLen) |
8164 | 0 | { |
8165 | 0 | unsigned char *buffer = NULL, *output_buffer = NULL; |
8166 | 0 | PRUint32 buffer_len, max_counter, i; |
8167 | 0 | SECStatus rv; |
8168 | 0 | CK_RV crv; |
8169 | | |
8170 | | /* Check that key_len isn't too long. The maximum key length could be |
8171 | | * greatly increased if the code below did not limit the 4-byte counter |
8172 | | * to a maximum value of 255. */ |
8173 | 0 | if (key_len > 254 * HashLen) |
8174 | 0 | return CKR_ARGUMENTS_BAD; |
8175 | | |
8176 | 0 | if (SharedInfo == NULL) |
8177 | 0 | SharedInfoLen = 0; |
8178 | |
|
8179 | 0 | if (SharedSecret->len > PR_UINT32_MAX - 4 || |
8180 | 0 | SharedInfoLen > PR_UINT32_MAX - 4 - SharedSecret->len) |
8181 | 0 | return CKR_ARGUMENTS_BAD; |
8182 | | |
8183 | 0 | buffer_len = SharedSecret->len + 4 + SharedInfoLen; |
8184 | 0 | buffer = (CK_BYTE *)PORT_Alloc(buffer_len); |
8185 | 0 | if (buffer == NULL) { |
8186 | 0 | crv = CKR_HOST_MEMORY; |
8187 | 0 | goto loser; |
8188 | 0 | } |
8189 | | |
8190 | 0 | max_counter = key_len / HashLen; |
8191 | 0 | if (key_len > max_counter * HashLen) |
8192 | 0 | max_counter++; |
8193 | |
|
8194 | 0 | output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen); |
8195 | 0 | if (output_buffer == NULL) { |
8196 | 0 | crv = CKR_HOST_MEMORY; |
8197 | 0 | goto loser; |
8198 | 0 | } |
8199 | | |
8200 | | /* Populate buffer with SharedSecret || Counter || [SharedInfo] |
8201 | | * where Counter is 0x00000001 */ |
8202 | 0 | PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len); |
8203 | 0 | buffer[SharedSecret->len] = 0; |
8204 | 0 | buffer[SharedSecret->len + 1] = 0; |
8205 | 0 | buffer[SharedSecret->len + 2] = 0; |
8206 | 0 | buffer[SharedSecret->len + 3] = 1; |
8207 | 0 | if (SharedInfo) { |
8208 | 0 | PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen); |
8209 | 0 | } |
8210 | |
|
8211 | 0 | for (i = 0; i < max_counter; i++) { |
8212 | 0 | rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len); |
8213 | 0 | if (rv != SECSuccess) { |
8214 | | /* 'Hash' should not fail. */ |
8215 | 0 | crv = CKR_FUNCTION_FAILED; |
8216 | 0 | goto loser; |
8217 | 0 | } |
8218 | | |
8219 | | /* Increment counter (assumes max_counter < 255) */ |
8220 | 0 | buffer[SharedSecret->len + 3]++; |
8221 | 0 | } |
8222 | | |
8223 | 0 | PORT_ZFree(buffer, buffer_len); |
8224 | 0 | if (key_len < max_counter * HashLen) { |
8225 | 0 | PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len); |
8226 | 0 | } |
8227 | 0 | *key = output_buffer; |
8228 | |
|
8229 | 0 | return CKR_OK; |
8230 | | |
8231 | 0 | loser: |
8232 | 0 | if (buffer) { |
8233 | 0 | PORT_ZFree(buffer, buffer_len); |
8234 | 0 | } |
8235 | 0 | if (output_buffer) { |
8236 | 0 | PORT_ZFree(output_buffer, max_counter * HashLen); |
8237 | 0 | } |
8238 | 0 | return crv; |
8239 | 0 | } |
8240 | | |
8241 | | static CK_RV |
8242 | | sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, |
8243 | | SECItem *SharedSecret, |
8244 | | CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, |
8245 | | CK_EC_KDF_TYPE kdf) |
8246 | 0 | { |
8247 | 0 | if (kdf == CKD_SHA1_KDF) |
8248 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
8249 | 0 | SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH); |
8250 | 0 | else if (kdf == CKD_SHA224_KDF) |
8251 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
8252 | 0 | SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH); |
8253 | 0 | else if (kdf == CKD_SHA256_KDF) |
8254 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
8255 | 0 | SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH); |
8256 | 0 | else if (kdf == CKD_SHA384_KDF) |
8257 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
8258 | 0 | SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH); |
8259 | 0 | else if (kdf == CKD_SHA512_KDF) |
8260 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
8261 | 0 | SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH); |
8262 | 0 | else |
8263 | 0 | return CKR_MECHANISM_INVALID; |
8264 | 0 | } |
8265 | | |
8266 | | /* |
8267 | | * Handle the derive from a block encryption cipher |
8268 | | */ |
8269 | | CK_RV |
8270 | | sftk_DeriveEncrypt(SFTKCipher encrypt, void *cipherInfo, |
8271 | | int blockSize, SFTKObject *key, CK_ULONG keySize, |
8272 | | unsigned char *data, CK_ULONG len) |
8273 | 0 | { |
8274 | | /* large enough for a 512-bit key */ |
8275 | 0 | unsigned char tmpdata[SFTK_MAX_DERIVE_KEY_SIZE]; |
8276 | 0 | SECStatus rv; |
8277 | 0 | unsigned int outLen; |
8278 | 0 | CK_RV crv; |
8279 | |
|
8280 | 0 | if ((len % blockSize) != 0) { |
8281 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8282 | 0 | } |
8283 | 0 | if (len > SFTK_MAX_DERIVE_KEY_SIZE) { |
8284 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8285 | 0 | } |
8286 | 0 | if (keySize && (len < keySize)) { |
8287 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8288 | 0 | } |
8289 | 0 | if (keySize == 0) { |
8290 | 0 | keySize = len; |
8291 | 0 | } |
8292 | |
|
8293 | 0 | rv = (*encrypt)(cipherInfo, (unsigned char *)&tmpdata, &outLen, len, data, len); |
8294 | 0 | if (rv != SECSuccess) { |
8295 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
8296 | 0 | return crv; |
8297 | 0 | } |
8298 | | |
8299 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize); |
8300 | 0 | PORT_Memset(tmpdata, 0, sizeof tmpdata); |
8301 | 0 | return crv; |
8302 | 0 | } |
8303 | | |
8304 | | CK_RV |
8305 | | sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession, |
8306 | | SFTKObject *sourceKey, const unsigned char *sourceKeyBytes, |
8307 | | int sourceKeyLen, SFTKObject *key, unsigned char *outKeyBytes, |
8308 | | int keySize, PRBool canBeData, PRBool isFIPS) |
8309 | 494k | { |
8310 | 494k | SFTKSession *session; |
8311 | 494k | SFTKAttribute *saltKey_att = NULL; |
8312 | 494k | const SECHashObject *rawHash; |
8313 | 494k | unsigned hashLen; |
8314 | 494k | unsigned genLen = 0; |
8315 | 494k | unsigned char hashbuf[HASH_LENGTH_MAX]; |
8316 | 494k | unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH]; |
8317 | 494k | unsigned char *keyBlockAlloc = NULL; /* allocated keyBlock */ |
8318 | 494k | unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */ |
8319 | 494k | const unsigned char *prk; /* psuedo-random key */ |
8320 | 494k | CK_ULONG prkLen; |
8321 | 494k | const unsigned char *okm; /* output keying material */ |
8322 | 494k | HASH_HashType hashType = sftk_GetHashTypeFromMechanism(params->prfHashMechanism); |
8323 | 494k | SFTKObject *saltKey = NULL; |
8324 | 494k | CK_RV crv = CKR_OK; |
8325 | | |
8326 | | /* Spec says it should be the base hash, but also accept the HMAC */ |
8327 | 494k | if (hashType == HASH_AlgNULL) { |
8328 | 0 | hashType = sftk_HMACMechanismToHash(params->prfHashMechanism); |
8329 | 0 | } |
8330 | 494k | rawHash = HASH_GetRawHashObject(hashType); |
8331 | 494k | if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) { |
8332 | 0 | return CKR_MECHANISM_INVALID; |
8333 | 0 | } |
8334 | 494k | hashLen = rawHash->length; |
8335 | | |
8336 | 494k | if ((!params->bExpand && !params->bExtract) || |
8337 | 494k | (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) || |
8338 | 494k | (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) { |
8339 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8340 | 0 | } |
8341 | 494k | if ((params->bExpand && keySize == 0) || |
8342 | 494k | (!params->bExpand && keySize > hashLen) || |
8343 | 494k | (params->bExpand && keySize > 255 * hashLen)) { |
8344 | 105 | return CKR_TEMPLATE_INCONSISTENT; |
8345 | 105 | } |
8346 | | |
8347 | 494k | if (!params->bExpand) { |
8348 | 36.1k | keySize = hashLen; |
8349 | 36.1k | } |
8350 | | |
8351 | | /* sourceKey is NULL if we are called from the POST, skip the |
8352 | | * sensitiveCheck */ |
8353 | 494k | if (sourceKey != NULL) { |
8354 | 494k | crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData); |
8355 | 494k | if (crv != CKR_OK) |
8356 | 0 | return crv; |
8357 | | /* if the source key is data, clear the FIPS flag |
8358 | | * and only get the FIPS state from the salt */ |
8359 | 494k | if (sourceKey->objclass == CKO_DATA) { |
8360 | 17.4k | sftk_setFIPS(key, PR_FALSE); |
8361 | 17.4k | } |
8362 | 494k | } |
8363 | | |
8364 | | /* HKDF-Extract(salt, base key value) */ |
8365 | 494k | if (params->bExtract) { |
8366 | 36.3k | CK_BYTE *salt; |
8367 | 36.3k | CK_ULONG saltLen; |
8368 | 36.3k | HMACContext *hmac; |
8369 | 36.3k | unsigned int bufLen; |
8370 | 36.3k | SFTKSource saltKeySource = SFTK_SOURCE_DEFAULT; |
8371 | | |
8372 | 36.3k | switch (params->ulSaltType) { |
8373 | 22.6k | case CKF_HKDF_SALT_NULL: |
8374 | 22.6k | saltLen = hashLen; |
8375 | 22.6k | salt = hashbuf; |
8376 | 22.6k | memset(salt, 0, saltLen); |
8377 | 22.6k | break; |
8378 | 117 | case CKF_HKDF_SALT_DATA: |
8379 | 117 | salt = params->pSalt; |
8380 | 117 | saltLen = params->ulSaltLen; |
8381 | 117 | if ((salt == NULL) || (params->ulSaltLen == 0)) { |
8382 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8383 | 0 | } |
8384 | 117 | break; |
8385 | 13.5k | case CKF_HKDF_SALT_KEY: |
8386 | | /* lookup key */ |
8387 | 13.5k | session = sftk_SessionFromHandle(hSession); |
8388 | 13.5k | if (session == NULL) { |
8389 | 0 | return CKR_SESSION_HANDLE_INVALID; |
8390 | 0 | } |
8391 | | |
8392 | 13.5k | saltKey = sftk_ObjectFromHandle(params->hSaltKey, session); |
8393 | 13.5k | sftk_FreeSession(session); |
8394 | 13.5k | if (saltKey == NULL) { |
8395 | 0 | return CKR_KEY_HANDLE_INVALID; |
8396 | 0 | } |
8397 | | /* if the base key is not fips, but the salt key is, the |
8398 | | * resulting key can be fips */ |
8399 | 13.5k | if (isFIPS && !sftk_hasFIPS(key) && sftk_hasFIPS(saltKey)) { |
8400 | 0 | CK_MECHANISM mech; |
8401 | 0 | mech.mechanism = CKM_HKDF_DERIVE; |
8402 | 0 | mech.pParameter = params; |
8403 | 0 | mech.ulParameterLen = sizeof(*params); |
8404 | 0 | sftk_setFIPS(key, sftk_operationIsFIPS(saltKey->slot, |
8405 | 0 | &mech, CKA_DERIVE, |
8406 | 0 | saltKey, |
8407 | 0 | keySize * PR_BITS_PER_BYTE)); |
8408 | 0 | } |
8409 | 13.5k | saltKeySource = saltKey->source; |
8410 | 13.5k | saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE); |
8411 | 13.5k | if (saltKey_att == NULL) { |
8412 | 0 | sftk_FreeObject(saltKey); |
8413 | 0 | return CKR_KEY_HANDLE_INVALID; |
8414 | 0 | } |
8415 | | /* save the resulting salt */ |
8416 | 13.5k | salt = saltKey_att->attrib.pValue; |
8417 | 13.5k | saltLen = saltKey_att->attrib.ulValueLen; |
8418 | 13.5k | break; |
8419 | 0 | default: |
8420 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8421 | 0 | break; |
8422 | 36.3k | } |
8423 | | /* only TLS style usage is FIPS approved, |
8424 | | * turn off the FIPS indicator for other usages */ |
8425 | 36.3k | if (isFIPS && key && sourceKey) { |
8426 | 0 | PRBool fipsOK = PR_FALSE; |
8427 | | /* case one: mix the kea with a previous or default |
8428 | | * salt */ |
8429 | 0 | if ((sourceKey->source == SFTK_SOURCE_KEA) && |
8430 | 0 | (saltKeySource == SFTK_SOURCE_HKDF_EXPAND) && |
8431 | 0 | (saltLen == rawHash->length)) { |
8432 | 0 | fipsOK = PR_TRUE; |
8433 | 0 | } |
8434 | | /* case two: restart, remix the previous secret as a salt */ |
8435 | 0 | if ((sourceKey->objclass == CKO_DATA) && |
8436 | 0 | (NSS_SecureMemcmpZero(sourceKeyBytes, sourceKeyLen) == 0) && |
8437 | 0 | (sourceKeyLen == rawHash->length) && |
8438 | 0 | (saltKeySource == SFTK_SOURCE_HKDF_EXPAND) && |
8439 | 0 | (saltLen == rawHash->length)) { |
8440 | 0 | fipsOK = PR_TRUE; |
8441 | 0 | } |
8442 | 0 | if (!fipsOK) { |
8443 | 0 | sftk_setFIPS(key, PR_FALSE); |
8444 | 0 | } |
8445 | 0 | } |
8446 | 36.3k | if (key) |
8447 | 36.3k | key->source = SFTK_SOURCE_HKDF_EXTRACT; |
8448 | | |
8449 | 36.3k | hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS); |
8450 | 36.3k | if (saltKey_att) { |
8451 | 13.5k | sftk_FreeAttribute(saltKey_att); |
8452 | 13.5k | } |
8453 | 36.3k | if (saltKey) { |
8454 | 13.5k | sftk_FreeObject(saltKey); |
8455 | 13.5k | } |
8456 | 36.3k | if (!hmac) { |
8457 | 0 | return CKR_HOST_MEMORY; |
8458 | 0 | } |
8459 | 36.3k | HMAC_Begin(hmac); |
8460 | 36.3k | HMAC_Update(hmac, sourceKeyBytes, sourceKeyLen); |
8461 | 36.3k | HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf)); |
8462 | 36.3k | HMAC_Destroy(hmac, PR_TRUE); |
8463 | 36.3k | PORT_Assert(bufLen == rawHash->length); |
8464 | 36.3k | prk = hashbuf; |
8465 | 36.3k | prkLen = bufLen; |
8466 | 458k | } else { |
8467 | | /* PRK = base key value */ |
8468 | 458k | prk = sourceKeyBytes; |
8469 | 458k | prkLen = sourceKeyLen; |
8470 | 458k | } |
8471 | | |
8472 | | /* HKDF-Expand */ |
8473 | 494k | if (!params->bExpand) { |
8474 | 36.1k | okm = prk; |
8475 | 36.1k | genLen = hashLen; |
8476 | 458k | } else { |
8477 | | /* T(1) = HMAC-Hash(prk, "" | info | 0x01) |
8478 | | * T(n) = HMAC-Hash(prk, T(n-1) | info | n |
8479 | | * key material = T(1) | ... | T(n) |
8480 | | */ |
8481 | 458k | HMACContext *hmac; |
8482 | 458k | CK_BYTE bi; |
8483 | 458k | unsigned iterations; |
8484 | | |
8485 | | /* only TLS style usage is FIPS approved, |
8486 | | * turn off the FIPS indicator for other usages */ |
8487 | 458k | if (isFIPS && key && sftk_hasFIPS(key) && sourceKey) { |
8488 | | /* only one case, |
8489 | | * 1) Expand only |
8490 | | * 2) with a key whose source was |
8491 | | * SFTK_SOURCE_HKDF_EXPAND or SFTK_SOURCE_HKDF_EXTRACT |
8492 | | * 3) source key length == rawHash->length |
8493 | | * 4) Info has tls or dtls |
8494 | | * If any of those conditions aren't met, then we turn |
8495 | | * off the fips indicator */ |
8496 | 0 | if (params->bExtract || |
8497 | 0 | ((sourceKey->source != SFTK_SOURCE_HKDF_EXTRACT) && |
8498 | 0 | (sourceKey->source != SFTK_SOURCE_HKDF_EXPAND)) || |
8499 | 0 | (sourceKeyLen != rawHash->length) || |
8500 | 0 | (params->ulInfoLen < 7) || |
8501 | 0 | ((PORT_Memcmp(¶ms->pInfo[3], "tls", 3) != 0) && |
8502 | 0 | (PORT_Memcmp(¶ms->pInfo[3], "dtls", 4) != 0))) { |
8503 | 0 | sftk_setFIPS(key, PR_FALSE); |
8504 | 0 | } |
8505 | 0 | } |
8506 | 458k | if (key) |
8507 | 458k | key->source = SFTK_SOURCE_HKDF_EXPAND; |
8508 | | |
8509 | 458k | genLen = PR_ROUNDUP(keySize, hashLen); |
8510 | 458k | iterations = genLen / hashLen; |
8511 | | |
8512 | 458k | if (genLen > sizeof(keyBlock)) { |
8513 | 153 | keyBlockAlloc = PORT_Alloc(genLen); |
8514 | 153 | if (keyBlockAlloc == NULL) { |
8515 | 0 | return CKR_HOST_MEMORY; |
8516 | 0 | } |
8517 | 153 | keyBlockData = keyBlockAlloc; |
8518 | 153 | } |
8519 | 458k | hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS); |
8520 | 458k | if (hmac == NULL) { |
8521 | 0 | PORT_Free(keyBlockAlloc); |
8522 | 0 | return CKR_HOST_MEMORY; |
8523 | 0 | } |
8524 | 960k | for (bi = 1; bi <= iterations && bi > 0; ++bi) { |
8525 | 501k | unsigned len; |
8526 | 501k | HMAC_Begin(hmac); |
8527 | 501k | if (bi > 1) { |
8528 | 43.4k | HMAC_Update(hmac, &keyBlockData[(bi - 2) * hashLen], hashLen); |
8529 | 43.4k | } |
8530 | 501k | if (params->ulInfoLen != 0) { |
8531 | 468k | HMAC_Update(hmac, params->pInfo, params->ulInfoLen); |
8532 | 468k | } |
8533 | 501k | HMAC_Update(hmac, &bi, 1); |
8534 | 501k | HMAC_Finish(hmac, &keyBlockData[(bi - 1) * hashLen], &len, |
8535 | 501k | hashLen); |
8536 | 501k | PORT_Assert(len == hashLen); |
8537 | 501k | } |
8538 | 458k | HMAC_Destroy(hmac, PR_TRUE); |
8539 | 458k | okm = &keyBlockData[0]; |
8540 | 458k | } |
8541 | | /* key material = okm */ |
8542 | 494k | crv = CKR_OK; |
8543 | 494k | if (key) { |
8544 | 494k | crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize); |
8545 | 494k | } else { |
8546 | 0 | PORT_Assert(outKeyBytes != NULL); |
8547 | 0 | PORT_Memcpy(outKeyBytes, okm, keySize); |
8548 | 0 | } |
8549 | 494k | PORT_Memset(keyBlockData, 0, genLen); |
8550 | 494k | PORT_Memset(hashbuf, 0, sizeof(hashbuf)); |
8551 | 494k | PORT_Free(keyBlockAlloc); |
8552 | 494k | return crv; |
8553 | 494k | } |
8554 | | |
8555 | | /* |
8556 | | * SSL Key generation given pre master secret |
8557 | | */ |
8558 | 0 | #define NUM_MIXERS 9 |
8559 | | static const char *const mixers[NUM_MIXERS] = { |
8560 | | "A", |
8561 | | "BB", |
8562 | | "CCC", |
8563 | | "DDDD", |
8564 | | "EEEEE", |
8565 | | "FFFFFF", |
8566 | | "GGGGGGG", |
8567 | | "HHHHHHHH", |
8568 | | "IIIIIIIII" |
8569 | | }; |
8570 | 107k | #define SSL3_PMS_LENGTH 48 |
8571 | 440k | #define SSL3_MASTER_SECRET_LENGTH 48 |
8572 | 1.11M | #define SSL3_RANDOM_LENGTH 32 |
8573 | | |
8574 | | /* NSC_DeriveKey derives a key from a base key, creating a new key object. */ |
8575 | | CK_RV |
8576 | | NSC_DeriveKey(CK_SESSION_HANDLE hSession, |
8577 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, |
8578 | | CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, |
8579 | | CK_OBJECT_HANDLE_PTR phKey) |
8580 | 864k | { |
8581 | 864k | SFTKSession *session; |
8582 | 864k | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
8583 | 864k | SFTKObject *key; |
8584 | 864k | SFTKObject *sourceKey; |
8585 | 864k | SFTKAttribute *att = NULL; |
8586 | 864k | SFTKAttribute *att2 = NULL; |
8587 | 864k | unsigned char *buf; |
8588 | 864k | SHA1Context *sha; |
8589 | 864k | MD5Context *md5; |
8590 | 864k | MD2Context *md2; |
8591 | 864k | CK_ULONG macSize; |
8592 | 864k | CK_ULONG tmpKeySize; |
8593 | 864k | CK_ULONG IVSize; |
8594 | 864k | CK_ULONG keySize = 0; |
8595 | 864k | CK_RV crv = CKR_OK; |
8596 | 864k | CK_BBOOL cktrue = CK_TRUE; |
8597 | 864k | CK_BBOOL ckfalse = CK_FALSE; |
8598 | 864k | CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
8599 | 864k | CK_OBJECT_CLASS classType = CKO_SECRET_KEY; |
8600 | 864k | CK_KEY_DERIVATION_STRING_DATA *stringPtr; |
8601 | 864k | PRBool isTLS = PR_FALSE; |
8602 | 864k | PRBool isDH = PR_FALSE; |
8603 | 864k | HASH_HashType tlsPrfHash = HASH_AlgNULL; |
8604 | 864k | SECStatus rv; |
8605 | 864k | int i; |
8606 | 864k | unsigned int outLen; |
8607 | 864k | unsigned char sha_out[SHA1_LENGTH]; |
8608 | 864k | unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH]; |
8609 | 864k | PRBool isFIPS; |
8610 | 864k | HASH_HashType hashType; |
8611 | 864k | CK_MECHANISM_TYPE hashMech; |
8612 | 864k | PRBool extractValue = PR_TRUE; |
8613 | 864k | CK_IKE1_EXTENDED_DERIVE_PARAMS ikeAppB; |
8614 | 864k | CK_IKE1_EXTENDED_DERIVE_PARAMS *pIkeAppB; |
8615 | | |
8616 | 864k | CHECK_FORK(); |
8617 | | |
8618 | 864k | if (!slot) { |
8619 | 0 | return CKR_SESSION_HANDLE_INVALID; |
8620 | 0 | } |
8621 | 864k | if (!pMechanism) { |
8622 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8623 | 0 | } |
8624 | 864k | CK_MECHANISM_TYPE mechanism = pMechanism->mechanism; |
8625 | | |
8626 | | /* |
8627 | | * now lets create an object to hang the attributes off of |
8628 | | */ |
8629 | 864k | if (phKey) { |
8630 | 864k | *phKey = CK_INVALID_HANDLE; |
8631 | 864k | } |
8632 | | |
8633 | 864k | key = sftk_NewObject(slot); /* fill in the handle later */ |
8634 | 864k | if (key == NULL) { |
8635 | 0 | return CKR_HOST_MEMORY; |
8636 | 0 | } |
8637 | 864k | isFIPS = sftk_isFIPS(slot->slotID); |
8638 | | |
8639 | | /* |
8640 | | * load the template values into the object |
8641 | | */ |
8642 | 5.30M | for (i = 0; i < (int)ulAttributeCount; i++) { |
8643 | 4.44M | crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); |
8644 | 4.44M | if (crv != CKR_OK) |
8645 | 0 | break; |
8646 | | |
8647 | 4.44M | if (pTemplate[i].type == CKA_KEY_TYPE) { |
8648 | 864k | keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue; |
8649 | 864k | } |
8650 | 4.44M | if (pTemplate[i].type == CKA_VALUE_LEN) { |
8651 | 628k | keySize = *(CK_ULONG *)pTemplate[i].pValue; |
8652 | 628k | } |
8653 | 4.44M | } |
8654 | 864k | if (crv != CKR_OK) { |
8655 | 0 | sftk_FreeObject(key); |
8656 | 0 | return crv; |
8657 | 0 | } |
8658 | | |
8659 | 864k | if (keySize == 0) { |
8660 | 236k | keySize = sftk_MapKeySize(keyType); |
8661 | 236k | } |
8662 | | |
8663 | 864k | switch (mechanism) { |
8664 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */ |
8665 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */ |
8666 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */ |
8667 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA512: |
8668 | 0 | extractValue = PR_FALSE; |
8669 | 0 | classType = CKO_PRIVATE_KEY; |
8670 | 0 | break; |
8671 | 86 | case CKM_NSS_PUB_FROM_PRIV: |
8672 | 86 | extractValue = PR_FALSE; |
8673 | 86 | classType = CKO_PUBLIC_KEY; |
8674 | 86 | break; |
8675 | 145k | case CKM_HKDF_DATA: /* fall through */ |
8676 | 145k | case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */ |
8677 | 145k | case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */ |
8678 | 145k | case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: |
8679 | 145k | classType = CKO_DATA; |
8680 | 145k | break; |
8681 | 0 | case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */ |
8682 | 0 | case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */ |
8683 | 0 | case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */ |
8684 | 0 | case CKM_NSS_JPAKE_FINAL_SHA512: |
8685 | 0 | extractValue = PR_FALSE; |
8686 | | /* fall through */ |
8687 | 718k | default: |
8688 | 718k | classType = CKO_SECRET_KEY; |
8689 | 864k | } |
8690 | | |
8691 | 864k | crv = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType)); |
8692 | 864k | if (crv != CKR_OK) { |
8693 | 0 | sftk_FreeObject(key); |
8694 | 0 | return crv; |
8695 | 0 | } |
8696 | | |
8697 | | /* look up the base key we're deriving with */ |
8698 | 864k | session = sftk_SessionFromHandle(hSession); |
8699 | 864k | if (session == NULL) { |
8700 | 0 | sftk_FreeObject(key); |
8701 | 0 | return CKR_SESSION_HANDLE_INVALID; |
8702 | 0 | } |
8703 | | |
8704 | 864k | sourceKey = sftk_ObjectFromHandle(hBaseKey, session); |
8705 | | /* is this eventually succeeds, lastOpWasFIPS will be set the resulting key's |
8706 | | * FIPS state below. */ |
8707 | 864k | session->lastOpWasFIPS = PR_FALSE; |
8708 | 864k | sftk_FreeSession(session); |
8709 | 864k | if (sourceKey == NULL) { |
8710 | 0 | sftk_FreeObject(key); |
8711 | 0 | return CKR_KEY_HANDLE_INVALID; |
8712 | 0 | } |
8713 | | |
8714 | 864k | if (extractValue) { |
8715 | | /* get the value of the base key */ |
8716 | 864k | att = sftk_FindAttribute(sourceKey, CKA_VALUE); |
8717 | 864k | if (att == NULL) { |
8718 | 0 | sftk_FreeObject(key); |
8719 | 0 | sftk_FreeObject(sourceKey); |
8720 | 0 | return CKR_KEY_HANDLE_INVALID; |
8721 | 0 | } |
8722 | 864k | } |
8723 | 864k | sftk_setFIPS(key, sftk_operationIsFIPS(slot, pMechanism, |
8724 | 864k | CKA_DERIVE, sourceKey, |
8725 | 864k | keySize * PR_BITS_PER_BYTE)); |
8726 | | |
8727 | 864k | switch (mechanism) { |
8728 | | /* get a public key from a private key. nsslowkey_ConvertToPublickey() |
8729 | | * will generate the public portion if it doesn't already exist. */ |
8730 | 86 | case CKM_NSS_PUB_FROM_PRIV: { |
8731 | 86 | NSSLOWKEYPrivateKey *privKey; |
8732 | 86 | NSSLOWKEYPublicKey *pubKey; |
8733 | 86 | int error; |
8734 | | |
8735 | 86 | crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType); |
8736 | 86 | if (crv != CKR_OK) { |
8737 | 0 | break; |
8738 | 0 | } |
8739 | | |
8740 | | /* privKey is stored in sourceKey and will be destroyed when |
8741 | | * the sourceKey is freed. */ |
8742 | 86 | privKey = sftk_GetPrivKey(sourceKey, keyType, &crv); |
8743 | 86 | if (privKey == NULL) { |
8744 | 0 | break; |
8745 | 0 | } |
8746 | 86 | pubKey = nsslowkey_ConvertToPublicKey(privKey); |
8747 | 86 | if (pubKey == NULL) { |
8748 | 11 | error = PORT_GetError(); |
8749 | 11 | crv = sftk_MapCryptError(error); |
8750 | 11 | break; |
8751 | 11 | } |
8752 | 75 | crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey); |
8753 | 75 | nsslowkey_DestroyPublicKey(pubKey); |
8754 | 75 | break; |
8755 | 86 | } |
8756 | 0 | case CKM_NSS_IKE_PRF_DERIVE: |
8757 | 0 | case CKM_IKE_PRF_DERIVE: |
8758 | 0 | if (pMechanism->ulParameterLen != |
8759 | 0 | sizeof(CK_IKE_PRF_DERIVE_PARAMS)) { |
8760 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8761 | 0 | break; |
8762 | 0 | } |
8763 | 0 | crv = sftk_ike_prf(hSession, att, |
8764 | 0 | (CK_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key); |
8765 | 0 | break; |
8766 | 0 | case CKM_NSS_IKE1_PRF_DERIVE: |
8767 | 0 | case CKM_IKE1_PRF_DERIVE: |
8768 | 0 | if (pMechanism->ulParameterLen != |
8769 | 0 | sizeof(CK_IKE1_PRF_DERIVE_PARAMS)) { |
8770 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8771 | 0 | break; |
8772 | 0 | } |
8773 | 0 | crv = sftk_ike1_prf(hSession, att, |
8774 | 0 | (CK_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter, |
8775 | 0 | key, keySize); |
8776 | 0 | break; |
8777 | 0 | case CKM_NSS_IKE1_APP_B_PRF_DERIVE: |
8778 | 0 | case CKM_IKE1_EXTENDED_DERIVE: |
8779 | 0 | pIkeAppB = (CK_IKE1_EXTENDED_DERIVE_PARAMS *)pMechanism->pParameter; |
8780 | 0 | if (pMechanism->ulParameterLen == |
8781 | 0 | sizeof(CK_MECHANISM_TYPE)) { |
8782 | 0 | ikeAppB.prfMechanism = *(CK_MECHANISM_TYPE *)pMechanism->pParameter; |
8783 | 0 | ikeAppB.bHasKeygxy = PR_FALSE; |
8784 | 0 | ikeAppB.hKeygxy = CK_INVALID_HANDLE; |
8785 | 0 | ikeAppB.pExtraData = NULL; |
8786 | 0 | ikeAppB.ulExtraDataLen = 0; |
8787 | 0 | pIkeAppB = &ikeAppB; |
8788 | 0 | } else if (pMechanism->ulParameterLen != |
8789 | 0 | sizeof(CK_IKE1_EXTENDED_DERIVE_PARAMS)) { |
8790 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8791 | 0 | break; |
8792 | 0 | } |
8793 | 0 | crv = sftk_ike1_appendix_b_prf(hSession, att, pIkeAppB, key, |
8794 | 0 | keySize); |
8795 | 0 | break; |
8796 | 0 | case CKM_NSS_IKE_PRF_PLUS_DERIVE: |
8797 | 0 | case CKM_IKE2_PRF_PLUS_DERIVE: |
8798 | 0 | if (pMechanism->ulParameterLen != |
8799 | 0 | sizeof(CK_IKE2_PRF_PLUS_DERIVE_PARAMS)) { |
8800 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8801 | 0 | break; |
8802 | 0 | } |
8803 | 0 | crv = sftk_ike_prf_plus(hSession, att, |
8804 | 0 | (CK_IKE2_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter, |
8805 | 0 | key, keySize); |
8806 | 0 | break; |
8807 | | /* |
8808 | | * generate the master secret |
8809 | | */ |
8810 | 84.4k | case CKM_TLS12_MASTER_KEY_DERIVE: |
8811 | 106k | case CKM_TLS12_MASTER_KEY_DERIVE_DH: |
8812 | 106k | case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256: |
8813 | 106k | case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256: |
8814 | 123k | case CKM_TLS_MASTER_KEY_DERIVE: |
8815 | 155k | case CKM_TLS_MASTER_KEY_DERIVE_DH: |
8816 | 155k | case CKM_SSL3_MASTER_KEY_DERIVE: |
8817 | 155k | case CKM_SSL3_MASTER_KEY_DERIVE_DH: { |
8818 | 155k | CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master; |
8819 | 155k | SSL3RSAPreMasterSecret *rsa_pms; |
8820 | 155k | unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; |
8821 | | |
8822 | 155k | if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) || |
8823 | 106k | (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { |
8824 | 106k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) { |
8825 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8826 | 0 | break; |
8827 | 0 | } |
8828 | 106k | CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master = |
8829 | 106k | (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter; |
8830 | 106k | tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_master->prfHashMechanism); |
8831 | 106k | if (tlsPrfHash == HASH_AlgNULL) { |
8832 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8833 | 0 | break; |
8834 | 0 | } |
8835 | 106k | } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) || |
8836 | 48.8k | (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) { |
8837 | 0 | tlsPrfHash = HASH_AlgSHA256; |
8838 | 0 | } |
8839 | | |
8840 | 155k | if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) && |
8841 | 155k | (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) { |
8842 | 155k | isTLS = PR_TRUE; |
8843 | 155k | } |
8844 | 155k | if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) || |
8845 | 155k | (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) || |
8846 | 123k | (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) || |
8847 | 123k | (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { |
8848 | 54.9k | isDH = PR_TRUE; |
8849 | 54.9k | } |
8850 | | |
8851 | | /* first do the consistency checks */ |
8852 | 155k | if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { |
8853 | 3.81k | crv = CKR_KEY_TYPE_INCONSISTENT; |
8854 | 3.81k | break; |
8855 | 3.81k | } |
8856 | 151k | att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); |
8857 | 151k | if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != |
8858 | 151k | CKK_GENERIC_SECRET)) { |
8859 | 0 | if (att2) |
8860 | 0 | sftk_FreeAttribute(att2); |
8861 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
8862 | 0 | break; |
8863 | 0 | } |
8864 | 151k | sftk_FreeAttribute(att2); |
8865 | 151k | if (keyType != CKK_GENERIC_SECRET) { |
8866 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
8867 | 0 | break; |
8868 | 0 | } |
8869 | 151k | if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { |
8870 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
8871 | 0 | break; |
8872 | 0 | } |
8873 | | |
8874 | | /* finally do the key gen */ |
8875 | 151k | ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) |
8876 | 151k | pMechanism->pParameter; |
8877 | | |
8878 | 151k | if (ssl3_master->pVersion) { |
8879 | 96.9k | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
8880 | 96.9k | rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue; |
8881 | | /* don't leak more key material then necessary for SSL to work */ |
8882 | 96.9k | if ((sessKey == NULL) || sessKey->wasDerived) { |
8883 | 0 | ssl3_master->pVersion->major = 0xff; |
8884 | 0 | ssl3_master->pVersion->minor = 0xff; |
8885 | 96.9k | } else { |
8886 | 96.9k | ssl3_master->pVersion->major = rsa_pms->client_version[0]; |
8887 | 96.9k | ssl3_master->pVersion->minor = rsa_pms->client_version[1]; |
8888 | 96.9k | } |
8889 | 96.9k | } |
8890 | 151k | if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) { |
8891 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8892 | 0 | break; |
8893 | 0 | } |
8894 | 151k | if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) { |
8895 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8896 | 0 | break; |
8897 | 0 | } |
8898 | 151k | PORT_Memcpy(crsrdata, |
8899 | 151k | ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); |
8900 | 151k | PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, |
8901 | 151k | ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); |
8902 | | |
8903 | 151k | if (isTLS) { |
8904 | 151k | SECStatus status; |
8905 | 151k | SECItem crsr = { siBuffer, NULL, 0 }; |
8906 | 151k | SECItem master = { siBuffer, NULL, 0 }; |
8907 | 151k | SECItem pms = { siBuffer, NULL, 0 }; |
8908 | | |
8909 | 151k | crsr.data = crsrdata; |
8910 | 151k | crsr.len = sizeof crsrdata; |
8911 | 151k | master.data = key_block; |
8912 | 151k | master.len = SSL3_MASTER_SECRET_LENGTH; |
8913 | 151k | pms.data = (unsigned char *)att->attrib.pValue; |
8914 | 151k | pms.len = att->attrib.ulValueLen; |
8915 | | |
8916 | 151k | if (tlsPrfHash != HASH_AlgNULL) { |
8917 | 104k | status = TLS_P_hash(tlsPrfHash, &pms, "master secret", |
8918 | 104k | &crsr, &master, isFIPS); |
8919 | 104k | } else { |
8920 | 47.9k | status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS); |
8921 | 47.9k | } |
8922 | 151k | if (status != SECSuccess) { |
8923 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
8924 | 0 | crv = CKR_FUNCTION_FAILED; |
8925 | 0 | break; |
8926 | 0 | } |
8927 | 151k | } else { |
8928 | | /* now allocate the hash contexts */ |
8929 | 0 | md5 = MD5_NewContext(); |
8930 | 0 | if (md5 == NULL) { |
8931 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
8932 | 0 | crv = CKR_HOST_MEMORY; |
8933 | 0 | break; |
8934 | 0 | } |
8935 | 0 | sha = SHA1_NewContext(); |
8936 | 0 | if (sha == NULL) { |
8937 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
8938 | 0 | PORT_Free(md5); |
8939 | 0 | crv = CKR_HOST_MEMORY; |
8940 | 0 | break; |
8941 | 0 | } |
8942 | 0 | for (i = 0; i < 3; i++) { |
8943 | 0 | SHA1_Begin(sha); |
8944 | 0 | SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i])); |
8945 | 0 | SHA1_Update(sha, (const unsigned char *)att->attrib.pValue, |
8946 | 0 | att->attrib.ulValueLen); |
8947 | 0 | SHA1_Update(sha, crsrdata, sizeof crsrdata); |
8948 | 0 | SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); |
8949 | 0 | PORT_Assert(outLen == SHA1_LENGTH); |
8950 | |
|
8951 | 0 | MD5_Begin(md5); |
8952 | 0 | MD5_Update(md5, (const unsigned char *)att->attrib.pValue, |
8953 | 0 | att->attrib.ulValueLen); |
8954 | 0 | MD5_Update(md5, sha_out, outLen); |
8955 | 0 | MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH); |
8956 | 0 | PORT_Assert(outLen == MD5_LENGTH); |
8957 | 0 | } |
8958 | 0 | PORT_Free(md5); |
8959 | 0 | PORT_Free(sha); |
8960 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
8961 | 0 | PORT_Memset(sha_out, 0, sizeof sha_out); |
8962 | 0 | } |
8963 | | |
8964 | | /* store the results */ |
8965 | 151k | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, SSL3_MASTER_SECRET_LENGTH); |
8966 | 151k | PORT_Memset(key_block, 0, sizeof key_block); |
8967 | 151k | if (crv != CKR_OK) |
8968 | 0 | break; |
8969 | 151k | keyType = CKK_GENERIC_SECRET; |
8970 | 151k | crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType)); |
8971 | 151k | if (isTLS) { |
8972 | | /* TLS's master secret is used to "sign" finished msgs with PRF. */ |
8973 | | /* XXX This seems like a hack. But SFTK_Derive only accepts |
8974 | | * one "operation" argument. */ |
8975 | 151k | crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); |
8976 | 151k | if (crv != CKR_OK) |
8977 | 0 | break; |
8978 | 151k | crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); |
8979 | 151k | if (crv != CKR_OK) |
8980 | 0 | break; |
8981 | | /* While we're here, we might as well force this, too. */ |
8982 | 151k | crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); |
8983 | 151k | if (crv != CKR_OK) |
8984 | 0 | break; |
8985 | 151k | } |
8986 | 151k | break; |
8987 | 151k | } |
8988 | | |
8989 | | /* Extended master key derivation [draft-ietf-tls-session-hash] */ |
8990 | 151k | case CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE: |
8991 | 9.23k | case CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE_DH: |
8992 | 9.23k | case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE: |
8993 | 9.23k | case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: { |
8994 | 9.23k | CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params; |
8995 | 9.23k | SSL3RSAPreMasterSecret *rsa_pms; |
8996 | 9.23k | SECStatus status; |
8997 | 9.23k | SECItem pms = { siBuffer, NULL, 0 }; |
8998 | 9.23k | SECItem seed = { siBuffer, NULL, 0 }; |
8999 | 9.23k | SECItem master = { siBuffer, NULL, 0 }; |
9000 | | |
9001 | 9.23k | ems_params = (CK_TLS12_EXTENDED_MASTER_KEY_DERIVE_PARAMS *) |
9002 | 9.23k | pMechanism->pParameter; |
9003 | | |
9004 | | /* First do the consistency checks */ |
9005 | 9.23k | if (((mechanism == CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE) || |
9006 | 2.61k | (mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE)) && |
9007 | 6.61k | (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { |
9008 | 61 | crv = CKR_KEY_TYPE_INCONSISTENT; |
9009 | 61 | break; |
9010 | 61 | } |
9011 | 9.17k | att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); |
9012 | 9.17k | if ((att2 == NULL) || |
9013 | 9.17k | (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) { |
9014 | 0 | if (att2) |
9015 | 0 | sftk_FreeAttribute(att2); |
9016 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
9017 | 0 | break; |
9018 | 0 | } |
9019 | 9.17k | sftk_FreeAttribute(att2); |
9020 | 9.17k | if (keyType != CKK_GENERIC_SECRET) { |
9021 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
9022 | 0 | break; |
9023 | 0 | } |
9024 | 9.17k | if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { |
9025 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
9026 | 0 | break; |
9027 | 0 | } |
9028 | | |
9029 | | /* Do the key derivation */ |
9030 | 9.17k | pms.data = (unsigned char *)att->attrib.pValue; |
9031 | 9.17k | pms.len = att->attrib.ulValueLen; |
9032 | 9.17k | seed.data = ems_params->pSessionHash; |
9033 | 9.17k | seed.len = ems_params->ulSessionHashLen; |
9034 | 9.17k | master.data = key_block; |
9035 | 9.17k | master.len = SSL3_MASTER_SECRET_LENGTH; |
9036 | 9.17k | if (ems_params->prfHashMechanism == CKM_TLS_PRF) { |
9037 | | /* |
9038 | | * In this case, the session hash is the concatenation of SHA-1 |
9039 | | * and MD5, so it should be 36 bytes long. |
9040 | | */ |
9041 | 2.54k | if (seed.len != MD5_LENGTH + SHA1_LENGTH) { |
9042 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9043 | 0 | break; |
9044 | 0 | } |
9045 | | |
9046 | 2.54k | status = TLS_PRF(&pms, "extended master secret", |
9047 | 2.54k | &seed, &master, isFIPS); |
9048 | 6.63k | } else { |
9049 | 6.63k | const SECHashObject *hashObj; |
9050 | | |
9051 | 6.63k | tlsPrfHash = sftk_GetHashTypeFromMechanism(ems_params->prfHashMechanism); |
9052 | 6.63k | if (tlsPrfHash == HASH_AlgNULL) { |
9053 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9054 | 0 | break; |
9055 | 0 | } |
9056 | | |
9057 | 6.63k | hashObj = HASH_GetRawHashObject(tlsPrfHash); |
9058 | 6.63k | if (seed.len != hashObj->length) { |
9059 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9060 | 0 | break; |
9061 | 0 | } |
9062 | | |
9063 | 6.63k | status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret", |
9064 | 6.63k | &seed, &master, isFIPS); |
9065 | 6.63k | } |
9066 | 9.17k | if (status != SECSuccess) { |
9067 | 0 | crv = CKR_FUNCTION_FAILED; |
9068 | 0 | break; |
9069 | 0 | } |
9070 | | |
9071 | | /* Reflect the version if required */ |
9072 | 9.17k | if (ems_params->pVersion) { |
9073 | 6.55k | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
9074 | 6.55k | rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue; |
9075 | | /* don't leak more key material than necessary for SSL to work */ |
9076 | 6.55k | if ((sessKey == NULL) || sessKey->wasDerived) { |
9077 | 0 | ems_params->pVersion->major = 0xff; |
9078 | 0 | ems_params->pVersion->minor = 0xff; |
9079 | 6.55k | } else { |
9080 | 6.55k | ems_params->pVersion->major = rsa_pms->client_version[0]; |
9081 | 6.55k | ems_params->pVersion->minor = rsa_pms->client_version[1]; |
9082 | 6.55k | } |
9083 | 6.55k | } |
9084 | | |
9085 | | /* Store the results */ |
9086 | 9.17k | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, |
9087 | 9.17k | SSL3_MASTER_SECRET_LENGTH); |
9088 | 9.17k | PORT_Memset(key_block, 0, sizeof key_block); |
9089 | 9.17k | break; |
9090 | 9.17k | } |
9091 | | |
9092 | 75.4k | case CKM_TLS12_KEY_AND_MAC_DERIVE: |
9093 | 75.4k | case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: |
9094 | 118k | case CKM_TLS_KEY_AND_MAC_DERIVE: |
9095 | 118k | case CKM_SSL3_KEY_AND_MAC_DERIVE: { |
9096 | 118k | CK_SSL3_KEY_MAT_PARAMS *ssl3_keys; |
9097 | 118k | CK_SSL3_KEY_MAT_OUT *ssl3_keys_out; |
9098 | 118k | CK_ULONG effKeySize; |
9099 | 118k | unsigned int block_needed; |
9100 | 118k | unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; |
9101 | | |
9102 | 118k | if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) { |
9103 | 75.4k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) { |
9104 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9105 | 0 | break; |
9106 | 0 | } |
9107 | 75.4k | CK_TLS12_KEY_MAT_PARAMS *tls12_keys = |
9108 | 75.4k | (CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter; |
9109 | 75.4k | tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_keys->prfHashMechanism); |
9110 | 75.4k | if (tlsPrfHash == HASH_AlgNULL) { |
9111 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9112 | 0 | break; |
9113 | 0 | } |
9114 | 75.4k | } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) { |
9115 | 0 | tlsPrfHash = HASH_AlgSHA256; |
9116 | 0 | } |
9117 | | |
9118 | 118k | if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) { |
9119 | 118k | isTLS = PR_TRUE; |
9120 | 118k | } |
9121 | | |
9122 | 118k | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9123 | 118k | if (crv != CKR_OK) |
9124 | 0 | break; |
9125 | | |
9126 | 118k | if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) { |
9127 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
9128 | 0 | break; |
9129 | 0 | } |
9130 | 118k | att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); |
9131 | 118k | if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != |
9132 | 118k | CKK_GENERIC_SECRET)) { |
9133 | 0 | if (att2) |
9134 | 0 | sftk_FreeAttribute(att2); |
9135 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
9136 | 0 | break; |
9137 | 0 | } |
9138 | 118k | sftk_FreeAttribute(att2); |
9139 | 118k | md5 = MD5_NewContext(); |
9140 | 118k | if (md5 == NULL) { |
9141 | 0 | crv = CKR_HOST_MEMORY; |
9142 | 0 | break; |
9143 | 0 | } |
9144 | 118k | sha = SHA1_NewContext(); |
9145 | 118k | if (sha == NULL) { |
9146 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
9147 | 0 | crv = CKR_HOST_MEMORY; |
9148 | 0 | break; |
9149 | 0 | } |
9150 | | |
9151 | 118k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_SSL3_KEY_MAT_PARAMS))) { |
9152 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
9153 | 0 | SHA1_DestroyContext(sha, PR_TRUE); |
9154 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9155 | 0 | break; |
9156 | 0 | } |
9157 | 118k | ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter; |
9158 | | |
9159 | 118k | PORT_Memcpy(srcrdata, |
9160 | 118k | ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); |
9161 | 118k | PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, |
9162 | 118k | ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); |
9163 | | |
9164 | | /* |
9165 | | * clear out our returned keys so we can recover on failure |
9166 | | */ |
9167 | 118k | ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial; |
9168 | 118k | ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE; |
9169 | 118k | ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE; |
9170 | 118k | ssl3_keys_out->hClientKey = CK_INVALID_HANDLE; |
9171 | 118k | ssl3_keys_out->hServerKey = CK_INVALID_HANDLE; |
9172 | | |
9173 | | /* |
9174 | | * How much key material do we need? |
9175 | | */ |
9176 | 118k | macSize = ssl3_keys->ulMacSizeInBits / 8; |
9177 | 118k | effKeySize = ssl3_keys->ulKeySizeInBits / 8; |
9178 | 118k | IVSize = ssl3_keys->ulIVSizeInBits / 8; |
9179 | 118k | if (keySize == 0) { |
9180 | 13.9k | effKeySize = keySize; |
9181 | 13.9k | } |
9182 | | |
9183 | | /* bIsExport must be false. */ |
9184 | 118k | if (ssl3_keys->bIsExport) { |
9185 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
9186 | 0 | SHA1_DestroyContext(sha, PR_TRUE); |
9187 | 0 | PORT_Memset(srcrdata, 0, sizeof srcrdata); |
9188 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9189 | 0 | break; |
9190 | 0 | } |
9191 | | |
9192 | 118k | block_needed = 2 * (macSize + effKeySize + IVSize); |
9193 | 118k | PORT_Assert(block_needed <= sizeof key_block); |
9194 | 118k | if (block_needed > sizeof key_block) |
9195 | 0 | block_needed = sizeof key_block; |
9196 | | |
9197 | | /* |
9198 | | * generate the key material: This looks amazingly similar to the |
9199 | | * PMS code, and is clearly crying out for a function to provide it. |
9200 | | */ |
9201 | 118k | if (isTLS) { |
9202 | 118k | SECStatus status; |
9203 | 118k | SECItem srcr = { siBuffer, NULL, 0 }; |
9204 | 118k | SECItem keyblk = { siBuffer, NULL, 0 }; |
9205 | 118k | SECItem master = { siBuffer, NULL, 0 }; |
9206 | | |
9207 | 118k | srcr.data = srcrdata; |
9208 | 118k | srcr.len = sizeof srcrdata; |
9209 | 118k | keyblk.data = key_block; |
9210 | 118k | keyblk.len = block_needed; |
9211 | 118k | master.data = (unsigned char *)att->attrib.pValue; |
9212 | 118k | master.len = att->attrib.ulValueLen; |
9213 | | |
9214 | 118k | if (tlsPrfHash != HASH_AlgNULL) { |
9215 | 75.4k | status = TLS_P_hash(tlsPrfHash, &master, "key expansion", |
9216 | 75.4k | &srcr, &keyblk, isFIPS); |
9217 | 75.4k | } else { |
9218 | 43.2k | status = TLS_PRF(&master, "key expansion", &srcr, &keyblk, |
9219 | 43.2k | isFIPS); |
9220 | 43.2k | } |
9221 | 118k | if (status != SECSuccess) { |
9222 | 0 | goto key_and_mac_derive_fail; |
9223 | 0 | } |
9224 | 118k | } else { |
9225 | 0 | unsigned int block_bytes = 0; |
9226 | | /* key_block = |
9227 | | * MD5(master_secret + SHA('A' + master_secret + |
9228 | | * ServerHello.random + ClientHello.random)) + |
9229 | | * MD5(master_secret + SHA('BB' + master_secret + |
9230 | | * ServerHello.random + ClientHello.random)) + |
9231 | | * MD5(master_secret + SHA('CCC' + master_secret + |
9232 | | * ServerHello.random + ClientHello.random)) + |
9233 | | * [...]; |
9234 | | */ |
9235 | 0 | for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) { |
9236 | 0 | SHA1_Begin(sha); |
9237 | 0 | SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i])); |
9238 | 0 | SHA1_Update(sha, (const unsigned char *)att->attrib.pValue, |
9239 | 0 | att->attrib.ulValueLen); |
9240 | 0 | SHA1_Update(sha, srcrdata, sizeof srcrdata); |
9241 | 0 | SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); |
9242 | 0 | PORT_Assert(outLen == SHA1_LENGTH); |
9243 | 0 | MD5_Begin(md5); |
9244 | 0 | MD5_Update(md5, (const unsigned char *)att->attrib.pValue, |
9245 | 0 | att->attrib.ulValueLen); |
9246 | 0 | MD5_Update(md5, sha_out, outLen); |
9247 | 0 | MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH); |
9248 | 0 | PORT_Assert(outLen == MD5_LENGTH); |
9249 | 0 | block_bytes += outLen; |
9250 | 0 | } |
9251 | 0 | PORT_Memset(sha_out, 0, sizeof sha_out); |
9252 | 0 | } |
9253 | | |
9254 | | /* |
9255 | | * Put the key material where it goes. |
9256 | | */ |
9257 | 118k | i = 0; /* now shows how much consumed */ |
9258 | | |
9259 | | /* |
9260 | | * The key_block is partitioned as follows: |
9261 | | * client_write_MAC_secret[CipherSpec.hash_size] |
9262 | | */ |
9263 | 118k | crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize, |
9264 | 118k | &ssl3_keys_out->hClientMacSecret); |
9265 | 118k | if (crv != CKR_OK) |
9266 | 0 | goto key_and_mac_derive_fail; |
9267 | | |
9268 | 118k | i += macSize; |
9269 | | |
9270 | | /* |
9271 | | * server_write_MAC_secret[CipherSpec.hash_size] |
9272 | | */ |
9273 | 118k | crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize, |
9274 | 118k | &ssl3_keys_out->hServerMacSecret); |
9275 | 118k | if (crv != CKR_OK) { |
9276 | 0 | goto key_and_mac_derive_fail; |
9277 | 0 | } |
9278 | 118k | i += macSize; |
9279 | | |
9280 | 118k | if (keySize) { |
9281 | | /* |
9282 | | ** Generate Domestic write keys and IVs. |
9283 | | ** client_write_key[CipherSpec.key_material] |
9284 | | */ |
9285 | 104k | crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i], |
9286 | 104k | keySize, &ssl3_keys_out->hClientKey); |
9287 | 104k | if (crv != CKR_OK) { |
9288 | 0 | goto key_and_mac_derive_fail; |
9289 | 0 | } |
9290 | 104k | i += keySize; |
9291 | | |
9292 | | /* |
9293 | | ** server_write_key[CipherSpec.key_material] |
9294 | | */ |
9295 | 104k | crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i], |
9296 | 104k | keySize, &ssl3_keys_out->hServerKey); |
9297 | 104k | if (crv != CKR_OK) { |
9298 | 0 | goto key_and_mac_derive_fail; |
9299 | 0 | } |
9300 | 104k | i += keySize; |
9301 | | |
9302 | | /* |
9303 | | ** client_write_IV[CipherSpec.IV_size] |
9304 | | */ |
9305 | 104k | if (IVSize > 0) { |
9306 | 101k | PORT_Memcpy(ssl3_keys_out->pIVClient, |
9307 | 101k | &key_block[i], IVSize); |
9308 | 101k | i += IVSize; |
9309 | 101k | } |
9310 | | |
9311 | | /* |
9312 | | ** server_write_IV[CipherSpec.IV_size] |
9313 | | */ |
9314 | 104k | if (IVSize > 0) { |
9315 | 101k | PORT_Memcpy(ssl3_keys_out->pIVServer, |
9316 | 101k | &key_block[i], IVSize); |
9317 | 101k | i += IVSize; |
9318 | 101k | } |
9319 | 104k | PORT_Assert(i <= sizeof key_block); |
9320 | 104k | } |
9321 | | |
9322 | 118k | crv = CKR_OK; |
9323 | | |
9324 | 118k | if (0) { |
9325 | 0 | key_and_mac_derive_fail: |
9326 | 0 | if (crv == CKR_OK) |
9327 | 0 | crv = CKR_FUNCTION_FAILED; |
9328 | 0 | sftk_freeSSLKeys(hSession, ssl3_keys_out); |
9329 | 0 | } |
9330 | 118k | PORT_Memset(srcrdata, 0, sizeof srcrdata); |
9331 | 118k | PORT_Memset(key_block, 0, sizeof key_block); |
9332 | 118k | MD5_DestroyContext(md5, PR_TRUE); |
9333 | 118k | SHA1_DestroyContext(sha, PR_TRUE); |
9334 | 118k | sftk_FreeObject(key); |
9335 | 118k | key = NULL; |
9336 | 118k | break; |
9337 | 118k | } |
9338 | | |
9339 | 0 | case CKM_DES3_ECB_ENCRYPT_DATA: |
9340 | 0 | case CKM_DES3_CBC_ENCRYPT_DATA: { |
9341 | 0 | void *cipherInfo; |
9342 | 0 | unsigned char des3key[MAX_DES3_KEY_SIZE]; |
9343 | 0 | CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr; |
9344 | 0 | int mode; |
9345 | 0 | unsigned char *iv; |
9346 | 0 | unsigned char *data; |
9347 | 0 | CK_ULONG len; |
9348 | |
|
9349 | 0 | if (mechanism == CKM_DES3_ECB_ENCRYPT_DATA) { |
9350 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9351 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9352 | 0 | break; |
9353 | 0 | } |
9354 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) |
9355 | 0 | pMechanism->pParameter; |
9356 | 0 | mode = NSS_DES_EDE3; |
9357 | 0 | iv = NULL; |
9358 | 0 | data = stringPtr->pData; |
9359 | 0 | len = stringPtr->ulLen; |
9360 | 0 | } else { |
9361 | 0 | mode = NSS_DES_EDE3_CBC; |
9362 | 0 | desEncryptPtr = |
9363 | 0 | (CK_DES_CBC_ENCRYPT_DATA_PARAMS *) |
9364 | 0 | pMechanism->pParameter; |
9365 | 0 | iv = desEncryptPtr->iv; |
9366 | 0 | data = desEncryptPtr->pData; |
9367 | 0 | len = desEncryptPtr->length; |
9368 | 0 | } |
9369 | 0 | if (att->attrib.ulValueLen == 16) { |
9370 | 0 | PORT_Memcpy(des3key, att->attrib.pValue, 16); |
9371 | 0 | PORT_Memcpy(des3key + 16, des3key, 8); |
9372 | 0 | } else if (att->attrib.ulValueLen == 24) { |
9373 | 0 | PORT_Memcpy(des3key, att->attrib.pValue, 24); |
9374 | 0 | } else { |
9375 | 0 | crv = CKR_KEY_SIZE_RANGE; |
9376 | 0 | break; |
9377 | 0 | } |
9378 | 0 | cipherInfo = DES_CreateContext(des3key, iv, mode, PR_TRUE); |
9379 | 0 | PORT_Memset(des3key, 0, 24); |
9380 | 0 | if (cipherInfo == NULL) { |
9381 | 0 | crv = CKR_HOST_MEMORY; |
9382 | 0 | break; |
9383 | 0 | } |
9384 | 0 | crv = sftk_DeriveEncrypt(SFTKCipher_DES_Encrypt, |
9385 | 0 | cipherInfo, 8, key, keySize, |
9386 | 0 | data, len); |
9387 | 0 | DES_DestroyContext(cipherInfo, PR_TRUE); |
9388 | 0 | break; |
9389 | 0 | } |
9390 | | |
9391 | 0 | case CKM_AES_ECB_ENCRYPT_DATA: |
9392 | 0 | case CKM_AES_CBC_ENCRYPT_DATA: { |
9393 | 0 | void *cipherInfo; |
9394 | 0 | CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; |
9395 | 0 | int mode; |
9396 | 0 | unsigned char *iv; |
9397 | 0 | unsigned char *data; |
9398 | 0 | CK_ULONG len; |
9399 | |
|
9400 | 0 | if (mechanism == CKM_AES_ECB_ENCRYPT_DATA) { |
9401 | 0 | mode = NSS_AES; |
9402 | 0 | iv = NULL; |
9403 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9404 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9405 | 0 | break; |
9406 | 0 | } |
9407 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
9408 | 0 | data = stringPtr->pData; |
9409 | 0 | len = stringPtr->ulLen; |
9410 | 0 | } else { |
9411 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) { |
9412 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9413 | 0 | break; |
9414 | 0 | } |
9415 | 0 | aesEncryptPtr = |
9416 | 0 | (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)pMechanism->pParameter; |
9417 | 0 | mode = NSS_AES_CBC; |
9418 | 0 | iv = aesEncryptPtr->iv; |
9419 | 0 | data = aesEncryptPtr->pData; |
9420 | 0 | len = aesEncryptPtr->length; |
9421 | 0 | } |
9422 | | |
9423 | 0 | cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue, |
9424 | 0 | iv, mode, PR_TRUE, |
9425 | 0 | att->attrib.ulValueLen, 16); |
9426 | 0 | if (cipherInfo == NULL) { |
9427 | 0 | crv = CKR_HOST_MEMORY; |
9428 | 0 | break; |
9429 | 0 | } |
9430 | 0 | crv = sftk_DeriveEncrypt(SFTKCipher_AES_Encrypt, |
9431 | 0 | cipherInfo, 16, key, keySize, |
9432 | 0 | data, len); |
9433 | 0 | AES_DestroyContext(cipherInfo, PR_TRUE); |
9434 | 0 | break; |
9435 | 0 | } |
9436 | | |
9437 | 0 | case CKM_CAMELLIA_ECB_ENCRYPT_DATA: |
9438 | 0 | case CKM_CAMELLIA_CBC_ENCRYPT_DATA: { |
9439 | 0 | void *cipherInfo; |
9440 | 0 | CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; |
9441 | 0 | int mode; |
9442 | 0 | unsigned char *iv; |
9443 | 0 | unsigned char *data; |
9444 | 0 | CK_ULONG len; |
9445 | |
|
9446 | 0 | if (mechanism == CKM_CAMELLIA_ECB_ENCRYPT_DATA) { |
9447 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9448 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9449 | 0 | break; |
9450 | 0 | } |
9451 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) |
9452 | 0 | pMechanism->pParameter; |
9453 | 0 | aesEncryptPtr = NULL; |
9454 | 0 | mode = NSS_CAMELLIA; |
9455 | 0 | data = stringPtr->pData; |
9456 | 0 | len = stringPtr->ulLen; |
9457 | 0 | iv = NULL; |
9458 | 0 | } else { |
9459 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) { |
9460 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9461 | 0 | break; |
9462 | 0 | } |
9463 | 0 | stringPtr = NULL; |
9464 | 0 | aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *) |
9465 | 0 | pMechanism->pParameter; |
9466 | 0 | mode = NSS_CAMELLIA_CBC; |
9467 | 0 | iv = aesEncryptPtr->iv; |
9468 | 0 | data = aesEncryptPtr->pData; |
9469 | 0 | len = aesEncryptPtr->length; |
9470 | 0 | } |
9471 | | |
9472 | 0 | cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue, |
9473 | 0 | iv, mode, PR_TRUE, |
9474 | 0 | att->attrib.ulValueLen); |
9475 | 0 | if (cipherInfo == NULL) { |
9476 | 0 | crv = CKR_HOST_MEMORY; |
9477 | 0 | break; |
9478 | 0 | } |
9479 | 0 | crv = sftk_DeriveEncrypt(SFTKCipher_Camellia_Encrypt, |
9480 | 0 | cipherInfo, 16, key, keySize, |
9481 | 0 | data, len); |
9482 | 0 | Camellia_DestroyContext(cipherInfo, PR_TRUE); |
9483 | 0 | break; |
9484 | 0 | } |
9485 | | |
9486 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
9487 | 0 | case CKM_SEED_ECB_ENCRYPT_DATA: |
9488 | 0 | case CKM_SEED_CBC_ENCRYPT_DATA: { |
9489 | 0 | void *cipherInfo; |
9490 | 0 | CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; |
9491 | 0 | int mode; |
9492 | 0 | unsigned char *iv; |
9493 | 0 | unsigned char *data; |
9494 | 0 | CK_ULONG len; |
9495 | |
|
9496 | 0 | if (mechanism == CKM_SEED_ECB_ENCRYPT_DATA) { |
9497 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9498 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9499 | 0 | break; |
9500 | 0 | } |
9501 | 0 | mode = NSS_SEED; |
9502 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) |
9503 | 0 | pMechanism->pParameter; |
9504 | 0 | aesEncryptPtr = NULL; |
9505 | 0 | data = stringPtr->pData; |
9506 | 0 | len = stringPtr->ulLen; |
9507 | 0 | iv = NULL; |
9508 | 0 | } else { |
9509 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) { |
9510 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9511 | 0 | break; |
9512 | 0 | } |
9513 | 0 | mode = NSS_SEED_CBC; |
9514 | 0 | aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *) |
9515 | 0 | pMechanism->pParameter; |
9516 | 0 | iv = aesEncryptPtr->iv; |
9517 | 0 | data = aesEncryptPtr->pData; |
9518 | 0 | len = aesEncryptPtr->length; |
9519 | 0 | } |
9520 | | |
9521 | 0 | cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue, |
9522 | 0 | iv, mode, PR_TRUE); |
9523 | 0 | if (cipherInfo == NULL) { |
9524 | 0 | crv = CKR_HOST_MEMORY; |
9525 | 0 | break; |
9526 | 0 | } |
9527 | 0 | crv = sftk_DeriveEncrypt(SFTKCipher_SEED_Encrypt, |
9528 | 0 | cipherInfo, 16, key, keySize, |
9529 | 0 | data, len); |
9530 | 0 | SEED_DestroyContext(cipherInfo, PR_TRUE); |
9531 | 0 | break; |
9532 | 0 | } |
9533 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
9534 | | |
9535 | 737 | case CKM_CONCATENATE_BASE_AND_KEY: { |
9536 | 737 | SFTKObject *paramKey; |
9537 | | |
9538 | 737 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9539 | 737 | if (crv != CKR_OK) |
9540 | 0 | break; |
9541 | | |
9542 | 737 | session = sftk_SessionFromHandle(hSession); |
9543 | 737 | if (session == NULL) { |
9544 | 0 | crv = CKR_SESSION_HANDLE_INVALID; |
9545 | 0 | break; |
9546 | 0 | } |
9547 | | |
9548 | 737 | paramKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *) |
9549 | 737 | pMechanism->pParameter, |
9550 | 737 | session); |
9551 | 737 | sftk_FreeSession(session); |
9552 | 737 | if (paramKey == NULL) { |
9553 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
9554 | 0 | break; |
9555 | 0 | } |
9556 | | |
9557 | 737 | if (sftk_isTrue(paramKey, CKA_SENSITIVE)) { |
9558 | 0 | crv = sftk_forceAttribute(key, CKA_SENSITIVE, &cktrue, |
9559 | 0 | sizeof(CK_BBOOL)); |
9560 | 0 | if (crv != CKR_OK) { |
9561 | 0 | sftk_FreeObject(paramKey); |
9562 | 0 | break; |
9563 | 0 | } |
9564 | 0 | } |
9565 | | |
9566 | 737 | if (sftk_hasAttribute(paramKey, CKA_EXTRACTABLE) && !sftk_isTrue(paramKey, CKA_EXTRACTABLE)) { |
9567 | 0 | crv = sftk_forceAttribute(key, CKA_EXTRACTABLE, &ckfalse, sizeof(CK_BBOOL)); |
9568 | 0 | if (crv != CKR_OK) { |
9569 | 0 | sftk_FreeObject(paramKey); |
9570 | 0 | break; |
9571 | 0 | } |
9572 | 0 | } |
9573 | | |
9574 | 737 | att2 = sftk_FindAttribute(paramKey, CKA_VALUE); |
9575 | 737 | if (att2 == NULL) { |
9576 | 0 | sftk_FreeObject(paramKey); |
9577 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
9578 | 0 | break; |
9579 | 0 | } |
9580 | 737 | tmpKeySize = att->attrib.ulValueLen + att2->attrib.ulValueLen; |
9581 | 737 | if (keySize == 0) |
9582 | 737 | keySize = tmpKeySize; |
9583 | 737 | if (keySize > tmpKeySize) { |
9584 | 0 | sftk_FreeAttribute(att2); |
9585 | 0 | sftk_FreeObject(paramKey); |
9586 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9587 | 0 | break; |
9588 | 0 | } |
9589 | 737 | buf = (unsigned char *)PORT_Alloc(tmpKeySize); |
9590 | 737 | if (buf == NULL) { |
9591 | 0 | sftk_FreeAttribute(att2); |
9592 | 0 | sftk_FreeObject(paramKey); |
9593 | 0 | crv = CKR_HOST_MEMORY; |
9594 | 0 | break; |
9595 | 0 | } |
9596 | | |
9597 | 737 | PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen); |
9598 | 737 | PORT_Memcpy(buf + att->attrib.ulValueLen, |
9599 | 737 | att2->attrib.pValue, att2->attrib.ulValueLen); |
9600 | | |
9601 | 737 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
9602 | 737 | PORT_ZFree(buf, tmpKeySize); |
9603 | | /* preserve the source of the original base key */ |
9604 | 737 | key->source = sourceKey->source; |
9605 | | |
9606 | | /* make sure this is fully fips approved, and mark it |
9607 | | * unapproved if not */ |
9608 | 737 | if (sftk_hasFIPS(key)) { |
9609 | 0 | sftk_setFIPS(key, sftk_hasFIPS(paramKey)); |
9610 | 0 | } |
9611 | 737 | sftk_FreeAttribute(att2); |
9612 | 737 | sftk_FreeObject(paramKey); |
9613 | 737 | break; |
9614 | 737 | } |
9615 | | |
9616 | 0 | case CKM_CONCATENATE_BASE_AND_DATA: |
9617 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9618 | 0 | if (crv != CKR_OK) |
9619 | 0 | break; |
9620 | | |
9621 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9622 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9623 | 0 | break; |
9624 | 0 | } |
9625 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
9626 | 0 | tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen; |
9627 | 0 | if (keySize == 0) |
9628 | 0 | keySize = tmpKeySize; |
9629 | 0 | if (keySize > tmpKeySize) { |
9630 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9631 | 0 | break; |
9632 | 0 | } |
9633 | 0 | buf = (unsigned char *)PORT_Alloc(tmpKeySize); |
9634 | 0 | if (buf == NULL) { |
9635 | 0 | crv = CKR_HOST_MEMORY; |
9636 | 0 | break; |
9637 | 0 | } |
9638 | | |
9639 | 0 | PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen); |
9640 | 0 | PORT_Memcpy(buf + att->attrib.ulValueLen, stringPtr->pData, |
9641 | 0 | stringPtr->ulLen); |
9642 | |
|
9643 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
9644 | 0 | PORT_ZFree(buf, tmpKeySize); |
9645 | 0 | break; |
9646 | 6.67k | case CKM_CONCATENATE_DATA_AND_BASE: |
9647 | 6.67k | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9648 | 6.67k | if (crv != CKR_OK) |
9649 | 0 | break; |
9650 | | |
9651 | 6.67k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9652 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9653 | 0 | break; |
9654 | 0 | } |
9655 | 6.67k | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
9656 | 6.67k | tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen; |
9657 | 6.67k | if (keySize == 0) |
9658 | 6.67k | keySize = tmpKeySize; |
9659 | 6.67k | if (keySize > tmpKeySize) { |
9660 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9661 | 0 | break; |
9662 | 0 | } |
9663 | 6.67k | buf = (unsigned char *)PORT_Alloc(tmpKeySize); |
9664 | 6.67k | if (buf == NULL) { |
9665 | 0 | crv = CKR_HOST_MEMORY; |
9666 | 0 | break; |
9667 | 0 | } |
9668 | | |
9669 | 6.67k | PORT_Memcpy(buf, stringPtr->pData, stringPtr->ulLen); |
9670 | 6.67k | PORT_Memcpy(buf + stringPtr->ulLen, att->attrib.pValue, |
9671 | 6.67k | att->attrib.ulValueLen); |
9672 | | |
9673 | 6.67k | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
9674 | 6.67k | PORT_ZFree(buf, tmpKeySize); |
9675 | 6.67k | break; |
9676 | 0 | case CKM_XOR_BASE_AND_DATA: |
9677 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9678 | 0 | if (crv != CKR_OK) |
9679 | 0 | break; |
9680 | | |
9681 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9682 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9683 | 0 | break; |
9684 | 0 | } |
9685 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
9686 | 0 | tmpKeySize = PR_MIN(att->attrib.ulValueLen, stringPtr->ulLen); |
9687 | 0 | if (keySize == 0) |
9688 | 0 | keySize = tmpKeySize; |
9689 | 0 | if (keySize > tmpKeySize) { |
9690 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9691 | 0 | break; |
9692 | 0 | } |
9693 | 0 | buf = (unsigned char *)PORT_Alloc(keySize); |
9694 | 0 | if (buf == NULL) { |
9695 | 0 | crv = CKR_HOST_MEMORY; |
9696 | 0 | break; |
9697 | 0 | } |
9698 | | |
9699 | 0 | PORT_Memcpy(buf, att->attrib.pValue, keySize); |
9700 | 0 | for (i = 0; i < (int)keySize; i++) { |
9701 | 0 | buf[i] ^= stringPtr->pData[i]; |
9702 | 0 | } |
9703 | |
|
9704 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
9705 | 0 | PORT_ZFree(buf, keySize); |
9706 | 0 | break; |
9707 | | |
9708 | 0 | case CKM_EXTRACT_KEY_FROM_KEY: { |
9709 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_EXTRACT_PARAMS))) { |
9710 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9711 | 0 | break; |
9712 | 0 | } |
9713 | | /* the following assumes 8 bits per byte */ |
9714 | 0 | CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter; |
9715 | 0 | CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */ |
9716 | 0 | CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */ |
9717 | |
|
9718 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9719 | 0 | if (crv != CKR_OK) |
9720 | 0 | break; |
9721 | | |
9722 | 0 | if (keySize == 0) { |
9723 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
9724 | 0 | break; |
9725 | 0 | } |
9726 | | /* make sure we have enough bits in the original key */ |
9727 | 0 | if (att->attrib.ulValueLen < |
9728 | 0 | (offset + keySize + ((shift != 0) ? 1 : 0))) { |
9729 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9730 | 0 | break; |
9731 | 0 | } |
9732 | 0 | buf = (unsigned char *)PORT_Alloc(keySize); |
9733 | 0 | if (buf == NULL) { |
9734 | 0 | crv = CKR_HOST_MEMORY; |
9735 | 0 | break; |
9736 | 0 | } |
9737 | | |
9738 | | /* copy the bits we need into the new key */ |
9739 | 0 | for (i = 0; i < (int)keySize; i++) { |
9740 | 0 | unsigned char *value = |
9741 | 0 | ((unsigned char *)att->attrib.pValue) + offset + i; |
9742 | 0 | if (shift) { |
9743 | 0 | buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift)); |
9744 | 0 | } else { |
9745 | 0 | buf[i] = value[0]; |
9746 | 0 | } |
9747 | 0 | } |
9748 | |
|
9749 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
9750 | 0 | PORT_ZFree(buf, keySize); |
9751 | 0 | break; |
9752 | 0 | } |
9753 | 0 | case CKM_MD2_KEY_DERIVATION: |
9754 | 0 | if (keySize == 0) |
9755 | 0 | keySize = MD2_LENGTH; |
9756 | 0 | if (keySize > MD2_LENGTH) { |
9757 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9758 | 0 | break; |
9759 | 0 | } |
9760 | | /* now allocate the hash contexts */ |
9761 | 0 | md2 = MD2_NewContext(); |
9762 | 0 | if (md2 == NULL) { |
9763 | 0 | crv = CKR_HOST_MEMORY; |
9764 | 0 | break; |
9765 | 0 | } |
9766 | 0 | MD2_Begin(md2); |
9767 | 0 | MD2_Update(md2, (const unsigned char *)att->attrib.pValue, |
9768 | 0 | att->attrib.ulValueLen); |
9769 | 0 | MD2_End(md2, key_block, &outLen, MD2_LENGTH); |
9770 | 0 | MD2_DestroyContext(md2, PR_TRUE); |
9771 | |
|
9772 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); |
9773 | 0 | PORT_Memset(key_block, 0, MD2_LENGTH); |
9774 | 0 | break; |
9775 | 0 | #define DERIVE_KEY_HASH(hash) \ |
9776 | 0 | case CKM_##hash##_KEY_DERIVATION: \ |
9777 | 0 | if (keySize == 0) \ |
9778 | 0 | keySize = hash##_LENGTH; \ |
9779 | 0 | if (keySize > hash##_LENGTH) { \ |
9780 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; \ |
9781 | 0 | break; \ |
9782 | 0 | } \ |
9783 | 0 | hash##_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, \ |
9784 | 0 | att->attrib.ulValueLen); \ |
9785 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); \ |
9786 | 0 | PORT_Memset(key_block, 0, hash##_LENGTH); \ |
9787 | 0 | break; |
9788 | 0 | DERIVE_KEY_HASH(MD5) |
9789 | 0 | DERIVE_KEY_HASH(SHA1) |
9790 | 0 | DERIVE_KEY_HASH(SHA224) |
9791 | 0 | DERIVE_KEY_HASH(SHA256) |
9792 | 0 | DERIVE_KEY_HASH(SHA384) |
9793 | 0 | DERIVE_KEY_HASH(SHA512) |
9794 | 0 | DERIVE_KEY_HASH(SHA3_224) |
9795 | 0 | DERIVE_KEY_HASH(SHA3_256) |
9796 | 0 | DERIVE_KEY_HASH(SHA3_384) |
9797 | 0 | DERIVE_KEY_HASH(SHA3_512) |
9798 | | |
9799 | 5.70k | case CKM_DH_PKCS_DERIVE: { |
9800 | 5.70k | SECItem derived, dhPublic; |
9801 | 5.70k | SECItem dhPrime, dhValue; |
9802 | 5.70k | const SECItem *subPrime; |
9803 | | /* sourceKey - values for the local existing low key */ |
9804 | | /* get prime and value attributes */ |
9805 | 5.70k | crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME); |
9806 | 5.70k | if (crv != CKR_OK) |
9807 | 0 | break; |
9808 | | |
9809 | 5.70k | dhPublic.data = pMechanism->pParameter; |
9810 | 5.70k | dhPublic.len = pMechanism->ulParameterLen; |
9811 | | |
9812 | | /* if the prime is an approved prime, we can skip all the other |
9813 | | * checks. */ |
9814 | 5.70k | subPrime = sftk_VerifyDH_Prime(&dhPrime, NULL, isFIPS); |
9815 | 5.70k | if (subPrime == NULL) { |
9816 | 7 | SECItem dhSubPrime; |
9817 | | /* If the caller set the subprime value, it means that |
9818 | | * either the caller knows the subprime value and wants us |
9819 | | * to validate the key against the subprime, or that the |
9820 | | * caller wants us to verify that the prime is a safe prime |
9821 | | * by passing in subprime = (prime-1)/2 */ |
9822 | 7 | dhSubPrime.data = NULL; |
9823 | 7 | dhSubPrime.len = 0; |
9824 | 7 | crv = sftk_Attribute2SecItem(NULL, &dhSubPrime, |
9825 | 7 | sourceKey, CKA_SUBPRIME); |
9826 | | /* we ignore the value of crv here, We treat a valid |
9827 | | * return of len = 0 and a failure to find a subrime the same |
9828 | | * NOTE: we free the subprime in both cases depending on |
9829 | | * PORT_Free of NULL to be a noop */ |
9830 | 7 | if (dhSubPrime.len != 0) { |
9831 | 0 | PRBool isSafe = PR_FALSE; |
9832 | | |
9833 | | /* Callers can set dhSubPrime to q=(p-1)/2 to force |
9834 | | * checks for safe primes. If so we only need to check |
9835 | | * q and p for primality and skip the group test. */ |
9836 | 0 | rv = sftk_IsSafePrime(&dhPrime, &dhSubPrime, &isSafe); |
9837 | 0 | if (rv != SECSuccess) { |
9838 | | /* either p or q was even and therefore not prime, |
9839 | | * we can stop processing here and fail now */ |
9840 | 0 | crv = CKR_ARGUMENTS_BAD; |
9841 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9842 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
9843 | 0 | break; |
9844 | 0 | } |
9845 | | |
9846 | | /* first make sure the primes are really prime */ |
9847 | 0 | if (!KEA_PrimeCheck(&dhPrime)) { |
9848 | 0 | crv = CKR_ARGUMENTS_BAD; |
9849 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9850 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
9851 | 0 | break; |
9852 | 0 | } |
9853 | 0 | if (!KEA_PrimeCheck(&dhSubPrime)) { |
9854 | 0 | crv = CKR_ARGUMENTS_BAD; |
9855 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9856 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
9857 | 0 | break; |
9858 | 0 | } |
9859 | 0 | if (isFIPS || !isSafe) { |
9860 | | /* With safe primes, there is only one other small |
9861 | | * subgroup. As long as y isn't 0, 1, or -1 mod p, |
9862 | | * any other y is safe. Only do the full check for |
9863 | | * non-safe primes, except in FIPS mode we need |
9864 | | * to do this check on all primes in which |
9865 | | * we receive the subprime value */ |
9866 | 0 | if (!KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime)) { |
9867 | 0 | crv = CKR_ARGUMENTS_BAD; |
9868 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9869 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
9870 | 0 | break; |
9871 | 0 | } |
9872 | 0 | } |
9873 | 7 | } else if (isFIPS) { |
9874 | | /* In FIPS mode we only accept approved primes, or |
9875 | | * primes with the full subprime value */ |
9876 | 0 | crv = CKR_ARGUMENTS_BAD; |
9877 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9878 | 0 | break; |
9879 | 0 | } |
9880 | | /* checks are complete, no need for the subPrime any longer */ |
9881 | 7 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
9882 | 7 | } |
9883 | | |
9884 | | /* now that the prime is validated, get the private value */ |
9885 | 5.70k | crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE); |
9886 | 5.70k | if (crv != CKR_OK) { |
9887 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9888 | 0 | break; |
9889 | 0 | } |
9890 | | |
9891 | | /* calculate private value - oct */ |
9892 | 5.70k | rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); |
9893 | | |
9894 | 5.70k | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9895 | 5.70k | SECITEM_ZfreeItem(&dhValue, PR_FALSE); |
9896 | | |
9897 | 5.70k | if (rv == SECSuccess) { |
9898 | 5.70k | key->source = SFTK_SOURCE_KEA; |
9899 | 5.70k | sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len); |
9900 | 5.70k | SECITEM_ZfreeItem(&derived, PR_FALSE); |
9901 | 5.70k | crv = CKR_OK; |
9902 | 5.70k | } else |
9903 | 0 | crv = CKR_HOST_MEMORY; |
9904 | | |
9905 | 5.70k | break; |
9906 | 5.70k | } |
9907 | | |
9908 | 73.0k | case CKM_ECDH1_DERIVE: |
9909 | 73.0k | case CKM_ECDH1_COFACTOR_DERIVE: { |
9910 | 73.0k | SECItem ecScalar, ecPoint; |
9911 | 73.0k | SECItem tmp; |
9912 | 73.0k | PRBool withCofactor = PR_FALSE; |
9913 | 73.0k | unsigned char *secret; |
9914 | 73.0k | unsigned char *keyData = NULL; |
9915 | 73.0k | unsigned int secretlen, pubKeyLen; |
9916 | 73.0k | CK_ECDH1_DERIVE_PARAMS *mechParams; |
9917 | 73.0k | NSSLOWKEYPrivateKey *privKey; |
9918 | 73.0k | PLArenaPool *arena = NULL; |
9919 | | |
9920 | | /* Check mechanism parameters */ |
9921 | 73.0k | mechParams = (CK_ECDH1_DERIVE_PARAMS *)pMechanism->pParameter; |
9922 | 73.0k | if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) || |
9923 | 73.0k | ((mechParams->kdf == CKD_NULL) && |
9924 | 73.0k | ((mechParams->ulSharedDataLen != 0) || |
9925 | 73.0k | (mechParams->pSharedData != NULL)))) { |
9926 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9927 | 0 | break; |
9928 | 0 | } |
9929 | | |
9930 | 73.0k | privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv); |
9931 | 73.0k | if (privKey == NULL) { |
9932 | 0 | break; |
9933 | 0 | } |
9934 | | |
9935 | | /* Now we are working with a non-NULL private key */ |
9936 | 73.0k | SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue); |
9937 | | |
9938 | 73.0k | ecPoint.data = mechParams->pPublicData; |
9939 | 73.0k | ecPoint.len = mechParams->ulPublicDataLen; |
9940 | | |
9941 | 73.0k | pubKeyLen = EC_GetPointSize(&privKey->u.ec.ecParams); |
9942 | | |
9943 | | /* if the len is too large, might be an encoded point */ |
9944 | 73.0k | if (ecPoint.len > pubKeyLen) { |
9945 | 6.35k | SECItem newPoint; |
9946 | | |
9947 | 6.35k | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
9948 | 6.35k | if (arena == NULL) { |
9949 | 0 | goto ec_loser; |
9950 | 0 | } |
9951 | | |
9952 | 6.35k | rv = SEC_QuickDERDecodeItem(arena, &newPoint, |
9953 | 6.35k | SEC_ASN1_GET(SEC_OctetStringTemplate), |
9954 | 6.35k | &ecPoint); |
9955 | 6.35k | if (rv != SECSuccess) { |
9956 | 344 | goto ec_loser; |
9957 | 344 | } |
9958 | 6.01k | ecPoint = newPoint; |
9959 | 6.01k | } |
9960 | | |
9961 | 72.7k | if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) { |
9962 | 0 | withCofactor = PR_TRUE; |
9963 | 0 | } |
9964 | | |
9965 | 72.7k | rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar, |
9966 | 72.7k | withCofactor, &tmp); |
9967 | 72.7k | SECITEM_ZfreeItem(&ecScalar, PR_FALSE); |
9968 | 72.7k | ecScalar.data = NULL; |
9969 | 72.7k | if (privKey != sourceKey->objectInfo) { |
9970 | 0 | nsslowkey_DestroyPrivateKey(privKey); |
9971 | 0 | privKey = NULL; |
9972 | 0 | } |
9973 | 72.7k | if (arena) { |
9974 | 6.01k | PORT_FreeArena(arena, PR_FALSE); |
9975 | 6.01k | arena = NULL; |
9976 | 6.01k | } |
9977 | | |
9978 | 72.7k | if (rv != SECSuccess) { |
9979 | 12.2k | crv = sftk_MapCryptError(PORT_GetError()); |
9980 | 12.2k | break; |
9981 | 12.2k | } |
9982 | | |
9983 | | /* |
9984 | | * apply the kdf function. |
9985 | | */ |
9986 | 60.4k | if (mechParams->kdf == CKD_NULL) { |
9987 | | /* |
9988 | | * tmp is the raw data created by ECDH_Derive, |
9989 | | * secret and secretlen are the values we will |
9990 | | * eventually pass as our generated key. |
9991 | | */ |
9992 | 60.4k | secret = tmp.data; |
9993 | 60.4k | secretlen = tmp.len; |
9994 | 60.4k | } else { |
9995 | 0 | secretlen = keySize; |
9996 | 0 | sftk_setFIPS(key, PR_FALSE); |
9997 | 0 | crv = sftk_ANSI_X9_63_kdf(&secret, keySize, |
9998 | 0 | &tmp, mechParams->pSharedData, |
9999 | 0 | mechParams->ulSharedDataLen, mechParams->kdf); |
10000 | 0 | PORT_ZFree(tmp.data, tmp.len); |
10001 | 0 | if (crv != CKR_OK) { |
10002 | 0 | break; |
10003 | 0 | } |
10004 | 0 | tmp.data = secret; |
10005 | 0 | tmp.len = secretlen; |
10006 | 0 | } |
10007 | | |
10008 | | /* |
10009 | | * if keySize is supplied, then we are generating a key of a specific |
10010 | | * length. This is done by taking the least significant 'keySize' |
10011 | | * bytes from the unsigned value calculated by ECDH. Note: this may |
10012 | | * mean padding temp with extra leading zeros from what ECDH_Derive |
10013 | | * already returned (which itself may contain leading zeros). |
10014 | | */ |
10015 | 60.4k | if (keySize) { |
10016 | 60.4k | if (secretlen < keySize) { |
10017 | 1 | keyData = PORT_ZAlloc(keySize); |
10018 | 1 | if (!keyData) { |
10019 | 0 | PORT_ZFree(tmp.data, tmp.len); |
10020 | 0 | crv = CKR_HOST_MEMORY; |
10021 | 0 | break; |
10022 | 0 | } |
10023 | 1 | PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen); |
10024 | 1 | secret = keyData; |
10025 | 60.4k | } else { |
10026 | 60.4k | secret += (secretlen - keySize); |
10027 | 60.4k | } |
10028 | 60.4k | secretlen = keySize; |
10029 | 60.4k | } |
10030 | 60.4k | key->source = SFTK_SOURCE_KEA; |
10031 | | |
10032 | 60.4k | sftk_forceAttribute(key, CKA_VALUE, secret, secretlen); |
10033 | 60.4k | PORT_ZFree(tmp.data, tmp.len); |
10034 | 60.4k | if (keyData) { |
10035 | 1 | PORT_ZFree(keyData, keySize); |
10036 | 1 | } |
10037 | 60.4k | break; |
10038 | | |
10039 | 344 | ec_loser: |
10040 | 344 | crv = CKR_ARGUMENTS_BAD; |
10041 | 344 | SECITEM_ZfreeItem(&ecScalar, PR_FALSE); |
10042 | 344 | if (privKey != sourceKey->objectInfo) |
10043 | 0 | nsslowkey_DestroyPrivateKey(privKey); |
10044 | 344 | if (arena) { |
10045 | 344 | PORT_FreeArena(arena, PR_TRUE); |
10046 | 344 | } |
10047 | 344 | break; |
10048 | 60.4k | } |
10049 | | /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */ |
10050 | 22 | case CKM_NSS_HKDF_SHA1: |
10051 | 22 | hashMech = CKM_SHA_1; |
10052 | 22 | goto hkdf; |
10053 | 114 | case CKM_NSS_HKDF_SHA256: |
10054 | 114 | hashMech = CKM_SHA256; |
10055 | 114 | goto hkdf; |
10056 | 100 | case CKM_NSS_HKDF_SHA384: |
10057 | 100 | hashMech = CKM_SHA384; |
10058 | 100 | goto hkdf; |
10059 | 113 | case CKM_NSS_HKDF_SHA512: |
10060 | 113 | hashMech = CKM_SHA512; |
10061 | 113 | goto hkdf; |
10062 | 349 | hkdf : { |
10063 | 349 | const CK_NSS_HKDFParams *params = |
10064 | 349 | (const CK_NSS_HKDFParams *)pMechanism->pParameter; |
10065 | 349 | CK_HKDF_PARAMS hkdfParams; |
10066 | | |
10067 | 349 | if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams)) { |
10068 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
10069 | 0 | break; |
10070 | 0 | } |
10071 | 349 | hkdfParams.bExtract = params->bExtract; |
10072 | 349 | hkdfParams.bExpand = params->bExpand; |
10073 | 349 | if (params->pSalt) { |
10074 | 128 | hkdfParams.ulSaltType = CKF_HKDF_SALT_DATA; |
10075 | 221 | } else { |
10076 | 221 | hkdfParams.ulSaltType = CKF_HKDF_SALT_NULL; |
10077 | 221 | } |
10078 | 349 | hkdfParams.pSalt = params->pSalt; |
10079 | 349 | hkdfParams.ulSaltLen = params->ulSaltLen; |
10080 | 349 | hkdfParams.hSaltKey = CK_INVALID_HANDLE; |
10081 | 349 | hkdfParams.pInfo = params->pInfo; |
10082 | 349 | hkdfParams.ulInfoLen = params->ulInfoLen; |
10083 | 349 | hkdfParams.prfHashMechanism = hashMech; |
10084 | | |
10085 | 349 | crv = sftk_HKDF(&hkdfParams, hSession, sourceKey, |
10086 | 349 | att->attrib.pValue, att->attrib.ulValueLen, |
10087 | 349 | key, NULL, keySize, PR_FALSE, isFIPS); |
10088 | 349 | } break; |
10089 | 348k | case CKM_HKDF_DERIVE: |
10090 | 494k | case CKM_HKDF_DATA: /* only difference is the class of key */ |
10091 | 494k | if ((pMechanism->pParameter == NULL) || |
10092 | 494k | (pMechanism->ulParameterLen != sizeof(CK_HKDF_PARAMS))) { |
10093 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
10094 | 0 | break; |
10095 | 0 | } |
10096 | 494k | crv = sftk_HKDF((CK_HKDF_PARAMS_PTR)pMechanism->pParameter, |
10097 | 494k | hSession, sourceKey, att->attrib.pValue, |
10098 | 494k | att->attrib.ulValueLen, key, NULL, keySize, PR_TRUE, |
10099 | 494k | isFIPS); |
10100 | 494k | break; |
10101 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA1: |
10102 | 0 | hashType = HASH_AlgSHA1; |
10103 | 0 | goto jpake2; |
10104 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA256: |
10105 | 0 | hashType = HASH_AlgSHA256; |
10106 | 0 | goto jpake2; |
10107 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA384: |
10108 | 0 | hashType = HASH_AlgSHA384; |
10109 | 0 | goto jpake2; |
10110 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA512: |
10111 | 0 | hashType = HASH_AlgSHA512; |
10112 | 0 | goto jpake2; |
10113 | 0 | jpake2: |
10114 | 0 | if (pMechanism->pParameter == NULL || |
10115 | 0 | pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params)) |
10116 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
10117 | 0 | if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN)) |
10118 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
10119 | 0 | if (crv == CKR_OK) |
10120 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
10121 | 0 | if (crv == CKR_OK) |
10122 | 0 | crv = jpake_Round2(hashType, |
10123 | 0 | (CK_NSS_JPAKERound2Params *)pMechanism->pParameter, |
10124 | 0 | sourceKey, key); |
10125 | 0 | break; |
10126 | | |
10127 | 0 | case CKM_NSS_JPAKE_FINAL_SHA1: |
10128 | 0 | hashType = HASH_AlgSHA1; |
10129 | 0 | goto jpakeFinal; |
10130 | 0 | case CKM_NSS_JPAKE_FINAL_SHA256: |
10131 | 0 | hashType = HASH_AlgSHA256; |
10132 | 0 | goto jpakeFinal; |
10133 | 0 | case CKM_NSS_JPAKE_FINAL_SHA384: |
10134 | 0 | hashType = HASH_AlgSHA384; |
10135 | 0 | goto jpakeFinal; |
10136 | 0 | case CKM_NSS_JPAKE_FINAL_SHA512: |
10137 | 0 | hashType = HASH_AlgSHA512; |
10138 | 0 | goto jpakeFinal; |
10139 | 0 | jpakeFinal: |
10140 | 0 | if (pMechanism->pParameter == NULL || |
10141 | 0 | pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams)) |
10142 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
10143 | | /* We purposely do not do the derive sensitivity check; we want to be |
10144 | | able to derive non-sensitive keys while allowing the ROUND1 and |
10145 | | ROUND2 keys to be sensitive (which they always are, since they are |
10146 | | in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE |
10147 | | in the template in order for the resultant keyblock key to be |
10148 | | sensitive. |
10149 | | */ |
10150 | 0 | if (crv == CKR_OK) |
10151 | 0 | crv = jpake_Final(hashType, |
10152 | 0 | (CK_NSS_JPAKEFinalParams *)pMechanism->pParameter, |
10153 | 0 | sourceKey, key); |
10154 | 0 | break; |
10155 | | |
10156 | 0 | case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */ |
10157 | 0 | case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */ |
10158 | 0 | case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */ |
10159 | 0 | case CKM_SP800_108_COUNTER_KDF: /* fall through */ |
10160 | 0 | case CKM_SP800_108_FEEDBACK_KDF: /* fall through */ |
10161 | 0 | case CKM_SP800_108_DOUBLE_PIPELINE_KDF: |
10162 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
10163 | 0 | if (crv != CKR_OK) { |
10164 | 0 | break; |
10165 | 0 | } |
10166 | | |
10167 | 0 | crv = kbkdf_Dispatch(mechanism, hSession, pMechanism, sourceKey, key, keySize); |
10168 | 0 | break; |
10169 | 0 | default: |
10170 | 0 | crv = CKR_MECHANISM_INVALID; |
10171 | 864k | } |
10172 | 864k | if (att) { |
10173 | 864k | sftk_FreeAttribute(att); |
10174 | 864k | } |
10175 | 864k | sftk_FreeObject(sourceKey); |
10176 | 864k | if (crv != CKR_OK) { |
10177 | 16.6k | if (key) |
10178 | 16.6k | sftk_FreeObject(key); |
10179 | 16.6k | return crv; |
10180 | 16.6k | } |
10181 | | |
10182 | | /* link the key object into the list */ |
10183 | 848k | if (key) { |
10184 | 729k | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
10185 | 729k | if (sessKey == NULL) { |
10186 | 0 | sftk_FreeObject(key); |
10187 | 0 | return CKR_DEVICE_ERROR; |
10188 | 0 | } |
10189 | 729k | sessKey->wasDerived = PR_TRUE; |
10190 | 729k | session = sftk_SessionFromHandle(hSession); |
10191 | 729k | if (session == NULL) { |
10192 | 0 | sftk_FreeObject(key); |
10193 | 0 | return CKR_HOST_MEMORY; |
10194 | 0 | } |
10195 | | |
10196 | 729k | crv = sftk_handleObject(key, session); |
10197 | 729k | session->lastOpWasFIPS = sftk_hasFIPS(key); |
10198 | 729k | sftk_FreeSession(session); |
10199 | 729k | if (phKey) { |
10200 | 729k | *phKey = key->handle; |
10201 | 729k | } |
10202 | 729k | sftk_FreeObject(key); |
10203 | 729k | } |
10204 | 848k | return crv; |
10205 | 848k | } |
10206 | | |
10207 | | /* NSC_GetFunctionStatus obtains an updated status of a function running |
10208 | | * in parallel with an application. */ |
10209 | | CK_RV |
10210 | | NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession) |
10211 | 0 | { |
10212 | 0 | CHECK_FORK(); |
10213 | |
|
10214 | 0 | return CKR_FUNCTION_NOT_PARALLEL; |
10215 | 0 | } |
10216 | | |
10217 | | /* NSC_CancelFunction cancels a function running in parallel */ |
10218 | | CK_RV |
10219 | | NSC_CancelFunction(CK_SESSION_HANDLE hSession) |
10220 | 0 | { |
10221 | 0 | CHECK_FORK(); |
10222 | |
|
10223 | 0 | return CKR_FUNCTION_NOT_PARALLEL; |
10224 | 0 | } |
10225 | | |
10226 | | /* NSC_GetOperationState saves the state of the cryptographic |
10227 | | * operation in a session. |
10228 | | * NOTE: This code only works for digest functions for now. eventually need |
10229 | | * to add full flatten/resurect to our state stuff so that all types of state |
10230 | | * can be saved */ |
10231 | | CK_RV |
10232 | | NSC_GetOperationState(CK_SESSION_HANDLE hSession, |
10233 | | CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) |
10234 | 220k | { |
10235 | 220k | SFTKSessionContext *context; |
10236 | 220k | SFTKSession *session; |
10237 | 220k | CK_RV crv; |
10238 | 220k | CK_ULONG pOSLen = *pulOperationStateLen; |
10239 | | |
10240 | 220k | CHECK_FORK(); |
10241 | | |
10242 | | /* make sure we're legal */ |
10243 | 220k | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); |
10244 | 220k | if (crv != CKR_OK) |
10245 | 0 | return crv; |
10246 | | |
10247 | | /* a zero cipherInfoLen signals that this context cannot be serialized */ |
10248 | 220k | if (context->cipherInfoLen == 0) { |
10249 | 0 | return CKR_STATE_UNSAVEABLE; |
10250 | 0 | } |
10251 | | |
10252 | 220k | *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) + sizeof(SFTKContextType); |
10253 | 220k | if (pOperationState == NULL) { |
10254 | 25.0k | sftk_FreeSession(session); |
10255 | 25.0k | return CKR_OK; |
10256 | 195k | } else { |
10257 | 195k | if (pOSLen < *pulOperationStateLen) { |
10258 | 0 | return CKR_BUFFER_TOO_SMALL; |
10259 | 0 | } |
10260 | 195k | } |
10261 | 195k | PORT_Memcpy(pOperationState, &context->type, sizeof(SFTKContextType)); |
10262 | 195k | pOperationState += sizeof(SFTKContextType); |
10263 | 195k | PORT_Memcpy(pOperationState, &context->currentMech, |
10264 | 195k | sizeof(CK_MECHANISM_TYPE)); |
10265 | 195k | pOperationState += sizeof(CK_MECHANISM_TYPE); |
10266 | 195k | PORT_Memcpy(pOperationState, context->cipherInfo, context->cipherInfoLen); |
10267 | 195k | sftk_FreeSession(session); |
10268 | 195k | return CKR_OK; |
10269 | 220k | } |
10270 | | |
10271 | | #define sftk_Decrement(stateSize, len) \ |
10272 | 586k | stateSize = ((stateSize) > (CK_ULONG)(len)) ? ((stateSize) - (CK_ULONG)(len)) : 0; |
10273 | | |
10274 | | /* NSC_SetOperationState restores the state of the cryptographic |
10275 | | * operation in a session. This is coded like it can restore lots of |
10276 | | * states, but it only works for truly flat cipher structures. */ |
10277 | | CK_RV |
10278 | | NSC_SetOperationState(CK_SESSION_HANDLE hSession, |
10279 | | CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, |
10280 | | CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) |
10281 | 195k | { |
10282 | 195k | SFTKSessionContext *context; |
10283 | 195k | SFTKSession *session; |
10284 | 195k | SFTKContextType type; |
10285 | 195k | CK_MECHANISM mech; |
10286 | 195k | CK_RV crv = CKR_OK; |
10287 | | |
10288 | 195k | CHECK_FORK(); |
10289 | | |
10290 | 391k | while (ulOperationStateLen != 0) { |
10291 | | /* get what type of state we're dealing with... */ |
10292 | 195k | PORT_Memcpy(&type, pOperationState, sizeof(SFTKContextType)); |
10293 | | |
10294 | | /* fix up session contexts based on type */ |
10295 | 195k | session = sftk_SessionFromHandle(hSession); |
10296 | 195k | if (session == NULL) |
10297 | 0 | return CKR_SESSION_HANDLE_INVALID; |
10298 | 195k | sftk_UninstallContext(session, type); |
10299 | 195k | pOperationState += sizeof(SFTKContextType); |
10300 | 195k | sftk_Decrement(ulOperationStateLen, sizeof(SFTKContextType)); |
10301 | | |
10302 | | /* get the mechanism structure */ |
10303 | 195k | PORT_Memcpy(&mech.mechanism, pOperationState, sizeof(CK_MECHANISM_TYPE)); |
10304 | 195k | pOperationState += sizeof(CK_MECHANISM_TYPE); |
10305 | 195k | sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE)); |
10306 | | /* should be filled in... but not necessary for hash */ |
10307 | 195k | mech.pParameter = NULL; |
10308 | 195k | mech.ulParameterLen = 0; |
10309 | 195k | switch (type) { |
10310 | 195k | case SFTK_HASH: |
10311 | 195k | crv = NSC_DigestInit(hSession, &mech); |
10312 | 195k | if (crv != CKR_OK) |
10313 | 0 | break; |
10314 | | /* NSC_DigestInit just installed a SFTK_HASH context on |
10315 | | * this session; the outer session reference keeps it |
10316 | | * alive across the load below. */ |
10317 | 195k | context = sftk_ReturnContextByType(session, SFTK_HASH); |
10318 | 195k | if (context == NULL || context->type != SFTK_HASH) { |
10319 | 0 | crv = CKR_OPERATION_NOT_INITIALIZED; |
10320 | 0 | break; |
10321 | 0 | } |
10322 | 195k | if (context->cipherInfoLen == 0) { |
10323 | 0 | crv = CKR_SAVED_STATE_INVALID; |
10324 | 0 | break; |
10325 | 0 | } |
10326 | 195k | PORT_Memcpy(context->cipherInfo, pOperationState, |
10327 | 195k | context->cipherInfoLen); |
10328 | 195k | pOperationState += context->cipherInfoLen; |
10329 | 195k | sftk_Decrement(ulOperationStateLen, context->cipherInfoLen); |
10330 | 195k | break; |
10331 | 0 | default: |
10332 | | /* do sign/encrypt/decrypt later */ |
10333 | 0 | crv = CKR_SAVED_STATE_INVALID; |
10334 | 195k | } |
10335 | 195k | sftk_FreeSession(session); |
10336 | 195k | if (crv != CKR_OK) |
10337 | 0 | break; |
10338 | 195k | } |
10339 | 195k | return crv; |
10340 | 195k | } |
10341 | | |
10342 | | /* Dual-function cryptographic operations */ |
10343 | | |
10344 | | /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption |
10345 | | * operation. */ |
10346 | | CK_RV |
10347 | | NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
10348 | | CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
10349 | | CK_ULONG_PTR pulEncryptedPartLen) |
10350 | 0 | { |
10351 | 0 | CK_RV crv; |
10352 | |
|
10353 | 0 | CHECK_FORK(); |
10354 | |
|
10355 | 0 | crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, |
10356 | 0 | pulEncryptedPartLen); |
10357 | 0 | if (crv != CKR_OK) |
10358 | 0 | return crv; |
10359 | 0 | crv = NSC_DigestUpdate(hSession, pPart, ulPartLen); |
10360 | |
|
10361 | 0 | return crv; |
10362 | 0 | } |
10363 | | |
10364 | | /* NSC_DecryptDigestUpdate continues a multiple-part decryption and |
10365 | | * digesting operation. */ |
10366 | | CK_RV |
10367 | | NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, |
10368 | | CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, |
10369 | | CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) |
10370 | 0 | { |
10371 | 0 | CK_RV crv; |
10372 | |
|
10373 | 0 | CHECK_FORK(); |
10374 | |
|
10375 | 0 | crv = NSC_DecryptUpdate(hSession, pEncryptedPart, ulEncryptedPartLen, |
10376 | 0 | pPart, pulPartLen); |
10377 | 0 | if (crv != CKR_OK) |
10378 | 0 | return crv; |
10379 | 0 | crv = NSC_DigestUpdate(hSession, pPart, *pulPartLen); |
10380 | |
|
10381 | 0 | return crv; |
10382 | 0 | } |
10383 | | |
10384 | | /* NSC_SignEncryptUpdate continues a multiple-part signing and |
10385 | | * encryption operation. */ |
10386 | | CK_RV |
10387 | | NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
10388 | | CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
10389 | | CK_ULONG_PTR pulEncryptedPartLen) |
10390 | 0 | { |
10391 | 0 | CK_RV crv; |
10392 | |
|
10393 | 0 | CHECK_FORK(); |
10394 | |
|
10395 | 0 | crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, |
10396 | 0 | pulEncryptedPartLen); |
10397 | 0 | if (crv != CKR_OK) |
10398 | 0 | return crv; |
10399 | 0 | crv = NSC_SignUpdate(hSession, pPart, ulPartLen); |
10400 | |
|
10401 | 0 | return crv; |
10402 | 0 | } |
10403 | | |
10404 | | /* NSC_DecryptVerifyUpdate continues a multiple-part decryption |
10405 | | * and verify operation. */ |
10406 | | CK_RV |
10407 | | NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, |
10408 | | CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, |
10409 | | CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) |
10410 | 0 | { |
10411 | 0 | CK_RV crv; |
10412 | |
|
10413 | 0 | CHECK_FORK(); |
10414 | |
|
10415 | 0 | crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, |
10416 | 0 | pData, pulDataLen); |
10417 | 0 | if (crv != CKR_OK) |
10418 | 0 | return crv; |
10419 | 0 | crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen); |
10420 | |
|
10421 | 0 | return crv; |
10422 | 0 | } |
10423 | | |
10424 | | /* NSC_DigestKey continues a multi-part message-digesting operation, |
10425 | | * by digesting the value of a secret key as part of the data already digested. |
10426 | | */ |
10427 | | CK_RV |
10428 | | NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) |
10429 | 0 | { |
10430 | 0 | SFTKSession *session = NULL; |
10431 | 0 | SFTKObject *key = NULL; |
10432 | 0 | SFTKAttribute *att; |
10433 | 0 | CK_RV crv; |
10434 | |
|
10435 | 0 | CHECK_FORK(); |
10436 | |
|
10437 | 0 | session = sftk_SessionFromHandle(hSession); |
10438 | 0 | if (session == NULL) |
10439 | 0 | return CKR_SESSION_HANDLE_INVALID; |
10440 | | |
10441 | 0 | key = sftk_ObjectFromHandle(hKey, session); |
10442 | 0 | sftk_FreeSession(session); |
10443 | 0 | if (key == NULL) |
10444 | 0 | return CKR_KEY_HANDLE_INVALID; |
10445 | | |
10446 | | /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */ |
10447 | | |
10448 | | /* make sure it's a valid key for this operation */ |
10449 | 0 | if (key->objclass != CKO_SECRET_KEY) { |
10450 | 0 | sftk_FreeObject(key); |
10451 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
10452 | 0 | } |
10453 | | /* get the key value */ |
10454 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
10455 | 0 | if (!att) { |
10456 | 0 | sftk_FreeObject(key); |
10457 | 0 | return CKR_KEY_HANDLE_INVALID; |
10458 | 0 | } |
10459 | 0 | crv = NSC_DigestUpdate(hSession, (CK_BYTE_PTR)att->attrib.pValue, |
10460 | 0 | att->attrib.ulValueLen); |
10461 | 0 | sftk_FreeAttribute(att); |
10462 | 0 | sftk_FreeObject(key); |
10463 | 0 | return crv; |
10464 | 0 | } |