/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 | 398k | #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 | 637k | #define CKM_SHA1 CKM_SHA_1 |
71 | 159k | #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 | 131k | { |
82 | 131k | return; |
83 | 131k | } |
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 | 13.3M | { \ |
112 | 13.3M | ctxtype *ctx = vctx; \ |
113 | 13.3M | mmm##_Update(ctx, input, len); \ |
114 | 13.3M | } \ Unexecuted instantiation: pkcs11c.c:SFTKHash_MD2_Update pkcs11c.c:SFTKHash_MD5_Update Line | Count | Source | 111 | 640k | { \ | 112 | 640k | ctxtype *ctx = vctx; \ | 113 | 640k | mmm##_Update(ctx, input, len); \ | 114 | 640k | } \ |
pkcs11c.c:SFTKHash_SHA1_Update Line | Count | Source | 111 | 856k | { \ | 112 | 856k | ctxtype *ctx = vctx; \ | 113 | 856k | mmm##_Update(ctx, input, len); \ | 114 | 856k | } \ |
pkcs11c.c:SFTKHash_SHA224_Update Line | Count | Source | 111 | 1.60M | { \ | 112 | 1.60M | ctxtype *ctx = vctx; \ | 113 | 1.60M | mmm##_Update(ctx, input, len); \ | 114 | 1.60M | } \ |
pkcs11c.c:SFTKHash_SHA256_Update Line | Count | Source | 111 | 879k | { \ | 112 | 879k | ctxtype *ctx = vctx; \ | 113 | 879k | mmm##_Update(ctx, input, len); \ | 114 | 879k | } \ |
pkcs11c.c:SFTKHash_SHA384_Update Line | Count | Source | 111 | 1.96M | { \ | 112 | 1.96M | ctxtype *ctx = vctx; \ | 113 | 1.96M | mmm##_Update(ctx, input, len); \ | 114 | 1.96M | } \ |
pkcs11c.c:SFTKHash_SHA512_Update Line | Count | Source | 111 | 3.13M | { \ | 112 | 3.13M | ctxtype *ctx = vctx; \ | 113 | 3.13M | mmm##_Update(ctx, input, len); \ | 114 | 3.13M | } \ |
pkcs11c.c:SFTKHash_SHA3_224_Update Line | Count | Source | 111 | 189k | { \ | 112 | 189k | ctxtype *ctx = vctx; \ | 113 | 189k | mmm##_Update(ctx, input, len); \ | 114 | 189k | } \ |
pkcs11c.c:SFTKHash_SHA3_256_Update Line | Count | Source | 111 | 2.51M | { \ | 112 | 2.51M | ctxtype *ctx = vctx; \ | 113 | 2.51M | mmm##_Update(ctx, input, len); \ | 114 | 2.51M | } \ |
pkcs11c.c:SFTKHash_SHA3_384_Update Line | Count | Source | 111 | 813k | { \ | 112 | 813k | ctxtype *ctx = vctx; \ | 113 | 813k | mmm##_Update(ctx, input, len); \ | 114 | 813k | } \ |
pkcs11c.c:SFTKHash_SHA3_512_Update Line | Count | Source | 111 | 637k | { \ | 112 | 637k | ctxtype *ctx = vctx; \ | 113 | 637k | mmm##_Update(ctx, input, len); \ | 114 | 637k | } \ |
pkcs11c.c:SFTKHash_sftk_MAC_Update Line | Count | Source | 111 | 82.6k | { \ | 112 | 82.6k | ctxtype *ctx = vctx; \ | 113 | 82.6k | mmm##_Update(ctx, input, len); \ | 114 | 82.6k | } \ |
|
115 | | static void \ |
116 | | SFTKHash_##mmm##_End(void *vctx, unsigned char *digest, \ |
117 | | unsigned int *len, unsigned int maxLen) \ |
118 | 676k | { \ |
119 | 676k | ctxtype *ctx = vctx; \ |
120 | 676k | mmm##_End(ctx, digest, len, maxLen); \ |
121 | 676k | } \ Unexecuted instantiation: pkcs11c.c:SFTKHash_MD2_End pkcs11c.c:SFTKHash_MD5_End Line | Count | Source | 118 | 79.7k | { \ | 119 | 79.7k | ctxtype *ctx = vctx; \ | 120 | 79.7k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 79.7k | } \ |
pkcs11c.c:SFTKHash_SHA1_End Line | Count | Source | 118 | 274k | { \ | 119 | 274k | ctxtype *ctx = vctx; \ | 120 | 274k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 274k | } \ |
pkcs11c.c:SFTKHash_SHA224_End Line | Count | Source | 118 | 27.2k | { \ | 119 | 27.2k | ctxtype *ctx = vctx; \ | 120 | 27.2k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 27.2k | } \ |
pkcs11c.c:SFTKHash_SHA256_End Line | Count | Source | 118 | 130k | { \ | 119 | 130k | ctxtype *ctx = vctx; \ | 120 | 130k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 130k | } \ |
pkcs11c.c:SFTKHash_SHA384_End Line | Count | Source | 118 | 53.3k | { \ | 119 | 53.3k | ctxtype *ctx = vctx; \ | 120 | 53.3k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 53.3k | } \ |
pkcs11c.c:SFTKHash_SHA512_End Line | Count | Source | 118 | 23.2k | { \ | 119 | 23.2k | ctxtype *ctx = vctx; \ | 120 | 23.2k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 23.2k | } \ |
pkcs11c.c:SFTKHash_SHA3_224_End Line | Count | Source | 118 | 1.91k | { \ | 119 | 1.91k | ctxtype *ctx = vctx; \ | 120 | 1.91k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 1.91k | } \ |
pkcs11c.c:SFTKHash_SHA3_256_End Line | Count | Source | 118 | 1.72k | { \ | 119 | 1.72k | ctxtype *ctx = vctx; \ | 120 | 1.72k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 1.72k | } \ |
pkcs11c.c:SFTKHash_SHA3_384_End Line | Count | Source | 118 | 30.1k | { \ | 119 | 30.1k | ctxtype *ctx = vctx; \ | 120 | 30.1k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 30.1k | } \ |
pkcs11c.c:SFTKHash_SHA3_512_End Line | Count | Source | 118 | 672 | { \ | 119 | 672 | ctxtype *ctx = vctx; \ | 120 | 672 | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 672 | } \ |
pkcs11c.c:SFTKHash_sftk_MAC_End Line | Count | Source | 118 | 53.8k | { \ | 119 | 53.8k | ctxtype *ctx = vctx; \ | 120 | 53.8k | mmm##_End(ctx, digest, len, maxLen); \ | 121 | 53.8k | } \ |
|
122 | | static void \ |
123 | | SFTKHash_##mmm##_DestroyContext(void *vctx, PRBool freeit) \ |
124 | 1.13M | { \ |
125 | 1.13M | ctxtype *ctx = vctx; \ |
126 | 1.13M | mmm##_DestroyContext(ctx, freeit); \ |
127 | 1.13M | } Unexecuted instantiation: pkcs11c.c:SFTKHash_MD2_DestroyContext pkcs11c.c:SFTKHash_MD5_DestroyContext Line | Count | Source | 124 | 123k | { \ | 125 | 123k | ctxtype *ctx = vctx; \ | 126 | 123k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 123k | } |
pkcs11c.c:SFTKHash_SHA1_DestroyContext Line | Count | Source | 124 | 318k | { \ | 125 | 318k | ctxtype *ctx = vctx; \ | 126 | 318k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 318k | } |
pkcs11c.c:SFTKHash_SHA224_DestroyContext Line | Count | Source | 124 | 164k | { \ | 125 | 164k | ctxtype *ctx = vctx; \ | 126 | 164k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 164k | } |
pkcs11c.c:SFTKHash_SHA256_DestroyContext Line | Count | Source | 124 | 151k | { \ | 125 | 151k | ctxtype *ctx = vctx; \ | 126 | 151k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 151k | } |
pkcs11c.c:SFTKHash_SHA384_DestroyContext Line | Count | Source | 124 | 66.3k | { \ | 125 | 66.3k | ctxtype *ctx = vctx; \ | 126 | 66.3k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 66.3k | } |
pkcs11c.c:SFTKHash_SHA512_DestroyContext Line | Count | Source | 124 | 35.6k | { \ | 125 | 35.6k | ctxtype *ctx = vctx; \ | 126 | 35.6k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 35.6k | } |
pkcs11c.c:SFTKHash_SHA3_224_DestroyContext Line | Count | Source | 124 | 2.60k | { \ | 125 | 2.60k | ctxtype *ctx = vctx; \ | 126 | 2.60k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 2.60k | } |
pkcs11c.c:SFTKHash_SHA3_256_DestroyContext Line | Count | Source | 124 | 9.47k | { \ | 125 | 9.47k | ctxtype *ctx = vctx; \ | 126 | 9.47k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 9.47k | } |
pkcs11c.c:SFTKHash_SHA3_384_DestroyContext Line | Count | Source | 124 | 30.7k | { \ | 125 | 30.7k | ctxtype *ctx = vctx; \ | 126 | 30.7k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 30.7k | } |
pkcs11c.c:SFTKHash_SHA3_512_DestroyContext Line | Count | Source | 124 | 1.56k | { \ | 125 | 1.56k | ctxtype *ctx = vctx; \ | 126 | 1.56k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 1.56k | } |
pkcs11c.c:SFTKHash_sftk_MAC_DestroyContext Line | Count | Source | 124 | 232k | { \ | 125 | 232k | ctxtype *ctx = vctx; \ | 126 | 232k | mmm##_DestroyContext(ctx, freeit); \ | 127 | 232k | } |
|
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 | 125k | { \ |
162 | 125k | ctxtype *ctx = vctx; \ |
163 | 125k | return mmm(ctx, output, outputLen, maxOutputLen, \ |
164 | 125k | input, inputLen); \ |
165 | 125k | } Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC2_Encrypt Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC2_Decrypt pkcs11c.c:SFTKCipher_RC4_Encrypt Line | Count | Source | 161 | 74 | { \ | 162 | 74 | ctxtype *ctx = vctx; \ | 163 | 74 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 74 | input, inputLen); \ | 165 | 74 | } |
pkcs11c.c:SFTKCipher_RC4_Decrypt Line | Count | Source | 161 | 48 | { \ | 162 | 48 | ctxtype *ctx = vctx; \ | 163 | 48 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 48 | input, inputLen); \ | 165 | 48 | } |
pkcs11c.c:SFTKCipher_DES_Encrypt Line | Count | Source | 161 | 52.8k | { \ | 162 | 52.8k | ctxtype *ctx = vctx; \ | 163 | 52.8k | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 52.8k | input, inputLen); \ | 165 | 52.8k | } |
pkcs11c.c:SFTKCipher_DES_Decrypt Line | Count | Source | 161 | 24.2k | { \ | 162 | 24.2k | ctxtype *ctx = vctx; \ | 163 | 24.2k | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 24.2k | input, inputLen); \ | 165 | 24.2k | } |
pkcs11c.c:SFTKCipher_SEED_Encrypt Line | Count | Source | 161 | 378 | { \ | 162 | 378 | ctxtype *ctx = vctx; \ | 163 | 378 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 378 | input, inputLen); \ | 165 | 378 | } |
pkcs11c.c:SFTKCipher_SEED_Decrypt Line | Count | Source | 161 | 1.25k | { \ | 162 | 1.25k | ctxtype *ctx = vctx; \ | 163 | 1.25k | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 1.25k | input, inputLen); \ | 165 | 1.25k | } |
pkcs11c.c:SFTKCipher_Camellia_Encrypt Line | Count | Source | 161 | 455 | { \ | 162 | 455 | ctxtype *ctx = vctx; \ | 163 | 455 | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 455 | input, inputLen); \ | 165 | 455 | } |
pkcs11c.c:SFTKCipher_Camellia_Decrypt Line | Count | Source | 161 | 4.62k | { \ | 162 | 4.62k | ctxtype *ctx = vctx; \ | 163 | 4.62k | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 4.62k | input, inputLen); \ | 165 | 4.62k | } |
pkcs11c.c:SFTKCipher_AES_Encrypt Line | Count | Source | 161 | 30.7k | { \ | 162 | 30.7k | ctxtype *ctx = vctx; \ | 163 | 30.7k | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 30.7k | input, inputLen); \ | 165 | 30.7k | } |
pkcs11c.c:SFTKCipher_AES_Decrypt Line | Count | Source | 161 | 11.2k | { \ | 162 | 11.2k | ctxtype *ctx = vctx; \ | 163 | 11.2k | return mmm(ctx, output, outputLen, maxOutputLen, \ | 164 | 11.2k | input, inputLen); \ | 165 | 11.2k | } |
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_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 | 241k | { \ |
175 | 241k | ctxtype *ctx = vctx; \ |
176 | 241k | mmm##_DestroyContext(ctx, freeit); \ |
177 | 241k | } Unexecuted instantiation: pkcs11c.c:SFTKCipher_RC2_DestroyContext pkcs11c.c:SFTKCipher_RC4_DestroyContext Line | Count | Source | 174 | 4.41k | { \ | 175 | 4.41k | ctxtype *ctx = vctx; \ | 176 | 4.41k | mmm##_DestroyContext(ctx, freeit); \ | 177 | 4.41k | } |
pkcs11c.c:SFTKCipher_DES_DestroyContext Line | Count | Source | 174 | 93.7k | { \ | 175 | 93.7k | ctxtype *ctx = vctx; \ | 176 | 93.7k | mmm##_DestroyContext(ctx, freeit); \ | 177 | 93.7k | } |
pkcs11c.c:SFTKCipher_SEED_DestroyContext Line | Count | Source | 174 | 9.59k | { \ | 175 | 9.59k | ctxtype *ctx = vctx; \ | 176 | 9.59k | mmm##_DestroyContext(ctx, freeit); \ | 177 | 9.59k | } |
pkcs11c.c:SFTKCipher_Camellia_DestroyContext Line | Count | Source | 174 | 22.2k | { \ | 175 | 22.2k | ctxtype *ctx = vctx; \ | 176 | 22.2k | mmm##_DestroyContext(ctx, freeit); \ | 177 | 22.2k | } |
pkcs11c.c:SFTKCipher_AES_DestroyContext Line | Count | Source | 174 | 111k | { \ | 175 | 111k | ctxtype *ctx = vctx; \ | 176 | 111k | mmm##_DestroyContext(ctx, freeit); \ | 177 | 111k | } |
Unexecuted instantiation: pkcs11c.c:SFTKCipher_AESKeyWrap_DestroyContext |
178 | | |
179 | | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
180 | | SFTKCipherWrap2(RC2Context, RC2); |
181 | | #endif |
182 | | SFTKCipherWrap2(RC4Context, RC4); |
183 | | SFTKCipherWrap2(DESContext, DES); |
184 | | #ifndef NSS_DISABLE_DEPRECATED_SEED |
185 | | SFTKCipherWrap2(SEEDContext, SEED); |
186 | | #endif |
187 | | SFTKCipherWrap2(CamelliaContext, Camellia); |
188 | | SFTKCipherWrap2(AESContext, AES); |
189 | | SFTKCipherWrap2(AESKeyWrapContext, AESKeyWrap); |
190 | | |
191 | | #if NSS_SOFTOKEN_DOES_RC5 |
192 | | SFTKCipherWrap2(RC5Context, RC5); |
193 | | #endif |
194 | | |
195 | | /* |
196 | | * free routines.... Free local type allocated data, and convert |
197 | | * other free routines to the destroy signature. |
198 | | */ |
199 | | static void |
200 | | sftk_FreePrivKey(void *vkey, PRBool freeit) |
201 | 0 | { |
202 | 0 | NSSLOWKEYPrivateKey *key = vkey; |
203 | 0 | nsslowkey_DestroyPrivateKey(key); |
204 | 0 | } |
205 | | |
206 | | static void |
207 | | sftk_Space(void *data, PRBool freeit) |
208 | 253k | { |
209 | 253k | PORT_Free(data); |
210 | 253k | } |
211 | | |
212 | | static void |
213 | | sftk_ZSpace(void *data, PRBool freeit) |
214 | 4.80k | { |
215 | 4.80k | size_t len = *(size_t *)data; |
216 | 4.80k | PORT_ZFree(data, len); |
217 | 4.80k | } |
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 | 0 | { |
226 | 0 | unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae }; |
227 | 0 | unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 }; |
228 | 0 | unsigned char enc_src[8]; |
229 | 0 | unsigned char enc_dest[8]; |
230 | 0 | unsigned int leng, i; |
231 | 0 | DESContext *descx; |
232 | 0 | SECStatus rv; |
233 | 0 | CK_RV crv = CKR_OK; |
234 | | |
235 | | /* zero the parity bits */ |
236 | 0 | for (i = 0; i < 8; i++) { |
237 | 0 | enc_src[i] = cdmfkey[i] & 0xfe; |
238 | 0 | } |
239 | | |
240 | | /* encrypt with key 1 */ |
241 | 0 | descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE); |
242 | 0 | if (descx == NULL) { |
243 | 0 | crv = CKR_HOST_MEMORY; |
244 | 0 | goto done; |
245 | 0 | } |
246 | 0 | rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8); |
247 | 0 | DES_DestroyContext(descx, PR_TRUE); |
248 | 0 | 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 | 0 | for (i = 0; i < 8; i++) { |
255 | 0 | if (i & 1) { |
256 | 0 | enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe; |
257 | 0 | } else { |
258 | 0 | enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e; |
259 | 0 | } |
260 | 0 | } |
261 | | |
262 | | /* encrypt with key 2 */ |
263 | 0 | descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE); |
264 | 0 | if (descx == NULL) { |
265 | 0 | crv = CKR_HOST_MEMORY; |
266 | 0 | goto done; |
267 | 0 | } |
268 | 0 | rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8); |
269 | 0 | DES_DestroyContext(descx, PR_TRUE); |
270 | 0 | 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 | 0 | sftk_FormatDESKey(deskey, 8); |
277 | 0 | done: |
278 | 0 | PORT_Memset(enc_src, 0, sizeof enc_src); |
279 | 0 | PORT_Memset(enc_dest, 0, sizeof enc_dest); |
280 | 0 | return crv; |
281 | 0 | } |
282 | | |
283 | | /* NSC_DestroyObject destroys an object. */ |
284 | | CK_RV |
285 | | NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) |
286 | 1.49M | { |
287 | 1.49M | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
288 | 1.49M | SFTKSession *session; |
289 | 1.49M | SFTKObject *object; |
290 | 1.49M | SFTKFreeStatus status; |
291 | | |
292 | 1.49M | CHECK_FORK(); |
293 | | |
294 | 1.49M | 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.49M | session = sftk_SessionFromHandle(hSession); |
302 | 1.49M | if (session == NULL) { |
303 | 0 | return CKR_SESSION_HANDLE_INVALID; |
304 | 0 | } |
305 | | |
306 | 1.49M | object = sftk_ObjectFromHandle(hObject, session); |
307 | 1.49M | if (object == NULL) { |
308 | 0 | sftk_FreeSession(session); |
309 | 0 | return CKR_OBJECT_HANDLE_INVALID; |
310 | 0 | } |
311 | | |
312 | | /* don't destroy a private object if we aren't logged in */ |
313 | 1.49M | if ((!slot->isLoggedIn) && (slot->needLogin) && |
314 | 0 | (sftk_isTrue(object, CKA_PRIVATE))) { |
315 | 0 | sftk_FreeSession(session); |
316 | 0 | sftk_FreeObject(object); |
317 | 0 | return CKR_USER_NOT_LOGGED_IN; |
318 | 0 | } |
319 | | |
320 | | /* don't destroy a token object if we aren't in a rw session */ |
321 | | |
322 | 1.49M | if (((session->info.flags & CKF_RW_SESSION) == 0) && |
323 | 1.49M | (sftk_isTrue(object, CKA_TOKEN))) { |
324 | 0 | sftk_FreeSession(session); |
325 | 0 | sftk_FreeObject(object); |
326 | 0 | return CKR_SESSION_READ_ONLY; |
327 | 0 | } |
328 | | |
329 | 1.49M | sftk_DeleteObject(session, object); |
330 | | |
331 | 1.49M | sftk_FreeSession(session); |
332 | | |
333 | | /* |
334 | | * get some indication if the object is destroyed. Note: this is not |
335 | | * 100%. Someone may have an object reference outstanding (though that |
336 | | * should not be the case by here. Also note that the object is "half" |
337 | | * destroyed. Our internal representation is destroyed, but it may still |
338 | | * be in the data base. |
339 | | */ |
340 | 1.49M | status = sftk_FreeObject(object); |
341 | | |
342 | 1.49M | return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR; |
343 | 1.49M | } |
344 | | |
345 | | /* |
346 | | * Returns true if "params" contains a valid set of PSS parameters |
347 | | */ |
348 | | static PRBool |
349 | | sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params) |
350 | 4.80k | { |
351 | 4.80k | if (!params) { |
352 | 0 | return PR_FALSE; |
353 | 0 | } |
354 | 4.80k | if (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL || |
355 | 4.80k | sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) { |
356 | 0 | return PR_FALSE; |
357 | 0 | } |
358 | 4.80k | return PR_TRUE; |
359 | 4.80k | } |
360 | | |
361 | | /* |
362 | | * Returns true if "params" contains a valid set of OAEP parameters |
363 | | */ |
364 | | static PRBool |
365 | | sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS *params) |
366 | 0 | { |
367 | 0 | if (!params) { |
368 | 0 | return PR_FALSE; |
369 | 0 | } |
370 | | /* The requirements of ulSourceLen/pSourceData come from PKCS #11, which |
371 | | * state: |
372 | | * If the parameter is empty, pSourceData must be NULL and |
373 | | * ulSourceDataLen must be zero. |
374 | | */ |
375 | 0 | if (params->source != CKZ_DATA_SPECIFIED || |
376 | 0 | (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) || |
377 | 0 | (sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) || |
378 | 0 | (params->ulSourceDataLen == 0 && params->pSourceData != NULL) || |
379 | 0 | (params->ulSourceDataLen != 0 && params->pSourceData == NULL)) { |
380 | 0 | return PR_FALSE; |
381 | 0 | } |
382 | 0 | return PR_TRUE; |
383 | 0 | } |
384 | | |
385 | | /* |
386 | | * return a context based on the SFTKContext type. |
387 | | */ |
388 | | SFTKSessionContext * |
389 | | sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type) |
390 | 17.4M | { |
391 | 17.4M | switch (type) { |
392 | 364k | case SFTK_ENCRYPT: |
393 | 628k | case SFTK_DECRYPT: |
394 | 752k | case SFTK_MESSAGE_ENCRYPT: |
395 | 871k | case SFTK_MESSAGE_DECRYPT: |
396 | 871k | return session->enc_context; |
397 | 15.4M | case SFTK_HASH: |
398 | 15.4M | return session->hash_context; |
399 | 1.09M | case SFTK_SIGN: |
400 | 1.09M | case SFTK_SIGN_RECOVER: |
401 | 1.12M | case SFTK_VERIFY: |
402 | 1.15M | case SFTK_VERIFY_RECOVER: |
403 | 1.15M | case SFTK_MESSAGE_SIGN: |
404 | 1.15M | case SFTK_MESSAGE_VERIFY: |
405 | 1.15M | return session->hash_context; |
406 | 17.4M | } |
407 | 0 | return NULL; |
408 | 17.4M | } |
409 | | |
410 | | /* |
411 | | * change a context based on the SFTKContext type. |
412 | | */ |
413 | | void |
414 | | sftk_SetContextByType(SFTKSession *session, SFTKContextType type, |
415 | | SFTKSessionContext *context) |
416 | 3.18M | { |
417 | 3.18M | switch (type) { |
418 | 294k | case SFTK_ENCRYPT: |
419 | 518k | case SFTK_DECRYPT: |
420 | 608k | case SFTK_MESSAGE_ENCRYPT: |
421 | 704k | case SFTK_MESSAGE_DECRYPT: |
422 | 704k | session->enc_context = context; |
423 | 704k | break; |
424 | 1.69M | case SFTK_HASH: |
425 | 1.69M | session->hash_context = context; |
426 | 1.69M | break; |
427 | 744k | case SFTK_SIGN: |
428 | 744k | case SFTK_SIGN_RECOVER: |
429 | 760k | case SFTK_VERIFY: |
430 | 787k | case SFTK_VERIFY_RECOVER: |
431 | 787k | case SFTK_MESSAGE_SIGN: |
432 | 787k | case SFTK_MESSAGE_VERIFY: |
433 | 787k | session->hash_context = context; |
434 | 787k | break; |
435 | 3.18M | } |
436 | 3.18M | return; |
437 | 3.18M | } |
438 | | |
439 | | /* |
440 | | * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal, |
441 | | * and C_XXX function. The function takes a session handle, the context type, |
442 | | * and wether or not the session needs to be multipart. It returns the context, |
443 | | * and optionally returns the session pointer (if sessionPtr != NULL) if session |
444 | | * pointer is returned, the caller is responsible for freeing it. |
445 | | */ |
446 | | CK_RV |
447 | | sftk_GetContext(CK_SESSION_HANDLE handle, SFTKSessionContext **contextPtr, |
448 | | SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr) |
449 | 15.3M | { |
450 | 15.3M | SFTKSession *session; |
451 | 15.3M | SFTKSessionContext *context; |
452 | | |
453 | 15.3M | session = sftk_SessionFromHandle(handle); |
454 | 15.3M | if (session == NULL) |
455 | 0 | return CKR_SESSION_HANDLE_INVALID; |
456 | 15.3M | context = sftk_ReturnContextByType(session, type); |
457 | | /* make sure the context is valid */ |
458 | 15.3M | if ((context == NULL) || (context->type != type) || (needMulti && !(context->multi))) { |
459 | 191k | sftk_FreeSession(session); |
460 | 191k | return CKR_OPERATION_NOT_INITIALIZED; |
461 | 191k | } |
462 | 15.1M | *contextPtr = context; |
463 | 15.1M | if (sessionPtr != NULL) { |
464 | 1.62M | *sessionPtr = session; |
465 | 13.5M | } else { |
466 | 13.5M | sftk_FreeSession(session); |
467 | 13.5M | } |
468 | 15.1M | return CKR_OK; |
469 | 15.3M | } |
470 | | |
471 | | /** Terminate operation (in the PKCS#11 spec sense). |
472 | | * Intuitive name for FreeContext/SetNullContext pair. |
473 | | */ |
474 | | void |
475 | | sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype, |
476 | | SFTKSessionContext *context) |
477 | 1.10M | { |
478 | 1.10M | session->lastOpWasFIPS = context->isFIPS; |
479 | 1.10M | sftk_FreeContext(context); |
480 | 1.10M | sftk_SetContextByType(session, ctype, NULL); |
481 | 1.10M | } |
482 | | |
483 | | /* |
484 | | ************** Crypto Functions: Encrypt ************************ |
485 | | */ |
486 | | |
487 | | /* |
488 | | * All the NSC_InitXXX functions have a set of common checks and processing they |
489 | | * all need to do at the beginning. This is done here. |
490 | | */ |
491 | | CK_RV |
492 | | sftk_InitGeneric(SFTKSession *session, CK_MECHANISM *pMechanism, |
493 | | SFTKSessionContext **contextPtr, |
494 | | SFTKContextType ctype, SFTKObject **keyPtr, |
495 | | CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr, |
496 | | CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation) |
497 | 1.90M | { |
498 | 1.90M | SFTKObject *key = NULL; |
499 | 1.90M | SFTKAttribute *att; |
500 | 1.90M | SFTKSessionContext *context; |
501 | | |
502 | | /* We can only init if there is not current context active */ |
503 | 1.90M | if (sftk_ReturnContextByType(session, ctype) != NULL) { |
504 | 0 | return CKR_OPERATION_ACTIVE; |
505 | 0 | } |
506 | | |
507 | | /* find the key */ |
508 | 1.90M | if (keyPtr) { |
509 | 1.00M | key = sftk_ObjectFromHandle(hKey, session); |
510 | 1.00M | if (key == NULL) { |
511 | 0 | return CKR_KEY_HANDLE_INVALID; |
512 | 0 | } |
513 | | |
514 | | /* make sure it's a valid key for this operation */ |
515 | 1.00M | if (((key->objclass != CKO_SECRET_KEY) && |
516 | 136k | (key->objclass != pubKeyType)) || |
517 | 1.00M | !sftk_isTrue(key, operation)) { |
518 | 0 | sftk_FreeObject(key); |
519 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
520 | 0 | } |
521 | | /* get the key type */ |
522 | 1.00M | att = sftk_FindAttribute(key, CKA_KEY_TYPE); |
523 | 1.00M | if (att == NULL) { |
524 | 0 | sftk_FreeObject(key); |
525 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
526 | 0 | } |
527 | 1.00M | PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE)); |
528 | 1.00M | if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) { |
529 | 0 | sftk_FreeAttribute(att); |
530 | 0 | sftk_FreeObject(key); |
531 | 0 | return CKR_ATTRIBUTE_VALUE_INVALID; |
532 | 0 | } |
533 | 1.00M | PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE)); |
534 | 1.00M | sftk_FreeAttribute(att); |
535 | 1.00M | *keyPtr = key; |
536 | 1.00M | } |
537 | | |
538 | | /* allocate the context structure */ |
539 | 1.90M | context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext)); |
540 | 1.90M | if (context == NULL) { |
541 | 0 | if (key) |
542 | 0 | sftk_FreeObject(key); |
543 | 0 | return CKR_HOST_MEMORY; |
544 | 0 | } |
545 | 1.90M | context->type = ctype; |
546 | 1.90M | context->multi = PR_TRUE; |
547 | 1.90M | context->rsa = PR_FALSE; |
548 | 1.90M | context->cipherInfo = NULL; |
549 | 1.90M | context->hashInfo = NULL; |
550 | 1.90M | context->doPad = PR_FALSE; |
551 | 1.90M | context->padDataLength = 0; |
552 | 1.90M | context->key = key; |
553 | 1.90M | context->blockSize = 0; |
554 | 1.90M | context->maxLen = 0; |
555 | 1.90M | context->signature = NULL; |
556 | 1.90M | context->isFIPS = sftk_operationIsFIPS(session->slot, pMechanism, |
557 | 1.90M | operation, key); |
558 | 1.90M | *contextPtr = context; |
559 | 1.90M | return CKR_OK; |
560 | 1.90M | } |
561 | | |
562 | | static int |
563 | | sftk_aes_mode(CK_MECHANISM_TYPE mechanism) |
564 | 111k | { |
565 | 111k | switch (mechanism) { |
566 | 469 | case CKM_AES_CBC_PAD: |
567 | 82.5k | case CKM_AES_CBC: |
568 | 82.5k | return NSS_AES_CBC; |
569 | 28.7k | case CKM_AES_ECB: |
570 | 28.7k | return NSS_AES; |
571 | 0 | case CKM_AES_CTS: |
572 | 0 | return NSS_AES_CTS; |
573 | 0 | case CKM_AES_CTR: |
574 | 0 | return NSS_AES_CTR; |
575 | 0 | case CKM_AES_GCM: |
576 | 0 | return NSS_AES_GCM; |
577 | 111k | } |
578 | 0 | return -1; |
579 | 111k | } |
580 | | |
581 | | static SECStatus |
582 | | sftk_RSAEncryptRaw(void *ctx, unsigned char *output, |
583 | | unsigned int *outputLen, unsigned int maxLen, |
584 | | const unsigned char *input, unsigned int inputLen) |
585 | 0 | { |
586 | 0 | NSSLOWKEYPublicKey *key = ctx; |
587 | 0 | SECStatus rv = SECFailure; |
588 | |
|
589 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
590 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
591 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
592 | 0 | return SECFailure; |
593 | 0 | } |
594 | | |
595 | 0 | rv = RSA_EncryptRaw(&key->u.rsa, output, outputLen, maxLen, input, |
596 | 0 | inputLen); |
597 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
598 | 0 | sftk_fatalError = PR_TRUE; |
599 | 0 | } |
600 | |
|
601 | 0 | return rv; |
602 | 0 | } |
603 | | |
604 | | static SECStatus |
605 | | sftk_RSADecryptRaw(void *ctx, unsigned char *output, |
606 | | unsigned int *outputLen, unsigned int maxLen, |
607 | | const unsigned char *input, unsigned int inputLen) |
608 | 0 | { |
609 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
610 | 0 | SECStatus rv = SECFailure; |
611 | |
|
612 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
613 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
614 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
615 | 0 | return SECFailure; |
616 | 0 | } |
617 | | |
618 | 0 | rv = RSA_DecryptRaw(&key->u.rsa, output, outputLen, maxLen, input, |
619 | 0 | inputLen); |
620 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
621 | 0 | sftk_fatalError = PR_TRUE; |
622 | 0 | } |
623 | |
|
624 | 0 | return rv; |
625 | 0 | } |
626 | | |
627 | | static SECStatus |
628 | | sftk_RSAEncrypt(void *ctx, unsigned char *output, |
629 | | unsigned int *outputLen, unsigned int maxLen, |
630 | | const unsigned char *input, unsigned int inputLen) |
631 | 13.5k | { |
632 | 13.5k | NSSLOWKEYPublicKey *key = ctx; |
633 | 13.5k | SECStatus rv = SECFailure; |
634 | | |
635 | 13.5k | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
636 | 13.5k | if (key->keyType != NSSLOWKEYRSAKey) { |
637 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
638 | 0 | return SECFailure; |
639 | 0 | } |
640 | | |
641 | 13.5k | rv = RSA_EncryptBlock(&key->u.rsa, output, outputLen, maxLen, input, |
642 | 13.5k | inputLen); |
643 | 13.5k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
644 | 0 | sftk_fatalError = PR_TRUE; |
645 | 0 | } |
646 | | |
647 | 13.5k | return rv; |
648 | 13.5k | } |
649 | | |
650 | | static SECStatus |
651 | | sftk_RSADecrypt(void *ctx, unsigned char *output, |
652 | | unsigned int *outputLen, unsigned int maxLen, |
653 | | const unsigned char *input, unsigned int inputLen) |
654 | 71.5k | { |
655 | 71.5k | NSSLOWKEYPrivateKey *key = ctx; |
656 | 71.5k | SECStatus rv = SECFailure; |
657 | | |
658 | 71.5k | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
659 | 71.5k | if (key->keyType != NSSLOWKEYRSAKey) { |
660 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
661 | 0 | return SECFailure; |
662 | 0 | } |
663 | | |
664 | 71.5k | rv = RSA_DecryptBlock(&key->u.rsa, output, outputLen, maxLen, input, |
665 | 71.5k | inputLen); |
666 | 71.5k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
667 | 0 | sftk_fatalError = PR_TRUE; |
668 | 0 | } |
669 | | |
670 | 71.5k | return rv; |
671 | 71.5k | } |
672 | | |
673 | | static void |
674 | | sftk_freeRSAOAEPInfo(void *ctx, PRBool freeit) |
675 | 0 | { |
676 | 0 | SFTKOAEPInfo *info = ctx; |
677 | 0 | PORT_ZFree(info->params.pSourceData, info->params.ulSourceDataLen); |
678 | 0 | PORT_ZFree(info, sizeof(SFTKOAEPInfo)); |
679 | 0 | } |
680 | | |
681 | | static SECStatus |
682 | | sftk_RSAEncryptOAEP(void *ctx, unsigned char *output, |
683 | | unsigned int *outputLen, unsigned int maxLen, |
684 | | const unsigned char *input, unsigned int inputLen) |
685 | 0 | { |
686 | 0 | SFTKOAEPInfo *info = ctx; |
687 | 0 | HASH_HashType hashAlg; |
688 | 0 | HASH_HashType maskHashAlg; |
689 | |
|
690 | 0 | PORT_Assert(info->key.pub->keyType == NSSLOWKEYRSAKey); |
691 | 0 | if (info->key.pub->keyType != NSSLOWKEYRSAKey) { |
692 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
693 | 0 | return SECFailure; |
694 | 0 | } |
695 | | |
696 | 0 | hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg); |
697 | 0 | maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf); |
698 | |
|
699 | 0 | return RSA_EncryptOAEP(&info->key.pub->u.rsa, hashAlg, maskHashAlg, |
700 | 0 | (const unsigned char *)info->params.pSourceData, |
701 | 0 | info->params.ulSourceDataLen, NULL, 0, |
702 | 0 | output, outputLen, maxLen, input, inputLen); |
703 | 0 | } |
704 | | |
705 | | static SECStatus |
706 | | sftk_RSADecryptOAEP(void *ctx, unsigned char *output, |
707 | | unsigned int *outputLen, unsigned int maxLen, |
708 | | const unsigned char *input, unsigned int inputLen) |
709 | 0 | { |
710 | 0 | SFTKOAEPInfo *info = ctx; |
711 | 0 | SECStatus rv = SECFailure; |
712 | 0 | HASH_HashType hashAlg; |
713 | 0 | HASH_HashType maskHashAlg; |
714 | |
|
715 | 0 | PORT_Assert(info->key.priv->keyType == NSSLOWKEYRSAKey); |
716 | 0 | if (info->key.priv->keyType != NSSLOWKEYRSAKey) { |
717 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
718 | 0 | return SECFailure; |
719 | 0 | } |
720 | | |
721 | 0 | hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg); |
722 | 0 | maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf); |
723 | |
|
724 | 0 | rv = RSA_DecryptOAEP(&info->key.priv->u.rsa, hashAlg, maskHashAlg, |
725 | 0 | (const unsigned char *)info->params.pSourceData, |
726 | 0 | info->params.ulSourceDataLen, |
727 | 0 | output, outputLen, maxLen, input, inputLen); |
728 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
729 | 0 | sftk_fatalError = PR_TRUE; |
730 | 0 | } |
731 | 0 | return rv; |
732 | 0 | } |
733 | | |
734 | | static SFTKChaCha20Poly1305Info * |
735 | | sftk_ChaCha20Poly1305_CreateContext(const unsigned char *key, |
736 | | unsigned int keyLen, |
737 | | const CK_NSS_AEAD_PARAMS *params) |
738 | 0 | { |
739 | 0 | SFTKChaCha20Poly1305Info *ctx; |
740 | |
|
741 | 0 | if (params->ulNonceLen != sizeof(ctx->nonce)) { |
742 | 0 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
743 | 0 | return NULL; |
744 | 0 | } |
745 | | |
746 | 0 | ctx = PORT_New(SFTKChaCha20Poly1305Info); |
747 | 0 | if (ctx == NULL) { |
748 | 0 | return NULL; |
749 | 0 | } |
750 | | |
751 | 0 | if (ChaCha20Poly1305_InitContext(&ctx->freeblCtx, key, keyLen, |
752 | 0 | params->ulTagLen) != SECSuccess) { |
753 | 0 | PORT_Free(ctx); |
754 | 0 | return NULL; |
755 | 0 | } |
756 | | |
757 | 0 | PORT_Memcpy(ctx->nonce, params->pNonce, sizeof(ctx->nonce)); |
758 | | |
759 | | /* AAD data and length must both be null, or both non-null. */ |
760 | 0 | PORT_Assert((params->pAAD == NULL) == (params->ulAADLen == 0)); |
761 | |
|
762 | 0 | if (params->ulAADLen > sizeof(ctx->ad)) { |
763 | | /* Need to allocate an overflow buffer for the additional data. */ |
764 | 0 | ctx->adOverflow = (unsigned char *)PORT_Alloc(params->ulAADLen); |
765 | 0 | if (!ctx->adOverflow) { |
766 | 0 | PORT_Free(ctx); |
767 | 0 | return NULL; |
768 | 0 | } |
769 | 0 | PORT_Memcpy(ctx->adOverflow, params->pAAD, params->ulAADLen); |
770 | 0 | } else { |
771 | 0 | ctx->adOverflow = NULL; |
772 | 0 | if (params->pAAD) { |
773 | 0 | PORT_Memcpy(ctx->ad, params->pAAD, params->ulAADLen); |
774 | 0 | } |
775 | 0 | } |
776 | 0 | ctx->adLen = params->ulAADLen; |
777 | |
|
778 | 0 | return ctx; |
779 | 0 | } |
780 | | |
781 | | static void |
782 | | sftk_ChaCha20Poly1305_DestroyContext(void *vctx, |
783 | | PRBool freeit) |
784 | 0 | { |
785 | 0 | SFTKChaCha20Poly1305Info *ctx = vctx; |
786 | 0 | ChaCha20Poly1305_DestroyContext(&ctx->freeblCtx, PR_FALSE); |
787 | 0 | if (ctx->adOverflow != NULL) { |
788 | 0 | PORT_ZFree(ctx->adOverflow, ctx->adLen); |
789 | 0 | ctx->adOverflow = NULL; |
790 | 0 | } else { |
791 | 0 | PORT_Memset(ctx->ad, 0, ctx->adLen); |
792 | 0 | } |
793 | 0 | ctx->adLen = 0; |
794 | 0 | if (freeit) { |
795 | 0 | PORT_Free(ctx); |
796 | 0 | } |
797 | 0 | } |
798 | | |
799 | | static SECStatus |
800 | | sftk_ChaCha20Poly1305_Encrypt(void *vctx, |
801 | | unsigned char *output, unsigned int *outputLen, |
802 | | unsigned int maxOutputLen, |
803 | | const unsigned char *input, unsigned int inputLen) |
804 | 0 | { |
805 | 0 | const SFTKChaCha20Poly1305Info *ctx = vctx; |
806 | 0 | const unsigned char *ad = ctx->adOverflow; |
807 | |
|
808 | 0 | if (ad == NULL) { |
809 | 0 | ad = ctx->ad; |
810 | 0 | } |
811 | |
|
812 | 0 | return ChaCha20Poly1305_Seal(&ctx->freeblCtx, output, outputLen, |
813 | 0 | maxOutputLen, input, inputLen, ctx->nonce, |
814 | 0 | sizeof(ctx->nonce), ad, ctx->adLen); |
815 | 0 | } |
816 | | |
817 | | static SECStatus |
818 | | sftk_ChaCha20Poly1305_Decrypt(void *vctx, |
819 | | unsigned char *output, unsigned int *outputLen, |
820 | | unsigned int maxOutputLen, |
821 | | const unsigned char *input, unsigned int inputLen) |
822 | 0 | { |
823 | 0 | const SFTKChaCha20Poly1305Info *ctx = vctx; |
824 | 0 | const unsigned char *ad = ctx->adOverflow; |
825 | |
|
826 | 0 | if (ad == NULL) { |
827 | 0 | ad = ctx->ad; |
828 | 0 | } |
829 | |
|
830 | 0 | return ChaCha20Poly1305_Open(&ctx->freeblCtx, output, outputLen, |
831 | 0 | maxOutputLen, input, inputLen, ctx->nonce, |
832 | 0 | sizeof(ctx->nonce), ad, ctx->adLen); |
833 | 0 | } |
834 | | |
835 | | static SECStatus |
836 | | sftk_ChaCha20Ctr(void *vctx, |
837 | | unsigned char *output, unsigned int *outputLen, |
838 | | unsigned int maxOutputLen, |
839 | | const unsigned char *input, unsigned int inputLen) |
840 | 12.9k | { |
841 | 12.9k | if (maxOutputLen < inputLen) { |
842 | 0 | PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
843 | 0 | return SECFailure; |
844 | 0 | } |
845 | 12.9k | SFTKChaCha20CtrInfo *ctx = vctx; |
846 | 12.9k | ChaCha20_Xor(output, input, inputLen, ctx->key, |
847 | 12.9k | ctx->nonce, ctx->counter); |
848 | 12.9k | *outputLen = inputLen; |
849 | 12.9k | return SECSuccess; |
850 | 12.9k | } |
851 | | |
852 | | static void |
853 | | sftk_ChaCha20Ctr_DestroyContext(void *vctx, |
854 | | PRBool freeit) |
855 | 12.9k | { |
856 | 12.9k | SFTKChaCha20CtrInfo *ctx = vctx; |
857 | 12.9k | memset(ctx, 0, sizeof(SFTKChaCha20CtrInfo)); |
858 | 12.9k | if (freeit) { |
859 | 12.9k | PORT_Free(ctx); |
860 | 12.9k | } |
861 | 12.9k | } |
862 | | |
863 | | /** NSC_CryptInit initializes an encryption/Decryption operation. |
864 | | * |
865 | | * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey. |
866 | | * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block |
867 | | * ciphers MAC'ing. |
868 | | */ |
869 | | CK_RV |
870 | | sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
871 | | CK_OBJECT_HANDLE hKey, |
872 | | CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage, |
873 | | SFTKContextType contextType, PRBool isEncrypt) |
874 | 339k | { |
875 | 339k | SFTKSession *session; |
876 | 339k | SFTKObject *key; |
877 | 339k | SFTKSessionContext *context; |
878 | 339k | SFTKAttribute *att; |
879 | 339k | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
880 | 339k | CK_RC2_CBC_PARAMS *rc2_param; |
881 | 339k | unsigned effectiveKeyLength; |
882 | 339k | #endif |
883 | | #if NSS_SOFTOKEN_DOES_RC5 |
884 | | CK_RC5_CBC_PARAMS *rc5_param; |
885 | | SECItem rc5Key; |
886 | | #endif |
887 | 339k | CK_NSS_GCM_PARAMS nss_gcm_param; |
888 | 339k | void *aes_param; |
889 | 339k | CK_NSS_AEAD_PARAMS nss_aead_params; |
890 | 339k | CK_NSS_AEAD_PARAMS *nss_aead_params_ptr = NULL; |
891 | 339k | CK_KEY_TYPE key_type; |
892 | 339k | CK_RV crv = CKR_OK; |
893 | 339k | unsigned char newdeskey[24]; |
894 | 339k | PRBool useNewKey = PR_FALSE; |
895 | 339k | int t; |
896 | | |
897 | 339k | if (!pMechanism) { |
898 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
899 | 0 | } |
900 | | |
901 | 339k | crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage); |
902 | 339k | if (crv != CKR_OK) |
903 | 35 | return crv; |
904 | | |
905 | 339k | session = sftk_SessionFromHandle(hSession); |
906 | 339k | if (session == NULL) |
907 | 0 | return CKR_SESSION_HANDLE_INVALID; |
908 | | |
909 | 339k | crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key, |
910 | 339k | hKey, &key_type, |
911 | 339k | isEncrypt ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY, |
912 | 339k | keyUsage); |
913 | | |
914 | 339k | if (crv != CKR_OK) { |
915 | 0 | sftk_FreeSession(session); |
916 | 0 | return crv; |
917 | 0 | } |
918 | | |
919 | 339k | context->doPad = PR_FALSE; |
920 | 339k | switch (pMechanism->mechanism) { |
921 | 85.0k | case CKM_RSA_PKCS: |
922 | 85.0k | case CKM_RSA_X_509: |
923 | 85.0k | if (key_type != CKK_RSA) { |
924 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
925 | 0 | break; |
926 | 0 | } |
927 | 85.0k | context->multi = PR_FALSE; |
928 | 85.0k | context->rsa = PR_TRUE; |
929 | 85.0k | if (isEncrypt) { |
930 | 13.5k | NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); |
931 | 13.5k | if (pubKey == NULL) { |
932 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
933 | 0 | break; |
934 | 0 | } |
935 | 13.5k | context->maxLen = nsslowkey_PublicModulusLen(pubKey); |
936 | 13.5k | context->cipherInfo = (void *)pubKey; |
937 | 13.5k | context->update = pMechanism->mechanism == CKM_RSA_X_509 |
938 | 13.5k | ? sftk_RSAEncryptRaw |
939 | 13.5k | : sftk_RSAEncrypt; |
940 | 71.5k | } else { |
941 | 71.5k | NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key, CKK_RSA, &crv); |
942 | 71.5k | if (privKey == NULL) { |
943 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
944 | 0 | break; |
945 | 0 | } |
946 | 71.5k | context->maxLen = nsslowkey_PrivateModulusLen(privKey); |
947 | 71.5k | context->cipherInfo = (void *)privKey; |
948 | 71.5k | context->update = pMechanism->mechanism == CKM_RSA_X_509 |
949 | 71.5k | ? sftk_RSADecryptRaw |
950 | 71.5k | : sftk_RSADecrypt; |
951 | 71.5k | } |
952 | 85.0k | context->destroy = sftk_Null; |
953 | 85.0k | break; |
954 | 0 | case CKM_RSA_PKCS_OAEP: |
955 | 0 | if (key_type != CKK_RSA) { |
956 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
957 | 0 | break; |
958 | 0 | } |
959 | 0 | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) || |
960 | 0 | !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter)) { |
961 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
962 | 0 | break; |
963 | 0 | } |
964 | 0 | context->multi = PR_FALSE; |
965 | 0 | context->rsa = PR_TRUE; |
966 | 0 | { |
967 | 0 | SFTKOAEPInfo *info; |
968 | 0 | CK_RSA_PKCS_OAEP_PARAMS *params = |
969 | 0 | (CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter; |
970 | | /* make a copy of the source data value for future |
971 | | * use (once the user has reclaimed his data in pParameter)*/ |
972 | 0 | void *newSource = NULL; |
973 | 0 | if (params->pSourceData) { |
974 | 0 | newSource = PORT_Alloc(params->ulSourceDataLen); |
975 | 0 | if (newSource == NULL) { |
976 | 0 | crv = CKR_HOST_MEMORY; |
977 | 0 | break; |
978 | 0 | } |
979 | 0 | PORT_Memcpy(newSource, params->pSourceData, params->ulSourceDataLen); |
980 | 0 | } |
981 | 0 | info = PORT_New(SFTKOAEPInfo); |
982 | 0 | if (info == NULL) { |
983 | 0 | PORT_ZFree(newSource, params->ulSourceDataLen); |
984 | 0 | crv = CKR_HOST_MEMORY; |
985 | 0 | break; |
986 | 0 | } |
987 | 0 | info->params = *params; |
988 | 0 | info->params.pSourceData = newSource; |
989 | 0 | info->isEncrypt = isEncrypt; |
990 | | |
991 | | /* now setup encryption and decryption contexts */ |
992 | 0 | if (isEncrypt) { |
993 | 0 | info->key.pub = sftk_GetPubKey(key, CKK_RSA, &crv); |
994 | 0 | if (info->key.pub == NULL) { |
995 | 0 | sftk_freeRSAOAEPInfo(info, PR_TRUE); |
996 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
997 | 0 | break; |
998 | 0 | } |
999 | 0 | context->update = sftk_RSAEncryptOAEP; |
1000 | 0 | context->maxLen = nsslowkey_PublicModulusLen(info->key.pub); |
1001 | 0 | } else { |
1002 | 0 | info->key.priv = sftk_GetPrivKey(key, CKK_RSA, &crv); |
1003 | 0 | if (info->key.priv == NULL) { |
1004 | 0 | sftk_freeRSAOAEPInfo(info, PR_TRUE); |
1005 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1006 | 0 | break; |
1007 | 0 | } |
1008 | 0 | context->update = sftk_RSADecryptOAEP; |
1009 | 0 | context->maxLen = nsslowkey_PrivateModulusLen(info->key.priv); |
1010 | 0 | } |
1011 | 0 | context->cipherInfo = info; |
1012 | 0 | } |
1013 | 0 | context->destroy = sftk_freeRSAOAEPInfo; |
1014 | 0 | break; |
1015 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
1016 | 0 | case CKM_RC2_CBC_PAD: |
1017 | 0 | context->doPad = PR_TRUE; |
1018 | | /* fall thru */ |
1019 | 0 | case CKM_RC2_ECB: |
1020 | 0 | case CKM_RC2_CBC: |
1021 | 0 | context->blockSize = 8; |
1022 | 0 | if (key_type != CKK_RC2) { |
1023 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1024 | 0 | break; |
1025 | 0 | } |
1026 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
1027 | 0 | if (att == NULL) { |
1028 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1029 | 0 | break; |
1030 | 0 | } |
1031 | | |
1032 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_CBC_PARAMS))) { |
1033 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1034 | 0 | break; |
1035 | 0 | } |
1036 | 0 | rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter; |
1037 | 0 | effectiveKeyLength = (rc2_param->ulEffectiveBits + 7) / 8; |
1038 | 0 | context->cipherInfo = |
1039 | 0 | RC2_CreateContext((unsigned char *)att->attrib.pValue, |
1040 | 0 | att->attrib.ulValueLen, rc2_param->iv, |
1041 | 0 | pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : NSS_RC2_CBC, effectiveKeyLength); |
1042 | 0 | sftk_FreeAttribute(att); |
1043 | 0 | if (context->cipherInfo == NULL) { |
1044 | 0 | crv = CKR_HOST_MEMORY; |
1045 | 0 | break; |
1046 | 0 | } |
1047 | 0 | context->update = isEncrypt ? SFTKCipher_RC2_Encrypt : SFTKCipher_RC2_Decrypt; |
1048 | 0 | context->destroy = SFTKCipher_RC2_DestroyContext; |
1049 | 0 | break; |
1050 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
1051 | | |
1052 | | #if NSS_SOFTOKEN_DOES_RC5 |
1053 | | case CKM_RC5_CBC_PAD: |
1054 | | context->doPad = PR_TRUE; |
1055 | | /* fall thru */ |
1056 | | case CKM_RC5_ECB: |
1057 | | case CKM_RC5_CBC: |
1058 | | if (key_type != CKK_RC5) { |
1059 | | crv = CKR_KEY_TYPE_INCONSISTENT; |
1060 | | break; |
1061 | | } |
1062 | | att = sftk_FindAttribute(key, CKA_VALUE); |
1063 | | if (att == NULL) { |
1064 | | crv = CKR_KEY_HANDLE_INVALID; |
1065 | | break; |
1066 | | } |
1067 | | |
1068 | | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_CBC_PARAMS))) { |
1069 | | crv = CKR_MECHANISM_PARAM_INVALID; |
1070 | | break; |
1071 | | } |
1072 | | rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter; |
1073 | | context->blockSize = rc5_param->ulWordsize * 2; |
1074 | | rc5Key.data = (unsigned char *)att->attrib.pValue; |
1075 | | rc5Key.len = att->attrib.ulValueLen; |
1076 | | context->cipherInfo = RC5_CreateContext(&rc5Key, rc5_param->ulRounds, |
1077 | | rc5_param->ulWordsize, rc5_param->pIv, |
1078 | | pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC); |
1079 | | sftk_FreeAttribute(att); |
1080 | | if (context->cipherInfo == NULL) { |
1081 | | crv = CKR_HOST_MEMORY; |
1082 | | break; |
1083 | | } |
1084 | | context->update = isEncrypt ? SFTKCipher_RC5_Encrypt : SFTKCipher_RC5_Decrypt; |
1085 | | context->destroy = SFTKCipher_RC5_DestroyContext; |
1086 | | break; |
1087 | | #endif |
1088 | 4.41k | case CKM_RC4: |
1089 | 4.41k | if (key_type != CKK_RC4) { |
1090 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1091 | 0 | break; |
1092 | 0 | } |
1093 | 4.41k | att = sftk_FindAttribute(key, CKA_VALUE); |
1094 | 4.41k | if (att == NULL) { |
1095 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1096 | 0 | break; |
1097 | 0 | } |
1098 | 4.41k | context->cipherInfo = |
1099 | 4.41k | RC4_CreateContext((unsigned char *)att->attrib.pValue, |
1100 | 4.41k | att->attrib.ulValueLen); |
1101 | 4.41k | sftk_FreeAttribute(att); |
1102 | 4.41k | if (context->cipherInfo == NULL) { |
1103 | 0 | crv = CKR_HOST_MEMORY; /* WRONG !!! */ |
1104 | 0 | break; |
1105 | 0 | } |
1106 | 4.41k | context->update = isEncrypt ? SFTKCipher_RC4_Encrypt : SFTKCipher_RC4_Decrypt; |
1107 | 4.41k | context->destroy = SFTKCipher_RC4_DestroyContext; |
1108 | 4.41k | break; |
1109 | 0 | case CKM_CDMF_CBC_PAD: |
1110 | 0 | context->doPad = PR_TRUE; |
1111 | | /* fall thru */ |
1112 | 0 | case CKM_CDMF_ECB: |
1113 | 0 | case CKM_CDMF_CBC: |
1114 | 0 | if (key_type != CKK_CDMF) { |
1115 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1116 | 0 | break; |
1117 | 0 | } |
1118 | 0 | t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC; |
1119 | 0 | goto finish_des; |
1120 | 0 | case CKM_DES_ECB: |
1121 | 0 | if (key_type != CKK_DES) { |
1122 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1123 | 0 | break; |
1124 | 0 | } |
1125 | 0 | t = NSS_DES; |
1126 | 0 | goto finish_des; |
1127 | 0 | case CKM_DES_CBC_PAD: |
1128 | 0 | context->doPad = PR_TRUE; |
1129 | | /* fall thru */ |
1130 | 8.66k | case CKM_DES_CBC: |
1131 | 8.66k | if (key_type != CKK_DES) { |
1132 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1133 | 0 | break; |
1134 | 0 | } |
1135 | 8.66k | t = NSS_DES_CBC; |
1136 | 8.66k | goto finish_des; |
1137 | 51.5k | case CKM_DES3_ECB: |
1138 | 51.5k | if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { |
1139 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1140 | 0 | break; |
1141 | 0 | } |
1142 | 51.5k | t = NSS_DES_EDE3; |
1143 | 51.5k | goto finish_des; |
1144 | 0 | case CKM_DES3_CBC_PAD: |
1145 | 0 | context->doPad = PR_TRUE; |
1146 | | /* fall thru */ |
1147 | 33.5k | case CKM_DES3_CBC: |
1148 | 33.5k | if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { |
1149 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1150 | 0 | break; |
1151 | 0 | } |
1152 | 33.5k | t = NSS_DES_EDE3_CBC; |
1153 | 93.7k | finish_des: |
1154 | 93.7k | if ((t != NSS_DES && t != NSS_DES_EDE3) && (pMechanism->pParameter == NULL || |
1155 | 42.2k | pMechanism->ulParameterLen < 8)) { |
1156 | 0 | crv = CKR_DOMAIN_PARAMS_INVALID; |
1157 | 0 | break; |
1158 | 0 | } |
1159 | 93.7k | context->blockSize = 8; |
1160 | 93.7k | att = sftk_FindAttribute(key, CKA_VALUE); |
1161 | 93.7k | if (att == NULL) { |
1162 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1163 | 0 | break; |
1164 | 0 | } |
1165 | 93.7k | if (key_type == CKK_DES2 && |
1166 | 0 | (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) { |
1167 | | /* extend DES2 key to DES3 key. */ |
1168 | 0 | memcpy(newdeskey, att->attrib.pValue, 16); |
1169 | 0 | memcpy(newdeskey + 16, newdeskey, 8); |
1170 | 0 | useNewKey = PR_TRUE; |
1171 | 93.7k | } else if (key_type == CKK_CDMF) { |
1172 | 0 | crv = sftk_cdmf2des((unsigned char *)att->attrib.pValue, newdeskey); |
1173 | 0 | if (crv != CKR_OK) { |
1174 | 0 | sftk_FreeAttribute(att); |
1175 | 0 | break; |
1176 | 0 | } |
1177 | 0 | useNewKey = PR_TRUE; |
1178 | 0 | } |
1179 | 93.7k | context->cipherInfo = DES_CreateContext( |
1180 | 93.7k | useNewKey ? newdeskey : (unsigned char *)att->attrib.pValue, |
1181 | 93.7k | (unsigned char *)pMechanism->pParameter, t, isEncrypt); |
1182 | 93.7k | if (useNewKey) |
1183 | 0 | memset(newdeskey, 0, sizeof newdeskey); |
1184 | 93.7k | sftk_FreeAttribute(att); |
1185 | 93.7k | if (context->cipherInfo == NULL) { |
1186 | 0 | crv = CKR_HOST_MEMORY; |
1187 | 0 | break; |
1188 | 0 | } |
1189 | 93.7k | context->update = isEncrypt ? SFTKCipher_DES_Encrypt : SFTKCipher_DES_Decrypt; |
1190 | 93.7k | context->destroy = SFTKCipher_DES_DestroyContext; |
1191 | 93.7k | break; |
1192 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
1193 | 0 | case CKM_SEED_CBC_PAD: |
1194 | 0 | context->doPad = PR_TRUE; |
1195 | | /* fall thru */ |
1196 | 9.59k | case CKM_SEED_CBC: |
1197 | 9.59k | if (!pMechanism->pParameter || |
1198 | 9.59k | pMechanism->ulParameterLen != 16) { |
1199 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1200 | 0 | break; |
1201 | 0 | } |
1202 | | /* fall thru */ |
1203 | 9.59k | case CKM_SEED_ECB: |
1204 | 9.59k | context->blockSize = 16; |
1205 | 9.59k | if (key_type != CKK_SEED) { |
1206 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1207 | 0 | break; |
1208 | 0 | } |
1209 | 9.59k | att = sftk_FindAttribute(key, CKA_VALUE); |
1210 | 9.59k | if (att == NULL) { |
1211 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1212 | 0 | break; |
1213 | 0 | } |
1214 | 9.59k | context->cipherInfo = SEED_CreateContext( |
1215 | 9.59k | (unsigned char *)att->attrib.pValue, |
1216 | 9.59k | (unsigned char *)pMechanism->pParameter, |
1217 | 9.59k | pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC, |
1218 | 9.59k | isEncrypt); |
1219 | 9.59k | sftk_FreeAttribute(att); |
1220 | 9.59k | if (context->cipherInfo == NULL) { |
1221 | 0 | crv = CKR_HOST_MEMORY; |
1222 | 0 | break; |
1223 | 0 | } |
1224 | 9.59k | context->update = isEncrypt ? SFTKCipher_SEED_Encrypt : SFTKCipher_SEED_Decrypt; |
1225 | 9.59k | context->destroy = SFTKCipher_SEED_DestroyContext; |
1226 | 9.59k | break; |
1227 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
1228 | 0 | case CKM_CAMELLIA_CBC_PAD: |
1229 | 0 | context->doPad = PR_TRUE; |
1230 | | /* fall thru */ |
1231 | 22.2k | case CKM_CAMELLIA_CBC: |
1232 | 22.2k | if (!pMechanism->pParameter || |
1233 | 22.2k | pMechanism->ulParameterLen != 16) { |
1234 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1235 | 0 | break; |
1236 | 0 | } |
1237 | | /* fall thru */ |
1238 | 22.2k | case CKM_CAMELLIA_ECB: |
1239 | 22.2k | context->blockSize = 16; |
1240 | 22.2k | if (key_type != CKK_CAMELLIA) { |
1241 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1242 | 0 | break; |
1243 | 0 | } |
1244 | 22.2k | att = sftk_FindAttribute(key, CKA_VALUE); |
1245 | 22.2k | if (att == NULL) { |
1246 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1247 | 0 | break; |
1248 | 0 | } |
1249 | 22.2k | context->cipherInfo = Camellia_CreateContext( |
1250 | 22.2k | (unsigned char *)att->attrib.pValue, |
1251 | 22.2k | (unsigned char *)pMechanism->pParameter, |
1252 | 22.2k | pMechanism->mechanism == |
1253 | 22.2k | CKM_CAMELLIA_ECB |
1254 | 22.2k | ? NSS_CAMELLIA |
1255 | 22.2k | : NSS_CAMELLIA_CBC, |
1256 | 22.2k | isEncrypt, att->attrib.ulValueLen); |
1257 | 22.2k | sftk_FreeAttribute(att); |
1258 | 22.2k | if (context->cipherInfo == NULL) { |
1259 | 0 | crv = CKR_HOST_MEMORY; |
1260 | 0 | break; |
1261 | 0 | } |
1262 | 22.2k | context->update = isEncrypt ? SFTKCipher_Camellia_Encrypt : SFTKCipher_Camellia_Decrypt; |
1263 | 22.2k | context->destroy = SFTKCipher_Camellia_DestroyContext; |
1264 | 22.2k | break; |
1265 | | |
1266 | 469 | case CKM_AES_CBC_PAD: |
1267 | 469 | context->doPad = PR_TRUE; |
1268 | | /* fall thru */ |
1269 | 29.1k | case CKM_AES_ECB: |
1270 | 111k | case CKM_AES_CBC: |
1271 | 111k | context->blockSize = 16; |
1272 | 111k | case CKM_AES_CTS: |
1273 | 111k | case CKM_AES_CTR: |
1274 | 111k | case CKM_AES_GCM: |
1275 | 111k | aes_param = pMechanism->pParameter; |
1276 | | /* |
1277 | | * Due to a mismatch between the documentation and the header |
1278 | | * file, two different definitions for CK_GCM_PARAMS exist. |
1279 | | * The header file is normative according to Oasis, but NSS used |
1280 | | * the documentation. In PKCS #11 v3.0, this was reconciled in |
1281 | | * favor of the header file definition. To maintain binary |
1282 | | * compatibility, NSS now defines CK_GCM_PARAMS_V3 as the official |
1283 | | * version v3 (V2.4 header file) and CK_NSS_GCM_PARAMS as the |
1284 | | * legacy (V2.4 documentation, NSS version). CK_GCM_PARAMS |
1285 | | * is defined as CK_GCM_PARAMS_V3 if NSS_PKCS11_2_0_COMPAT is not |
1286 | | * defined and CK_NSS_GCM_PARAMS if it is. Internally |
1287 | | * softoken continues to use the legacy version. The code below |
1288 | | * automatically detects which parameter was passed in and |
1289 | | * converts CK_GCM_PARAMS_V3 to the CK_NSS_GCM_PARAMS (legacy |
1290 | | * version) on the fly. NSS proper will eventually start |
1291 | | * using the CK_GCM_PARAMS_V3 version and fall back to the |
1292 | | * CK_NSS_GCM_PARAMS if the CK_GCM_PARAMS_V3 version fails with |
1293 | | * CKR_MECHANISM_PARAM_INVALID. |
1294 | | */ |
1295 | 111k | if (pMechanism->mechanism == CKM_AES_GCM) { |
1296 | 0 | if (!aes_param) { |
1297 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1298 | 0 | break; |
1299 | 0 | } |
1300 | 0 | if (pMechanism->ulParameterLen == sizeof(CK_GCM_PARAMS_V3)) { |
1301 | | /* convert the true V3 parameters into the old NSS parameters */ |
1302 | 0 | CK_GCM_PARAMS_V3 *gcm_params = (CK_GCM_PARAMS_V3 *)aes_param; |
1303 | 0 | if (gcm_params->ulIvLen * 8 != gcm_params->ulIvBits) { |
1304 | | /* only support byte aligned IV lengths */ |
1305 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1306 | 0 | break; |
1307 | 0 | } |
1308 | 0 | aes_param = (void *)&nss_gcm_param; |
1309 | 0 | nss_gcm_param.pIv = gcm_params->pIv; |
1310 | 0 | nss_gcm_param.ulIvLen = gcm_params->ulIvLen; |
1311 | 0 | nss_gcm_param.pAAD = gcm_params->pAAD; |
1312 | 0 | nss_gcm_param.ulAADLen = gcm_params->ulAADLen; |
1313 | 0 | nss_gcm_param.ulTagBits = gcm_params->ulTagBits; |
1314 | 0 | } else if (pMechanism->ulParameterLen != sizeof(CK_NSS_GCM_PARAMS)) { |
1315 | | /* neither old nor new style params, must be invalid */ |
1316 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1317 | 0 | break; |
1318 | 0 | } |
1319 | 111k | } else if ((pMechanism->mechanism == CKM_AES_CTR && BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CTR_PARAMS))) || |
1320 | 111k | ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CTS) && BAD_PARAM_CAST(pMechanism, AES_BLOCK_SIZE))) { |
1321 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1322 | 0 | break; |
1323 | 0 | } |
1324 | | |
1325 | 111k | if (pMechanism->mechanism == CKM_AES_GCM) { |
1326 | 0 | context->multi = PR_FALSE; |
1327 | 0 | } |
1328 | 111k | if (key_type != CKK_AES) { |
1329 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1330 | 0 | break; |
1331 | 0 | } |
1332 | 111k | att = sftk_FindAttribute(key, CKA_VALUE); |
1333 | 111k | if (att == NULL) { |
1334 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1335 | 0 | break; |
1336 | 0 | } |
1337 | 111k | context->cipherInfo = AES_CreateContext( |
1338 | 111k | (unsigned char *)att->attrib.pValue, |
1339 | 111k | (unsigned char *)aes_param, |
1340 | 111k | sftk_aes_mode(pMechanism->mechanism), |
1341 | 111k | isEncrypt, att->attrib.ulValueLen, 16); |
1342 | 111k | sftk_FreeAttribute(att); |
1343 | 111k | if (context->cipherInfo == NULL) { |
1344 | 0 | crv = CKR_HOST_MEMORY; |
1345 | 0 | break; |
1346 | 0 | } |
1347 | 111k | context->update = isEncrypt ? SFTKCipher_AES_Encrypt : SFTKCipher_AES_Decrypt; |
1348 | 111k | context->destroy = SFTKCipher_AES_DestroyContext; |
1349 | 111k | break; |
1350 | | |
1351 | 0 | case CKM_NSS_CHACHA20_POLY1305: |
1352 | 0 | case CKM_CHACHA20_POLY1305: |
1353 | 0 | if (pMechanism->mechanism == CKM_NSS_CHACHA20_POLY1305) { |
1354 | 0 | if (key_type != CKK_NSS_CHACHA20) { |
1355 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1356 | 0 | break; |
1357 | 0 | } |
1358 | 0 | if ((pMechanism->pParameter == NULL) || |
1359 | 0 | (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS))) { |
1360 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1361 | 0 | break; |
1362 | 0 | } |
1363 | 0 | nss_aead_params_ptr = (CK_NSS_AEAD_PARAMS *)pMechanism->pParameter; |
1364 | 0 | } else { |
1365 | 0 | CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR chacha_poly_params; |
1366 | 0 | if (key_type != CKK_CHACHA20) { |
1367 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1368 | 0 | break; |
1369 | 0 | } |
1370 | 0 | if ((pMechanism->pParameter == NULL) || |
1371 | 0 | (pMechanism->ulParameterLen != |
1372 | 0 | sizeof(CK_SALSA20_CHACHA20_POLY1305_PARAMS))) { |
1373 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1374 | 0 | break; |
1375 | 0 | } |
1376 | 0 | chacha_poly_params = (CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR) |
1377 | 0 | pMechanism->pParameter; |
1378 | 0 | nss_aead_params_ptr = &nss_aead_params; |
1379 | 0 | nss_aead_params.pNonce = chacha_poly_params->pNonce; |
1380 | 0 | nss_aead_params.ulNonceLen = chacha_poly_params->ulNonceLen; |
1381 | 0 | nss_aead_params.pAAD = chacha_poly_params->pAAD; |
1382 | 0 | nss_aead_params.ulAADLen = chacha_poly_params->ulAADLen; |
1383 | 0 | nss_aead_params.ulTagLen = 16; /* Poly1305 is always 16 */ |
1384 | 0 | } |
1385 | | |
1386 | 0 | context->multi = PR_FALSE; |
1387 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
1388 | 0 | if (att == NULL) { |
1389 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1390 | 0 | break; |
1391 | 0 | } |
1392 | 0 | context->cipherInfo = sftk_ChaCha20Poly1305_CreateContext( |
1393 | 0 | (unsigned char *)att->attrib.pValue, att->attrib.ulValueLen, |
1394 | 0 | nss_aead_params_ptr); |
1395 | 0 | sftk_FreeAttribute(att); |
1396 | 0 | if (context->cipherInfo == NULL) { |
1397 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
1398 | 0 | break; |
1399 | 0 | } |
1400 | 0 | context->update = isEncrypt ? sftk_ChaCha20Poly1305_Encrypt : sftk_ChaCha20Poly1305_Decrypt; |
1401 | 0 | context->destroy = sftk_ChaCha20Poly1305_DestroyContext; |
1402 | 0 | break; |
1403 | | |
1404 | 12.9k | case CKM_NSS_CHACHA20_CTR: /* old NSS private version */ |
1405 | 12.9k | case CKM_CHACHA20: /* PKCS #11 v3 version */ |
1406 | 12.9k | { |
1407 | 12.9k | unsigned char *counter; |
1408 | 12.9k | unsigned char *nonce; |
1409 | 12.9k | unsigned long counter_len; |
1410 | 12.9k | unsigned long nonce_len; |
1411 | 12.9k | context->multi = PR_FALSE; |
1412 | 12.9k | if (pMechanism->mechanism == CKM_NSS_CHACHA20_CTR) { |
1413 | 12.9k | if (key_type != CKK_NSS_CHACHA20) { |
1414 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1415 | 0 | break; |
1416 | 0 | } |
1417 | 12.9k | if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) { |
1418 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1419 | 0 | break; |
1420 | 0 | } |
1421 | 12.9k | counter_len = 4; |
1422 | 12.9k | counter = pMechanism->pParameter; |
1423 | 12.9k | nonce = counter + 4; |
1424 | 12.9k | nonce_len = 12; |
1425 | 12.9k | } else { |
1426 | 0 | CK_CHACHA20_PARAMS_PTR chacha20_param_ptr; |
1427 | 0 | if (key_type != CKK_CHACHA20) { |
1428 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1429 | 0 | break; |
1430 | 0 | } |
1431 | 0 | if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != sizeof(CK_CHACHA20_PARAMS)) { |
1432 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1433 | 0 | break; |
1434 | 0 | } |
1435 | 0 | chacha20_param_ptr = (CK_CHACHA20_PARAMS_PTR)pMechanism->pParameter; |
1436 | 0 | if ((chacha20_param_ptr->blockCounterBits != 32) && |
1437 | 0 | (chacha20_param_ptr->blockCounterBits != 64)) { |
1438 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1439 | 0 | break; |
1440 | 0 | } |
1441 | 0 | counter_len = chacha20_param_ptr->blockCounterBits / PR_BITS_PER_BYTE; |
1442 | 0 | counter = chacha20_param_ptr->pBlockCounter; |
1443 | 0 | nonce = chacha20_param_ptr->pNonce; |
1444 | 0 | nonce_len = chacha20_param_ptr->ulNonceBits / PR_BITS_PER_BYTE; |
1445 | 0 | } |
1446 | | |
1447 | 12.9k | att = sftk_FindAttribute(key, CKA_VALUE); |
1448 | 12.9k | if (att == NULL) { |
1449 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1450 | 0 | break; |
1451 | 0 | } |
1452 | 12.9k | SFTKChaCha20CtrInfo *ctx = PORT_ZNew(SFTKChaCha20CtrInfo); |
1453 | 12.9k | if (!ctx) { |
1454 | 0 | sftk_FreeAttribute(att); |
1455 | 0 | crv = CKR_HOST_MEMORY; |
1456 | 0 | break; |
1457 | 0 | } |
1458 | 12.9k | if (att->attrib.ulValueLen != sizeof(ctx->key)) { |
1459 | 0 | sftk_FreeAttribute(att); |
1460 | 0 | PORT_Free(ctx); |
1461 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1462 | 0 | break; |
1463 | 0 | } |
1464 | 12.9k | memcpy(ctx->key, att->attrib.pValue, att->attrib.ulValueLen); |
1465 | 12.9k | sftk_FreeAttribute(att); |
1466 | | |
1467 | | /* make sure we don't overflow our parameters */ |
1468 | 12.9k | if ((sizeof(ctx->counter) < counter_len) || |
1469 | 12.9k | (sizeof(ctx->nonce) < nonce_len)) { |
1470 | 0 | PORT_Free(ctx); |
1471 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
1472 | 0 | break; |
1473 | 0 | } |
1474 | | |
1475 | | /* The counter is little endian. */ |
1476 | 12.9k | int i = 0; |
1477 | 64.7k | for (; i < counter_len; ++i) { |
1478 | 51.8k | ctx->counter |= (PRUint32)counter[i] << (i * 8); |
1479 | 51.8k | } |
1480 | 12.9k | memcpy(ctx->nonce, nonce, nonce_len); |
1481 | 12.9k | context->cipherInfo = ctx; |
1482 | 12.9k | context->update = sftk_ChaCha20Ctr; |
1483 | 12.9k | context->destroy = sftk_ChaCha20Ctr_DestroyContext; |
1484 | 12.9k | break; |
1485 | 12.9k | } |
1486 | | |
1487 | 0 | case CKM_NSS_AES_KEY_WRAP_PAD: |
1488 | 0 | case CKM_AES_KEY_WRAP_PAD: |
1489 | 0 | context->doPad = PR_TRUE; |
1490 | | /* fall thru */ |
1491 | 0 | case CKM_NSS_AES_KEY_WRAP: |
1492 | 0 | case CKM_AES_KEY_WRAP: |
1493 | 0 | context->blockSize = 8; |
1494 | 0 | case CKM_AES_KEY_WRAP_KWP: |
1495 | 0 | context->multi = PR_FALSE; |
1496 | 0 | if (key_type != CKK_AES) { |
1497 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
1498 | 0 | break; |
1499 | 0 | } |
1500 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
1501 | 0 | if (att == NULL) { |
1502 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
1503 | 0 | break; |
1504 | 0 | } |
1505 | 0 | context->cipherInfo = AESKeyWrap_CreateContext( |
1506 | 0 | (unsigned char *)att->attrib.pValue, |
1507 | 0 | (unsigned char *)pMechanism->pParameter, |
1508 | 0 | isEncrypt, att->attrib.ulValueLen); |
1509 | 0 | sftk_FreeAttribute(att); |
1510 | 0 | if (context->cipherInfo == NULL) { |
1511 | 0 | crv = CKR_HOST_MEMORY; |
1512 | 0 | break; |
1513 | 0 | } |
1514 | 0 | if (pMechanism->mechanism == CKM_AES_KEY_WRAP_KWP) { |
1515 | 0 | context->update = isEncrypt ? SFTKCipher_AESKeyWrap_EncryptKWP |
1516 | 0 | : SFTKCipher_AESKeyWrap_DecryptKWP; |
1517 | 0 | } else { |
1518 | 0 | context->update = isEncrypt ? SFTKCipher_AESKeyWrap_Encrypt |
1519 | 0 | : SFTKCipher_AESKeyWrap_Decrypt; |
1520 | 0 | } |
1521 | 0 | context->destroy = SFTKCipher_AESKeyWrap_DestroyContext; |
1522 | 0 | break; |
1523 | | |
1524 | 0 | default: |
1525 | 0 | crv = CKR_MECHANISM_INVALID; |
1526 | 0 | break; |
1527 | 339k | } |
1528 | | |
1529 | 339k | if (crv != CKR_OK) { |
1530 | 0 | sftk_FreeContext(context); |
1531 | 0 | sftk_FreeSession(session); |
1532 | 0 | return crv; |
1533 | 0 | } |
1534 | 339k | sftk_SetContextByType(session, contextType, context); |
1535 | 339k | sftk_FreeSession(session); |
1536 | 339k | return CKR_OK; |
1537 | 339k | } |
1538 | | |
1539 | | /* NSC_EncryptInit initializes an encryption operation. */ |
1540 | | CK_RV |
1541 | | NSC_EncryptInit(CK_SESSION_HANDLE hSession, |
1542 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
1543 | 122k | { |
1544 | 122k | CHECK_FORK(); |
1545 | 122k | return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT, |
1546 | 122k | SFTK_ENCRYPT, PR_TRUE); |
1547 | 122k | } |
1548 | | |
1549 | | /* NSC_EncryptUpdate continues a multiple-part encryption operation. */ |
1550 | | CK_RV |
1551 | | NSC_EncryptUpdate(CK_SESSION_HANDLE hSession, |
1552 | | CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
1553 | | CK_ULONG_PTR pulEncryptedPartLen) |
1554 | 3.77k | { |
1555 | 3.77k | SFTKSessionContext *context; |
1556 | 3.77k | unsigned int outlen, i; |
1557 | 3.77k | unsigned int padoutlen = 0; |
1558 | 3.77k | unsigned int maxout = *pulEncryptedPartLen; |
1559 | 3.77k | CK_RV crv; |
1560 | 3.77k | SECStatus rv; |
1561 | | |
1562 | 3.77k | CHECK_FORK(); |
1563 | | |
1564 | | /* make sure we're legal */ |
1565 | 3.77k | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, NULL); |
1566 | 3.77k | if (crv != CKR_OK) |
1567 | 0 | return crv; |
1568 | | |
1569 | 3.77k | if (!pEncryptedPart) { |
1570 | 0 | if (context->doPad) { |
1571 | 0 | CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength; |
1572 | 0 | CK_ULONG blocksToSend = totalDataAvailable / context->blockSize; |
1573 | |
|
1574 | 0 | *pulEncryptedPartLen = blocksToSend * context->blockSize; |
1575 | 0 | return CKR_OK; |
1576 | 0 | } |
1577 | 0 | *pulEncryptedPartLen = ulPartLen; |
1578 | 0 | return CKR_OK; |
1579 | 0 | } |
1580 | | |
1581 | | /* do padding */ |
1582 | 3.77k | if (context->doPad) { |
1583 | | /* deal with previous buffered data */ |
1584 | 469 | if (context->padDataLength != 0) { |
1585 | | /* fill in the padded to a full block size */ |
1586 | 0 | for (i = context->padDataLength; |
1587 | 0 | (ulPartLen != 0) && i < context->blockSize; i++) { |
1588 | 0 | context->padBuf[i] = *pPart++; |
1589 | 0 | ulPartLen--; |
1590 | 0 | context->padDataLength++; |
1591 | 0 | } |
1592 | | |
1593 | | /* not enough data to encrypt yet? then return */ |
1594 | 0 | if (context->padDataLength != context->blockSize) { |
1595 | 0 | *pulEncryptedPartLen = 0; |
1596 | 0 | return CKR_OK; |
1597 | 0 | } |
1598 | | /* encrypt the current padded data */ |
1599 | 0 | rv = (*context->update)(context->cipherInfo, pEncryptedPart, |
1600 | 0 | &padoutlen, maxout, context->padBuf, |
1601 | 0 | context->blockSize); |
1602 | 0 | if (rv != SECSuccess) { |
1603 | 0 | return sftk_MapCryptError(PORT_GetError()); |
1604 | 0 | } |
1605 | 0 | pEncryptedPart += padoutlen; |
1606 | 0 | maxout -= padoutlen; |
1607 | 0 | } |
1608 | | /* save the residual */ |
1609 | 469 | context->padDataLength = ulPartLen % context->blockSize; |
1610 | 469 | if (context->padDataLength) { |
1611 | 469 | PORT_Memcpy(context->padBuf, |
1612 | 469 | &pPart[ulPartLen - context->padDataLength], |
1613 | 469 | context->padDataLength); |
1614 | 469 | ulPartLen -= context->padDataLength; |
1615 | 469 | } |
1616 | | /* if we've exhausted our new buffer, we're done */ |
1617 | 469 | if (ulPartLen == 0) { |
1618 | 0 | *pulEncryptedPartLen = padoutlen; |
1619 | 0 | return CKR_OK; |
1620 | 0 | } |
1621 | 469 | } |
1622 | | |
1623 | | /* do it: NOTE: this assumes buf size in is >= buf size out! */ |
1624 | 3.77k | rv = (*context->update)(context->cipherInfo, pEncryptedPart, |
1625 | 3.77k | &outlen, maxout, pPart, ulPartLen); |
1626 | 3.77k | if (rv != SECSuccess) { |
1627 | 0 | return sftk_MapCryptError(PORT_GetError()); |
1628 | 0 | } |
1629 | 3.77k | *pulEncryptedPartLen = (CK_ULONG)(outlen + padoutlen); |
1630 | 3.77k | return CKR_OK; |
1631 | 3.77k | } |
1632 | | |
1633 | | /* NSC_EncryptFinal finishes a multiple-part encryption operation. */ |
1634 | | CK_RV |
1635 | | NSC_EncryptFinal(CK_SESSION_HANDLE hSession, |
1636 | | CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) |
1637 | 469 | { |
1638 | 469 | SFTKSession *session; |
1639 | 469 | SFTKSessionContext *context; |
1640 | 469 | unsigned int outlen, i; |
1641 | 469 | unsigned int maxout = *pulLastEncryptedPartLen; |
1642 | 469 | CK_RV crv; |
1643 | 469 | SECStatus rv = SECSuccess; |
1644 | 469 | PRBool contextFinished = PR_TRUE; |
1645 | | |
1646 | 469 | CHECK_FORK(); |
1647 | | |
1648 | | /* make sure we're legal */ |
1649 | 469 | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, &session); |
1650 | 469 | if (crv != CKR_OK) |
1651 | 0 | return crv; |
1652 | | |
1653 | 469 | *pulLastEncryptedPartLen = 0; |
1654 | 469 | if (!pLastEncryptedPart) { |
1655 | | /* caller is checking the amount of remaining data */ |
1656 | 0 | if (context->blockSize > 0 && context->doPad) { |
1657 | 0 | *pulLastEncryptedPartLen = context->blockSize; |
1658 | 0 | contextFinished = PR_FALSE; /* still have padding to go */ |
1659 | 0 | } |
1660 | 0 | goto finish; |
1661 | 0 | } |
1662 | | |
1663 | | /* do padding */ |
1664 | 469 | if (context->doPad) { |
1665 | 469 | unsigned char padbyte = (unsigned char)(context->blockSize - context->padDataLength); |
1666 | | /* fill out rest of pad buffer with pad magic*/ |
1667 | 4.24k | for (i = context->padDataLength; i < context->blockSize; i++) { |
1668 | 3.77k | context->padBuf[i] = padbyte; |
1669 | 3.77k | } |
1670 | 469 | rv = (*context->update)(context->cipherInfo, pLastEncryptedPart, |
1671 | 469 | &outlen, maxout, context->padBuf, context->blockSize); |
1672 | 469 | if (rv == SECSuccess) |
1673 | 469 | *pulLastEncryptedPartLen = (CK_ULONG)outlen; |
1674 | 469 | } |
1675 | | |
1676 | 469 | finish: |
1677 | 469 | if (contextFinished) |
1678 | 469 | sftk_TerminateOp(session, SFTK_ENCRYPT, context); |
1679 | 469 | sftk_FreeSession(session); |
1680 | 469 | return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
1681 | 469 | } |
1682 | | |
1683 | | /* NSC_Encrypt encrypts single-part data. */ |
1684 | | CK_RV |
1685 | | NSC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
1686 | | CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, |
1687 | | CK_ULONG_PTR pulEncryptedDataLen) |
1688 | 107k | { |
1689 | 107k | SFTKSession *session; |
1690 | 107k | SFTKSessionContext *context; |
1691 | 107k | unsigned int outlen; |
1692 | 107k | unsigned int maxoutlen = *pulEncryptedDataLen; |
1693 | 107k | CK_RV crv; |
1694 | 107k | CK_RV crv2; |
1695 | 107k | SECStatus rv = SECSuccess; |
1696 | 107k | SECItem pText; |
1697 | | |
1698 | 107k | pText.type = siBuffer; |
1699 | 107k | pText.data = pData; |
1700 | 107k | pText.len = ulDataLen; |
1701 | | |
1702 | 107k | CHECK_FORK(); |
1703 | | |
1704 | | /* make sure we're legal */ |
1705 | 107k | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, &session); |
1706 | 107k | if (crv != CKR_OK) |
1707 | 0 | return crv; |
1708 | | |
1709 | 107k | if (!pEncryptedData) { |
1710 | 0 | outlen = context->rsa ? context->maxLen : ulDataLen + 2 * context->blockSize; |
1711 | 0 | goto done; |
1712 | 0 | } |
1713 | | |
1714 | 107k | if (context->doPad) { |
1715 | 469 | if (context->multi) { |
1716 | 469 | CK_ULONG updateLen = maxoutlen; |
1717 | 469 | CK_ULONG finalLen; |
1718 | | /* padding is fairly complicated, have the update and final |
1719 | | * code deal with it */ |
1720 | 469 | sftk_FreeSession(session); |
1721 | 469 | crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData, |
1722 | 469 | &updateLen); |
1723 | 469 | if (crv != CKR_OK) { |
1724 | 0 | updateLen = 0; |
1725 | 0 | } |
1726 | 469 | maxoutlen -= updateLen; |
1727 | 469 | pEncryptedData += updateLen; |
1728 | 469 | finalLen = maxoutlen; |
1729 | 469 | crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen); |
1730 | 469 | if (crv == CKR_OK && crv2 == CKR_OK) { |
1731 | 469 | *pulEncryptedDataLen = updateLen + finalLen; |
1732 | 469 | } |
1733 | 469 | return crv == CKR_OK ? crv2 : crv; |
1734 | 469 | } |
1735 | | /* doPad without multi means that padding must be done on the first |
1736 | | ** and only update. There will be no final. |
1737 | | */ |
1738 | 0 | PORT_Assert(context->blockSize > 1); |
1739 | 0 | if (context->blockSize > 1) { |
1740 | 0 | CK_ULONG remainder = ulDataLen % context->blockSize; |
1741 | 0 | CK_ULONG padding = context->blockSize - remainder; |
1742 | 0 | pText.len += padding; |
1743 | 0 | pText.data = PORT_ZAlloc(pText.len); |
1744 | 0 | if (pText.data) { |
1745 | 0 | memcpy(pText.data, pData, ulDataLen); |
1746 | 0 | memset(pText.data + ulDataLen, padding, padding); |
1747 | 0 | } else { |
1748 | 0 | crv = CKR_HOST_MEMORY; |
1749 | 0 | goto fail; |
1750 | 0 | } |
1751 | 0 | } |
1752 | 0 | } |
1753 | | |
1754 | | /* do it: NOTE: this assumes buf size is big enough. */ |
1755 | 106k | rv = (*context->update)(context->cipherInfo, pEncryptedData, |
1756 | 106k | &outlen, maxoutlen, pText.data, pText.len); |
1757 | 106k | crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
1758 | 106k | if (pText.data != pData) |
1759 | 0 | PORT_ZFree(pText.data, pText.len); |
1760 | 106k | fail: |
1761 | 106k | sftk_TerminateOp(session, SFTK_ENCRYPT, context); |
1762 | 106k | done: |
1763 | 106k | sftk_FreeSession(session); |
1764 | 106k | if (crv == CKR_OK) { |
1765 | 106k | *pulEncryptedDataLen = (CK_ULONG)outlen; |
1766 | 106k | } |
1767 | 106k | return crv; |
1768 | 106k | } |
1769 | | |
1770 | | /* |
1771 | | ************** Crypto Functions: Decrypt ************************ |
1772 | | */ |
1773 | | |
1774 | | /* NSC_DecryptInit initializes a decryption operation. */ |
1775 | | CK_RV |
1776 | | NSC_DecryptInit(CK_SESSION_HANDLE hSession, |
1777 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
1778 | 114k | { |
1779 | 114k | CHECK_FORK(); |
1780 | 114k | return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT, |
1781 | 114k | SFTK_DECRYPT, PR_FALSE); |
1782 | 114k | } |
1783 | | |
1784 | | /* NSC_DecryptUpdate continues a multiple-part decryption operation. */ |
1785 | | CK_RV |
1786 | | NSC_DecryptUpdate(CK_SESSION_HANDLE hSession, |
1787 | | CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, |
1788 | | CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) |
1789 | 41.4k | { |
1790 | 41.4k | SFTKSessionContext *context; |
1791 | 41.4k | unsigned int padoutlen = 0; |
1792 | 41.4k | unsigned int outlen; |
1793 | 41.4k | unsigned int maxout = *pulPartLen; |
1794 | 41.4k | CK_RV crv; |
1795 | 41.4k | SECStatus rv; |
1796 | | |
1797 | 41.4k | CHECK_FORK(); |
1798 | | |
1799 | | /* make sure we're legal */ |
1800 | 41.4k | crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, NULL); |
1801 | 41.4k | if (crv != CKR_OK) |
1802 | 0 | return crv; |
1803 | | |
1804 | | /* this can only happen on an NSS programming error */ |
1805 | 41.4k | PORT_Assert((context->padDataLength == 0) || context->padDataLength == context->blockSize); |
1806 | | |
1807 | 41.4k | if (context->doPad) { |
1808 | | /* Check the data length for block ciphers. If we are padding, |
1809 | | * then we must be using a block cipher. In the non-padding case |
1810 | | * the error will be returned by the underlying decryption |
1811 | | * function when we do the actual decrypt. We need to do the |
1812 | | * check here to avoid returning a negative length to the caller |
1813 | | * or reading before the beginning of the pEncryptedPart buffer. |
1814 | | */ |
1815 | 0 | if ((ulEncryptedPartLen == 0) || |
1816 | 0 | (ulEncryptedPartLen % context->blockSize) != 0) { |
1817 | 0 | return CKR_ENCRYPTED_DATA_LEN_RANGE; |
1818 | 0 | } |
1819 | 0 | } |
1820 | | |
1821 | 41.4k | if (!pPart) { |
1822 | 0 | if (context->doPad) { |
1823 | 0 | *pulPartLen = |
1824 | 0 | ulEncryptedPartLen + context->padDataLength - context->blockSize; |
1825 | 0 | return CKR_OK; |
1826 | 0 | } |
1827 | | /* for stream ciphers there is are no constraints on ulEncryptedPartLen. |
1828 | | * for block ciphers, it must be a multiple of blockSize. The error is |
1829 | | * detected when this function is called again do decrypt the output. |
1830 | | */ |
1831 | 0 | *pulPartLen = ulEncryptedPartLen; |
1832 | 0 | return CKR_OK; |
1833 | 0 | } |
1834 | | |
1835 | 41.4k | if (context->doPad) { |
1836 | | /* first decrypt our saved buffer */ |
1837 | 0 | if (context->padDataLength != 0) { |
1838 | 0 | rv = (*context->update)(context->cipherInfo, pPart, &padoutlen, |
1839 | 0 | maxout, context->padBuf, context->blockSize); |
1840 | 0 | if (rv != SECSuccess) |
1841 | 0 | return sftk_MapDecryptError(PORT_GetError()); |
1842 | 0 | pPart += padoutlen; |
1843 | 0 | maxout -= padoutlen; |
1844 | 0 | } |
1845 | | /* now save the final block for the next decrypt or the final */ |
1846 | 0 | PORT_Memcpy(context->padBuf, &pEncryptedPart[ulEncryptedPartLen - context->blockSize], |
1847 | 0 | context->blockSize); |
1848 | 0 | context->padDataLength = context->blockSize; |
1849 | 0 | ulEncryptedPartLen -= context->padDataLength; |
1850 | 0 | } |
1851 | | |
1852 | | /* do it: NOTE: this assumes buf size in is >= buf size out! */ |
1853 | 41.4k | rv = (*context->update)(context->cipherInfo, pPart, &outlen, |
1854 | 41.4k | maxout, pEncryptedPart, ulEncryptedPartLen); |
1855 | 41.4k | if (rv != SECSuccess) { |
1856 | 0 | return sftk_MapDecryptError(PORT_GetError()); |
1857 | 0 | } |
1858 | 41.4k | *pulPartLen = (CK_ULONG)(outlen + padoutlen); |
1859 | 41.4k | return CKR_OK; |
1860 | 41.4k | } |
1861 | | |
1862 | | /* NSC_DecryptFinal finishes a multiple-part decryption operation. */ |
1863 | | CK_RV |
1864 | | NSC_DecryptFinal(CK_SESSION_HANDLE hSession, |
1865 | | CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) |
1866 | 0 | { |
1867 | 0 | SFTKSession *session; |
1868 | 0 | SFTKSessionContext *context; |
1869 | 0 | unsigned int outlen; |
1870 | 0 | unsigned int maxout = *pulLastPartLen; |
1871 | 0 | CK_RV crv; |
1872 | 0 | SECStatus rv = SECSuccess; |
1873 | |
|
1874 | 0 | CHECK_FORK(); |
1875 | | |
1876 | | /* make sure we're legal */ |
1877 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, &session); |
1878 | 0 | if (crv != CKR_OK) |
1879 | 0 | return crv; |
1880 | | |
1881 | 0 | *pulLastPartLen = 0; |
1882 | 0 | if (!pLastPart) { |
1883 | | /* caller is checking the amount of remaining data */ |
1884 | 0 | if (context->padDataLength > 0) { |
1885 | 0 | *pulLastPartLen = context->padDataLength; |
1886 | 0 | } |
1887 | 0 | goto finish; |
1888 | 0 | } |
1889 | | |
1890 | 0 | if (context->doPad) { |
1891 | | /* decrypt our saved buffer */ |
1892 | 0 | if (context->padDataLength != 0) { |
1893 | | /* this assumes that pLastPart is big enough to hold the *whole* |
1894 | | * buffer!!! */ |
1895 | 0 | rv = (*context->update)(context->cipherInfo, pLastPart, &outlen, |
1896 | 0 | maxout, context->padBuf, context->blockSize); |
1897 | 0 | if (rv != SECSuccess) { |
1898 | 0 | crv = sftk_MapDecryptError(PORT_GetError()); |
1899 | 0 | } else { |
1900 | 0 | unsigned int padSize = 0; |
1901 | 0 | crv = sftk_CheckCBCPadding(pLastPart, outlen, |
1902 | 0 | context->blockSize, &padSize); |
1903 | | /* Update pulLastPartLen, in constant time, if crv is OK */ |
1904 | 0 | *pulLastPartLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulLastPartLen); |
1905 | 0 | } |
1906 | 0 | } |
1907 | 0 | } |
1908 | |
|
1909 | 0 | sftk_TerminateOp(session, SFTK_DECRYPT, context); |
1910 | 0 | finish: |
1911 | 0 | sftk_FreeSession(session); |
1912 | 0 | return crv; |
1913 | 0 | } |
1914 | | |
1915 | | /* NSC_Decrypt decrypts encrypted data in a single part. */ |
1916 | | CK_RV |
1917 | | NSC_Decrypt(CK_SESSION_HANDLE hSession, |
1918 | | CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, |
1919 | | CK_ULONG_PTR pulDataLen) |
1920 | 71.5k | { |
1921 | 71.5k | SFTKSession *session; |
1922 | 71.5k | SFTKSessionContext *context; |
1923 | 71.5k | unsigned int outlen; |
1924 | 71.5k | unsigned int maxoutlen = *pulDataLen; |
1925 | 71.5k | CK_RV crv; |
1926 | 71.5k | CK_RV crv2; |
1927 | 71.5k | SECStatus rv = SECSuccess; |
1928 | | |
1929 | 71.5k | CHECK_FORK(); |
1930 | | |
1931 | | /* make sure we're legal */ |
1932 | 71.5k | crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_FALSE, &session); |
1933 | 71.5k | if (crv != CKR_OK) |
1934 | 0 | return crv; |
1935 | | |
1936 | 71.5k | if (!pData) { |
1937 | 0 | *pulDataLen = (CK_ULONG)(ulEncryptedDataLen + context->blockSize); |
1938 | 0 | goto done; |
1939 | 0 | } |
1940 | | |
1941 | 71.5k | if (context->doPad && context->multi) { |
1942 | 0 | CK_ULONG updateLen = maxoutlen; |
1943 | 0 | CK_ULONG finalLen; |
1944 | | /* padding is fairly complicated, have the update and final |
1945 | | * code deal with it */ |
1946 | 0 | sftk_FreeSession(session); |
1947 | 0 | crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, |
1948 | 0 | pData, &updateLen); |
1949 | 0 | if (crv == CKR_OK) { |
1950 | 0 | maxoutlen -= updateLen; |
1951 | 0 | pData += updateLen; |
1952 | 0 | } |
1953 | 0 | finalLen = maxoutlen; |
1954 | 0 | crv2 = NSC_DecryptFinal(hSession, pData, &finalLen); |
1955 | 0 | if (crv == CKR_OK) { |
1956 | 0 | *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv2), updateLen + finalLen, *pulDataLen); |
1957 | 0 | return crv2; |
1958 | 0 | } else { |
1959 | 0 | return crv; |
1960 | 0 | } |
1961 | 0 | } |
1962 | | |
1963 | 71.5k | rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, |
1964 | 71.5k | pEncryptedData, ulEncryptedDataLen); |
1965 | | /* XXX need to do MUCH better error mapping than this. */ |
1966 | 71.5k | crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError()); |
1967 | 71.5k | if (rv == SECSuccess) { |
1968 | 2.90k | if (context->doPad) { |
1969 | 0 | unsigned int padSize = 0; |
1970 | 0 | crv = sftk_CheckCBCPadding(pData, outlen, context->blockSize, |
1971 | 0 | &padSize); |
1972 | | /* Update pulDataLen, in constant time, if crv is OK */ |
1973 | 0 | *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulDataLen); |
1974 | 2.90k | } else { |
1975 | 2.90k | *pulDataLen = (CK_ULONG)outlen; |
1976 | 2.90k | } |
1977 | 2.90k | } |
1978 | 71.5k | sftk_TerminateOp(session, SFTK_DECRYPT, context); |
1979 | 71.5k | done: |
1980 | 71.5k | sftk_FreeSession(session); |
1981 | 71.5k | return crv; |
1982 | 71.5k | } |
1983 | | |
1984 | | /* |
1985 | | ************** Crypto Functions: Digest (HASH) ************************ |
1986 | | */ |
1987 | | |
1988 | | /* NSC_DigestInit initializes a message-digesting operation. */ |
1989 | | CK_RV |
1990 | | NSC_DigestInit(CK_SESSION_HANDLE hSession, |
1991 | | CK_MECHANISM_PTR pMechanism) |
1992 | 901k | { |
1993 | 901k | SFTKSession *session; |
1994 | 901k | SFTKSessionContext *context; |
1995 | 901k | CK_RV crv = CKR_OK; |
1996 | | |
1997 | 901k | CHECK_FORK(); |
1998 | | |
1999 | 901k | session = sftk_SessionFromHandle(hSession); |
2000 | 901k | if (session == NULL) |
2001 | 0 | return CKR_SESSION_HANDLE_INVALID; |
2002 | 901k | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_HASH, |
2003 | 901k | NULL, 0, NULL, 0, CKA_DIGEST); |
2004 | 901k | if (crv != CKR_OK) { |
2005 | 0 | sftk_FreeSession(session); |
2006 | 0 | return crv; |
2007 | 0 | } |
2008 | | |
2009 | 901k | #define INIT_MECH(mmm) \ |
2010 | 901k | case CKM_##mmm: { \ |
2011 | 901k | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ |
2012 | 901k | context->cipherInfo = (void *)mmm##_ctx; \ |
2013 | 901k | context->cipherInfoLen = mmm##_FlattenSize(mmm##_ctx); \ |
2014 | 901k | context->currentMech = CKM_##mmm; \ |
2015 | 901k | context->hashUpdate = SFTKHash_##mmm##_Update; \ |
2016 | 901k | context->end = SFTKHash_##mmm##_End; \ |
2017 | 901k | context->destroy = SFTKHash_##mmm##_DestroyContext; \ |
2018 | 901k | context->maxLen = mmm##_LENGTH; \ |
2019 | 901k | if (mmm##_ctx) \ |
2020 | 901k | mmm##_Begin(mmm##_ctx); \ |
2021 | 901k | else \ |
2022 | 901k | crv = CKR_HOST_MEMORY; \ |
2023 | 901k | break; \ |
2024 | 901k | } |
2025 | | |
2026 | 901k | switch (pMechanism->mechanism) { |
2027 | 0 | INIT_MECH(MD2) |
2028 | 123k | INIT_MECH(MD5) |
2029 | 318k | INIT_MECH(SHA1) |
2030 | 164k | INIT_MECH(SHA224) |
2031 | 149k | INIT_MECH(SHA256) |
2032 | 66.0k | INIT_MECH(SHA384) |
2033 | 35.1k | INIT_MECH(SHA512) |
2034 | 2.60k | INIT_MECH(SHA3_224) |
2035 | 9.47k | INIT_MECH(SHA3_256) |
2036 | 30.7k | INIT_MECH(SHA3_384) |
2037 | 1.56k | INIT_MECH(SHA3_512) |
2038 | | |
2039 | 0 | default: |
2040 | 0 | crv = CKR_MECHANISM_INVALID; |
2041 | 0 | break; |
2042 | 901k | } |
2043 | | |
2044 | 901k | if (crv != CKR_OK) { |
2045 | 0 | sftk_FreeContext(context); |
2046 | 0 | sftk_FreeSession(session); |
2047 | 0 | return crv; |
2048 | 0 | } |
2049 | 901k | sftk_SetContextByType(session, SFTK_HASH, context); |
2050 | 901k | sftk_FreeSession(session); |
2051 | 901k | return CKR_OK; |
2052 | 901k | } |
2053 | | |
2054 | | /* NSC_Digest digests data in a single part. */ |
2055 | | CK_RV |
2056 | | NSC_Digest(CK_SESSION_HANDLE hSession, |
2057 | | CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, |
2058 | | CK_ULONG_PTR pulDigestLen) |
2059 | 0 | { |
2060 | 0 | SFTKSession *session; |
2061 | 0 | SFTKSessionContext *context; |
2062 | 0 | unsigned int digestLen; |
2063 | 0 | unsigned int maxout = *pulDigestLen; |
2064 | 0 | CK_RV crv; |
2065 | |
|
2066 | 0 | CHECK_FORK(); |
2067 | | |
2068 | | /* make sure we're legal */ |
2069 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_FALSE, &session); |
2070 | 0 | if (crv != CKR_OK) |
2071 | 0 | return crv; |
2072 | | |
2073 | 0 | if (pDigest == NULL) { |
2074 | 0 | *pulDigestLen = context->maxLen; |
2075 | 0 | goto finish; |
2076 | 0 | } |
2077 | | |
2078 | 0 | #if (ULONG_MAX > UINT_MAX) |
2079 | | /* The context->hashUpdate function takes an unsigned int for its data |
2080 | | * length argument, but NSC_Digest takes an unsigned long. */ |
2081 | 0 | while (ulDataLen > UINT_MAX) { |
2082 | 0 | (*context->hashUpdate)(context->cipherInfo, pData, UINT_MAX); |
2083 | 0 | pData += UINT_MAX; |
2084 | 0 | ulDataLen -= UINT_MAX; |
2085 | 0 | } |
2086 | 0 | #endif |
2087 | 0 | (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen); |
2088 | | |
2089 | | /* NOTE: this assumes buf size is bigenough for the algorithm */ |
2090 | 0 | (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout); |
2091 | 0 | *pulDigestLen = digestLen; |
2092 | |
|
2093 | 0 | sftk_TerminateOp(session, SFTK_HASH, context); |
2094 | 0 | finish: |
2095 | 0 | sftk_FreeSession(session); |
2096 | 0 | return CKR_OK; |
2097 | 0 | } |
2098 | | |
2099 | | /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */ |
2100 | | CK_RV |
2101 | | NSC_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
2102 | | CK_ULONG ulPartLen) |
2103 | 13.2M | { |
2104 | 13.2M | SFTKSessionContext *context; |
2105 | 13.2M | CK_RV crv; |
2106 | | |
2107 | 13.2M | CHECK_FORK(); |
2108 | | |
2109 | | /* make sure we're legal */ |
2110 | 13.2M | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, NULL); |
2111 | 13.2M | if (crv != CKR_OK) |
2112 | 0 | return crv; |
2113 | | |
2114 | 13.2M | #if (ULONG_MAX > UINT_MAX) |
2115 | | /* The context->hashUpdate function takes an unsigned int for its data |
2116 | | * length argument, but NSC_DigestUpdate takes an unsigned long. */ |
2117 | 13.2M | while (ulPartLen > UINT_MAX) { |
2118 | 0 | (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX); |
2119 | 0 | pPart += UINT_MAX; |
2120 | 0 | ulPartLen -= UINT_MAX; |
2121 | 0 | } |
2122 | 13.2M | #endif |
2123 | 13.2M | (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen); |
2124 | | |
2125 | 13.2M | return CKR_OK; |
2126 | 13.2M | } |
2127 | | |
2128 | | /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */ |
2129 | | CK_RV |
2130 | | NSC_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, |
2131 | | CK_ULONG_PTR pulDigestLen) |
2132 | 772k | { |
2133 | 772k | SFTKSession *session; |
2134 | 772k | SFTKSessionContext *context; |
2135 | 772k | unsigned int maxout = *pulDigestLen; |
2136 | 772k | unsigned int digestLen; |
2137 | 772k | CK_RV crv; |
2138 | | |
2139 | 772k | CHECK_FORK(); |
2140 | | |
2141 | | /* make sure we're legal */ |
2142 | 772k | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); |
2143 | 772k | if (crv != CKR_OK) |
2144 | 151k | return crv; |
2145 | | |
2146 | 620k | if (pDigest != NULL) { |
2147 | 620k | (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout); |
2148 | 620k | *pulDigestLen = digestLen; |
2149 | 620k | sftk_TerminateOp(session, SFTK_HASH, context); |
2150 | 620k | } else { |
2151 | 0 | *pulDigestLen = context->maxLen; |
2152 | 0 | } |
2153 | | |
2154 | 620k | sftk_FreeSession(session); |
2155 | 620k | return CKR_OK; |
2156 | 772k | } |
2157 | | |
2158 | | /* |
2159 | | * these helper functions are used by Generic Macing and Signing functions |
2160 | | * that use hashes as part of their operations. |
2161 | | */ |
2162 | | #define DOSUB(mmm) \ |
2163 | | static CK_RV \ |
2164 | | sftk_doSub##mmm(SFTKSessionContext *context) \ |
2165 | 2.31k | { \ |
2166 | 2.31k | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ |
2167 | 2.31k | context->hashInfo = (void *)mmm##_ctx; \ |
2168 | 2.31k | context->hashUpdate = SFTKHash_##mmm##_Update; \ |
2169 | 2.31k | context->end = SFTKHash_##mmm##_End; \ |
2170 | 2.31k | context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \ |
2171 | 2.31k | if (!context->hashInfo) { \ |
2172 | 0 | return CKR_HOST_MEMORY; \ |
2173 | 0 | } \ |
2174 | 2.31k | mmm##_Begin(mmm##_ctx); \ |
2175 | 2.31k | return CKR_OK; \ |
2176 | 2.31k | } Unexecuted instantiation: pkcs11c.c:sftk_doSubMD5 Unexecuted instantiation: pkcs11c.c:sftk_doSubMD2 Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA1 Unexecuted instantiation: pkcs11c.c:sftk_doSubSHA224 pkcs11c.c:sftk_doSubSHA256 Line | Count | Source | 2165 | 1.52k | { \ | 2166 | 1.52k | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ | 2167 | 1.52k | context->hashInfo = (void *)mmm##_ctx; \ | 2168 | 1.52k | context->hashUpdate = SFTKHash_##mmm##_Update; \ | 2169 | 1.52k | context->end = SFTKHash_##mmm##_End; \ | 2170 | 1.52k | context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \ | 2171 | 1.52k | if (!context->hashInfo) { \ | 2172 | 0 | return CKR_HOST_MEMORY; \ | 2173 | 0 | } \ | 2174 | 1.52k | mmm##_Begin(mmm##_ctx); \ | 2175 | 1.52k | return CKR_OK; \ | 2176 | 1.52k | } |
pkcs11c.c:sftk_doSubSHA384 Line | Count | Source | 2165 | 289 | { \ | 2166 | 289 | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ | 2167 | 289 | context->hashInfo = (void *)mmm##_ctx; \ | 2168 | 289 | context->hashUpdate = SFTKHash_##mmm##_Update; \ | 2169 | 289 | context->end = SFTKHash_##mmm##_End; \ | 2170 | 289 | context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \ | 2171 | 289 | if (!context->hashInfo) { \ | 2172 | 0 | return CKR_HOST_MEMORY; \ | 2173 | 0 | } \ | 2174 | 289 | mmm##_Begin(mmm##_ctx); \ | 2175 | 289 | return CKR_OK; \ | 2176 | 289 | } |
pkcs11c.c:sftk_doSubSHA512 Line | Count | Source | 2165 | 502 | { \ | 2166 | 502 | mmm##Context *mmm##_ctx = mmm##_NewContext(); \ | 2167 | 502 | context->hashInfo = (void *)mmm##_ctx; \ | 2168 | 502 | context->hashUpdate = SFTKHash_##mmm##_Update; \ | 2169 | 502 | context->end = SFTKHash_##mmm##_End; \ | 2170 | 502 | context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \ | 2171 | 502 | if (!context->hashInfo) { \ | 2172 | 0 | return CKR_HOST_MEMORY; \ | 2173 | 0 | } \ | 2174 | 502 | mmm##_Begin(mmm##_ctx); \ | 2175 | 502 | return CKR_OK; \ | 2176 | 502 | } |
|
2177 | | |
2178 | | DOSUB(MD2) |
2179 | | DOSUB(MD5) |
2180 | | DOSUB(SHA1) |
2181 | | DOSUB(SHA224) |
2182 | | DOSUB(SHA256) |
2183 | | DOSUB(SHA384) |
2184 | | DOSUB(SHA512) |
2185 | | |
2186 | | static SECStatus |
2187 | | sftk_SignCopy( |
2188 | | void *copyLen, |
2189 | | unsigned char *out, unsigned int *outLength, |
2190 | | unsigned int maxLength, |
2191 | | const unsigned char *hashResult, |
2192 | | unsigned int hashResultLength) |
2193 | 74.3k | { |
2194 | 74.3k | unsigned int toCopy = *(CK_ULONG *)copyLen; |
2195 | 74.3k | if (toCopy > maxLength) { |
2196 | 0 | toCopy = maxLength; |
2197 | 0 | } |
2198 | 74.3k | if (toCopy > hashResultLength) { |
2199 | 0 | toCopy = hashResultLength; |
2200 | 0 | } |
2201 | 74.3k | memcpy(out, hashResult, toCopy); |
2202 | 74.3k | if (outLength) { |
2203 | 74.3k | *outLength = toCopy; |
2204 | 74.3k | } |
2205 | 74.3k | return SECSuccess; |
2206 | 74.3k | } |
2207 | | |
2208 | | /* Verify is just a compare for HMAC */ |
2209 | | static SECStatus |
2210 | | sftk_HMACCmp(void *copyLen, const unsigned char *sig, unsigned int sigLen, |
2211 | | const unsigned char *hash, unsigned int hashLen) |
2212 | 0 | { |
2213 | 0 | if (NSS_SecureMemcmp(sig, hash, *(CK_ULONG *)copyLen) == 0) { |
2214 | 0 | return SECSuccess; |
2215 | 0 | } |
2216 | | |
2217 | 0 | PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
2218 | 0 | return SECFailure; |
2219 | 0 | } |
2220 | | |
2221 | | /* |
2222 | | * common HMAC + CMAC initialization routine |
2223 | | */ |
2224 | | static CK_RV |
2225 | | sftk_doMACInit(CK_MECHANISM_TYPE mech, SFTKSessionContext *session, |
2226 | | SFTKObject *key, CK_ULONG mac_size) |
2227 | 232k | { |
2228 | 232k | CK_RV crv; |
2229 | 232k | sftk_MACCtx *context; |
2230 | 232k | CK_ULONG *intpointer; |
2231 | 232k | PRBool isFIPS = sftk_isFIPS(key->slot->slotID); |
2232 | | |
2233 | | /* Set up the initial context. */ |
2234 | 232k | crv = sftk_MAC_Create(mech, key, &context); |
2235 | 232k | if (crv != CKR_OK) { |
2236 | 0 | return crv; |
2237 | 0 | } |
2238 | | |
2239 | 232k | session->hashInfo = context; |
2240 | 232k | session->multi = PR_TRUE; |
2241 | | |
2242 | | /* Required by FIPS 198 Section 4. Delay this check until after the MAC |
2243 | | * has been initialized to steal the output size of the MAC. */ |
2244 | 232k | if (isFIPS && (mac_size < 4 || mac_size < context->mac_size / 2)) { |
2245 | 0 | sftk_MAC_DestroyContext(context, PR_TRUE); |
2246 | 0 | return CKR_BUFFER_TOO_SMALL; |
2247 | 0 | } |
2248 | | |
2249 | | /* Configure our helper functions appropriately. Note that these casts |
2250 | | * ignore the return values. */ |
2251 | 232k | session->hashUpdate = SFTKHash_sftk_MAC_Update; |
2252 | 232k | session->end = SFTKHash_sftk_MAC_End; |
2253 | 232k | session->hashdestroy = SFTKHash_sftk_MAC_DestroyContext; |
2254 | | |
2255 | 232k | intpointer = PORT_New(CK_ULONG); |
2256 | 232k | if (intpointer == NULL) { |
2257 | 0 | sftk_MAC_DestroyContext(context, PR_TRUE); |
2258 | 0 | return CKR_HOST_MEMORY; |
2259 | 0 | } |
2260 | 232k | *intpointer = mac_size; |
2261 | 232k | session->cipherInfo = intpointer; |
2262 | | |
2263 | | /* Since we're only "hashing", copy the result from session->end to the |
2264 | | * caller using sftk_SignCopy. */ |
2265 | 232k | session->update = sftk_SignCopy; |
2266 | 232k | session->verify = sftk_HMACCmp; |
2267 | 232k | session->destroy = sftk_Space; |
2268 | | |
2269 | 232k | session->maxLen = context->mac_size; |
2270 | | |
2271 | 232k | return CKR_OK; |
2272 | 232k | } |
2273 | | |
2274 | | /* |
2275 | | * SSL Macing support. SSL Macs are inited, then update with the base |
2276 | | * hashing algorithm, then finalized in sign and verify |
2277 | | */ |
2278 | | |
2279 | | /* |
2280 | | * FROM SSL: |
2281 | | * 60 bytes is 3 times the maximum length MAC size that is supported. |
2282 | | * We probably should have one copy of this table. We still need this table |
2283 | | * in ssl to 'sign' the handshake hashes. |
2284 | | */ |
2285 | | static unsigned char ssl_pad_1[60] = { |
2286 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2287 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2288 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2289 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2290 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2291 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2292 | | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
2293 | | 0x36, 0x36, 0x36, 0x36 |
2294 | | }; |
2295 | | static unsigned char ssl_pad_2[60] = { |
2296 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2297 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2298 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2299 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2300 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2301 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2302 | | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
2303 | | 0x5c, 0x5c, 0x5c, 0x5c |
2304 | | }; |
2305 | | |
2306 | | static SECStatus |
2307 | | sftk_SSLMACSign(void *ctx, unsigned char *sig, unsigned int *sigLen, |
2308 | | unsigned int maxLen, const unsigned char *hash, unsigned int hashLen) |
2309 | 0 | { |
2310 | 0 | SFTKSSLMACInfo *info = ctx; |
2311 | 0 | unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; |
2312 | 0 | unsigned int out; |
2313 | |
|
2314 | 0 | info->begin(info->hashContext); |
2315 | 0 | info->update(info->hashContext, info->key, info->keySize); |
2316 | 0 | info->update(info->hashContext, ssl_pad_2, info->padSize); |
2317 | 0 | info->update(info->hashContext, hash, hashLen); |
2318 | 0 | info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH); |
2319 | 0 | PORT_Memcpy(sig, tmpBuf, info->macSize); |
2320 | 0 | PORT_Memset(tmpBuf, 0, info->macSize); |
2321 | 0 | *sigLen = info->macSize; |
2322 | 0 | return SECSuccess; |
2323 | 0 | } |
2324 | | |
2325 | | static SECStatus |
2326 | | sftk_SSLMACVerify(void *ctx, const unsigned char *sig, unsigned int sigLen, |
2327 | | const unsigned char *hash, unsigned int hashLen) |
2328 | 0 | { |
2329 | 0 | SFTKSSLMACInfo *info = ctx; |
2330 | 0 | unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; |
2331 | 0 | unsigned int out; |
2332 | 0 | int cmp; |
2333 | |
|
2334 | 0 | info->begin(info->hashContext); |
2335 | 0 | info->update(info->hashContext, info->key, info->keySize); |
2336 | 0 | info->update(info->hashContext, ssl_pad_2, info->padSize); |
2337 | 0 | info->update(info->hashContext, hash, hashLen); |
2338 | 0 | info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH); |
2339 | 0 | cmp = NSS_SecureMemcmp(sig, tmpBuf, info->macSize); |
2340 | 0 | PORT_Memset(tmpBuf, 0, info->macSize); |
2341 | 0 | return (cmp == 0) ? SECSuccess : SECFailure; |
2342 | 0 | } |
2343 | | |
2344 | | /* |
2345 | | * common HMAC initalization routine |
2346 | | */ |
2347 | | static CK_RV |
2348 | | sftk_doSSLMACInit(SFTKSessionContext *context, SECOidTag oid, |
2349 | | SFTKObject *key, CK_ULONG mac_size) |
2350 | 0 | { |
2351 | 0 | SFTKAttribute *keyval; |
2352 | 0 | SFTKBegin begin; |
2353 | 0 | int padSize; |
2354 | 0 | SFTKSSLMACInfo *sslmacinfo; |
2355 | 0 | CK_RV crv = CKR_MECHANISM_INVALID; |
2356 | |
|
2357 | 0 | if (oid == SEC_OID_SHA1) { |
2358 | 0 | crv = sftk_doSubSHA1(context); |
2359 | 0 | if (crv != CKR_OK) |
2360 | 0 | return crv; |
2361 | 0 | begin = SFTKHash_SHA1_Begin; |
2362 | 0 | padSize = 40; |
2363 | 0 | } else { |
2364 | 0 | crv = sftk_doSubMD5(context); |
2365 | 0 | if (crv != CKR_OK) |
2366 | 0 | return crv; |
2367 | 0 | begin = SFTKHash_MD5_Begin; |
2368 | 0 | padSize = 48; |
2369 | 0 | } |
2370 | 0 | context->multi = PR_TRUE; |
2371 | |
|
2372 | 0 | keyval = sftk_FindAttribute(key, CKA_VALUE); |
2373 | 0 | if (keyval == NULL) |
2374 | 0 | return CKR_KEY_SIZE_RANGE; |
2375 | | |
2376 | 0 | context->hashUpdate(context->hashInfo, keyval->attrib.pValue, |
2377 | 0 | keyval->attrib.ulValueLen); |
2378 | 0 | context->hashUpdate(context->hashInfo, ssl_pad_1, padSize); |
2379 | 0 | sslmacinfo = (SFTKSSLMACInfo *)PORT_Alloc(sizeof(SFTKSSLMACInfo)); |
2380 | 0 | if (sslmacinfo == NULL) { |
2381 | 0 | sftk_FreeAttribute(keyval); |
2382 | 0 | return CKR_HOST_MEMORY; |
2383 | 0 | } |
2384 | 0 | sslmacinfo->size = sizeof(SFTKSSLMACInfo); |
2385 | 0 | sslmacinfo->macSize = mac_size; |
2386 | 0 | sslmacinfo->hashContext = context->hashInfo; |
2387 | 0 | PORT_Memcpy(sslmacinfo->key, keyval->attrib.pValue, |
2388 | 0 | keyval->attrib.ulValueLen); |
2389 | 0 | sslmacinfo->keySize = keyval->attrib.ulValueLen; |
2390 | 0 | sslmacinfo->begin = begin; |
2391 | 0 | sslmacinfo->end = context->end; |
2392 | 0 | sslmacinfo->update = context->hashUpdate; |
2393 | 0 | sslmacinfo->padSize = padSize; |
2394 | 0 | sftk_FreeAttribute(keyval); |
2395 | 0 | context->cipherInfo = (void *)sslmacinfo; |
2396 | 0 | context->destroy = sftk_ZSpace; |
2397 | 0 | context->update = sftk_SSLMACSign; |
2398 | 0 | context->verify = sftk_SSLMACVerify; |
2399 | 0 | context->maxLen = mac_size; |
2400 | 0 | return CKR_OK; |
2401 | 0 | } |
2402 | | |
2403 | | /* |
2404 | | ************** Crypto Functions: Sign ************************ |
2405 | | */ |
2406 | | |
2407 | | /** |
2408 | | * Check if We're using CBCMacing and initialize the session context if we are. |
2409 | | * @param contextType SFTK_SIGN or SFTK_VERIFY |
2410 | | * @param keyUsage check whether key allows this usage |
2411 | | */ |
2412 | | static CK_RV |
2413 | | sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, |
2414 | | CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage, |
2415 | | SFTKContextType contextType) |
2416 | | |
2417 | 469k | { |
2418 | 469k | CK_MECHANISM cbc_mechanism; |
2419 | 469k | CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE; |
2420 | 469k | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
2421 | 469k | CK_RC2_CBC_PARAMS rc2_params; |
2422 | 469k | #endif |
2423 | | #if NSS_SOFTOKEN_DOES_RC5 |
2424 | | CK_RC5_CBC_PARAMS rc5_params; |
2425 | | CK_RC5_MAC_GENERAL_PARAMS *rc5_mac; |
2426 | | #endif |
2427 | 469k | unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE]; |
2428 | 469k | unsigned char k2[SFTK_MAX_BLOCK_SIZE]; |
2429 | 469k | unsigned char k3[SFTK_MAX_BLOCK_SIZE]; |
2430 | 469k | SFTKSessionContext *context; |
2431 | 469k | CK_RV crv; |
2432 | 469k | unsigned int blockSize; |
2433 | 469k | PRBool isXCBC = PR_FALSE; |
2434 | | |
2435 | 469k | if (!pMechanism) { |
2436 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
2437 | 0 | } |
2438 | | |
2439 | 469k | switch (pMechanism->mechanism) { |
2440 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
2441 | 0 | case CKM_RC2_MAC_GENERAL: |
2442 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_MAC_GENERAL_PARAMS))) { |
2443 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
2444 | 0 | } |
2445 | 0 | mac_bytes = |
2446 | 0 | ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; |
2447 | | /* fall through */ |
2448 | 0 | case CKM_RC2_MAC: |
2449 | | /* this works because ulEffectiveBits is in the same place in both the |
2450 | | * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */ |
2451 | 0 | rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *) |
2452 | 0 | pMechanism->pParameter) |
2453 | 0 | ->ulEffectiveBits; |
2454 | 0 | PORT_Memset(rc2_params.iv, 0, sizeof(rc2_params.iv)); |
2455 | 0 | cbc_mechanism.mechanism = CKM_RC2_CBC; |
2456 | 0 | cbc_mechanism.pParameter = &rc2_params; |
2457 | 0 | cbc_mechanism.ulParameterLen = sizeof(rc2_params); |
2458 | 0 | blockSize = 8; |
2459 | 0 | break; |
2460 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
2461 | | |
2462 | | #if NSS_SOFTOKEN_DOES_RC5 |
2463 | | case CKM_RC5_MAC_GENERAL: |
2464 | | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) { |
2465 | | return CKR_MECHANISM_PARAM_INVALID; |
2466 | | } |
2467 | | mac_bytes = |
2468 | | ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; |
2469 | | /* fall through */ |
2470 | | case CKM_RC5_MAC: |
2471 | | /* this works because ulEffectiveBits is in the same place in both the |
2472 | | * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */ |
2473 | | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) { |
2474 | | return CKR_MECHANISM_PARAM_INVALID; |
2475 | | } |
2476 | | rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter; |
2477 | | rc5_params.ulWordsize = rc5_mac->ulWordsize; |
2478 | | rc5_params.ulRounds = rc5_mac->ulRounds; |
2479 | | rc5_params.pIv = ivBlock; |
2480 | | if ((blockSize = rc5_mac->ulWordsize * 2) > SFTK_MAX_BLOCK_SIZE) |
2481 | | return CKR_MECHANISM_PARAM_INVALID; |
2482 | | rc5_params.ulIvLen = blockSize; |
2483 | | PORT_Memset(ivBlock, 0, blockSize); |
2484 | | cbc_mechanism.mechanism = CKM_RC5_CBC; |
2485 | | cbc_mechanism.pParameter = &rc5_params; |
2486 | | cbc_mechanism.ulParameterLen = sizeof(rc5_params); |
2487 | | break; |
2488 | | #endif |
2489 | | /* add cast and idea later */ |
2490 | 0 | case CKM_DES_MAC_GENERAL: |
2491 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2492 | | /* fall through */ |
2493 | 0 | case CKM_DES_MAC: |
2494 | 0 | blockSize = 8; |
2495 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2496 | 0 | cbc_mechanism.mechanism = CKM_DES_CBC; |
2497 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2498 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2499 | 0 | break; |
2500 | 0 | case CKM_DES3_MAC_GENERAL: |
2501 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2502 | | /* fall through */ |
2503 | 0 | case CKM_DES3_MAC: |
2504 | 0 | blockSize = 8; |
2505 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2506 | 0 | cbc_mechanism.mechanism = CKM_DES3_CBC; |
2507 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2508 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2509 | 0 | break; |
2510 | 0 | case CKM_CDMF_MAC_GENERAL: |
2511 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2512 | | /* fall through */ |
2513 | 0 | case CKM_CDMF_MAC: |
2514 | 0 | blockSize = 8; |
2515 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2516 | 0 | cbc_mechanism.mechanism = CKM_CDMF_CBC; |
2517 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2518 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2519 | 0 | break; |
2520 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
2521 | 0 | case CKM_SEED_MAC_GENERAL: |
2522 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2523 | | /* fall through */ |
2524 | 0 | case CKM_SEED_MAC: |
2525 | 0 | blockSize = 16; |
2526 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2527 | 0 | cbc_mechanism.mechanism = CKM_SEED_CBC; |
2528 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2529 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2530 | 0 | break; |
2531 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
2532 | 0 | case CKM_CAMELLIA_MAC_GENERAL: |
2533 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2534 | | /* fall through */ |
2535 | 0 | case CKM_CAMELLIA_MAC: |
2536 | 0 | blockSize = 16; |
2537 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2538 | 0 | cbc_mechanism.mechanism = CKM_CAMELLIA_CBC; |
2539 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2540 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2541 | 0 | break; |
2542 | 0 | case CKM_AES_MAC_GENERAL: |
2543 | 0 | mac_bytes = *(CK_ULONG *)pMechanism->pParameter; |
2544 | | /* fall through */ |
2545 | 0 | case CKM_AES_MAC: |
2546 | 0 | blockSize = 16; |
2547 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2548 | 0 | cbc_mechanism.mechanism = CKM_AES_CBC; |
2549 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2550 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2551 | 0 | break; |
2552 | 0 | case CKM_AES_XCBC_MAC_96: |
2553 | 0 | case CKM_AES_XCBC_MAC: |
2554 | | /* The only difference between CKM_AES_XCBC_MAC |
2555 | | * and CKM_AES_XCBC_MAC_96 is the size of the returned mac. */ |
2556 | 0 | mac_bytes = pMechanism->mechanism == CKM_AES_XCBC_MAC_96 ? 12 : 16; |
2557 | 0 | blockSize = 16; |
2558 | 0 | PORT_Memset(ivBlock, 0, blockSize); |
2559 | 0 | cbc_mechanism.mechanism = CKM_AES_CBC; |
2560 | 0 | cbc_mechanism.pParameter = &ivBlock; |
2561 | 0 | cbc_mechanism.ulParameterLen = blockSize; |
2562 | | /* is XCBC requires extra processing at the end of the operation */ |
2563 | 0 | isXCBC = PR_TRUE; |
2564 | | /* The input key is used to generate k1, k2, and k3. k2 and k3 |
2565 | | * are used at the end in the pad step. k1 replaces the input |
2566 | | * key in the aes cbc mac */ |
2567 | 0 | crv = sftk_aes_xcbc_new_keys(hSession, hKey, &hKey, k2, k3); |
2568 | 0 | if (crv != CKR_OK) { |
2569 | 0 | return crv; |
2570 | 0 | } |
2571 | 0 | break; |
2572 | 469k | default: |
2573 | 469k | return CKR_FUNCTION_NOT_SUPPORTED; |
2574 | 469k | } |
2575 | | |
2576 | | /* if MAC size is externally supplied, it should be checked. |
2577 | | */ |
2578 | 0 | if (mac_bytes == SFTK_INVALID_MAC_SIZE) |
2579 | 0 | mac_bytes = blockSize >> 1; |
2580 | 0 | else { |
2581 | 0 | if (mac_bytes > blockSize) { |
2582 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
2583 | 0 | goto fail; |
2584 | 0 | } |
2585 | 0 | } |
2586 | | |
2587 | 0 | crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey, |
2588 | 0 | CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */ |
2589 | 0 | keyUsage, contextType, PR_TRUE); |
2590 | 0 | if (crv != CKR_OK) |
2591 | 0 | goto fail; |
2592 | 0 | crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL); |
2593 | | |
2594 | | /* this shouldn't happen! */ |
2595 | 0 | PORT_Assert(crv == CKR_OK); |
2596 | 0 | if (crv != CKR_OK) |
2597 | 0 | goto fail; |
2598 | 0 | context->blockSize = blockSize; |
2599 | 0 | context->macSize = mac_bytes; |
2600 | 0 | context->isXCBC = isXCBC; |
2601 | 0 | if (isXCBC) { |
2602 | | /* save the xcbc specific parameters */ |
2603 | 0 | PORT_Memcpy(context->k2, k2, blockSize); |
2604 | 0 | PORT_Memcpy(context->k3, k3, blockSize); |
2605 | 0 | PORT_Memset(k2, 0, blockSize); |
2606 | 0 | PORT_Memset(k3, 0, blockSize); |
2607 | | /* get rid of the temp key now that the context has been created */ |
2608 | 0 | NSC_DestroyObject(hSession, hKey); |
2609 | 0 | } |
2610 | 0 | return CKR_OK; |
2611 | 0 | fail: |
2612 | 0 | if (isXCBC) { |
2613 | 0 | PORT_Memset(k2, 0, blockSize); |
2614 | 0 | PORT_Memset(k3, 0, blockSize); |
2615 | 0 | NSC_DestroyObject(hSession, hKey); /* get rid of our temp key */ |
2616 | 0 | } |
2617 | 0 | return crv; |
2618 | 0 | } |
2619 | | |
2620 | | /* |
2621 | | * encode RSA PKCS #1 Signature data before signing... |
2622 | | */ |
2623 | | static SECStatus |
2624 | | sftk_RSAHashSign(void *ctx, unsigned char *sig, |
2625 | | unsigned int *sigLen, unsigned int maxLen, |
2626 | | const unsigned char *hash, unsigned int hashLen) |
2627 | 0 | { |
2628 | 0 | SFTKHashSignInfo *info = ctx; |
2629 | 0 | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
2630 | 0 | if (info->key->keyType != NSSLOWKEYRSAKey) { |
2631 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2632 | 0 | return SECFailure; |
2633 | 0 | } |
2634 | | |
2635 | 0 | return RSA_HashSign(info->hashOid, info->key, sig, sigLen, maxLen, |
2636 | 0 | hash, hashLen); |
2637 | 0 | } |
2638 | | |
2639 | | /* XXX Old template; want to expunge it eventually. */ |
2640 | | static DERTemplate SECAlgorithmIDTemplate[] = { |
2641 | | { DER_SEQUENCE, |
2642 | | 0, NULL, sizeof(SECAlgorithmID) }, |
2643 | | { DER_OBJECT_ID, |
2644 | | offsetof(SECAlgorithmID, algorithm) }, |
2645 | | { DER_OPTIONAL | DER_ANY, |
2646 | | offsetof(SECAlgorithmID, parameters) }, |
2647 | | { 0 } |
2648 | | }; |
2649 | | |
2650 | | /* |
2651 | | * XXX OLD Template. Once all uses have been switched over to new one, |
2652 | | * remove this. |
2653 | | */ |
2654 | | static DERTemplate SGNDigestInfoTemplate[] = { |
2655 | | { DER_SEQUENCE, |
2656 | | 0, NULL, sizeof(SGNDigestInfo) }, |
2657 | | { DER_INLINE, |
2658 | | offsetof(SGNDigestInfo, digestAlgorithm), |
2659 | | SECAlgorithmIDTemplate }, |
2660 | | { DER_OCTET_STRING, |
2661 | | offsetof(SGNDigestInfo, digest) }, |
2662 | | { 0 } |
2663 | | }; |
2664 | | |
2665 | | /* |
2666 | | * encode RSA PKCS #1 Signature data before signing... |
2667 | | */ |
2668 | | SECStatus |
2669 | | RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, |
2670 | | unsigned char *sig, unsigned int *sigLen, unsigned int maxLen, |
2671 | | const unsigned char *hash, unsigned int hashLen) |
2672 | 0 | { |
2673 | 0 | SECStatus rv = SECFailure; |
2674 | 0 | SECItem digder; |
2675 | 0 | PLArenaPool *arena = NULL; |
2676 | 0 | SGNDigestInfo *di = NULL; |
2677 | |
|
2678 | 0 | digder.data = NULL; |
2679 | |
|
2680 | 0 | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
2681 | 0 | if (!arena) { |
2682 | 0 | goto loser; |
2683 | 0 | } |
2684 | | |
2685 | | /* Construct digest info */ |
2686 | 0 | di = SGN_CreateDigestInfo(hashOid, hash, hashLen); |
2687 | 0 | if (!di) { |
2688 | 0 | goto loser; |
2689 | 0 | } |
2690 | | |
2691 | | /* Der encode the digest as a DigestInfo */ |
2692 | 0 | rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di); |
2693 | 0 | if (rv != SECSuccess) { |
2694 | 0 | goto loser; |
2695 | 0 | } |
2696 | | |
2697 | | /* |
2698 | | ** Encrypt signature after constructing appropriate PKCS#1 signature |
2699 | | ** block |
2700 | | */ |
2701 | 0 | rv = RSA_Sign(&key->u.rsa, sig, sigLen, maxLen, digder.data, |
2702 | 0 | digder.len); |
2703 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2704 | 0 | sftk_fatalError = PR_TRUE; |
2705 | 0 | } |
2706 | |
|
2707 | 0 | loser: |
2708 | 0 | SGN_DestroyDigestInfo(di); |
2709 | 0 | if (arena != NULL) { |
2710 | 0 | PORT_FreeArena(arena, PR_TRUE); |
2711 | 0 | } |
2712 | 0 | return rv; |
2713 | 0 | } |
2714 | | |
2715 | | static SECStatus |
2716 | | sftk_RSASign(void *ctx, unsigned char *output, |
2717 | | unsigned int *outputLen, unsigned int maxOutputLen, |
2718 | | const unsigned char *input, unsigned int inputLen) |
2719 | 18.9k | { |
2720 | 18.9k | NSSLOWKEYPrivateKey *key = ctx; |
2721 | 18.9k | SECStatus rv = SECFailure; |
2722 | | |
2723 | 18.9k | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
2724 | 18.9k | if (key->keyType != NSSLOWKEYRSAKey) { |
2725 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2726 | 0 | return SECFailure; |
2727 | 0 | } |
2728 | | |
2729 | 18.9k | rv = RSA_Sign(&key->u.rsa, output, outputLen, maxOutputLen, input, |
2730 | 18.9k | inputLen); |
2731 | 18.9k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2732 | 0 | sftk_fatalError = PR_TRUE; |
2733 | 0 | } |
2734 | 18.9k | return rv; |
2735 | 18.9k | } |
2736 | | |
2737 | | static SECStatus |
2738 | | sftk_RSASignRaw(void *ctx, unsigned char *output, |
2739 | | unsigned int *outputLen, unsigned int maxOutputLen, |
2740 | | const unsigned char *input, unsigned int inputLen) |
2741 | 0 | { |
2742 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
2743 | 0 | SECStatus rv = SECFailure; |
2744 | |
|
2745 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
2746 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
2747 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2748 | 0 | return SECFailure; |
2749 | 0 | } |
2750 | | |
2751 | 0 | rv = RSA_SignRaw(&key->u.rsa, output, outputLen, maxOutputLen, input, |
2752 | 0 | inputLen); |
2753 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2754 | 0 | sftk_fatalError = PR_TRUE; |
2755 | 0 | } |
2756 | 0 | return rv; |
2757 | 0 | } |
2758 | | |
2759 | | static SECStatus |
2760 | | sftk_RSASignPSS(void *ctx, unsigned char *sig, |
2761 | | unsigned int *sigLen, unsigned int maxLen, |
2762 | | const unsigned char *hash, unsigned int hashLen) |
2763 | 2.20k | { |
2764 | 2.20k | SFTKPSSSignInfo *info = ctx; |
2765 | 2.20k | SECStatus rv = SECFailure; |
2766 | 2.20k | HASH_HashType hashAlg; |
2767 | 2.20k | HASH_HashType maskHashAlg; |
2768 | 2.20k | CK_RSA_PKCS_PSS_PARAMS *params = &info->params; |
2769 | | |
2770 | 2.20k | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
2771 | 2.20k | if (info->key->keyType != NSSLOWKEYRSAKey) { |
2772 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
2773 | 0 | return SECFailure; |
2774 | 0 | } |
2775 | | |
2776 | 2.20k | hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg); |
2777 | 2.20k | maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf); |
2778 | | |
2779 | 2.20k | rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL, |
2780 | 2.20k | params->sLen, sig, sigLen, maxLen, hash, hashLen); |
2781 | 2.20k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2782 | 0 | sftk_fatalError = PR_TRUE; |
2783 | 0 | } |
2784 | 2.20k | return rv; |
2785 | 2.20k | } |
2786 | | |
2787 | | #ifndef NSS_DISABLE_DSA |
2788 | | static SECStatus |
2789 | | nsc_DSA_Verify_Stub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen, |
2790 | | const unsigned char *dataBuf, unsigned int dataLen) |
2791 | 3.33k | { |
2792 | 3.33k | NSSLOWKEYPublicKey *key = ctx; |
2793 | 3.33k | SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen }; |
2794 | 3.33k | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2795 | 3.33k | return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest); |
2796 | 3.33k | } |
2797 | | |
2798 | | static SECStatus |
2799 | | nsc_DSA_Sign_Stub(void *ctx, unsigned char *sigBuf, |
2800 | | unsigned int *sigLen, unsigned int maxSigLen, |
2801 | | const unsigned char *dataBuf, unsigned int dataLen) |
2802 | 0 | { |
2803 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
2804 | 0 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen }; |
2805 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2806 | 0 | SECStatus rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest); |
2807 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2808 | 0 | sftk_fatalError = PR_TRUE; |
2809 | 0 | } |
2810 | 0 | *sigLen = signature.len; |
2811 | 0 | return rv; |
2812 | 0 | } |
2813 | | #endif |
2814 | | |
2815 | | static SECStatus |
2816 | | nsc_ECDSAVerifyStub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen, |
2817 | | const unsigned char *dataBuf, unsigned int dataLen) |
2818 | 389 | { |
2819 | 389 | NSSLOWKEYPublicKey *key = ctx; |
2820 | 389 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen }; |
2821 | 389 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2822 | 389 | return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest); |
2823 | 389 | } |
2824 | | |
2825 | | static SECStatus |
2826 | | nsc_ECDSASignStub(void *ctx, unsigned char *sigBuf, |
2827 | | unsigned int *sigLen, unsigned int maxSigLen, |
2828 | | const unsigned char *dataBuf, unsigned int dataLen) |
2829 | 9.06k | { |
2830 | 9.06k | NSSLOWKEYPrivateKey *key = ctx; |
2831 | 9.06k | SECItem signature = { siBuffer, sigBuf, maxSigLen }; |
2832 | 9.06k | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2833 | | |
2834 | 9.06k | SECStatus rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest); |
2835 | 9.06k | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2836 | 0 | sftk_fatalError = PR_TRUE; |
2837 | 0 | } |
2838 | 9.06k | *sigLen = signature.len; |
2839 | 9.06k | return rv; |
2840 | 9.06k | } |
2841 | | |
2842 | | static SECStatus |
2843 | | nsc_EDDSAVerifyStub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen, |
2844 | | const unsigned char *dataBuf, unsigned int dataLen) |
2845 | 0 | { |
2846 | 0 | NSSLOWKEYPublicKey *key = ctx; |
2847 | 0 | SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen }; |
2848 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2849 | 0 | return ED_VerifyMessage(&(key->u.ec), &signature, &digest); |
2850 | 0 | } |
2851 | | |
2852 | | static SECStatus |
2853 | | nsc_EDDSASignStub(void *ctx, unsigned char *sigBuf, |
2854 | | unsigned int *sigLen, unsigned int maxSigLen, |
2855 | | const unsigned char *dataBuf, unsigned int dataLen) |
2856 | 0 | { |
2857 | 0 | NSSLOWKEYPrivateKey *key = ctx; |
2858 | 0 | SECItem signature = { siBuffer, sigBuf, maxSigLen }; |
2859 | 0 | SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen }; |
2860 | |
|
2861 | 0 | SECStatus rv = ED_SignMessage(&(key->u.ec), &signature, &digest); |
2862 | 0 | if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
2863 | 0 | sftk_fatalError = PR_TRUE; |
2864 | 0 | } |
2865 | 0 | *sigLen = signature.len; |
2866 | 0 | return rv; |
2867 | 0 | } |
2868 | | |
2869 | | void |
2870 | | sftk_MLDSASignUpdate(void *info, const unsigned char *data, unsigned int len) |
2871 | 0 | { |
2872 | 0 | MLDSAContext *ctptr = (MLDSAContext *)info; |
2873 | 0 | const SECItem inData = { siBuffer, (unsigned char *)data, len }; |
2874 | 0 | (void)MLDSA_SignUpdate(ctptr, &inData); |
2875 | 0 | } |
2876 | | |
2877 | | void |
2878 | | sftk_MLDSAVerifyUpdate(void *info, const unsigned char *data, unsigned int len) |
2879 | 0 | { |
2880 | 0 | MLDSAContext *ctptr = (MLDSAContext *)info; |
2881 | 0 | const SECItem inData = { siBuffer, (unsigned char *)data, len }; |
2882 | 0 | (void)MLDSA_VerifyUpdate(ctptr, &inData); |
2883 | 0 | } |
2884 | | |
2885 | | SECStatus |
2886 | | sftk_MLDSASignFinal(void *info, unsigned char *sig, unsigned int *sigLen, |
2887 | | unsigned int maxLen, const unsigned char *data, |
2888 | | unsigned int len) |
2889 | 0 | { |
2890 | 0 | MLDSAContext *ctptr = (MLDSAContext *)info; |
2891 | 0 | SECItem sigOut = { siBuffer, sig, maxLen }; |
2892 | 0 | SECStatus rv; |
2893 | |
|
2894 | 0 | if (len != 0) { |
2895 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2896 | 0 | return SECFailure; |
2897 | 0 | } |
2898 | | |
2899 | 0 | rv = MLDSA_SignFinal(ctptr, &sigOut); |
2900 | 0 | *sigLen = sigOut.len; |
2901 | 0 | return rv; |
2902 | 0 | } |
2903 | | |
2904 | | SECStatus |
2905 | | sftk_MLDSAVerifyFinal(void *info, const unsigned char *sig, unsigned int sigLen, |
2906 | | const unsigned char *data, unsigned int len) |
2907 | 0 | { |
2908 | 0 | MLDSAContext *ctptr = (MLDSAContext *)info; |
2909 | 0 | const SECItem sigIn = { siBuffer, (unsigned char *)sig, sigLen }; |
2910 | |
|
2911 | 0 | if (len != 0) { |
2912 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
2913 | 0 | return SECFailure; |
2914 | 0 | } |
2915 | | |
2916 | 0 | return MLDSA_VerifyFinal(ctptr, &sigIn); |
2917 | 0 | } |
2918 | | |
2919 | | unsigned int |
2920 | | sftk_MLDSAGetSigLen(CK_ML_DSA_PARAMETER_SET_TYPE paramSet) |
2921 | 0 | { |
2922 | 0 | switch (paramSet) { |
2923 | 0 | case CKP_ML_DSA_44: |
2924 | 0 | return ML_DSA_44_SIGNATURE_LEN; |
2925 | 0 | case CKP_ML_DSA_65: |
2926 | 0 | return ML_DSA_65_SIGNATURE_LEN; |
2927 | 0 | case CKP_ML_DSA_87: |
2928 | 0 | return ML_DSA_87_SIGNATURE_LEN; |
2929 | 0 | } |
2930 | | /* this is a programming error if we get a valid DSA key with an unknown |
2931 | | * parmaSet */ |
2932 | 0 | PORT_Assert(/* unknown param set */ 0); |
2933 | 0 | return 0; |
2934 | 0 | } |
2935 | | |
2936 | | /* NSC_SignInit setups up the signing operations. There are three basic |
2937 | | * types of signing: |
2938 | | * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied |
2939 | | * to data in a single Sign operation (which often looks a lot like an |
2940 | | * encrypt, with data coming in and data going out). |
2941 | | * (2) Hash based signing, where we continually hash the data, then apply |
2942 | | * some sort of signature to the end. |
2943 | | * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key, |
2944 | | * and only the final block is part of the mac. |
2945 | | * |
2946 | | * For case number 3, we initialize a context much like the Encryption Context |
2947 | | * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and |
2948 | | * C_Final by the following method... if it's not multi-part, and it's doesn't |
2949 | | * have a hash context, it must be a block Encryption CBC MAC. |
2950 | | * |
2951 | | * For case number 2, we initialize a hash structure, as well as make it |
2952 | | * multi-part. Updates are simple calls to the hash update function. Final |
2953 | | * calls the hashend, then passes the result to the 'update' function (which |
2954 | | * operates as a final signature function). In some hash based MAC'ing (as |
2955 | | * opposed to hash base signatures), the update function is can be simply a |
2956 | | * copy (as is the case with HMAC). |
2957 | | */ |
2958 | | CK_RV |
2959 | | NSC_SignInit(CK_SESSION_HANDLE hSession, |
2960 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
2961 | 461k | { |
2962 | 461k | SFTKSession *session; |
2963 | 461k | SFTKObject *key; |
2964 | 461k | SFTKSessionContext *context; |
2965 | 461k | CK_KEY_TYPE key_type; |
2966 | 461k | CK_RV crv = CKR_OK; |
2967 | 461k | NSSLOWKEYPrivateKey *privKey; |
2968 | 461k | SFTKHashSignInfo *info = NULL; |
2969 | 461k | SFTKPSSSignInfo *pinfo = NULL; |
2970 | | |
2971 | 461k | CHECK_FORK(); |
2972 | | |
2973 | | /* Block Cipher MACing Algorithms use a different Context init method..*/ |
2974 | 461k | crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN); |
2975 | 461k | if (crv != CKR_FUNCTION_NOT_SUPPORTED) |
2976 | 0 | return crv; |
2977 | | |
2978 | | /* we're not using a block cipher mac */ |
2979 | 461k | session = sftk_SessionFromHandle(hSession); |
2980 | 461k | if (session == NULL) |
2981 | 0 | return CKR_SESSION_HANDLE_INVALID; |
2982 | 461k | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_SIGN, &key, |
2983 | 461k | hKey, &key_type, CKO_PRIVATE_KEY, CKA_SIGN); |
2984 | 461k | if (crv != CKR_OK) { |
2985 | 0 | sftk_FreeSession(session); |
2986 | 0 | return crv; |
2987 | 0 | } |
2988 | | |
2989 | 461k | context->multi = PR_FALSE; |
2990 | | |
2991 | 461k | #define INIT_RSA_SIGN_MECH(mmm) \ |
2992 | 461k | case CKM_##mmm##_RSA_PKCS: \ |
2993 | 0 | context->multi = PR_TRUE; \ |
2994 | 0 | crv = sftk_doSub##mmm(context); \ |
2995 | 0 | if (crv != CKR_OK) \ |
2996 | 0 | break; \ |
2997 | 0 | context->update = sftk_RSAHashSign; \ |
2998 | 0 | info = PORT_New(SFTKHashSignInfo); \ |
2999 | 0 | if (info == NULL) { \ |
3000 | 0 | crv = CKR_HOST_MEMORY; \ |
3001 | 0 | break; \ |
3002 | 0 | } \ |
3003 | 0 | info->hashOid = SEC_OID_##mmm; \ |
3004 | 0 | goto finish_rsa; |
3005 | | |
3006 | 461k | switch (pMechanism->mechanism) { |
3007 | 0 | INIT_RSA_SIGN_MECH(MD5) |
3008 | 0 | INIT_RSA_SIGN_MECH(MD2) |
3009 | 0 | INIT_RSA_SIGN_MECH(SHA1) |
3010 | 0 | INIT_RSA_SIGN_MECH(SHA224) |
3011 | 0 | INIT_RSA_SIGN_MECH(SHA256) |
3012 | 0 | INIT_RSA_SIGN_MECH(SHA384) |
3013 | 0 | INIT_RSA_SIGN_MECH(SHA512) |
3014 | | |
3015 | 18.9k | case CKM_RSA_PKCS: |
3016 | 18.9k | context->update = sftk_RSASign; |
3017 | 18.9k | goto finish_rsa; |
3018 | 0 | case CKM_RSA_X_509: |
3019 | 0 | context->update = sftk_RSASignRaw; |
3020 | 18.9k | finish_rsa: |
3021 | 18.9k | if (key_type != CKK_RSA) { |
3022 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3023 | 0 | break; |
3024 | 0 | } |
3025 | 18.9k | context->rsa = PR_TRUE; |
3026 | 18.9k | privKey = sftk_GetPrivKey(key, CKK_RSA, &crv); |
3027 | 18.9k | if (privKey == NULL) { |
3028 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3029 | 0 | break; |
3030 | 0 | } |
3031 | | /* OK, info is allocated only if we're doing hash and sign mechanism. |
3032 | | * It's necessary to be able to set the correct OID in the final |
3033 | | * signature. |
3034 | | */ |
3035 | 18.9k | if (info) { |
3036 | 0 | info->key = privKey; |
3037 | 0 | context->cipherInfo = info; |
3038 | 0 | context->destroy = sftk_Space; |
3039 | 18.9k | } else { |
3040 | 18.9k | context->cipherInfo = privKey; |
3041 | 18.9k | context->destroy = sftk_Null; |
3042 | 18.9k | } |
3043 | 18.9k | context->maxLen = nsslowkey_PrivateModulusLen(privKey); |
3044 | 18.9k | break; |
3045 | | |
3046 | 0 | #define INIT_RSA_PSS_SIG_MECH(mmm) \ |
3047 | 1.78k | case CKM_##mmm##_RSA_PKCS_PSS: \ |
3048 | 1.78k | context->multi = PR_TRUE; \ |
3049 | 1.78k | crv = sftk_doSub##mmm(context); \ |
3050 | 1.78k | if (crv != CKR_OK) \ |
3051 | 1.78k | break; \ |
3052 | 1.78k | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) { \ |
3053 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; \ |
3054 | 0 | break; \ |
3055 | 0 | } \ |
3056 | 1.78k | if (((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)->hashAlg != CKM_##mmm) { \ |
3057 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; \ |
3058 | 0 | break; \ |
3059 | 0 | } \ |
3060 | 1.78k | goto finish_rsa_pss; |
3061 | 0 | INIT_RSA_PSS_SIG_MECH(SHA1) |
3062 | 0 | INIT_RSA_PSS_SIG_MECH(SHA224) |
3063 | 2.97k | INIT_RSA_PSS_SIG_MECH(SHA256) |
3064 | 992 | INIT_RSA_PSS_SIG_MECH(SHA384) |
3065 | 1.50k | INIT_RSA_PSS_SIG_MECH(SHA512) |
3066 | 502 | case CKM_RSA_PKCS_PSS: |
3067 | 2.20k | finish_rsa_pss: |
3068 | 2.20k | if (key_type != CKK_RSA) { |
3069 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3070 | 0 | break; |
3071 | 0 | } |
3072 | 2.20k | context->rsa = PR_TRUE; |
3073 | 2.20k | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || |
3074 | 2.20k | !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) { |
3075 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3076 | 0 | break; |
3077 | 0 | } |
3078 | 2.20k | pinfo = PORT_New(SFTKPSSSignInfo); |
3079 | 2.20k | if (pinfo == NULL) { |
3080 | 0 | crv = CKR_HOST_MEMORY; |
3081 | 0 | break; |
3082 | 0 | } |
3083 | 2.20k | pinfo->size = sizeof(SFTKPSSSignInfo); |
3084 | 2.20k | pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter; |
3085 | 2.20k | pinfo->key = sftk_GetPrivKey(key, CKK_RSA, &crv); |
3086 | 2.20k | if (pinfo->key == NULL) { |
3087 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3088 | 0 | break; |
3089 | 0 | } |
3090 | 2.20k | context->cipherInfo = pinfo; |
3091 | 2.20k | context->destroy = sftk_ZSpace; |
3092 | 2.20k | context->update = sftk_RSASignPSS; |
3093 | 2.20k | context->maxLen = nsslowkey_PrivateModulusLen(pinfo->key); |
3094 | 2.20k | break; |
3095 | | |
3096 | 0 | #ifndef NSS_DISABLE_DSA |
3097 | 0 | #define INIT_DSA_SIG_MECH(mmm) \ |
3098 | 0 | case CKM_DSA_##mmm: \ |
3099 | 0 | context->multi = PR_TRUE; \ |
3100 | 0 | crv = sftk_doSub##mmm(context); \ |
3101 | 0 | if (crv != CKR_OK) \ |
3102 | 0 | break; \ |
3103 | 0 | goto finish_dsa; |
3104 | 0 | INIT_DSA_SIG_MECH(SHA1) |
3105 | 0 | INIT_DSA_SIG_MECH(SHA224) |
3106 | 0 | INIT_DSA_SIG_MECH(SHA256) |
3107 | 0 | INIT_DSA_SIG_MECH(SHA384) |
3108 | 0 | INIT_DSA_SIG_MECH(SHA512) |
3109 | 0 | case CKM_DSA: |
3110 | 0 | finish_dsa: |
3111 | 0 | if (key_type != CKK_DSA) { |
3112 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3113 | 0 | break; |
3114 | 0 | } |
3115 | 0 | privKey = sftk_GetPrivKey(key, CKK_DSA, &crv); |
3116 | 0 | if (privKey == NULL) { |
3117 | 0 | break; |
3118 | 0 | } |
3119 | 0 | context->cipherInfo = privKey; |
3120 | 0 | context->update = nsc_DSA_Sign_Stub; |
3121 | 0 | context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey; |
3122 | 0 | context->maxLen = DSA_MAX_SIGNATURE_LEN; |
3123 | |
|
3124 | 0 | break; |
3125 | 0 | #endif |
3126 | 0 | case CKM_ML_DSA: { |
3127 | | /* set our defaults */ |
3128 | 0 | CK_HEDGE_TYPE hedgeType = CKH_HEDGE_PREFERRED; |
3129 | 0 | SECItem signCtx = { siBuffer, NULL, 0 }; |
3130 | 0 | MLDSAContext *ctptr = NULL; |
3131 | 0 | SECStatus rv; |
3132 | | |
3133 | | /* make sure we have the right key type */ |
3134 | 0 | if (key_type != CKK_ML_DSA) { |
3135 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3136 | 0 | break; |
3137 | 0 | } |
3138 | | /* fill in our parameters from the mechanism parameters if |
3139 | | * supplied */ |
3140 | 0 | if (pMechanism->ulParameterLen != 0) { |
3141 | 0 | CK_SIGN_ADDITIONAL_CONTEXT *param; |
3142 | 0 | if (pMechanism->ulParameterLen != |
3143 | 0 | sizeof(CK_SIGN_ADDITIONAL_CONTEXT)) { |
3144 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3145 | 0 | break; |
3146 | 0 | } |
3147 | 0 | param = (CK_SIGN_ADDITIONAL_CONTEXT *)pMechanism->pParameter; |
3148 | 0 | hedgeType = param->hedgeVariant; |
3149 | 0 | signCtx.data = param->pContext; |
3150 | 0 | signCtx.len = param->ulContextLen; |
3151 | 0 | } |
3152 | | /* fetch the key */ |
3153 | 0 | privKey = sftk_GetPrivKey(key, key_type, &crv); |
3154 | 0 | if (privKey == NULL) { |
3155 | 0 | crv = CKR_HOST_MEMORY; |
3156 | 0 | break; |
3157 | 0 | } |
3158 | | /* now initialize it the signature */ |
3159 | 0 | rv = MLDSA_SignInit(&privKey->u.mldsa, hedgeType, &signCtx, &ctptr); |
3160 | 0 | if (rv != SECSuccess) { |
3161 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
3162 | 0 | if (privKey != key->objectInfo) { |
3163 | 0 | nsslowkey_DestroyPrivateKey(privKey); |
3164 | 0 | } |
3165 | 0 | break; |
3166 | 0 | } |
3167 | | /* set up our cipher info. MLDSA is only a combined hash/sign |
3168 | | * so the hash update is our sign update, the hash end is a null |
3169 | | * function returning a zero length value, and the final gets our |
3170 | | * signature based on the context. Both the cipher context and the |
3171 | | * hash Info is the same. The MLDSA_SignFinal frees the context, |
3172 | | * so we don't have to */ |
3173 | 0 | context->multi = PR_TRUE; |
3174 | 0 | context->cipherInfo = ctptr; |
3175 | 0 | context->hashInfo = ctptr; |
3176 | 0 | context->hashUpdate = sftk_MLDSASignUpdate; |
3177 | 0 | context->end = sftk_NullHashEnd; |
3178 | 0 | context->hashdestroy = sftk_Null; |
3179 | 0 | context->destroy = sftk_Null; |
3180 | 0 | context->update = sftk_MLDSASignFinal; |
3181 | 0 | context->maxLen = sftk_MLDSAGetSigLen(privKey->u.mldsa.paramSet); |
3182 | 0 | if (privKey != key->objectInfo) { |
3183 | 0 | nsslowkey_DestroyPrivateKey(privKey); |
3184 | 0 | } |
3185 | 0 | break; |
3186 | 0 | } |
3187 | | |
3188 | 0 | #define INIT_ECDSA_SIG_MECH(mmm) \ |
3189 | 531 | case CKM_ECDSA_##mmm: \ |
3190 | 531 | context->multi = PR_TRUE; \ |
3191 | 531 | crv = sftk_doSub##mmm(context); \ |
3192 | 531 | if (crv != CKR_OK) \ |
3193 | 531 | break; \ |
3194 | 531 | goto finish_ecdsa; |
3195 | 0 | INIT_ECDSA_SIG_MECH(SHA1) |
3196 | 0 | INIT_ECDSA_SIG_MECH(SHA224) |
3197 | 531 | INIT_ECDSA_SIG_MECH(SHA256) |
3198 | 531 | INIT_ECDSA_SIG_MECH(SHA384) |
3199 | 0 | INIT_ECDSA_SIG_MECH(SHA512) |
3200 | 8.52k | case CKM_ECDSA: |
3201 | 9.06k | finish_ecdsa: |
3202 | 9.06k | if (key_type != CKK_EC) { |
3203 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3204 | 0 | break; |
3205 | 0 | } |
3206 | 9.06k | privKey = sftk_GetPrivKey(key, CKK_EC, &crv); |
3207 | 9.06k | if (privKey == NULL) { |
3208 | 0 | crv = CKR_HOST_MEMORY; |
3209 | 0 | break; |
3210 | 0 | } |
3211 | 9.06k | context->cipherInfo = privKey; |
3212 | 9.06k | context->update = nsc_ECDSASignStub; |
3213 | 9.06k | context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey; |
3214 | 9.06k | context->maxLen = MAX_ECKEY_LEN * 2; |
3215 | | |
3216 | 9.06k | break; |
3217 | | |
3218 | 0 | case CKM_EDDSA: |
3219 | 0 | if (key_type != CKK_EC_EDWARDS) { |
3220 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3221 | 0 | break; |
3222 | 0 | } |
3223 | | |
3224 | 0 | if (pMechanism->pParameter) { |
3225 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3226 | 0 | break; |
3227 | 0 | } |
3228 | | |
3229 | 0 | privKey = sftk_GetPrivKey(key, CKK_EC_EDWARDS, &crv); |
3230 | 0 | if (privKey == NULL) { |
3231 | 0 | crv = CKR_HOST_MEMORY; |
3232 | 0 | break; |
3233 | 0 | } |
3234 | 0 | context->cipherInfo = privKey; |
3235 | 0 | context->update = nsc_EDDSASignStub; |
3236 | 0 | context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey; |
3237 | 0 | context->maxLen = MAX_ECKEY_LEN * 2; |
3238 | |
|
3239 | 0 | break; |
3240 | | |
3241 | 0 | #define INIT_HMAC_MECH(mmm) \ |
3242 | 0 | case CKM_##mmm##_HMAC_GENERAL: \ |
3243 | 0 | PORT_Assert(pMechanism->pParameter); \ |
3244 | 0 | if (!pMechanism->pParameter) { \ |
3245 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; \ |
3246 | 0 | break; \ |
3247 | 0 | } \ |
3248 | 0 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, \ |
3249 | 0 | *(CK_ULONG *)pMechanism->pParameter); \ |
3250 | 0 | break; \ |
3251 | 232k | case CKM_##mmm##_HMAC: \ |
3252 | 232k | crv = sftk_doMACInit(pMechanism->mechanism, context, key, \ |
3253 | 232k | mmm##_LENGTH); \ |
3254 | 232k | break; |
3255 | | |
3256 | 0 | INIT_HMAC_MECH(MD2) |
3257 | 0 | INIT_HMAC_MECH(MD5) |
3258 | 0 | INIT_HMAC_MECH(SHA1) |
3259 | 0 | INIT_HMAC_MECH(SHA224) |
3260 | 0 | INIT_HMAC_MECH(SHA256) |
3261 | 0 | INIT_HMAC_MECH(SHA384) |
3262 | 0 | INIT_HMAC_MECH(SHA512) |
3263 | 0 | INIT_HMAC_MECH(SHA3_224) |
3264 | 0 | INIT_HMAC_MECH(SHA3_256) |
3265 | 0 | INIT_HMAC_MECH(SHA3_384) |
3266 | 0 | INIT_HMAC_MECH(SHA3_512) |
3267 | | |
3268 | 0 | case CKM_AES_CMAC_GENERAL: |
3269 | 0 | PORT_Assert(pMechanism->pParameter); |
3270 | 0 | if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) { |
3271 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3272 | 0 | break; |
3273 | 0 | } |
3274 | 0 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, *(CK_ULONG *)pMechanism->pParameter); |
3275 | 0 | break; |
3276 | 0 | case CKM_AES_CMAC: |
3277 | 0 | crv = sftk_doMACInit(pMechanism->mechanism, context, key, AES_BLOCK_SIZE); |
3278 | 0 | break; |
3279 | 0 | case CKM_SSL3_MD5_MAC: |
3280 | 0 | PORT_Assert(pMechanism->pParameter); |
3281 | 0 | if (!pMechanism->pParameter) { |
3282 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3283 | 0 | break; |
3284 | 0 | } |
3285 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key, |
3286 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
3287 | 0 | break; |
3288 | 0 | case CKM_SSL3_SHA1_MAC: |
3289 | 0 | PORT_Assert(pMechanism->pParameter); |
3290 | 0 | if (!pMechanism->pParameter) { |
3291 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3292 | 0 | break; |
3293 | 0 | } |
3294 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key, |
3295 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
3296 | 0 | break; |
3297 | 0 | case CKM_TLS_PRF_GENERAL: |
3298 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); |
3299 | 0 | break; |
3300 | 178k | case CKM_TLS_MAC: { |
3301 | 178k | CK_TLS_MAC_PARAMS *tls12_mac_params; |
3302 | 178k | HASH_HashType tlsPrfHash; |
3303 | 178k | const char *label; |
3304 | | |
3305 | 178k | if (pMechanism->ulParameterLen != sizeof(CK_TLS_MAC_PARAMS)) { |
3306 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3307 | 0 | break; |
3308 | 0 | } |
3309 | 178k | tls12_mac_params = (CK_TLS_MAC_PARAMS *)pMechanism->pParameter; |
3310 | 178k | if (tls12_mac_params->prfHashMechanism == CKM_TLS_PRF) { |
3311 | | /* The TLS 1.0 and 1.1 PRF */ |
3312 | 74.1k | tlsPrfHash = HASH_AlgNULL; |
3313 | 74.1k | if (tls12_mac_params->ulMacLength != 12) { |
3314 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3315 | 0 | break; |
3316 | 0 | } |
3317 | 104k | } else { |
3318 | | /* The hash function for the TLS 1.2 PRF */ |
3319 | 104k | tlsPrfHash = |
3320 | 104k | sftk_GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism); |
3321 | 104k | if (tlsPrfHash == HASH_AlgNULL || |
3322 | 104k | tls12_mac_params->ulMacLength < 12) { |
3323 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3324 | 0 | break; |
3325 | 0 | } |
3326 | 104k | } |
3327 | 178k | if (tls12_mac_params->ulServerOrClient == 1) { |
3328 | 86.1k | label = "server finished"; |
3329 | 92.4k | } else if (tls12_mac_params->ulServerOrClient == 2) { |
3330 | 92.4k | label = "client finished"; |
3331 | 92.4k | } else { |
3332 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3333 | 0 | break; |
3334 | 0 | } |
3335 | 178k | crv = sftk_TLSPRFInit(context, key, key_type, tlsPrfHash, |
3336 | 178k | tls12_mac_params->ulMacLength); |
3337 | 178k | if (crv == CKR_OK) { |
3338 | 178k | context->hashUpdate(context->hashInfo, (unsigned char *)label, 15); |
3339 | 178k | } |
3340 | 178k | break; |
3341 | 178k | } |
3342 | 0 | case CKM_NSS_TLS_PRF_GENERAL_SHA256: |
3343 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); |
3344 | 0 | break; |
3345 | | |
3346 | 20.5k | case CKM_NSS_HMAC_CONSTANT_TIME: { |
3347 | 20.5k | sftk_MACConstantTimeCtx *ctx = |
3348 | 20.5k | sftk_HMACConstantTime_New(pMechanism, key); |
3349 | 20.5k | CK_ULONG *intpointer; |
3350 | | |
3351 | 20.5k | if (ctx == NULL) { |
3352 | 0 | crv = CKR_ARGUMENTS_BAD; |
3353 | 0 | break; |
3354 | 0 | } |
3355 | 20.5k | intpointer = PORT_New(CK_ULONG); |
3356 | 20.5k | if (intpointer == NULL) { |
3357 | 0 | PORT_Free(ctx); |
3358 | 0 | crv = CKR_HOST_MEMORY; |
3359 | 0 | break; |
3360 | 0 | } |
3361 | 20.5k | *intpointer = ctx->hash->length; |
3362 | | |
3363 | 20.5k | context->cipherInfo = intpointer; |
3364 | 20.5k | context->hashInfo = ctx; |
3365 | 20.5k | context->currentMech = pMechanism->mechanism; |
3366 | 20.5k | context->hashUpdate = sftk_HMACConstantTime_Update; |
3367 | 20.5k | context->hashdestroy = sftk_MACConstantTime_DestroyContext; |
3368 | 20.5k | context->end = sftk_MACConstantTime_EndHash; |
3369 | 20.5k | context->update = sftk_SignCopy; |
3370 | 20.5k | context->destroy = sftk_Space; |
3371 | 20.5k | context->maxLen = 64; |
3372 | 20.5k | context->multi = PR_TRUE; |
3373 | 20.5k | break; |
3374 | 20.5k | } |
3375 | | |
3376 | 0 | case CKM_NSS_SSL3_MAC_CONSTANT_TIME: { |
3377 | 0 | sftk_MACConstantTimeCtx *ctx = |
3378 | 0 | sftk_SSLv3MACConstantTime_New(pMechanism, key); |
3379 | 0 | CK_ULONG *intpointer; |
3380 | |
|
3381 | 0 | if (ctx == NULL) { |
3382 | 0 | crv = CKR_ARGUMENTS_BAD; |
3383 | 0 | break; |
3384 | 0 | } |
3385 | 0 | intpointer = PORT_New(CK_ULONG); |
3386 | 0 | if (intpointer == NULL) { |
3387 | 0 | PORT_Free(ctx); |
3388 | 0 | crv = CKR_HOST_MEMORY; |
3389 | 0 | break; |
3390 | 0 | } |
3391 | 0 | *intpointer = ctx->hash->length; |
3392 | |
|
3393 | 0 | context->cipherInfo = intpointer; |
3394 | 0 | context->hashInfo = ctx; |
3395 | 0 | context->currentMech = pMechanism->mechanism; |
3396 | 0 | context->hashUpdate = sftk_SSLv3MACConstantTime_Update; |
3397 | 0 | context->hashdestroy = sftk_MACConstantTime_DestroyContext; |
3398 | 0 | context->end = sftk_MACConstantTime_EndHash; |
3399 | 0 | context->update = sftk_SignCopy; |
3400 | 0 | context->destroy = sftk_Space; |
3401 | 0 | context->maxLen = 64; |
3402 | 0 | context->multi = PR_TRUE; |
3403 | 0 | break; |
3404 | 0 | } |
3405 | | |
3406 | 0 | default: |
3407 | 0 | crv = CKR_MECHANISM_INVALID; |
3408 | 0 | break; |
3409 | 461k | } |
3410 | | |
3411 | 461k | if (crv != CKR_OK) { |
3412 | 0 | if (info) |
3413 | 0 | PORT_Free(info); |
3414 | 0 | if (pinfo) |
3415 | 0 | PORT_ZFree(pinfo, pinfo->size); |
3416 | 0 | sftk_FreeContext(context); |
3417 | 0 | sftk_FreeSession(session); |
3418 | 0 | return crv; |
3419 | 0 | } |
3420 | 461k | sftk_SetContextByType(session, SFTK_SIGN, context); |
3421 | 461k | sftk_FreeSession(session); |
3422 | 461k | return CKR_OK; |
3423 | 461k | } |
3424 | | |
3425 | | /** MAC one block of data by block cipher |
3426 | | */ |
3427 | | static CK_RV |
3428 | | sftk_MACBlock(SFTKSessionContext *ctx, void *blk) |
3429 | 0 | { |
3430 | 0 | unsigned int outlen; |
3431 | 0 | return (SECSuccess == (ctx->update)(ctx->cipherInfo, ctx->macBuf, &outlen, |
3432 | 0 | SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize)) |
3433 | 0 | ? CKR_OK |
3434 | 0 | : sftk_MapCryptError(PORT_GetError()); |
3435 | 0 | } |
3436 | | |
3437 | | /** MAC last (incomplete) block of data by block cipher |
3438 | | * |
3439 | | * Call once, then terminate MACing operation. |
3440 | | */ |
3441 | | static CK_RV |
3442 | | sftk_MACFinal(SFTKSessionContext *ctx) |
3443 | 0 | { |
3444 | 0 | unsigned int padLen = ctx->padDataLength; |
3445 | | /* pad and proceed the residual */ |
3446 | 0 | if (ctx->isXCBC) { |
3447 | 0 | CK_RV crv = sftk_xcbc_mac_pad(ctx->padBuf, padLen, ctx->blockSize, |
3448 | 0 | ctx->k2, ctx->k3); |
3449 | 0 | if (crv != CKR_OK) |
3450 | 0 | return crv; |
3451 | 0 | return sftk_MACBlock(ctx, ctx->padBuf); |
3452 | 0 | } |
3453 | 0 | if (padLen) { |
3454 | | /* shd clr ctx->padLen to make sftk_MACFinal idempotent */ |
3455 | 0 | PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen); |
3456 | 0 | return sftk_MACBlock(ctx, ctx->padBuf); |
3457 | 0 | } else |
3458 | 0 | return CKR_OK; |
3459 | 0 | } |
3460 | | |
3461 | | /** The common implementation for {Sign,Verify}Update. (S/V only vary in their |
3462 | | * setup and final operations). |
3463 | | * |
3464 | | * A call which results in an error terminates the operation [PKCS#11,v2.11] |
3465 | | */ |
3466 | | static CK_RV |
3467 | | sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
3468 | | CK_ULONG ulPartLen, SFTKContextType type) |
3469 | 288k | { |
3470 | 288k | SFTKSession *session; |
3471 | 288k | SFTKSessionContext *context; |
3472 | 288k | CK_RV crv; |
3473 | | |
3474 | | /* make sure we're legal */ |
3475 | 288k | crv = sftk_GetContext(hSession, &context, type, PR_TRUE, &session); |
3476 | 288k | if (crv != CKR_OK) |
3477 | 0 | return crv; |
3478 | | |
3479 | 288k | if (context->hashInfo) { |
3480 | 288k | #if (ULONG_MAX > UINT_MAX) |
3481 | 288k | while (ulPartLen > UINT_MAX) { |
3482 | 0 | (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX); |
3483 | 0 | pPart += UINT_MAX; |
3484 | 0 | ulPartLen -= UINT_MAX; |
3485 | 0 | } |
3486 | 288k | #endif |
3487 | 288k | (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen); |
3488 | 288k | } else { |
3489 | | /* must be block cipher MACing */ |
3490 | |
|
3491 | 0 | unsigned int blkSize = context->blockSize; |
3492 | 0 | unsigned char *residual = /* free room in context->padBuf */ |
3493 | 0 | context->padBuf + context->padDataLength; |
3494 | 0 | unsigned int minInput = /* min input for MACing at least one block */ |
3495 | 0 | blkSize - context->padDataLength; |
3496 | | |
3497 | | /* not enough data even for one block */ |
3498 | 0 | if (ulPartLen <= minInput) { |
3499 | 0 | PORT_Memcpy(residual, pPart, ulPartLen); |
3500 | 0 | context->padDataLength += ulPartLen; |
3501 | 0 | goto cleanup; |
3502 | 0 | } |
3503 | | /* MACing residual */ |
3504 | 0 | if (context->padDataLength) { |
3505 | 0 | PORT_Memcpy(residual, pPart, minInput); |
3506 | 0 | ulPartLen -= minInput; |
3507 | 0 | pPart += minInput; |
3508 | 0 | if (CKR_OK != (crv = sftk_MACBlock(context, context->padBuf))) |
3509 | 0 | goto terminate; |
3510 | 0 | } |
3511 | | /* MACing full blocks */ |
3512 | 0 | while (ulPartLen > blkSize) { |
3513 | 0 | if (CKR_OK != (crv = sftk_MACBlock(context, pPart))) |
3514 | 0 | goto terminate; |
3515 | 0 | ulPartLen -= blkSize; |
3516 | 0 | pPart += blkSize; |
3517 | 0 | } |
3518 | | /* save the residual */ |
3519 | 0 | if ((context->padDataLength = ulPartLen)) |
3520 | 0 | PORT_Memcpy(context->padBuf, pPart, ulPartLen); |
3521 | 0 | } /* blk cipher MACing */ |
3522 | | |
3523 | 288k | goto cleanup; |
3524 | | |
3525 | 288k | terminate: |
3526 | 0 | sftk_TerminateOp(session, type, context); |
3527 | 288k | cleanup: |
3528 | 288k | sftk_FreeSession(session); |
3529 | 288k | return crv; |
3530 | 0 | } |
3531 | | |
3532 | | /* NSC_SignUpdate continues a multiple-part signature operation, |
3533 | | * where the signature is (will be) an appendix to the data, |
3534 | | * and plaintext cannot be recovered from the signature |
3535 | | * |
3536 | | * A call which results in an error terminates the operation [PKCS#11,v2.11] |
3537 | | */ |
3538 | | CK_RV |
3539 | | NSC_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
3540 | | CK_ULONG ulPartLen) |
3541 | 288k | { |
3542 | 288k | CHECK_FORK(); |
3543 | 288k | return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN); |
3544 | 288k | } |
3545 | | |
3546 | | struct SFTK_SESSION_FLAGS { |
3547 | | CK_FLAGS flag; |
3548 | | SFTKContextType type; |
3549 | | }; |
3550 | | |
3551 | | const static struct SFTK_SESSION_FLAGS sftk_session_flags[] = { |
3552 | | { CKF_ENCRYPT, SFTK_ENCRYPT }, |
3553 | | { CKF_DECRYPT, SFTK_DECRYPT }, |
3554 | | { CKF_DIGEST, SFTK_HASH }, |
3555 | | { CKF_SIGN, SFTK_SIGN }, |
3556 | | { CKF_SIGN_RECOVER, SFTK_SIGN_RECOVER }, |
3557 | | { CKF_VERIFY, SFTK_VERIFY }, |
3558 | | { CKF_VERIFY_RECOVER, SFTK_VERIFY_RECOVER }, |
3559 | | { CKF_MESSAGE_ENCRYPT, SFTK_MESSAGE_ENCRYPT }, |
3560 | | { CKF_MESSAGE_DECRYPT, SFTK_MESSAGE_DECRYPT }, |
3561 | | { CKF_MESSAGE_SIGN, SFTK_MESSAGE_SIGN }, |
3562 | | { CKF_MESSAGE_VERIFY, SFTK_MESSAGE_VERIFY }, |
3563 | | }; |
3564 | | const static int sftk_flag_count = PR_ARRAY_SIZE(sftk_session_flags); |
3565 | | |
3566 | | /* |
3567 | | * Cancel one or more operations running on the existing session. |
3568 | | */ |
3569 | | CK_RV |
3570 | | NSC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags) |
3571 | 0 | { |
3572 | 0 | SFTKSession *session; |
3573 | 0 | SFTKSessionContext *context; |
3574 | 0 | CK_RV gcrv = CKR_OK; |
3575 | 0 | CK_RV crv; |
3576 | 0 | int i; |
3577 | |
|
3578 | 0 | for (i = 0; i < sftk_flag_count; i++) { |
3579 | 0 | if (flags & sftk_session_flags[i].flag) { |
3580 | 0 | flags &= ~sftk_session_flags[i].flag; |
3581 | 0 | crv = sftk_GetContext(hSession, &context, sftk_session_flags[i].type, PR_TRUE, &session); |
3582 | 0 | if (crv != CKR_OK) { |
3583 | 0 | gcrv = CKR_OPERATION_CANCEL_FAILED; |
3584 | 0 | continue; |
3585 | 0 | } |
3586 | 0 | sftk_TerminateOp(session, sftk_session_flags[i].type, context); |
3587 | 0 | } |
3588 | 0 | } |
3589 | 0 | if (flags & CKF_FIND_OBJECTS) { |
3590 | 0 | flags &= ~CKF_FIND_OBJECTS; |
3591 | 0 | crv = NSC_FindObjectsFinal(hSession); |
3592 | 0 | if (crv != CKR_OK) { |
3593 | 0 | gcrv = CKR_OPERATION_CANCEL_FAILED; |
3594 | 0 | } |
3595 | 0 | } |
3596 | 0 | if (flags) { |
3597 | 0 | gcrv = CKR_OPERATION_CANCEL_FAILED; |
3598 | 0 | } |
3599 | 0 | return gcrv; |
3600 | 0 | } |
3601 | | |
3602 | | /* NSC_SignFinal finishes a multiple-part signature operation, |
3603 | | * returning the signature. */ |
3604 | | CK_RV |
3605 | | NSC_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, |
3606 | | CK_ULONG_PTR pulSignatureLen) |
3607 | 294k | { |
3608 | 294k | SFTKSession *session; |
3609 | 294k | SFTKSessionContext *context; |
3610 | 294k | unsigned int outlen; |
3611 | 294k | unsigned int maxoutlen = *pulSignatureLen; |
3612 | 294k | CK_RV crv; |
3613 | | |
3614 | 294k | CHECK_FORK(); |
3615 | | |
3616 | | /* make sure we're legal */ |
3617 | 294k | crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_TRUE, &session); |
3618 | 294k | if (crv != CKR_OK) |
3619 | 39.2k | return crv; |
3620 | | |
3621 | 255k | if (context->hashInfo) { |
3622 | 255k | unsigned int digestLen; |
3623 | 255k | unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; |
3624 | | |
3625 | 255k | if (!pSignature) { |
3626 | 0 | outlen = context->maxLen; |
3627 | 0 | goto finish; |
3628 | 0 | } |
3629 | 255k | (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); |
3630 | 255k | if (SECSuccess != (context->update)(context->cipherInfo, pSignature, |
3631 | 255k | &outlen, maxoutlen, tmpbuf, digestLen)) |
3632 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
3633 | | /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate. |
3634 | | * Keeping "too small" CK_RV intact is a standard violation, but allows |
3635 | | * application read EXACT signature length */ |
3636 | 255k | PORT_Memset(tmpbuf, 0, sizeof tmpbuf); |
3637 | 255k | } else { |
3638 | | /* must be block cipher MACing */ |
3639 | 0 | outlen = context->macSize; |
3640 | | /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/ |
3641 | 0 | if (!pSignature || maxoutlen < outlen) { |
3642 | 0 | if (pSignature) |
3643 | 0 | crv = CKR_BUFFER_TOO_SMALL; |
3644 | 0 | goto finish; |
3645 | 0 | } |
3646 | 0 | if (CKR_OK == (crv = sftk_MACFinal(context))) |
3647 | 0 | PORT_Memcpy(pSignature, context->macBuf, outlen); |
3648 | 0 | } |
3649 | | |
3650 | 255k | sftk_TerminateOp(session, SFTK_SIGN, context); |
3651 | 255k | finish: |
3652 | 255k | *pulSignatureLen = outlen; |
3653 | 255k | sftk_FreeSession(session); |
3654 | 255k | return crv; |
3655 | 255k | } |
3656 | | |
3657 | | /* NSC_Sign signs (encrypts with private key) data in a single part, |
3658 | | * where the signature is (will be) an appendix to the data, |
3659 | | * and plaintext cannot be recovered from the signature */ |
3660 | | CK_RV |
3661 | | NSC_Sign(CK_SESSION_HANDLE hSession, |
3662 | | CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, |
3663 | | CK_ULONG_PTR pulSignatureLen) |
3664 | 48.4k | { |
3665 | 48.4k | SFTKSession *session; |
3666 | 48.4k | SFTKSessionContext *context; |
3667 | 48.4k | CK_RV crv; |
3668 | | |
3669 | 48.4k | CHECK_FORK(); |
3670 | | |
3671 | | /* make sure we're legal */ |
3672 | 48.4k | crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_FALSE, &session); |
3673 | 48.4k | if (crv != CKR_OK) |
3674 | 0 | return crv; |
3675 | | |
3676 | 48.4k | if (!pSignature) { |
3677 | | /* see also how C_SignUpdate implements this */ |
3678 | 0 | *pulSignatureLen = (!context->multi || context->hashInfo) |
3679 | 0 | ? context->maxLen |
3680 | 0 | : context->macSize; /* must be block cipher MACing */ |
3681 | 0 | goto finish; |
3682 | 0 | } |
3683 | | |
3684 | | /* multi part Signing are completely implemented by SignUpdate and |
3685 | | * sign Final */ |
3686 | 48.4k | if (context->multi) { |
3687 | | /* SignFinal can't follow failed SignUpdate */ |
3688 | 20.5k | if (CKR_OK == (crv = NSC_SignUpdate(hSession, pData, ulDataLen))) |
3689 | 20.5k | crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen); |
3690 | 27.9k | } else { |
3691 | | /* single-part PKC signature (e.g. CKM_ECDSA) */ |
3692 | 27.9k | unsigned int outlen; |
3693 | 27.9k | unsigned int maxoutlen = *pulSignatureLen; |
3694 | 27.9k | if (SECSuccess != (*context->update)(context->cipherInfo, pSignature, |
3695 | 27.9k | &outlen, maxoutlen, pData, ulDataLen)) |
3696 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
3697 | 27.9k | *pulSignatureLen = (CK_ULONG)outlen; |
3698 | | /* "too small" here is certainly continuable */ |
3699 | 27.9k | if (crv != CKR_BUFFER_TOO_SMALL) |
3700 | 27.9k | sftk_TerminateOp(session, SFTK_SIGN, context); |
3701 | 27.9k | } /* single-part */ |
3702 | | |
3703 | 48.4k | finish: |
3704 | 48.4k | sftk_FreeSession(session); |
3705 | 48.4k | return crv; |
3706 | 48.4k | } |
3707 | | |
3708 | | /* |
3709 | | ************** Crypto Functions: Sign Recover ************************ |
3710 | | */ |
3711 | | /* NSC_SignRecoverInit initializes a signature operation, |
3712 | | * where the (digest) data can be recovered from the signature. |
3713 | | * E.g. encryption with the user's private key */ |
3714 | | CK_RV |
3715 | | NSC_SignRecoverInit(CK_SESSION_HANDLE hSession, |
3716 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
3717 | 0 | { |
3718 | 0 | CHECK_FORK(); |
3719 | |
|
3720 | 0 | switch (pMechanism->mechanism) { |
3721 | 0 | case CKM_RSA_PKCS: |
3722 | 0 | case CKM_RSA_X_509: |
3723 | 0 | return NSC_SignInit(hSession, pMechanism, hKey); |
3724 | 0 | default: |
3725 | 0 | break; |
3726 | 0 | } |
3727 | 0 | return CKR_MECHANISM_INVALID; |
3728 | 0 | } |
3729 | | |
3730 | | /* NSC_SignRecover signs data in a single operation |
3731 | | * where the (digest) data can be recovered from the signature. |
3732 | | * E.g. encryption with the user's private key */ |
3733 | | CK_RV |
3734 | | NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
3735 | | CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) |
3736 | 0 | { |
3737 | 0 | CHECK_FORK(); |
3738 | |
|
3739 | 0 | return NSC_Sign(hSession, pData, ulDataLen, pSignature, pulSignatureLen); |
3740 | 0 | } |
3741 | | |
3742 | | /* |
3743 | | ************** Crypto Functions: verify ************************ |
3744 | | */ |
3745 | | |
3746 | | /* Handle RSA Signature formatting */ |
3747 | | static SECStatus |
3748 | | sftk_hashCheckSign(void *ctx, const unsigned char *sig, |
3749 | | unsigned int sigLen, const unsigned char *digest, |
3750 | | unsigned int digestLen) |
3751 | 0 | { |
3752 | 0 | SFTKHashVerifyInfo *info = ctx; |
3753 | 0 | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
3754 | 0 | if (info->key->keyType != NSSLOWKEYRSAKey) { |
3755 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3756 | 0 | return SECFailure; |
3757 | 0 | } |
3758 | | |
3759 | 0 | return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, digest, |
3760 | 0 | digestLen); |
3761 | 0 | } |
3762 | | |
3763 | | SECStatus |
3764 | | RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key, |
3765 | | const unsigned char *sig, unsigned int sigLen, |
3766 | | const unsigned char *digestData, unsigned int digestLen) |
3767 | 0 | { |
3768 | 0 | unsigned char *pkcs1DigestInfoData; |
3769 | 0 | SECItem pkcs1DigestInfo; |
3770 | 0 | SECItem digest; |
3771 | 0 | unsigned int bufferSize; |
3772 | 0 | SECStatus rv; |
3773 | | |
3774 | | /* pkcs1DigestInfo.data must be less than key->u.rsa.modulus.len */ |
3775 | 0 | bufferSize = key->u.rsa.modulus.len; |
3776 | 0 | pkcs1DigestInfoData = PORT_ZAlloc(bufferSize); |
3777 | 0 | if (!pkcs1DigestInfoData) { |
3778 | 0 | PORT_SetError(SEC_ERROR_NO_MEMORY); |
3779 | 0 | return SECFailure; |
3780 | 0 | } |
3781 | | |
3782 | 0 | pkcs1DigestInfo.data = pkcs1DigestInfoData; |
3783 | 0 | pkcs1DigestInfo.len = bufferSize; |
3784 | | |
3785 | | /* decrypt the block */ |
3786 | 0 | rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data, |
3787 | 0 | &pkcs1DigestInfo.len, pkcs1DigestInfo.len, |
3788 | 0 | sig, sigLen); |
3789 | 0 | if (rv != SECSuccess) { |
3790 | 0 | PORT_SetError(SEC_ERROR_BAD_SIGNATURE); |
3791 | 0 | } else { |
3792 | 0 | digest.data = (PRUint8 *)digestData; |
3793 | 0 | digest.len = digestLen; |
3794 | 0 | rv = _SGN_VerifyPKCS1DigestInfo( |
3795 | 0 | digestOid, &digest, &pkcs1DigestInfo, |
3796 | 0 | PR_FALSE /*XXX: unsafeAllowMissingParameters*/); |
3797 | 0 | } |
3798 | |
|
3799 | 0 | PORT_ZFree(pkcs1DigestInfoData, bufferSize); |
3800 | 0 | return rv; |
3801 | 0 | } |
3802 | | |
3803 | | static SECStatus |
3804 | | sftk_RSACheckSign(void *ctx, const unsigned char *sig, |
3805 | | unsigned int sigLen, const unsigned char *digest, |
3806 | | unsigned int digestLen) |
3807 | 1.24k | { |
3808 | 1.24k | NSSLOWKEYPublicKey *key = ctx; |
3809 | 1.24k | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
3810 | 1.24k | if (key->keyType != NSSLOWKEYRSAKey) { |
3811 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3812 | 0 | return SECFailure; |
3813 | 0 | } |
3814 | | |
3815 | 1.24k | return RSA_CheckSign(&key->u.rsa, sig, sigLen, digest, digestLen); |
3816 | 1.24k | } |
3817 | | |
3818 | | static SECStatus |
3819 | | sftk_RSACheckSignRaw(void *ctx, const unsigned char *sig, |
3820 | | unsigned int sigLen, const unsigned char *digest, |
3821 | | unsigned int digestLen) |
3822 | 0 | { |
3823 | 0 | NSSLOWKEYPublicKey *key = ctx; |
3824 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
3825 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
3826 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3827 | 0 | return SECFailure; |
3828 | 0 | } |
3829 | | |
3830 | 0 | return RSA_CheckSignRaw(&key->u.rsa, sig, sigLen, digest, digestLen); |
3831 | 0 | } |
3832 | | |
3833 | | static SECStatus |
3834 | | sftk_RSACheckSignPSS(void *ctx, const unsigned char *sig, |
3835 | | unsigned int sigLen, const unsigned char *digest, |
3836 | | unsigned int digestLen) |
3837 | 2.59k | { |
3838 | 2.59k | SFTKPSSVerifyInfo *info = ctx; |
3839 | 2.59k | HASH_HashType hashAlg; |
3840 | 2.59k | HASH_HashType maskHashAlg; |
3841 | 2.59k | CK_RSA_PKCS_PSS_PARAMS *params = &info->params; |
3842 | | |
3843 | 2.59k | PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey); |
3844 | 2.59k | if (info->key->keyType != NSSLOWKEYRSAKey) { |
3845 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
3846 | 0 | return SECFailure; |
3847 | 0 | } |
3848 | | |
3849 | 2.59k | hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg); |
3850 | 2.59k | maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf); |
3851 | | |
3852 | 2.59k | return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, |
3853 | 2.59k | params->sLen, sig, sigLen, digest, digestLen); |
3854 | 2.59k | } |
3855 | | |
3856 | | /* NSC_VerifyInit initializes a verification operation, |
3857 | | * where the signature is an appendix to the data, |
3858 | | * and plaintext cannot be recovered from the signature (e.g. DSA) */ |
3859 | | CK_RV |
3860 | | NSC_VerifyInit(CK_SESSION_HANDLE hSession, |
3861 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
3862 | 7.56k | { |
3863 | 7.56k | SFTKSession *session; |
3864 | 7.56k | SFTKObject *key; |
3865 | 7.56k | SFTKSessionContext *context; |
3866 | 7.56k | CK_KEY_TYPE key_type; |
3867 | 7.56k | CK_RV crv = CKR_OK; |
3868 | 7.56k | NSSLOWKEYPublicKey *pubKey; |
3869 | 7.56k | SFTKHashVerifyInfo *info = NULL; |
3870 | 7.56k | SFTKPSSVerifyInfo *pinfo = NULL; |
3871 | | |
3872 | 7.56k | CHECK_FORK(); |
3873 | | |
3874 | | /* Block Cipher MACing Algorithms use a different Context init method..*/ |
3875 | 7.56k | crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY); |
3876 | 7.56k | if (crv != CKR_FUNCTION_NOT_SUPPORTED) |
3877 | 0 | return crv; |
3878 | | |
3879 | 7.56k | session = sftk_SessionFromHandle(hSession); |
3880 | 7.56k | if (session == NULL) |
3881 | 0 | return CKR_SESSION_HANDLE_INVALID; |
3882 | 7.56k | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY, &key, |
3883 | 7.56k | hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY); |
3884 | 7.56k | if (crv != CKR_OK) { |
3885 | 0 | sftk_FreeSession(session); |
3886 | 0 | return crv; |
3887 | 0 | } |
3888 | | |
3889 | 7.56k | context->multi = PR_FALSE; |
3890 | | |
3891 | 7.56k | #define INIT_RSA_VFY_MECH(mmm) \ |
3892 | 7.56k | case CKM_##mmm##_RSA_PKCS: \ |
3893 | 0 | context->multi = PR_TRUE; \ |
3894 | 0 | crv = sftk_doSub##mmm(context); \ |
3895 | 0 | if (crv != CKR_OK) \ |
3896 | 0 | break; \ |
3897 | 0 | context->verify = sftk_hashCheckSign; \ |
3898 | 0 | info = PORT_New(SFTKHashVerifyInfo); \ |
3899 | 0 | if (info == NULL) { \ |
3900 | 0 | crv = CKR_HOST_MEMORY; \ |
3901 | 0 | break; \ |
3902 | 0 | } \ |
3903 | 0 | info->hashOid = SEC_OID_##mmm; \ |
3904 | 0 | goto finish_rsa; |
3905 | | |
3906 | 7.56k | switch (pMechanism->mechanism) { |
3907 | 0 | INIT_RSA_VFY_MECH(MD5) |
3908 | 0 | INIT_RSA_VFY_MECH(MD2) |
3909 | 0 | INIT_RSA_VFY_MECH(SHA1) |
3910 | 0 | INIT_RSA_VFY_MECH(SHA224) |
3911 | 0 | INIT_RSA_VFY_MECH(SHA256) |
3912 | 0 | INIT_RSA_VFY_MECH(SHA384) |
3913 | 0 | INIT_RSA_VFY_MECH(SHA512) |
3914 | | |
3915 | 1.24k | case CKM_RSA_PKCS: |
3916 | 1.24k | context->verify = sftk_RSACheckSign; |
3917 | 1.24k | goto finish_rsa; |
3918 | 0 | case CKM_RSA_X_509: |
3919 | 0 | context->verify = sftk_RSACheckSignRaw; |
3920 | 1.24k | finish_rsa: |
3921 | 1.24k | if (key_type != CKK_RSA) { |
3922 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3923 | 0 | break; |
3924 | 0 | } |
3925 | 1.24k | context->rsa = PR_TRUE; |
3926 | 1.24k | pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); |
3927 | 1.24k | if (pubKey == NULL) { |
3928 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3929 | 0 | break; |
3930 | 0 | } |
3931 | 1.24k | if (info) { |
3932 | 0 | info->key = pubKey; |
3933 | 0 | context->cipherInfo = info; |
3934 | 0 | context->destroy = sftk_Space; |
3935 | 1.24k | } else { |
3936 | 1.24k | context->cipherInfo = pubKey; |
3937 | 1.24k | context->destroy = sftk_Null; |
3938 | 1.24k | } |
3939 | 1.24k | break; |
3940 | | |
3941 | 0 | INIT_RSA_PSS_SIG_MECH(SHA1) |
3942 | 0 | INIT_RSA_PSS_SIG_MECH(SHA224) |
3943 | 0 | INIT_RSA_PSS_SIG_MECH(SHA256) |
3944 | 0 | INIT_RSA_PSS_SIG_MECH(SHA384) |
3945 | 0 | INIT_RSA_PSS_SIG_MECH(SHA512) |
3946 | 2.59k | case CKM_RSA_PKCS_PSS: |
3947 | 2.59k | finish_rsa_pss: |
3948 | 2.59k | if (key_type != CKK_RSA) { |
3949 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3950 | 0 | break; |
3951 | 0 | } |
3952 | 2.59k | context->rsa = PR_TRUE; |
3953 | 2.59k | if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || |
3954 | 2.59k | !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) { |
3955 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
3956 | 0 | break; |
3957 | 0 | } |
3958 | 2.59k | pinfo = PORT_New(SFTKPSSVerifyInfo); |
3959 | 2.59k | if (pinfo == NULL) { |
3960 | 0 | crv = CKR_HOST_MEMORY; |
3961 | 0 | break; |
3962 | 0 | } |
3963 | 2.59k | pinfo->size = sizeof(SFTKPSSVerifyInfo); |
3964 | 2.59k | pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter; |
3965 | 2.59k | pinfo->key = sftk_GetPubKey(key, CKK_RSA, &crv); |
3966 | 2.59k | if (pinfo->key == NULL) { |
3967 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3968 | 0 | break; |
3969 | 0 | } |
3970 | 2.59k | context->cipherInfo = pinfo; |
3971 | 2.59k | context->destroy = sftk_ZSpace; |
3972 | 2.59k | context->verify = sftk_RSACheckSignPSS; |
3973 | 2.59k | break; |
3974 | | |
3975 | 0 | #ifndef NSS_DISABLE_DSA |
3976 | 0 | INIT_DSA_SIG_MECH(SHA1) |
3977 | 0 | INIT_DSA_SIG_MECH(SHA224) |
3978 | 0 | INIT_DSA_SIG_MECH(SHA256) |
3979 | 0 | INIT_DSA_SIG_MECH(SHA384) |
3980 | 0 | INIT_DSA_SIG_MECH(SHA512) |
3981 | 3.33k | case CKM_DSA: |
3982 | 3.33k | finish_dsa: |
3983 | 3.33k | if (key_type != CKK_DSA) { |
3984 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
3985 | 0 | break; |
3986 | 0 | } |
3987 | 3.33k | pubKey = sftk_GetPubKey(key, CKK_DSA, &crv); |
3988 | 3.33k | if (pubKey == NULL) { |
3989 | 0 | break; |
3990 | 0 | } |
3991 | 3.33k | context->cipherInfo = pubKey; |
3992 | 3.33k | context->verify = nsc_DSA_Verify_Stub; |
3993 | 3.33k | context->destroy = sftk_Null; |
3994 | 3.33k | break; |
3995 | 0 | #endif |
3996 | 0 | case CKM_ML_DSA: { |
3997 | | /* set our defaults */ |
3998 | 0 | SECItem signCtx = { siBuffer, NULL, 0 }; |
3999 | 0 | MLDSAContext *ctptr = NULL; |
4000 | 0 | SECStatus rv; |
4001 | | |
4002 | | /* make sure we have the right key type */ |
4003 | 0 | if (key_type != CKK_ML_DSA) { |
4004 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4005 | 0 | break; |
4006 | 0 | } |
4007 | | /* fill in our parameters from the mechanism parameters if |
4008 | | * supplied */ |
4009 | 0 | if (pMechanism->ulParameterLen != 0) { |
4010 | 0 | CK_SIGN_ADDITIONAL_CONTEXT *param; |
4011 | 0 | if (pMechanism->ulParameterLen != |
4012 | 0 | sizeof(CK_SIGN_ADDITIONAL_CONTEXT)) { |
4013 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
4014 | 0 | break; |
4015 | 0 | } |
4016 | 0 | param = (CK_SIGN_ADDITIONAL_CONTEXT *)pMechanism->pParameter; |
4017 | 0 | signCtx.data = param->pContext; |
4018 | 0 | signCtx.len = param->ulContextLen; |
4019 | 0 | } |
4020 | | /* fetch the key */ |
4021 | 0 | pubKey = sftk_GetPubKey(key, key_type, &crv); |
4022 | 0 | if (pubKey == NULL) { |
4023 | | /* crv already set */ |
4024 | 0 | break; |
4025 | 0 | } |
4026 | | /* now initialize it the signature */ |
4027 | 0 | rv = MLDSA_VerifyInit(&(pubKey->u.mldsa), &signCtx, &ctptr); |
4028 | 0 | if (rv != SECSuccess) { |
4029 | 0 | crv = sftk_MapVerifyError(PORT_GetError()); |
4030 | 0 | break; |
4031 | 0 | } |
4032 | | /* set up our cipher info. MLDSA is only a combined hash/sign |
4033 | | * so the hash update is our sign update, the hash end is a null |
4034 | | * function returning a zero length value, and the final gets our |
4035 | | * signature based on the context. Both the cipher context and the |
4036 | | * hash Info is the same. The MLDSA_VerifyFinal frees the context, |
4037 | | * so we don't have to */ |
4038 | 0 | context->multi = PR_TRUE; |
4039 | 0 | context->cipherInfo = ctptr; |
4040 | 0 | context->hashInfo = ctptr; |
4041 | 0 | context->hashUpdate = sftk_MLDSAVerifyUpdate; |
4042 | 0 | context->end = sftk_NullHashEnd; |
4043 | 0 | context->hashdestroy = sftk_Null; |
4044 | 0 | context->destroy = sftk_Null; |
4045 | 0 | context->verify = sftk_MLDSAVerifyFinal; |
4046 | 0 | context->maxLen = sftk_MLDSAGetSigLen(pubKey->u.mldsa.paramSet); |
4047 | 0 | break; |
4048 | 0 | } |
4049 | | |
4050 | 0 | INIT_ECDSA_SIG_MECH(SHA1) |
4051 | 0 | INIT_ECDSA_SIG_MECH(SHA224) |
4052 | 0 | INIT_ECDSA_SIG_MECH(SHA256) |
4053 | 0 | INIT_ECDSA_SIG_MECH(SHA384) |
4054 | 0 | INIT_ECDSA_SIG_MECH(SHA512) |
4055 | 389 | case CKM_ECDSA: |
4056 | 389 | finish_ecdsa: |
4057 | 389 | if (key_type != CKK_EC) { |
4058 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4059 | 0 | break; |
4060 | 0 | } |
4061 | 389 | pubKey = sftk_GetPubKey(key, CKK_EC, &crv); |
4062 | 389 | if (pubKey == NULL) { |
4063 | 0 | crv = CKR_HOST_MEMORY; |
4064 | 0 | break; |
4065 | 0 | } |
4066 | 389 | context->cipherInfo = pubKey; |
4067 | 389 | context->verify = nsc_ECDSAVerifyStub; |
4068 | 389 | context->destroy = sftk_Null; |
4069 | 389 | break; |
4070 | | |
4071 | 0 | INIT_HMAC_MECH(MD2) |
4072 | 0 | INIT_HMAC_MECH(MD5) |
4073 | 0 | INIT_HMAC_MECH(SHA1) |
4074 | 0 | INIT_HMAC_MECH(SHA224) |
4075 | 0 | INIT_HMAC_MECH(SHA256) |
4076 | 0 | INIT_HMAC_MECH(SHA384) |
4077 | 0 | INIT_HMAC_MECH(SHA512) |
4078 | 0 | INIT_HMAC_MECH(SHA3_224) |
4079 | 0 | INIT_HMAC_MECH(SHA3_256) |
4080 | 0 | INIT_HMAC_MECH(SHA3_384) |
4081 | 0 | INIT_HMAC_MECH(SHA3_512) |
4082 | | |
4083 | 0 | case CKM_EDDSA: |
4084 | 0 | if (key_type != CKK_EC_EDWARDS) { |
4085 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4086 | 0 | break; |
4087 | 0 | } |
4088 | 0 | pubKey = sftk_GetPubKey(key, CKK_EC_EDWARDS, &crv); |
4089 | 0 | if (pubKey == NULL) { |
4090 | 0 | crv = CKR_HOST_MEMORY; |
4091 | 0 | break; |
4092 | 0 | } |
4093 | | |
4094 | 0 | if (pMechanism->pParameter) { |
4095 | 0 | crv = CKR_FUNCTION_NOT_SUPPORTED; |
4096 | 0 | break; |
4097 | 0 | } |
4098 | | |
4099 | 0 | context->cipherInfo = pubKey; |
4100 | 0 | context->verify = nsc_EDDSAVerifyStub; |
4101 | 0 | context->destroy = sftk_Null; |
4102 | 0 | break; |
4103 | | |
4104 | 0 | case CKM_SSL3_MD5_MAC: |
4105 | 0 | PORT_Assert(pMechanism->pParameter); |
4106 | 0 | if (!pMechanism->pParameter) { |
4107 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
4108 | 0 | break; |
4109 | 0 | } |
4110 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key, |
4111 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
4112 | 0 | break; |
4113 | 0 | case CKM_SSL3_SHA1_MAC: |
4114 | 0 | PORT_Assert(pMechanism->pParameter); |
4115 | 0 | if (!pMechanism->pParameter) { |
4116 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
4117 | 0 | break; |
4118 | 0 | } |
4119 | 0 | crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key, |
4120 | 0 | *(CK_ULONG *)pMechanism->pParameter); |
4121 | 0 | break; |
4122 | 0 | case CKM_TLS_PRF_GENERAL: |
4123 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); |
4124 | 0 | break; |
4125 | 0 | case CKM_NSS_TLS_PRF_GENERAL_SHA256: |
4126 | 0 | crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); |
4127 | 0 | break; |
4128 | | |
4129 | 0 | default: |
4130 | 0 | crv = CKR_MECHANISM_INVALID; |
4131 | 0 | break; |
4132 | 7.56k | } |
4133 | | |
4134 | 7.56k | if (crv != CKR_OK) { |
4135 | 0 | if (info) |
4136 | 0 | PORT_Free(info); |
4137 | 0 | if (pinfo) |
4138 | 0 | PORT_ZFree(pinfo, pinfo->size); |
4139 | 0 | sftk_FreeContext(context); |
4140 | 0 | sftk_FreeSession(session); |
4141 | 0 | return crv; |
4142 | 0 | } |
4143 | 7.56k | sftk_SetContextByType(session, SFTK_VERIFY, context); |
4144 | 7.56k | sftk_FreeSession(session); |
4145 | 7.56k | return CKR_OK; |
4146 | 7.56k | } |
4147 | | |
4148 | | /* NSC_Verify verifies a signature in a single-part operation, |
4149 | | * where the signature is an appendix to the data, |
4150 | | * and plaintext cannot be recovered from the signature */ |
4151 | | CK_RV |
4152 | | NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
4153 | | CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) |
4154 | 7.56k | { |
4155 | 7.56k | SFTKSession *session; |
4156 | 7.56k | SFTKSessionContext *context; |
4157 | 7.56k | CK_RV crv; |
4158 | | |
4159 | 7.56k | CHECK_FORK(); |
4160 | | |
4161 | | /* make sure we're legal */ |
4162 | 7.56k | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session); |
4163 | 7.56k | if (crv != CKR_OK) |
4164 | 0 | return crv; |
4165 | | |
4166 | | /* multi part Verifying are completely implemented by VerifyUpdate and |
4167 | | * VerifyFinal */ |
4168 | 7.56k | if (context->multi) { |
4169 | | /* VerifyFinal can't follow failed VerifyUpdate */ |
4170 | 0 | if (CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen))) |
4171 | 0 | crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen); |
4172 | 7.56k | } else { |
4173 | 7.56k | if (SECSuccess != (*context->verify)(context->cipherInfo, pSignature, |
4174 | 7.56k | ulSignatureLen, pData, ulDataLen)) |
4175 | 7.49k | crv = sftk_MapCryptError(PORT_GetError()); |
4176 | | |
4177 | 7.56k | sftk_TerminateOp(session, SFTK_VERIFY, context); |
4178 | 7.56k | } |
4179 | 7.56k | sftk_FreeSession(session); |
4180 | 7.56k | return crv; |
4181 | 7.56k | } |
4182 | | |
4183 | | /* NSC_VerifyUpdate continues a multiple-part verification operation, |
4184 | | * where the signature is an appendix to the data, |
4185 | | * and plaintext cannot be recovered from the signature |
4186 | | * |
4187 | | * A call which results in an error terminates the operation [PKCS#11,v2.11] |
4188 | | */ |
4189 | | CK_RV |
4190 | | NSC_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
4191 | | CK_ULONG ulPartLen) |
4192 | 0 | { |
4193 | 0 | CHECK_FORK(); |
4194 | 0 | return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY); |
4195 | 0 | } |
4196 | | |
4197 | | /* NSC_VerifyFinal finishes a multiple-part verification operation, |
4198 | | * checking the signature. */ |
4199 | | CK_RV |
4200 | | NSC_VerifyFinal(CK_SESSION_HANDLE hSession, |
4201 | | CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) |
4202 | 0 | { |
4203 | 0 | SFTKSession *session; |
4204 | 0 | SFTKSessionContext *context; |
4205 | 0 | CK_RV crv; |
4206 | |
|
4207 | 0 | CHECK_FORK(); |
4208 | |
|
4209 | 0 | if (!pSignature) |
4210 | 0 | return CKR_ARGUMENTS_BAD; |
4211 | | |
4212 | | /* make sure we're legal */ |
4213 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session); |
4214 | 0 | if (crv != CKR_OK) |
4215 | 0 | return crv; |
4216 | | |
4217 | 0 | if (context->hashInfo) { |
4218 | 0 | unsigned int digestLen; |
4219 | 0 | unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; |
4220 | |
|
4221 | 0 | (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); |
4222 | 0 | if (SECSuccess != (context->verify)(context->cipherInfo, pSignature, |
4223 | 0 | ulSignatureLen, tmpbuf, digestLen)) |
4224 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
4225 | 0 | PORT_Memset(tmpbuf, 0, sizeof tmpbuf); |
4226 | 0 | } else if (ulSignatureLen != context->macSize) { |
4227 | | /* must be block cipher MACing */ |
4228 | 0 | crv = CKR_SIGNATURE_LEN_RANGE; |
4229 | 0 | } else if (CKR_OK == (crv = sftk_MACFinal(context))) { |
4230 | 0 | if (NSS_SecureMemcmp(pSignature, context->macBuf, ulSignatureLen)) |
4231 | 0 | crv = CKR_SIGNATURE_INVALID; |
4232 | 0 | } |
4233 | |
|
4234 | 0 | sftk_TerminateOp(session, SFTK_VERIFY, context); |
4235 | 0 | sftk_FreeSession(session); |
4236 | 0 | return crv; |
4237 | 0 | } |
4238 | | |
4239 | | /* |
4240 | | ************** Crypto Functions: Verify Signature ************************ |
4241 | | * some algorithms need the signature at the beginning of the verification, |
4242 | | * VerifySignature provides such and API. For algorithms that don't need |
4243 | | * the signature first, we stash the signature and just pass it to |
4244 | | * NSC_VerifyXXX. |
4245 | | */ |
4246 | | CK_RV |
4247 | | NSC_VerifySignatureInit(CK_SESSION_HANDLE hSession, |
4248 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, |
4249 | | CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) |
4250 | 7.56k | { |
4251 | 7.56k | SFTKSession *session; |
4252 | 7.56k | SFTKSessionContext *context; |
4253 | 7.56k | CK_RV crv; |
4254 | 7.56k | SECItem tmpItem; |
4255 | | |
4256 | 7.56k | crv = NSC_VerifyInit(hSession, pMechanism, hKey); |
4257 | 7.56k | if (crv != CKR_OK) { |
4258 | 0 | return crv; |
4259 | 0 | } |
4260 | | |
4261 | 7.56k | CHECK_FORK(); |
4262 | | |
4263 | 7.56k | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session); |
4264 | 7.56k | if (crv != CKR_OK) |
4265 | 0 | return crv; |
4266 | | |
4267 | 7.56k | tmpItem.type = siBuffer; |
4268 | 7.56k | tmpItem.data = pSignature; |
4269 | 7.56k | tmpItem.len = ulSignatureLen; |
4270 | 7.56k | context->signature = SECITEM_DupItem(&tmpItem); |
4271 | 7.56k | if (!context->signature) { |
4272 | 0 | sftk_TerminateOp(session, SFTK_VERIFY, context); |
4273 | 0 | sftk_FreeSession(session); |
4274 | 0 | return CKR_HOST_MEMORY; |
4275 | 0 | } |
4276 | 7.56k | sftk_FreeSession(session); |
4277 | 7.56k | return CKR_OK; |
4278 | 7.56k | } |
4279 | | |
4280 | | CK_RV |
4281 | | NSC_VerifySignature(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, |
4282 | | CK_ULONG ulDataLen) |
4283 | 7.56k | { |
4284 | 7.56k | SFTKSession *session; |
4285 | 7.56k | SFTKSessionContext *context; |
4286 | 7.56k | CK_RV crv; |
4287 | | |
4288 | 7.56k | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session); |
4289 | 7.56k | if (crv != CKR_OK) |
4290 | 0 | return crv; |
4291 | | |
4292 | | /* make sure we're legal */ |
4293 | 7.56k | if (!context->signature) { |
4294 | 0 | sftk_FreeSession(session); |
4295 | 0 | return CKR_OPERATION_NOT_INITIALIZED; |
4296 | 0 | } |
4297 | 7.56k | crv = NSC_Verify(hSession, pData, ulDataLen, |
4298 | 7.56k | context->signature->data, context->signature->len); |
4299 | | /* we free the signature here because the context is part of the session and has |
4300 | | * a lifetime tied to the session. So we want to hold our reference to the |
4301 | | * session so it doesn't go away on us */ |
4302 | 7.56k | sftk_FreeSession(session); |
4303 | 7.56k | return crv; |
4304 | 7.56k | } |
4305 | | |
4306 | | CK_RV |
4307 | | NSC_VerifySignatureUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
4308 | | CK_ULONG ulPartLen) |
4309 | 0 | { |
4310 | 0 | SFTKSession *session; |
4311 | 0 | SFTKSessionContext *context; |
4312 | 0 | CK_RV crv; |
4313 | | |
4314 | | /* make sure we're legal */ |
4315 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session); |
4316 | 0 | if (crv != CKR_OK) |
4317 | 0 | return crv; |
4318 | | |
4319 | | /* like verify above, we bother keeping the session to make sure the context |
4320 | | * doesn't go way on use. there's little chance that it will since that application |
4321 | | * must protect against multiple threads calling the same same session at the same |
4322 | | * time (nss has session locks for this), but there are a couple of corner cases, |
4323 | | * (like close all sessions, or shutting down the whole module. Also if the |
4324 | | * application breaks the contract, we want to just fail rather than crash */ |
4325 | 0 | if (!context->signature) { |
4326 | 0 | sftk_FreeSession(session); |
4327 | 0 | return CKR_OPERATION_NOT_INITIALIZED; |
4328 | 0 | } |
4329 | 0 | sftk_FreeSession(session); |
4330 | 0 | return NSC_VerifyUpdate(hSession, pPart, ulPartLen); |
4331 | 0 | } |
4332 | | |
4333 | | CK_RV |
4334 | | NSC_VerifySignatureFinal(CK_SESSION_HANDLE hSession) |
4335 | 0 | { |
4336 | 0 | SFTKSession *session; |
4337 | 0 | SFTKSessionContext *context; |
4338 | 0 | CK_RV crv; |
4339 | | |
4340 | | /* make sure we're legal */ |
4341 | 0 | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session); |
4342 | 0 | if (crv != CKR_OK) |
4343 | 0 | return crv; |
4344 | | |
4345 | 0 | if (!context->signature) { |
4346 | 0 | sftk_FreeSession(session); |
4347 | 0 | return CKR_OPERATION_NOT_INITIALIZED; |
4348 | 0 | } |
4349 | 0 | crv = NSC_VerifyFinal(hSession, context->signature->data, |
4350 | 0 | context->signature->len); |
4351 | | /* see comment in NSC_VerifySignature() */ |
4352 | 0 | sftk_FreeSession(session); |
4353 | 0 | return crv; |
4354 | 0 | } |
4355 | | |
4356 | | /* |
4357 | | ************** Crypto Functions: Verify Recover ************************ |
4358 | | */ |
4359 | | static SECStatus |
4360 | | sftk_RSACheckSignRecover(void *ctx, unsigned char *data, |
4361 | | unsigned int *dataLen, unsigned int maxDataLen, |
4362 | | const unsigned char *sig, unsigned int sigLen) |
4363 | 13.5k | { |
4364 | 13.5k | NSSLOWKEYPublicKey *key = ctx; |
4365 | 13.5k | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
4366 | 13.5k | if (key->keyType != NSSLOWKEYRSAKey) { |
4367 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
4368 | 0 | return SECFailure; |
4369 | 0 | } |
4370 | | |
4371 | 13.5k | return RSA_CheckSignRecover(&key->u.rsa, data, dataLen, maxDataLen, |
4372 | 13.5k | sig, sigLen); |
4373 | 13.5k | } |
4374 | | |
4375 | | static SECStatus |
4376 | | sftk_RSACheckSignRecoverRaw(void *ctx, unsigned char *data, |
4377 | | unsigned int *dataLen, unsigned int maxDataLen, |
4378 | | const unsigned char *sig, unsigned int sigLen) |
4379 | 0 | { |
4380 | 0 | NSSLOWKEYPublicKey *key = ctx; |
4381 | 0 | PORT_Assert(key->keyType == NSSLOWKEYRSAKey); |
4382 | 0 | if (key->keyType != NSSLOWKEYRSAKey) { |
4383 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
4384 | 0 | return SECFailure; |
4385 | 0 | } |
4386 | | |
4387 | 0 | return RSA_CheckSignRecoverRaw(&key->u.rsa, data, dataLen, maxDataLen, |
4388 | 0 | sig, sigLen); |
4389 | 0 | } |
4390 | | |
4391 | | /* NSC_VerifyRecoverInit initializes a signature verification operation, |
4392 | | * where the data is recovered from the signature. |
4393 | | * E.g. Decryption with the user's public key */ |
4394 | | CK_RV |
4395 | | NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, |
4396 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) |
4397 | 13.5k | { |
4398 | 13.5k | SFTKSession *session; |
4399 | 13.5k | SFTKObject *key; |
4400 | 13.5k | SFTKSessionContext *context; |
4401 | 13.5k | CK_KEY_TYPE key_type; |
4402 | 13.5k | CK_RV crv = CKR_OK; |
4403 | 13.5k | NSSLOWKEYPublicKey *pubKey; |
4404 | | |
4405 | 13.5k | CHECK_FORK(); |
4406 | | |
4407 | 13.5k | session = sftk_SessionFromHandle(hSession); |
4408 | 13.5k | if (session == NULL) |
4409 | 0 | return CKR_SESSION_HANDLE_INVALID; |
4410 | 13.5k | crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY_RECOVER, |
4411 | 13.5k | &key, hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY_RECOVER); |
4412 | 13.5k | if (crv != CKR_OK) { |
4413 | 0 | sftk_FreeSession(session); |
4414 | 0 | return crv; |
4415 | 0 | } |
4416 | | |
4417 | 13.5k | context->multi = PR_TRUE; |
4418 | | |
4419 | 13.5k | switch (pMechanism->mechanism) { |
4420 | 13.5k | case CKM_RSA_PKCS: |
4421 | 13.5k | case CKM_RSA_X_509: |
4422 | 13.5k | if (key_type != CKK_RSA) { |
4423 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
4424 | 0 | break; |
4425 | 0 | } |
4426 | 13.5k | context->multi = PR_FALSE; |
4427 | 13.5k | context->rsa = PR_TRUE; |
4428 | 13.5k | pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); |
4429 | 13.5k | if (pubKey == NULL) { |
4430 | 0 | break; |
4431 | 0 | } |
4432 | 13.5k | context->cipherInfo = pubKey; |
4433 | 13.5k | context->update = pMechanism->mechanism == CKM_RSA_X_509 |
4434 | 13.5k | ? sftk_RSACheckSignRecoverRaw |
4435 | 13.5k | : sftk_RSACheckSignRecover; |
4436 | 13.5k | context->destroy = sftk_Null; |
4437 | 13.5k | break; |
4438 | 0 | default: |
4439 | 0 | crv = CKR_MECHANISM_INVALID; |
4440 | 0 | break; |
4441 | 13.5k | } |
4442 | | |
4443 | 13.5k | if (crv != CKR_OK) { |
4444 | 0 | PORT_Free(context); |
4445 | 0 | sftk_FreeSession(session); |
4446 | 0 | return crv; |
4447 | 0 | } |
4448 | 13.5k | sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context); |
4449 | 13.5k | sftk_FreeSession(session); |
4450 | 13.5k | return CKR_OK; |
4451 | 13.5k | } |
4452 | | |
4453 | | /* NSC_VerifyRecover verifies a signature in a single-part operation, |
4454 | | * where the data is recovered from the signature. |
4455 | | * E.g. Decryption with the user's public key */ |
4456 | | CK_RV |
4457 | | NSC_VerifyRecover(CK_SESSION_HANDLE hSession, |
4458 | | CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, |
4459 | | CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) |
4460 | 13.5k | { |
4461 | 13.5k | SFTKSession *session; |
4462 | 13.5k | SFTKSessionContext *context; |
4463 | 13.5k | unsigned int outlen; |
4464 | 13.5k | unsigned int maxoutlen = *pulDataLen; |
4465 | 13.5k | CK_RV crv; |
4466 | 13.5k | SECStatus rv; |
4467 | | |
4468 | 13.5k | CHECK_FORK(); |
4469 | | |
4470 | | /* make sure we're legal */ |
4471 | 13.5k | crv = sftk_GetContext(hSession, &context, SFTK_VERIFY_RECOVER, |
4472 | 13.5k | PR_FALSE, &session); |
4473 | 13.5k | if (crv != CKR_OK) |
4474 | 0 | return crv; |
4475 | 13.5k | if (pData == NULL) { |
4476 | | /* to return the actual size, we need to do the decrypt, just return |
4477 | | * the max size, which is the size of the input signature. */ |
4478 | 0 | *pulDataLen = ulSignatureLen; |
4479 | 0 | rv = SECSuccess; |
4480 | 0 | goto finish; |
4481 | 0 | } |
4482 | | |
4483 | 13.5k | rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, |
4484 | 13.5k | pSignature, ulSignatureLen); |
4485 | 13.5k | *pulDataLen = (CK_ULONG)outlen; |
4486 | | |
4487 | 13.5k | sftk_TerminateOp(session, SFTK_VERIFY_RECOVER, context); |
4488 | 13.5k | finish: |
4489 | 13.5k | sftk_FreeSession(session); |
4490 | 13.5k | return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError()); |
4491 | 13.5k | } |
4492 | | |
4493 | | /* |
4494 | | **************************** Random Functions: ************************ |
4495 | | */ |
4496 | | |
4497 | | /* NSC_SeedRandom mixes additional seed material into the token's random number |
4498 | | * generator. */ |
4499 | | CK_RV |
4500 | | NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, |
4501 | | CK_ULONG ulSeedLen) |
4502 | 0 | { |
4503 | 0 | SECStatus rv; |
4504 | |
|
4505 | 0 | CHECK_FORK(); |
4506 | |
|
4507 | 0 | rv = RNG_RandomUpdate(pSeed, ulSeedLen); |
4508 | 0 | return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
4509 | 0 | } |
4510 | | |
4511 | | /* NSC_GenerateRandom generates random data. */ |
4512 | | CK_RV |
4513 | | NSC_GenerateRandom(CK_SESSION_HANDLE hSession, |
4514 | | CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) |
4515 | 338k | { |
4516 | 338k | SECStatus rv; |
4517 | | |
4518 | 338k | CHECK_FORK(); |
4519 | | |
4520 | 338k | rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen); |
4521 | | /* |
4522 | | * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't |
4523 | | * seeded with enough entropy. |
4524 | | */ |
4525 | 338k | return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); |
4526 | 338k | } |
4527 | | |
4528 | | /* |
4529 | | **************************** Key Functions: ************************ |
4530 | | */ |
4531 | | |
4532 | | /* |
4533 | | * generate a password based encryption key. This code uses |
4534 | | * PKCS5 to do the work. |
4535 | | */ |
4536 | | static CK_RV |
4537 | | nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism, |
4538 | | void *buf, CK_ULONG *key_length, PRBool faulty3DES) |
4539 | 0 | { |
4540 | 0 | SECItem *pbe_key = NULL, iv, pwitem; |
4541 | 0 | CK_PBE_PARAMS *pbe_params = NULL; |
4542 | 0 | CK_PKCS5_PBKD2_PARAMS2 *pbkd2_params = NULL; |
4543 | |
|
4544 | 0 | *key_length = 0; |
4545 | 0 | iv.data = NULL; |
4546 | 0 | iv.len = 0; |
4547 | |
|
4548 | 0 | if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { |
4549 | 0 | pbkd2_params = (CK_PKCS5_PBKD2_PARAMS2 *)pMechanism->pParameter; |
4550 | 0 | if (!pMechanism->pParameter) { |
4551 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4552 | 0 | } |
4553 | | |
4554 | | #ifdef SOFTOKEN_USE_PKCS5_PBKD2_PARAMS2_ONLY |
4555 | | if (pMechanism->ulParameterLen < sizeof(CK_PKCS5_PBKD2_PARAMS2)) { |
4556 | | return CKR_MECHANISM_PARAM_INVALID; |
4557 | | } |
4558 | | pwitem.len = pbkd2_params->ulPasswordLen; |
4559 | | #else |
4560 | 0 | int v2; |
4561 | 0 | if (pMechanism->ulParameterLen < PR_MIN(sizeof(CK_PKCS5_PBKD2_PARAMS), |
4562 | 0 | sizeof(CK_PKCS5_PBKD2_PARAMS2))) { |
4563 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4564 | 0 | } |
4565 | | |
4566 | 0 | if (sizeof(CK_PKCS5_PBKD2_PARAMS2) != sizeof(CK_PKCS5_PBKD2_PARAMS)) { |
4567 | 0 | if (pMechanism->ulParameterLen == sizeof(CK_PKCS5_PBKD2_PARAMS)) { |
4568 | 0 | v2 = 0; |
4569 | 0 | } else if (pMechanism->ulParameterLen == sizeof(CK_PKCS5_PBKD2_PARAMS2)) { |
4570 | 0 | v2 = 1; |
4571 | 0 | } else { |
4572 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4573 | 0 | } |
4574 | 0 | } else { |
4575 | | /* it's unlikely that the password will be longer than 8192 bytes, if so it is |
4576 | | * most likely a pointer => CK_PKCS5_PBKD2_PARAMS */ |
4577 | 0 | v2 = pbkd2_params->ulPasswordLen <= CK_PKCS5_PBKD2_PARAMS_PTR_BOUNDARY; |
4578 | 0 | } |
4579 | 0 | pwitem.len = v2 ? pbkd2_params->ulPasswordLen : *((CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter)->ulPasswordLen; |
4580 | 0 | #endif |
4581 | 0 | pwitem.data = (unsigned char *)pbkd2_params->pPassword; |
4582 | 0 | } else { |
4583 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) { |
4584 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4585 | 0 | } |
4586 | 0 | pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
4587 | 0 | pwitem.data = (unsigned char *)pbe_params->pPassword; |
4588 | 0 | pwitem.len = pbe_params->ulPasswordLen; |
4589 | 0 | } |
4590 | 0 | pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES); |
4591 | 0 | if (pbe_key == NULL) { |
4592 | 0 | return CKR_HOST_MEMORY; |
4593 | 0 | } |
4594 | | |
4595 | 0 | PORT_Memcpy(buf, pbe_key->data, pbe_key->len); |
4596 | 0 | *key_length = pbe_key->len; |
4597 | 0 | SECITEM_ZfreeItem(pbe_key, PR_TRUE); |
4598 | 0 | pbe_key = NULL; |
4599 | |
|
4600 | 0 | if (iv.data) { |
4601 | 0 | if (pbe_params && pbe_params->pInitVector != NULL) { |
4602 | 0 | PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len); |
4603 | 0 | } |
4604 | 0 | PORT_Free(iv.data); |
4605 | 0 | } |
4606 | |
|
4607 | 0 | return CKR_OK; |
4608 | 0 | } |
4609 | | |
4610 | | /* |
4611 | | * this is coded for "full" support. These selections will be limitted to |
4612 | | * the official subset by freebl. |
4613 | | */ |
4614 | | static unsigned int |
4615 | | sftk_GetSubPrimeFromPrime(unsigned int primeBits) |
4616 | 0 | { |
4617 | 0 | if (primeBits <= 1024) { |
4618 | 0 | return 160; |
4619 | 0 | } else if (primeBits <= 2048) { |
4620 | 0 | return 224; |
4621 | 0 | } else if (primeBits <= 3072) { |
4622 | 0 | return 256; |
4623 | 0 | } else if (primeBits <= 7680) { |
4624 | 0 | return 384; |
4625 | 0 | } else { |
4626 | 0 | return 512; |
4627 | 0 | } |
4628 | 0 | } |
4629 | | |
4630 | | static CK_RV |
4631 | | nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key) |
4632 | 0 | { |
4633 | 0 | SFTKAttribute *attribute; |
4634 | 0 | CK_ULONG counter; |
4635 | 0 | unsigned int seedBits = 0; |
4636 | 0 | unsigned int subprimeBits = 0; |
4637 | 0 | unsigned int primeBits; |
4638 | 0 | unsigned int j = 8; /* default to 1024 bits */ |
4639 | 0 | CK_RV crv = CKR_OK; |
4640 | 0 | PQGParams *params = NULL; |
4641 | 0 | PQGVerify *vfy = NULL; |
4642 | 0 | SECStatus rv; |
4643 | |
|
4644 | 0 | attribute = sftk_FindAttribute(key, CKA_PRIME_BITS); |
4645 | 0 | if (attribute == NULL) { |
4646 | 0 | attribute = sftk_FindAttribute(key, CKA_PRIME); |
4647 | 0 | if (attribute == NULL) { |
4648 | 0 | return CKR_TEMPLATE_INCOMPLETE; |
4649 | 0 | } else { |
4650 | 0 | primeBits = attribute->attrib.ulValueLen; |
4651 | 0 | sftk_FreeAttribute(attribute); |
4652 | 0 | } |
4653 | 0 | } else { |
4654 | 0 | primeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; |
4655 | 0 | sftk_FreeAttribute(attribute); |
4656 | 0 | } |
4657 | 0 | if (primeBits < 1024) { |
4658 | 0 | j = PQG_PBITS_TO_INDEX(primeBits); |
4659 | 0 | if (j == (unsigned int)-1) { |
4660 | 0 | return CKR_ATTRIBUTE_VALUE_INVALID; |
4661 | 0 | } |
4662 | 0 | } |
4663 | | |
4664 | 0 | attribute = sftk_FindAttribute(key, CKA_NSS_PQG_SEED_BITS); |
4665 | 0 | if (attribute != NULL) { |
4666 | 0 | seedBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; |
4667 | 0 | sftk_FreeAttribute(attribute); |
4668 | 0 | } |
4669 | |
|
4670 | 0 | attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS); |
4671 | 0 | if (attribute != NULL) { |
4672 | 0 | subprimeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; |
4673 | 0 | sftk_FreeAttribute(attribute); |
4674 | 0 | } |
4675 | | |
4676 | | /* if P and Q are supplied, we want to generate a new G */ |
4677 | 0 | attribute = sftk_FindAttribute(key, CKA_PRIME); |
4678 | 0 | if (attribute != NULL) { |
4679 | 0 | PLArenaPool *arena; |
4680 | |
|
4681 | 0 | sftk_FreeAttribute(attribute); |
4682 | 0 | arena = PORT_NewArena(1024); |
4683 | 0 | if (arena == NULL) { |
4684 | 0 | crv = CKR_HOST_MEMORY; |
4685 | 0 | goto loser; |
4686 | 0 | } |
4687 | 0 | params = PORT_ArenaAlloc(arena, sizeof(*params)); |
4688 | 0 | if (params == NULL) { |
4689 | 0 | crv = CKR_HOST_MEMORY; |
4690 | 0 | goto loser; |
4691 | 0 | } |
4692 | 0 | params->arena = arena; |
4693 | 0 | crv = sftk_Attribute2SSecItem(arena, ¶ms->prime, key, CKA_PRIME); |
4694 | 0 | if (crv != CKR_OK) { |
4695 | 0 | goto loser; |
4696 | 0 | } |
4697 | 0 | crv = sftk_Attribute2SSecItem(arena, ¶ms->subPrime, |
4698 | 0 | key, CKA_SUBPRIME); |
4699 | 0 | if (crv != CKR_OK) { |
4700 | 0 | goto loser; |
4701 | 0 | } |
4702 | | |
4703 | 0 | arena = PORT_NewArena(1024); |
4704 | 0 | if (arena == NULL) { |
4705 | 0 | crv = CKR_HOST_MEMORY; |
4706 | 0 | goto loser; |
4707 | 0 | } |
4708 | 0 | vfy = PORT_ArenaAlloc(arena, sizeof(*vfy)); |
4709 | 0 | if (vfy == NULL) { |
4710 | 0 | crv = CKR_HOST_MEMORY; |
4711 | 0 | goto loser; |
4712 | 0 | } |
4713 | 0 | vfy->arena = arena; |
4714 | 0 | crv = sftk_Attribute2SSecItem(arena, &vfy->seed, key, CKA_NSS_PQG_SEED); |
4715 | 0 | if (crv != CKR_OK) { |
4716 | 0 | goto loser; |
4717 | 0 | } |
4718 | 0 | crv = sftk_Attribute2SSecItem(arena, &vfy->h, key, CKA_NSS_PQG_H); |
4719 | 0 | if (crv != CKR_OK) { |
4720 | 0 | goto loser; |
4721 | 0 | } |
4722 | 0 | sftk_DeleteAttributeType(key, CKA_PRIME); |
4723 | 0 | sftk_DeleteAttributeType(key, CKA_SUBPRIME); |
4724 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED); |
4725 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_PQG_H); |
4726 | 0 | } |
4727 | | |
4728 | 0 | sftk_DeleteAttributeType(key, CKA_PRIME_BITS); |
4729 | 0 | sftk_DeleteAttributeType(key, CKA_SUBPRIME_BITS); |
4730 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED_BITS); |
4731 | | |
4732 | | /* use the old PQG interface if we have old input data */ |
4733 | 0 | if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) { |
4734 | 0 | if (seedBits == 0) { |
4735 | 0 | rv = PQG_ParamGen(j, ¶ms, &vfy); |
4736 | 0 | } else { |
4737 | 0 | rv = PQG_ParamGenSeedLen(j, seedBits / 8, ¶ms, &vfy); |
4738 | 0 | } |
4739 | 0 | } else { |
4740 | 0 | if (subprimeBits == 0) { |
4741 | 0 | subprimeBits = sftk_GetSubPrimeFromPrime(primeBits); |
4742 | 0 | } |
4743 | 0 | if (seedBits == 0) { |
4744 | 0 | seedBits = primeBits; |
4745 | 0 | } |
4746 | 0 | rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits / 8, ¶ms, &vfy); |
4747 | 0 | } |
4748 | |
|
4749 | 0 | if (rv != SECSuccess) { |
4750 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
4751 | 0 | sftk_fatalError = PR_TRUE; |
4752 | 0 | } |
4753 | 0 | return sftk_MapCryptError(PORT_GetError()); |
4754 | 0 | } |
4755 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME, |
4756 | 0 | params->prime.data, params->prime.len); |
4757 | 0 | if (crv != CKR_OK) |
4758 | 0 | goto loser; |
4759 | 0 | crv = sftk_AddAttributeType(key, CKA_SUBPRIME, |
4760 | 0 | params->subPrime.data, params->subPrime.len); |
4761 | 0 | if (crv != CKR_OK) |
4762 | 0 | goto loser; |
4763 | 0 | crv = sftk_AddAttributeType(key, CKA_BASE, |
4764 | 0 | params->base.data, params->base.len); |
4765 | 0 | if (crv != CKR_OK) |
4766 | 0 | goto loser; |
4767 | 0 | counter = vfy->counter; |
4768 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_PQG_COUNTER, |
4769 | 0 | &counter, sizeof(counter)); |
4770 | 0 | if (crv != CKR_OK) |
4771 | 0 | goto loser; |
4772 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_PQG_SEED, |
4773 | 0 | vfy->seed.data, vfy->seed.len); |
4774 | 0 | if (crv != CKR_OK) |
4775 | 0 | goto loser; |
4776 | 0 | crv = sftk_AddAttributeType(key, CKA_NSS_PQG_H, |
4777 | 0 | vfy->h.data, vfy->h.len); |
4778 | 0 | if (crv != CKR_OK) |
4779 | 0 | goto loser; |
4780 | | |
4781 | 0 | loser: |
4782 | 0 | if (params) { |
4783 | 0 | PQG_DestroyParams(params); |
4784 | 0 | } |
4785 | |
|
4786 | 0 | if (vfy) { |
4787 | 0 | PQG_DestroyVerify(vfy); |
4788 | 0 | } |
4789 | 0 | return crv; |
4790 | 0 | } |
4791 | | |
4792 | | static CK_RV |
4793 | | nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type, |
4794 | | CK_ULONG *key_length) |
4795 | 39.7k | { |
4796 | 39.7k | CK_RV crv = CKR_OK; |
4797 | | |
4798 | 39.7k | switch (mechanism) { |
4799 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
4800 | 0 | case CKM_RC2_KEY_GEN: |
4801 | 0 | *key_type = CKK_RC2; |
4802 | 0 | if (*key_length == 0) |
4803 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4804 | 0 | break; |
4805 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
4806 | | #if NSS_SOFTOKEN_DOES_RC5 |
4807 | | case CKM_RC5_KEY_GEN: |
4808 | | *key_type = CKK_RC5; |
4809 | | if (*key_length == 0) |
4810 | | crv = CKR_TEMPLATE_INCOMPLETE; |
4811 | | break; |
4812 | | #endif |
4813 | 0 | case CKM_RC4_KEY_GEN: |
4814 | 0 | *key_type = CKK_RC4; |
4815 | 0 | if (*key_length == 0) |
4816 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4817 | 0 | break; |
4818 | 1.66k | case CKM_GENERIC_SECRET_KEY_GEN: |
4819 | 1.66k | *key_type = CKK_GENERIC_SECRET; |
4820 | 1.66k | if (*key_length == 0) |
4821 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4822 | 1.66k | break; |
4823 | 0 | case CKM_CDMF_KEY_GEN: |
4824 | 0 | *key_type = CKK_CDMF; |
4825 | 0 | *key_length = 8; |
4826 | 0 | break; |
4827 | 0 | case CKM_DES_KEY_GEN: |
4828 | 0 | *key_type = CKK_DES; |
4829 | 0 | *key_length = 8; |
4830 | 0 | break; |
4831 | 0 | case CKM_DES2_KEY_GEN: |
4832 | 0 | *key_type = CKK_DES2; |
4833 | 0 | *key_length = 16; |
4834 | 0 | break; |
4835 | 5.54k | case CKM_DES3_KEY_GEN: |
4836 | 5.54k | *key_type = CKK_DES3; |
4837 | 5.54k | *key_length = 24; |
4838 | 5.54k | break; |
4839 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
4840 | 0 | case CKM_SEED_KEY_GEN: |
4841 | 0 | *key_type = CKK_SEED; |
4842 | 0 | *key_length = 16; |
4843 | 0 | break; |
4844 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
4845 | 0 | case CKM_CAMELLIA_KEY_GEN: |
4846 | 0 | *key_type = CKK_CAMELLIA; |
4847 | 0 | if (*key_length == 0) |
4848 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4849 | 0 | break; |
4850 | 4 | case CKM_AES_KEY_GEN: |
4851 | 4 | *key_type = CKK_AES; |
4852 | 4 | if (*key_length == 0) |
4853 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4854 | 4 | break; |
4855 | 32.5k | case CKM_NSS_CHACHA20_KEY_GEN: |
4856 | 32.5k | *key_type = CKK_NSS_CHACHA20; |
4857 | 32.5k | *key_length = 32; |
4858 | 32.5k | break; |
4859 | 0 | case CKM_CHACHA20_KEY_GEN: |
4860 | 0 | *key_type = CKK_CHACHA20; |
4861 | 0 | *key_length = 32; |
4862 | 0 | break; |
4863 | 0 | case CKM_HKDF_KEY_GEN: |
4864 | 0 | *key_type = CKK_HKDF; |
4865 | 0 | if (*key_length == 0) |
4866 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
4867 | 0 | break; |
4868 | 0 | default: |
4869 | 0 | PORT_Assert(0); |
4870 | 0 | crv = CKR_MECHANISM_INVALID; |
4871 | 0 | break; |
4872 | 39.7k | } |
4873 | | |
4874 | 39.7k | return crv; |
4875 | 39.7k | } |
4876 | | |
4877 | | CK_RV |
4878 | | nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe) |
4879 | 0 | { |
4880 | 0 | SECItem salt; |
4881 | 0 | CK_PBE_PARAMS *pbe_params = NULL; |
4882 | 0 | NSSPKCS5PBEParameter *params; |
4883 | 0 | PLArenaPool *arena = NULL; |
4884 | 0 | SECStatus rv; |
4885 | |
|
4886 | 0 | *pbe = NULL; |
4887 | |
|
4888 | 0 | arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); |
4889 | 0 | if (arena == NULL) { |
4890 | 0 | return CKR_HOST_MEMORY; |
4891 | 0 | } |
4892 | | |
4893 | 0 | params = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena, |
4894 | 0 | sizeof(NSSPKCS5PBEParameter)); |
4895 | 0 | if (params == NULL) { |
4896 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4897 | 0 | return CKR_HOST_MEMORY; |
4898 | 0 | } |
4899 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) { |
4900 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4901 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4902 | 0 | } |
4903 | | |
4904 | 0 | params->poolp = arena; |
4905 | 0 | params->ivLen = 0; |
4906 | 0 | params->pbeType = NSSPKCS5_PKCS12_V2; |
4907 | 0 | params->hashType = HASH_AlgSHA1; |
4908 | 0 | params->encAlg = SEC_OID_SHA1; /* any invalid value */ |
4909 | 0 | params->is2KeyDES = PR_FALSE; |
4910 | 0 | params->keyID = pbeBitGenIntegrityKey; |
4911 | 0 | pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
4912 | 0 | params->iter = pbe_params->ulIteration; |
4913 | |
|
4914 | 0 | salt.data = (unsigned char *)pbe_params->pSalt; |
4915 | 0 | salt.len = (unsigned int)pbe_params->ulSaltLen; |
4916 | 0 | salt.type = siBuffer; |
4917 | 0 | rv = SECITEM_CopyItem(arena, ¶ms->salt, &salt); |
4918 | 0 | if (rv != SECSuccess) { |
4919 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4920 | 0 | return CKR_HOST_MEMORY; |
4921 | 0 | } |
4922 | 0 | switch (pMechanism->mechanism) { |
4923 | 0 | case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN: |
4924 | 0 | case CKM_PBA_SHA1_WITH_SHA1_HMAC: |
4925 | 0 | params->hashType = HASH_AlgSHA1; |
4926 | 0 | params->keyLen = 20; |
4927 | 0 | break; |
4928 | 0 | case CKM_NSS_PBE_MD5_HMAC_KEY_GEN: |
4929 | 0 | params->hashType = HASH_AlgMD5; |
4930 | 0 | params->keyLen = 16; |
4931 | 0 | break; |
4932 | 0 | case CKM_NSS_PBE_MD2_HMAC_KEY_GEN: |
4933 | 0 | params->hashType = HASH_AlgMD2; |
4934 | 0 | params->keyLen = 16; |
4935 | 0 | break; |
4936 | 0 | case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN: |
4937 | 0 | params->hashType = HASH_AlgSHA224; |
4938 | 0 | params->keyLen = 28; |
4939 | 0 | break; |
4940 | 0 | case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN: |
4941 | 0 | params->hashType = HASH_AlgSHA256; |
4942 | 0 | params->keyLen = 32; |
4943 | 0 | break; |
4944 | 0 | case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN: |
4945 | 0 | params->hashType = HASH_AlgSHA384; |
4946 | 0 | params->keyLen = 48; |
4947 | 0 | break; |
4948 | 0 | case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN: |
4949 | 0 | params->hashType = HASH_AlgSHA512; |
4950 | 0 | params->keyLen = 64; |
4951 | 0 | break; |
4952 | 0 | default: |
4953 | 0 | PORT_FreeArena(arena, PR_TRUE); |
4954 | 0 | return CKR_MECHANISM_INVALID; |
4955 | 0 | } |
4956 | 0 | *pbe = params; |
4957 | 0 | return CKR_OK; |
4958 | 0 | } |
4959 | | |
4960 | | /* maybe this should be table driven? */ |
4961 | | static CK_RV |
4962 | | nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe, |
4963 | | CK_KEY_TYPE *key_type, CK_ULONG *key_length) |
4964 | 0 | { |
4965 | 0 | CK_RV crv = CKR_OK; |
4966 | 0 | SECOidData *oid; |
4967 | 0 | CK_PBE_PARAMS *pbe_params = NULL; |
4968 | 0 | NSSPKCS5PBEParameter *params = NULL; |
4969 | 0 | HASH_HashType hashType = HASH_AlgSHA1; |
4970 | 0 | CK_PKCS5_PBKD2_PARAMS2 *pbkd2_params = NULL; |
4971 | 0 | SECItem salt; |
4972 | 0 | CK_ULONG iteration = 0; |
4973 | |
|
4974 | 0 | *pbe = NULL; |
4975 | |
|
4976 | 0 | oid = SECOID_FindOIDByMechanism(pMechanism->mechanism); |
4977 | 0 | if (oid == NULL) { |
4978 | 0 | return CKR_MECHANISM_INVALID; |
4979 | 0 | } |
4980 | | |
4981 | 0 | if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { |
4982 | 0 | if (pMechanism->ulParameterLen < PR_MIN(sizeof(CK_PKCS5_PBKD2_PARAMS2), |
4983 | 0 | sizeof(CK_PKCS5_PBKD2_PARAMS))) { |
4984 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
4985 | 0 | } |
4986 | 0 | pbkd2_params = (CK_PKCS5_PBKD2_PARAMS2 *)pMechanism->pParameter; |
4987 | 0 | switch (pbkd2_params->prf) { |
4988 | 0 | case CKP_PKCS5_PBKD2_HMAC_SHA1: |
4989 | 0 | hashType = HASH_AlgSHA1; |
4990 | 0 | break; |
4991 | 0 | case CKP_PKCS5_PBKD2_HMAC_SHA224: |
4992 | 0 | hashType = HASH_AlgSHA224; |
4993 | 0 | break; |
4994 | 0 | case CKP_PKCS5_PBKD2_HMAC_SHA256: |
4995 | 0 | hashType = HASH_AlgSHA256; |
4996 | 0 | break; |
4997 | 0 | case CKP_PKCS5_PBKD2_HMAC_SHA384: |
4998 | 0 | hashType = HASH_AlgSHA384; |
4999 | 0 | break; |
5000 | 0 | case CKP_PKCS5_PBKD2_HMAC_SHA512: |
5001 | 0 | hashType = HASH_AlgSHA512; |
5002 | 0 | break; |
5003 | 0 | default: |
5004 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
5005 | 0 | } |
5006 | 0 | if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) { |
5007 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
5008 | 0 | } |
5009 | 0 | salt.data = (unsigned char *)pbkd2_params->pSaltSourceData; |
5010 | 0 | salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen; |
5011 | 0 | iteration = pbkd2_params->iterations; |
5012 | 0 | } else { |
5013 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) { |
5014 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
5015 | 0 | } |
5016 | 0 | pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; |
5017 | 0 | salt.data = (unsigned char *)pbe_params->pSalt; |
5018 | 0 | salt.len = (unsigned int)pbe_params->ulSaltLen; |
5019 | 0 | iteration = pbe_params->ulIteration; |
5020 | 0 | } |
5021 | 0 | params = nsspkcs5_NewParam(oid->offset, hashType, &salt, iteration); |
5022 | 0 | if (params == NULL) { |
5023 | 0 | return CKR_MECHANISM_INVALID; |
5024 | 0 | } |
5025 | | |
5026 | 0 | switch (params->encAlg) { |
5027 | 0 | case SEC_OID_DES_CBC: |
5028 | 0 | *key_type = CKK_DES; |
5029 | 0 | *key_length = params->keyLen; |
5030 | 0 | break; |
5031 | 0 | case SEC_OID_DES_EDE3_CBC: |
5032 | 0 | *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3; |
5033 | 0 | *key_length = params->keyLen; |
5034 | 0 | break; |
5035 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
5036 | 0 | case SEC_OID_RC2_CBC: |
5037 | 0 | *key_type = CKK_RC2; |
5038 | 0 | *key_length = params->keyLen; |
5039 | 0 | break; |
5040 | 0 | #endif /* NSS_DISABLE_DEPRECATED_RC2 */ |
5041 | 0 | case SEC_OID_RC4: |
5042 | 0 | *key_type = CKK_RC4; |
5043 | 0 | *key_length = params->keyLen; |
5044 | 0 | break; |
5045 | 0 | case SEC_OID_PKCS5_PBKDF2: |
5046 | | /* key type must already be set */ |
5047 | 0 | if (*key_type == CKK_INVALID_KEY_TYPE) { |
5048 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5049 | 0 | break; |
5050 | 0 | } |
5051 | | /* PBKDF2 needs to calculate the key length from the other parameters |
5052 | | */ |
5053 | 0 | if (*key_length == 0) { |
5054 | 0 | *key_length = sftk_MapKeySize(*key_type); |
5055 | 0 | } |
5056 | 0 | if (*key_length == 0) { |
5057 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
5058 | 0 | break; |
5059 | 0 | } |
5060 | 0 | params->keyLen = *key_length; |
5061 | 0 | break; |
5062 | 0 | default: |
5063 | 0 | crv = CKR_MECHANISM_INVALID; |
5064 | 0 | break; |
5065 | 0 | } |
5066 | 0 | if (crv == CKR_OK) { |
5067 | 0 | *pbe = params; |
5068 | 0 | } else { |
5069 | 0 | nsspkcs5_DestroyPBEParameter(params); |
5070 | 0 | } |
5071 | 0 | return crv; |
5072 | 0 | } |
5073 | | |
5074 | | /* NSC_GenerateKey generates a secret key, creating a new key object. */ |
5075 | | CK_RV |
5076 | | NSC_GenerateKey(CK_SESSION_HANDLE hSession, |
5077 | | CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, |
5078 | | CK_OBJECT_HANDLE_PTR phKey) |
5079 | 90.6k | { |
5080 | 90.6k | SFTKObject *key; |
5081 | 90.6k | SFTKSession *session; |
5082 | 90.6k | PRBool checkWeak = PR_FALSE; |
5083 | 90.6k | CK_ULONG key_length = 0; |
5084 | 90.6k | CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE; |
5085 | 90.6k | CK_OBJECT_CLASS objclass = CKO_SECRET_KEY; |
5086 | 90.6k | CK_RV crv = CKR_OK; |
5087 | 90.6k | CK_BBOOL cktrue = CK_TRUE; |
5088 | 90.6k | NSSPKCS5PBEParameter *pbe_param = NULL; |
5089 | 90.6k | int i; |
5090 | 90.6k | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
5091 | 90.6k | unsigned char buf[MAX_KEY_LEN]; |
5092 | 90.6k | enum { nsc_pbe, |
5093 | 90.6k | nsc_ssl, |
5094 | 90.6k | nsc_bulk, |
5095 | 90.6k | nsc_param, |
5096 | 90.6k | nsc_jpake } key_gen_type; |
5097 | 90.6k | SSL3RSAPreMasterSecret *rsa_pms; |
5098 | 90.6k | CK_VERSION *version; |
5099 | | /* in very old versions of NSS, there were implementation errors with key |
5100 | | * generation methods. We want to beable to read these, but not |
5101 | | * produce them any more. The affected algorithm was 3DES. |
5102 | | */ |
5103 | 90.6k | PRBool faultyPBE3DES = PR_FALSE; |
5104 | 90.6k | HASH_HashType hashType = HASH_AlgNULL; |
5105 | | |
5106 | 90.6k | CHECK_FORK(); |
5107 | | |
5108 | 90.6k | if (!slot) { |
5109 | 0 | return CKR_SESSION_HANDLE_INVALID; |
5110 | 0 | } |
5111 | | /* |
5112 | | * now lets create an object to hang the attributes off of |
5113 | | */ |
5114 | 90.6k | key = sftk_NewObject(slot); /* fill in the handle later */ |
5115 | 90.6k | if (key == NULL) { |
5116 | 0 | return CKR_HOST_MEMORY; |
5117 | 0 | } |
5118 | | |
5119 | | /* |
5120 | | * load the template values into the object |
5121 | | */ |
5122 | 306k | for (i = 0; i < (int)ulCount; i++) { |
5123 | 215k | if (pTemplate[i].type == CKA_VALUE_LEN) { |
5124 | 34.2k | key_length = *(CK_ULONG *)pTemplate[i].pValue; |
5125 | 34.2k | continue; |
5126 | 34.2k | } |
5127 | | /* some algorithms need keytype specified */ |
5128 | 181k | if (pTemplate[i].type == CKA_KEY_TYPE) { |
5129 | 0 | key_type = *(CK_ULONG *)pTemplate[i].pValue; |
5130 | 0 | continue; |
5131 | 0 | } |
5132 | | |
5133 | 181k | crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); |
5134 | 181k | if (crv != CKR_OK) { |
5135 | 0 | break; |
5136 | 0 | } |
5137 | 181k | } |
5138 | 90.6k | if (crv != CKR_OK) { |
5139 | 0 | goto loser; |
5140 | 0 | } |
5141 | | |
5142 | | /* make sure we don't have any class, key_type, or value fields */ |
5143 | 90.6k | sftk_DeleteAttributeType(key, CKA_CLASS); |
5144 | 90.6k | sftk_DeleteAttributeType(key, CKA_KEY_TYPE); |
5145 | 90.6k | sftk_DeleteAttributeType(key, CKA_VALUE); |
5146 | | |
5147 | | /* Now Set up the parameters to generate the key (based on mechanism) */ |
5148 | 90.6k | key_gen_type = nsc_bulk; /* bulk key by default */ |
5149 | 90.6k | switch (pMechanism->mechanism) { |
5150 | 0 | case CKM_CDMF_KEY_GEN: |
5151 | 0 | case CKM_DES_KEY_GEN: |
5152 | 0 | case CKM_DES2_KEY_GEN: |
5153 | 5.54k | case CKM_DES3_KEY_GEN: |
5154 | 5.54k | checkWeak = PR_TRUE; |
5155 | | /* fall through */ |
5156 | 5.54k | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
5157 | 5.54k | case CKM_RC2_KEY_GEN: |
5158 | 5.54k | #endif |
5159 | 5.54k | case CKM_RC4_KEY_GEN: |
5160 | 7.20k | case CKM_GENERIC_SECRET_KEY_GEN: |
5161 | 7.20k | #ifndef NSS_DISABLE_DEPRECATED_SEED |
5162 | 7.20k | case CKM_SEED_KEY_GEN: |
5163 | 7.20k | #endif |
5164 | 7.20k | case CKM_CAMELLIA_KEY_GEN: |
5165 | 7.21k | case CKM_AES_KEY_GEN: |
5166 | 39.7k | case CKM_NSS_CHACHA20_KEY_GEN: |
5167 | 39.7k | case CKM_CHACHA20_KEY_GEN: |
5168 | | #if NSS_SOFTOKEN_DOES_RC5 |
5169 | | case CKM_RC5_KEY_GEN: |
5170 | | #endif |
5171 | 39.7k | crv = nsc_SetupBulkKeyGen(pMechanism->mechanism, &key_type, &key_length); |
5172 | 39.7k | break; |
5173 | 50.8k | case CKM_SSL3_PRE_MASTER_KEY_GEN: |
5174 | 50.8k | key_type = CKK_GENERIC_SECRET; |
5175 | 50.8k | key_length = 48; |
5176 | 50.8k | key_gen_type = nsc_ssl; |
5177 | 50.8k | break; |
5178 | 0 | case CKM_PBA_SHA1_WITH_SHA1_HMAC: |
5179 | 0 | case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN: |
5180 | 0 | case CKM_NSS_PBE_MD5_HMAC_KEY_GEN: |
5181 | 0 | case CKM_NSS_PBE_MD2_HMAC_KEY_GEN: |
5182 | 0 | case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN: |
5183 | 0 | case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN: |
5184 | 0 | case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN: |
5185 | 0 | case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN: |
5186 | 0 | key_gen_type = nsc_pbe; |
5187 | 0 | key_type = CKK_GENERIC_SECRET; |
5188 | 0 | crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param); |
5189 | 0 | break; |
5190 | 0 | case CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC: |
5191 | 0 | faultyPBE3DES = PR_TRUE; |
5192 | | /* fall through */ |
5193 | 0 | case CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC: |
5194 | 0 | #ifndef NSS_DISABLE_DEPRECATED_RC2 |
5195 | 0 | case CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC: |
5196 | 0 | case CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC: |
5197 | 0 | case CKM_PBE_SHA1_RC2_128_CBC: |
5198 | 0 | case CKM_PBE_SHA1_RC2_40_CBC: |
5199 | 0 | #endif |
5200 | 0 | case CKM_NSS_PBE_SHA1_DES_CBC: |
5201 | 0 | case CKM_NSS_PBE_SHA1_40_BIT_RC4: |
5202 | 0 | case CKM_NSS_PBE_SHA1_128_BIT_RC4: |
5203 | 0 | case CKM_PBE_SHA1_DES3_EDE_CBC: |
5204 | 0 | case CKM_PBE_SHA1_DES2_EDE_CBC: |
5205 | 0 | case CKM_PBE_SHA1_RC4_128: |
5206 | 0 | case CKM_PBE_SHA1_RC4_40: |
5207 | 0 | case CKM_PBE_MD5_DES_CBC: |
5208 | 0 | case CKM_PBE_MD2_DES_CBC: |
5209 | 0 | case CKM_PKCS5_PBKD2: |
5210 | 0 | key_gen_type = nsc_pbe; |
5211 | 0 | crv = nsc_SetupPBEKeyGen(pMechanism, &pbe_param, &key_type, &key_length); |
5212 | 0 | break; |
5213 | | /*#ifndef NSS_DISABLE_DSA */ |
5214 | | /* some applications use CKM_DSA_PARAMETER_GEN for weak DH keys... |
5215 | | * most notably tests and even ssl... continue to allow it for now */ |
5216 | 0 | case CKM_DSA_PARAMETER_GEN: |
5217 | 0 | key_gen_type = nsc_param; |
5218 | 0 | key_type = CKK_DSA; |
5219 | 0 | objclass = CKO_DOMAIN_PARAMETERS; |
5220 | 0 | crv = CKR_OK; |
5221 | 0 | break; |
5222 | | /* #endif */ |
5223 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA1: |
5224 | 0 | hashType = HASH_AlgSHA1; |
5225 | 0 | goto jpake1; |
5226 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA256: |
5227 | 0 | hashType = HASH_AlgSHA256; |
5228 | 0 | goto jpake1; |
5229 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA384: |
5230 | 0 | hashType = HASH_AlgSHA384; |
5231 | 0 | goto jpake1; |
5232 | 0 | case CKM_NSS_JPAKE_ROUND1_SHA512: |
5233 | 0 | hashType = HASH_AlgSHA512; |
5234 | 0 | goto jpake1; |
5235 | 0 | jpake1: |
5236 | 0 | key_gen_type = nsc_jpake; |
5237 | 0 | key_type = CKK_NSS_JPAKE_ROUND1; |
5238 | 0 | objclass = CKO_PRIVATE_KEY; |
5239 | 0 | if (pMechanism->pParameter == NULL || |
5240 | 0 | pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) { |
5241 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
5242 | 0 | break; |
5243 | 0 | } |
5244 | 0 | if (sftk_isTrue(key, CKA_TOKEN)) { |
5245 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
5246 | 0 | break; |
5247 | 0 | } |
5248 | 0 | crv = CKR_OK; |
5249 | 0 | break; |
5250 | 0 | default: |
5251 | 0 | crv = CKR_MECHANISM_INVALID; |
5252 | 0 | break; |
5253 | 90.6k | } |
5254 | | |
5255 | | /* make sure we aren't going to overflow the buffer */ |
5256 | 90.6k | if (sizeof(buf) < key_length) { |
5257 | | /* someone is getting pretty optimistic about how big their key can |
5258 | | * be... */ |
5259 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
5260 | 0 | } |
5261 | | |
5262 | 90.6k | if (crv != CKR_OK) { |
5263 | 0 | if (pbe_param) { |
5264 | 0 | nsspkcs5_DestroyPBEParameter(pbe_param); |
5265 | 0 | } |
5266 | 0 | goto loser; |
5267 | 0 | } |
5268 | | |
5269 | | /* if there was no error, |
5270 | | * key_type *MUST* be set in the switch statement above */ |
5271 | 90.6k | PORT_Assert(key_type != CKK_INVALID_KEY_TYPE); |
5272 | | |
5273 | | /* |
5274 | | * now to the actual key gen. |
5275 | | */ |
5276 | 90.6k | switch (key_gen_type) { |
5277 | 0 | case nsc_pbe: |
5278 | 0 | crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length, |
5279 | 0 | faultyPBE3DES); |
5280 | 0 | nsspkcs5_DestroyPBEParameter(pbe_param); |
5281 | 0 | break; |
5282 | 50.8k | case nsc_ssl: |
5283 | 50.8k | rsa_pms = (SSL3RSAPreMasterSecret *)buf; |
5284 | 50.8k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_VERSION))) { |
5285 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
5286 | 0 | goto loser; |
5287 | 0 | } |
5288 | 50.8k | version = (CK_VERSION *)pMechanism->pParameter; |
5289 | 50.8k | rsa_pms->client_version[0] = version->major; |
5290 | 50.8k | rsa_pms->client_version[1] = version->minor; |
5291 | 50.8k | crv = |
5292 | 50.8k | NSC_GenerateRandom(0, &rsa_pms->random[0], sizeof(rsa_pms->random)); |
5293 | 50.8k | break; |
5294 | 39.7k | case nsc_bulk: |
5295 | | /* get the key, check for weak keys and repeat if found */ |
5296 | 39.7k | do { |
5297 | 39.7k | crv = NSC_GenerateRandom(0, buf, key_length); |
5298 | 39.7k | } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf, key_type)); |
5299 | 39.7k | break; |
5300 | 0 | case nsc_param: |
5301 | | /* generate parameters */ |
5302 | 0 | *buf = 0; |
5303 | 0 | crv = nsc_parameter_gen(key_type, key); |
5304 | 0 | break; |
5305 | 0 | case nsc_jpake: |
5306 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_NSS_JPAKERound1Params))) { |
5307 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
5308 | 0 | goto loser; |
5309 | 0 | } |
5310 | 0 | crv = jpake_Round1(hashType, |
5311 | 0 | (CK_NSS_JPAKERound1Params *)pMechanism->pParameter, |
5312 | 0 | key); |
5313 | 0 | break; |
5314 | 90.6k | } |
5315 | | |
5316 | 90.6k | if (crv != CKR_OK) { |
5317 | 0 | goto loser; |
5318 | 0 | } |
5319 | | |
5320 | | /* Add the class, key_type, and value */ |
5321 | 90.6k | crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS)); |
5322 | 90.6k | if (crv != CKR_OK) { |
5323 | 0 | goto loser; |
5324 | 0 | } |
5325 | 90.6k | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE)); |
5326 | 90.6k | if (crv != CKR_OK) { |
5327 | 0 | goto loser; |
5328 | 0 | } |
5329 | 90.6k | if (key_length != 0) { |
5330 | 90.6k | crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length); |
5331 | 90.6k | if (crv != CKR_OK) { |
5332 | 0 | goto loser; |
5333 | 0 | } |
5334 | 90.6k | } |
5335 | | |
5336 | | /* get the session */ |
5337 | 90.6k | session = sftk_SessionFromHandle(hSession); |
5338 | 90.6k | if (session == NULL) { |
5339 | 0 | crv = CKR_SESSION_HANDLE_INVALID; |
5340 | 0 | goto loser; |
5341 | 0 | } |
5342 | | |
5343 | | /* |
5344 | | * handle the base object stuff |
5345 | | */ |
5346 | 90.6k | crv = sftk_handleObject(key, session); |
5347 | 90.6k | sftk_FreeSession(session); |
5348 | 90.6k | if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) { |
5349 | 0 | crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL)); |
5350 | 0 | } |
5351 | 90.6k | if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) { |
5352 | 0 | crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL)); |
5353 | 0 | } |
5354 | 90.6k | if (crv == CKR_OK) { |
5355 | 90.6k | *phKey = key->handle; |
5356 | 90.6k | } |
5357 | 90.6k | loser: |
5358 | 90.6k | PORT_Memset(buf, 0, sizeof buf); |
5359 | 90.6k | sftk_FreeObject(key); |
5360 | 90.6k | return crv; |
5361 | 90.6k | } |
5362 | | |
5363 | | /* takes raw sessions and key handles and determines if the keys |
5364 | | * have the same value. */ |
5365 | | PRBool |
5366 | | sftk_compareKeysEqual(CK_SESSION_HANDLE hSession, |
5367 | | CK_OBJECT_HANDLE key1, CK_OBJECT_HANDLE key2) |
5368 | 0 | { |
5369 | 0 | PRBool result = PR_FALSE; |
5370 | 0 | SFTKSession *session; |
5371 | 0 | SFTKObject *key1obj = NULL; |
5372 | 0 | SFTKObject *key2obj = NULL; |
5373 | 0 | SFTKAttribute *att1 = NULL; |
5374 | 0 | SFTKAttribute *att2 = NULL; |
5375 | | |
5376 | | /* fetch the pkcs11 objects from the handles */ |
5377 | 0 | session = sftk_SessionFromHandle(hSession); |
5378 | 0 | if (session == NULL) { |
5379 | 0 | return CKR_SESSION_HANDLE_INVALID; |
5380 | 0 | } |
5381 | | |
5382 | 0 | key1obj = sftk_ObjectFromHandle(key1, session); |
5383 | 0 | key2obj = sftk_ObjectFromHandle(key2, session); |
5384 | 0 | sftk_FreeSession(session); |
5385 | 0 | if ((key1obj == NULL) || (key2obj == NULL)) { |
5386 | 0 | goto loser; |
5387 | 0 | } |
5388 | | /* fetch the value attributes */ |
5389 | 0 | att1 = sftk_FindAttribute(key1obj, CKA_VALUE); |
5390 | 0 | if (att1 == NULL) { |
5391 | 0 | goto loser; |
5392 | 0 | } |
5393 | 0 | att2 = sftk_FindAttribute(key2obj, CKA_VALUE); |
5394 | 0 | if (att2 == NULL) { |
5395 | 0 | goto loser; |
5396 | 0 | } |
5397 | | /* make sure that they are equal */ |
5398 | 0 | if (att1->attrib.ulValueLen != att2->attrib.ulValueLen) { |
5399 | 0 | goto loser; |
5400 | 0 | } |
5401 | 0 | if (PORT_Memcmp(att1->attrib.pValue, att2->attrib.pValue, |
5402 | 0 | att1->attrib.ulValueLen) != 0) { |
5403 | 0 | goto loser; |
5404 | 0 | } |
5405 | 0 | result = PR_TRUE; |
5406 | 0 | loser: |
5407 | 0 | if (key1obj) { |
5408 | 0 | sftk_FreeObject(key1obj); |
5409 | 0 | } |
5410 | 0 | if (key2obj) { |
5411 | 0 | sftk_FreeObject(key1obj); |
5412 | 0 | } |
5413 | 0 | if (att1) { |
5414 | 0 | sftk_FreeAttribute(att1); |
5415 | 0 | } |
5416 | 0 | if (att2) { |
5417 | 0 | sftk_FreeAttribute(att2); |
5418 | 0 | } |
5419 | 0 | return result; |
5420 | 0 | } |
5421 | | |
5422 | 0 | #define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ |
5423 | | |
5424 | | /* |
5425 | | * FIPS 140-3 pairwise consistency check utilized to validate key pair. |
5426 | | * |
5427 | | * This function returns |
5428 | | * CKR_OK if pairwise consistency check passed |
5429 | | * CKR_GENERAL_ERROR if pairwise consistency check failed |
5430 | | * other error codes if paiswise consistency check could not be |
5431 | | * performed, for example, CKR_HOST_MEMORY. |
5432 | | */ |
5433 | | static CK_RV |
5434 | | sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, SFTKSlot *slot, |
5435 | | SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType) |
5436 | 16.6k | { |
5437 | | /* |
5438 | | * Key type Mechanism type |
5439 | | * -------------------------------- |
5440 | | * For encrypt/decrypt: CKK_RSA => CKM_RSA_PKCS_OAEP |
5441 | | * others => CKM_INVALID_MECHANISM |
5442 | | * |
5443 | | * For sign/verify: CKK_RSA => CKM_SHA256_RSA_PKCS_PSS |
5444 | | * CKK_DSA => CKM_DSA_SHA256 |
5445 | | * CKK_EC => CKM_ECDSA_SHA256 |
5446 | | * CKK_ML_DSA => CKM_ML_DSA |
5447 | | * others => CKM_INVALID_MECHANISM |
5448 | | * |
5449 | | * None of these mechanisms has a parameter. |
5450 | | * |
5451 | | * For derive CKK_DH => CKM_DH_PKCS_DERIVE |
5452 | | * CKK_EC => CKM_ECDH1_DERIVE |
5453 | | * CKK_EC_MONTGOMERY => CKM_ECDH1_DERIVE |
5454 | | * others => CKM_INVALID_MECHANISM |
5455 | | * |
5456 | | * For KEM mechanisms: |
5457 | | * CKK_NSS_KYBER => don't |
5458 | | * CKK_NSS_ML_KEM => don't |
5459 | | * CKK_ML_KEM => CM_ML_KEM |
5460 | | * |
5461 | | * The parameters for these mechanisms is the public key. |
5462 | | */ |
5463 | 16.6k | CK_MECHANISM mech = { 0, NULL, 0 }; |
5464 | | |
5465 | 16.6k | CK_ULONG modulusLen = 0; |
5466 | 16.6k | #ifndef NSS_DISABLE_DSA |
5467 | 16.6k | CK_ULONG subPrimeLen = 0; |
5468 | 16.6k | #endif |
5469 | 16.6k | PRBool isEncryptable = PR_FALSE; |
5470 | 16.6k | PRBool canSignVerify = PR_FALSE; |
5471 | 16.6k | PRBool isDerivable = PR_FALSE; |
5472 | 16.6k | PRBool isKEM = PR_FALSE; |
5473 | 16.6k | CK_RV crv; |
5474 | | |
5475 | | /* Variables used for Encrypt/Decrypt functions. */ |
5476 | 16.6k | unsigned char *known_message = (unsigned char *)"Known Crypto Message"; |
5477 | 16.6k | unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH]; |
5478 | 16.6k | CK_ULONG bytes_decrypted; |
5479 | 16.6k | unsigned char *ciphertext; |
5480 | 16.6k | unsigned char *text_compared; |
5481 | 16.6k | CK_ULONG bytes_encrypted; |
5482 | 16.6k | CK_ULONG bytes_compared; |
5483 | | |
5484 | | /* Variables used for Signature/Verification functions. */ |
5485 | 16.6k | unsigned char *signature; |
5486 | 16.6k | CK_ULONG signature_length; |
5487 | 16.6k | SFTKAttribute *attribute; |
5488 | | |
5489 | 16.6k | switch (keyType) { |
5490 | 0 | case CKK_RSA: |
5491 | | /* Get modulus length of private key. */ |
5492 | 0 | attribute = sftk_FindAttribute(privateKey, CKA_MODULUS); |
5493 | 0 | if (attribute == NULL) { |
5494 | 0 | return CKR_DEVICE_ERROR; |
5495 | 0 | } |
5496 | 0 | modulusLen = attribute->attrib.ulValueLen; |
5497 | 0 | if (*(unsigned char *)attribute->attrib.pValue == 0) { |
5498 | 0 | modulusLen--; |
5499 | 0 | } |
5500 | 0 | sftk_FreeAttribute(attribute); |
5501 | 0 | #if RSA_MIN_MODULUS_BITS < 1023 |
5502 | | /* if we allow weak RSA keys, and this is a weak RSA key and |
5503 | | * we aren't in FIPS mode, skip the tests, These keys are |
5504 | | * factorable anyway, the pairwise test doen't matter. */ |
5505 | 0 | if ((modulusLen < 1023) && !sftk_isFIPS(slot->slotID)) { |
5506 | 0 | return CKR_OK; |
5507 | 0 | } |
5508 | 0 | #endif |
5509 | 0 | break; |
5510 | 0 | #ifndef NSS_DISABLE_DSA |
5511 | 0 | case CKK_DSA: |
5512 | | /* Get subprime length of private key. */ |
5513 | 0 | attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME); |
5514 | 0 | if (attribute == NULL) { |
5515 | 0 | return CKR_DEVICE_ERROR; |
5516 | 0 | } |
5517 | 0 | subPrimeLen = attribute->attrib.ulValueLen; |
5518 | 0 | if (subPrimeLen > 1 && |
5519 | 0 | *(unsigned char *)attribute->attrib.pValue == 0) { |
5520 | 0 | subPrimeLen--; |
5521 | 0 | } |
5522 | 0 | sftk_FreeAttribute(attribute); |
5523 | 0 | break; |
5524 | 0 | #endif |
5525 | 0 | case CKK_NSS_KYBER: |
5526 | 140 | case CKK_NSS_ML_KEM: |
5527 | | /* these aren't FIPS. we use them to generate keys without a |
5528 | | * pairwise consistency check */ |
5529 | 140 | return CKR_OK; |
5530 | 16.6k | } |
5531 | | |
5532 | | /**************************************************/ |
5533 | | /* Pairwise Consistency Check of Encrypt/Decrypt. */ |
5534 | | /**************************************************/ |
5535 | | |
5536 | 16.5k | isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT); |
5537 | | |
5538 | | /* |
5539 | | * If the decryption attribute is set, attempt to encrypt |
5540 | | * with the public key and decrypt with the private key. |
5541 | | */ |
5542 | 16.5k | if (isEncryptable) { |
5543 | 0 | if (keyType != CKK_RSA) { |
5544 | 0 | return CKR_DEVICE_ERROR; |
5545 | 0 | } |
5546 | 0 | bytes_encrypted = modulusLen; |
5547 | 0 | mech.mechanism = CKM_RSA_PKCS_OAEP; |
5548 | 0 | CK_RSA_PKCS_OAEP_PARAMS oaepParams; |
5549 | 0 | oaepParams.hashAlg = CKM_SHA256; |
5550 | 0 | oaepParams.mgf = CKG_MGF1_SHA256; |
5551 | 0 | oaepParams.source = CKZ_DATA_SPECIFIED; |
5552 | 0 | oaepParams.pSourceData = NULL; |
5553 | 0 | oaepParams.ulSourceDataLen = 0; |
5554 | 0 | mech.pParameter = &oaepParams; |
5555 | 0 | mech.ulParameterLen = sizeof(oaepParams); |
5556 | | |
5557 | | /* Allocate space for ciphertext. */ |
5558 | 0 | ciphertext = (unsigned char *)PORT_ZAlloc(bytes_encrypted); |
5559 | 0 | if (ciphertext == NULL) { |
5560 | 0 | return CKR_HOST_MEMORY; |
5561 | 0 | } |
5562 | | |
5563 | | /* Prepare for encryption using the public key. */ |
5564 | 0 | crv = NSC_EncryptInit(hSession, &mech, publicKey->handle); |
5565 | 0 | if (crv != CKR_OK) { |
5566 | 0 | PORT_Free(ciphertext); |
5567 | 0 | return crv; |
5568 | 0 | } |
5569 | | |
5570 | | /* Encrypt using the public key. */ |
5571 | 0 | crv = NSC_Encrypt(hSession, |
5572 | 0 | known_message, |
5573 | 0 | PAIRWISE_MESSAGE_LENGTH, |
5574 | 0 | ciphertext, |
5575 | 0 | &bytes_encrypted); |
5576 | 0 | if (crv != CKR_OK) { |
5577 | 0 | PORT_Free(ciphertext); |
5578 | 0 | return crv; |
5579 | 0 | } |
5580 | | |
5581 | | /* Always use the smaller of these two values . . . */ |
5582 | 0 | bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH); |
5583 | | |
5584 | | /* |
5585 | | * If there was a failure, the plaintext |
5586 | | * goes at the end, therefore . . . |
5587 | | */ |
5588 | 0 | text_compared = ciphertext + bytes_encrypted - bytes_compared; |
5589 | | |
5590 | | /* |
5591 | | * Check to ensure that ciphertext does |
5592 | | * NOT EQUAL known input message text |
5593 | | * per FIPS PUB 140-2 directive. |
5594 | | */ |
5595 | 0 | if (PORT_Memcmp(text_compared, known_message, |
5596 | 0 | bytes_compared) == 0) { |
5597 | | /* Set error to Invalid PRIVATE Key. */ |
5598 | 0 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
5599 | 0 | PORT_Free(ciphertext); |
5600 | 0 | return CKR_GENERAL_ERROR; |
5601 | 0 | } |
5602 | | |
5603 | | /* Prepare for decryption using the private key. */ |
5604 | 0 | crv = NSC_DecryptInit(hSession, &mech, privateKey->handle); |
5605 | 0 | if (crv != CKR_OK) { |
5606 | 0 | PORT_Free(ciphertext); |
5607 | 0 | return crv; |
5608 | 0 | } |
5609 | | |
5610 | 0 | memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH); |
5611 | | |
5612 | | /* |
5613 | | * Initialize bytes decrypted to be the |
5614 | | * expected PAIRWISE_MESSAGE_LENGTH. |
5615 | | */ |
5616 | 0 | bytes_decrypted = PAIRWISE_MESSAGE_LENGTH; |
5617 | | |
5618 | | /* |
5619 | | * Decrypt using the private key. |
5620 | | * NOTE: No need to reset the |
5621 | | * value of bytes_encrypted. |
5622 | | */ |
5623 | 0 | crv = NSC_Decrypt(hSession, |
5624 | 0 | ciphertext, |
5625 | 0 | bytes_encrypted, |
5626 | 0 | plaintext, |
5627 | 0 | &bytes_decrypted); |
5628 | | |
5629 | | /* Finished with ciphertext; free it. */ |
5630 | 0 | PORT_Free(ciphertext); |
5631 | |
|
5632 | 0 | if (crv != CKR_OK) { |
5633 | 0 | return crv; |
5634 | 0 | } |
5635 | | |
5636 | | /* |
5637 | | * Check to ensure that the output plaintext |
5638 | | * does EQUAL known input message text. |
5639 | | */ |
5640 | 0 | if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) || |
5641 | 0 | (PORT_Memcmp(plaintext, known_message, |
5642 | 0 | PAIRWISE_MESSAGE_LENGTH) != 0)) { |
5643 | | /* Set error to Bad PUBLIC Key. */ |
5644 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); |
5645 | 0 | return CKR_GENERAL_ERROR; |
5646 | 0 | } |
5647 | 0 | } |
5648 | | |
5649 | | /**********************************************/ |
5650 | | /* Pairwise Consistency Check of Sign/Verify. */ |
5651 | | /**********************************************/ |
5652 | | |
5653 | 16.5k | canSignVerify = sftk_isTrue(privateKey, CKA_SIGN); |
5654 | | /* Unfortunately CKA_SIGN is always true in lg dbs. We have to check the |
5655 | | * actual curve to determine if we can do sign/verify. */ |
5656 | 16.5k | if (canSignVerify && keyType == CKK_EC) { |
5657 | 3.60k | NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(privateKey, CKK_EC, &crv); |
5658 | 3.60k | if (privKey && privKey->u.ec.ecParams.name == ECCurve25519) { |
5659 | 3.60k | canSignVerify = PR_FALSE; |
5660 | 3.60k | } |
5661 | 3.60k | } |
5662 | | |
5663 | 16.5k | if (canSignVerify) { |
5664 | 0 | CK_RSA_PKCS_PSS_PARAMS pssParams; |
5665 | | /* Determine length of signature. */ |
5666 | 0 | switch (keyType) { |
5667 | 0 | case CKK_RSA: |
5668 | 0 | signature_length = modulusLen; |
5669 | 0 | mech.mechanism = CKM_SHA256_RSA_PKCS_PSS; |
5670 | 0 | pssParams.hashAlg = CKM_SHA256; |
5671 | 0 | pssParams.mgf = CKG_MGF1_SHA256; |
5672 | 0 | pssParams.sLen = 0; |
5673 | 0 | mech.pParameter = &pssParams; |
5674 | 0 | mech.ulParameterLen = sizeof(pssParams); |
5675 | 0 | break; |
5676 | 0 | #ifndef NSS_DISABLE_DSA |
5677 | 0 | case CKK_DSA: |
5678 | 0 | signature_length = DSA_MAX_SIGNATURE_LEN; |
5679 | 0 | mech.mechanism = CKM_DSA_SHA256; |
5680 | 0 | break; |
5681 | 0 | #endif |
5682 | 0 | case CKK_EC: |
5683 | 0 | signature_length = MAX_ECKEY_LEN * 2; |
5684 | 0 | mech.mechanism = CKM_ECDSA_SHA256; |
5685 | 0 | break; |
5686 | 0 | case CKK_ML_DSA: |
5687 | 0 | signature_length = MAX_ML_DSA_SIGNATURE_LEN; |
5688 | 0 | mech.mechanism = CKM_ML_DSA; |
5689 | 0 | break; |
5690 | 0 | case CKK_EC_EDWARDS: |
5691 | 0 | signature_length = ED25519_SIGN_LEN; |
5692 | 0 | mech.mechanism = CKM_EDDSA; |
5693 | 0 | break; |
5694 | 0 | default: |
5695 | 0 | return CKR_DEVICE_ERROR; |
5696 | 0 | } |
5697 | | |
5698 | | /* Allocate space for signature data. */ |
5699 | 0 | signature = (unsigned char *)PORT_ZAlloc(signature_length); |
5700 | 0 | if (signature == NULL) { |
5701 | 0 | return CKR_HOST_MEMORY; |
5702 | 0 | } |
5703 | | |
5704 | | /* Sign the known hash using the private key. */ |
5705 | 0 | crv = NSC_SignInit(hSession, &mech, privateKey->handle); |
5706 | 0 | if (crv != CKR_OK) { |
5707 | 0 | PORT_Free(signature); |
5708 | 0 | return crv; |
5709 | 0 | } |
5710 | | |
5711 | 0 | crv = NSC_Sign(hSession, |
5712 | 0 | known_message, |
5713 | 0 | PAIRWISE_MESSAGE_LENGTH, |
5714 | 0 | signature, |
5715 | 0 | &signature_length); |
5716 | 0 | if (crv != CKR_OK) { |
5717 | 0 | PORT_Free(signature); |
5718 | 0 | return crv; |
5719 | 0 | } |
5720 | | |
5721 | | /* detect trivial signing transforms */ |
5722 | 0 | if ((signature_length >= PAIRWISE_MESSAGE_LENGTH) && |
5723 | 0 | (PORT_Memcmp(known_message, signature + (signature_length - PAIRWISE_MESSAGE_LENGTH), PAIRWISE_MESSAGE_LENGTH) == 0)) { |
5724 | 0 | PORT_Free(signature); |
5725 | 0 | return CKR_GENERAL_ERROR; |
5726 | 0 | } |
5727 | | |
5728 | | /* Verify the known hash using the public key. */ |
5729 | 0 | crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); |
5730 | 0 | if (crv != CKR_OK) { |
5731 | 0 | PORT_Free(signature); |
5732 | 0 | return crv; |
5733 | 0 | } |
5734 | | |
5735 | 0 | crv = NSC_Verify(hSession, |
5736 | 0 | known_message, |
5737 | 0 | PAIRWISE_MESSAGE_LENGTH, |
5738 | 0 | signature, |
5739 | 0 | signature_length); |
5740 | | |
5741 | | /* Free signature data. */ |
5742 | 0 | PORT_Free(signature); |
5743 | |
|
5744 | 0 | if ((crv == CKR_SIGNATURE_LEN_RANGE) || |
5745 | 0 | (crv == CKR_SIGNATURE_INVALID)) { |
5746 | 0 | return CKR_GENERAL_ERROR; |
5747 | 0 | } |
5748 | 0 | if (crv != CKR_OK) { |
5749 | 0 | return crv; |
5750 | 0 | } |
5751 | 0 | } |
5752 | | |
5753 | | /**********************************************/ |
5754 | | /* Pairwise Consistency Check for Derivation */ |
5755 | | /**********************************************/ |
5756 | | |
5757 | 16.5k | isDerivable = sftk_isTrue(privateKey, CKA_DERIVE); |
5758 | | |
5759 | 16.5k | if (isDerivable) { |
5760 | 16.5k | SFTKAttribute *pubAttribute = NULL; |
5761 | 16.5k | PRBool isFIPS = sftk_isFIPS(slot->slotID); |
5762 | 16.5k | NSSLOWKEYPrivateKey *lowPrivKey = NULL; |
5763 | 16.5k | ECPrivateKey *ecPriv = NULL; |
5764 | 16.5k | SECItem *lowPubValue = NULL; |
5765 | 16.5k | SECItem item = { siBuffer, NULL, 0 }; |
5766 | 16.5k | SECStatus rv; |
5767 | | |
5768 | 16.5k | crv = CKR_OK; /*paranoia, already get's set before we drop to the end */ |
5769 | | |
5770 | | /* FIPS 140-3 requires we verify that the resulting key is a valid key |
5771 | | * by recalculating the public can an compare it to our own public |
5772 | | * key. */ |
5773 | 16.5k | lowPrivKey = sftk_GetPrivKey(privateKey, keyType, &crv); |
5774 | 16.5k | if (lowPrivKey == NULL) { |
5775 | 0 | return sftk_MapCryptError(PORT_GetError()); |
5776 | 0 | } |
5777 | | /* recalculate the public key from the private key */ |
5778 | 16.5k | switch (keyType) { |
5779 | 7.41k | case CKK_DH: |
5780 | 7.41k | rv = DH_Derive(&lowPrivKey->u.dh.base, &lowPrivKey->u.dh.prime, |
5781 | 7.41k | &lowPrivKey->u.dh.privateValue, &item, 0); |
5782 | 7.41k | if (rv != SECSuccess) { |
5783 | 0 | return CKR_GENERAL_ERROR; |
5784 | 0 | } |
5785 | 7.41k | lowPubValue = SECITEM_DupItem(&item); |
5786 | 7.41k | SECITEM_ZfreeItem(&item, PR_FALSE); |
5787 | 7.41k | pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE); |
5788 | 7.41k | break; |
5789 | 0 | case CKK_EC_MONTGOMERY: |
5790 | 9.14k | case CKK_EC: |
5791 | 9.14k | rv = EC_NewKeyFromSeed(&lowPrivKey->u.ec.ecParams, &ecPriv, |
5792 | 9.14k | lowPrivKey->u.ec.privateValue.data, |
5793 | 9.14k | lowPrivKey->u.ec.privateValue.len); |
5794 | 9.14k | if (rv != SECSuccess) { |
5795 | 0 | return CKR_GENERAL_ERROR; |
5796 | 0 | } |
5797 | | /* make sure it has the same encoding */ |
5798 | 9.14k | if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") || |
5799 | 9.14k | lowPrivKey->u.ec.ecParams.type != ec_params_named) { |
5800 | 3.60k | lowPubValue = SECITEM_DupItem(&ecPriv->publicValue); |
5801 | 5.53k | } else { |
5802 | 5.53k | lowPubValue = SEC_ASN1EncodeItem(NULL, NULL, &ecPriv->publicValue, |
5803 | 5.53k | SEC_ASN1_GET(SEC_OctetStringTemplate)); |
5804 | 5.53k | } |
5805 | 9.14k | pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT); |
5806 | | /* clear out our generated private key */ |
5807 | 9.14k | PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); |
5808 | 9.14k | break; |
5809 | 0 | default: |
5810 | 0 | return CKR_DEVICE_ERROR; |
5811 | 16.5k | } |
5812 | | |
5813 | | /* now compare new public key with our already generated key */ |
5814 | 16.5k | if ((pubAttribute == NULL) || (lowPubValue == NULL) || |
5815 | 16.5k | (pubAttribute->attrib.ulValueLen != lowPubValue->len) || |
5816 | 16.5k | (PORT_Memcmp(pubAttribute->attrib.pValue, lowPubValue->data, |
5817 | 16.5k | lowPubValue->len) != 0)) { |
5818 | 0 | if (pubAttribute) |
5819 | 0 | sftk_FreeAttribute(pubAttribute); |
5820 | 0 | if (lowPubValue) |
5821 | 0 | SECITEM_ZfreeItem(lowPubValue, PR_TRUE); |
5822 | 0 | PORT_SetError(SEC_ERROR_BAD_KEY); |
5823 | 0 | return CKR_GENERAL_ERROR; |
5824 | 0 | } |
5825 | 16.5k | SECITEM_ZfreeItem(lowPubValue, PR_TRUE); |
5826 | | |
5827 | | /* FIPS requires full validation, but in fipx mode NSC_Derive |
5828 | | * only does partial validation with approved primes, now handle |
5829 | | * full validation */ |
5830 | 16.5k | if (isFIPS && keyType == CKK_DH) { |
5831 | 0 | SECItem pubKey = { siBuffer, pubAttribute->attrib.pValue, |
5832 | 0 | pubAttribute->attrib.ulValueLen }; |
5833 | 0 | SECItem base = { siBuffer, NULL, 0 }; |
5834 | 0 | SECItem prime = { siBuffer, NULL, 0 }; |
5835 | 0 | SECItem subPrime = { siBuffer, NULL, 0 }; |
5836 | 0 | SECItem generator = { siBuffer, NULL, 0 }; |
5837 | 0 | const SECItem *subPrimePtr = &subPrime; |
5838 | |
|
5839 | 0 | crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME); |
5840 | 0 | if (crv != CKR_OK) { |
5841 | 0 | goto done; |
5842 | 0 | } |
5843 | 0 | crv = sftk_Attribute2SecItem(NULL, &base, privateKey, CKA_BASE); |
5844 | 0 | if (crv != CKR_OK) { |
5845 | 0 | goto done; |
5846 | 0 | } |
5847 | | /* we ignore the return code an only look at the length */ |
5848 | | /* do we have a known prime ? */ |
5849 | 0 | subPrimePtr = sftk_VerifyDH_Prime(&prime, &generator, isFIPS); |
5850 | 0 | if (subPrimePtr == NULL) { |
5851 | 0 | if (subPrime.len == 0) { |
5852 | | /* if not a known prime, subprime must be supplied */ |
5853 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5854 | 0 | goto done; |
5855 | 0 | } else { |
5856 | | /* not a known prime, check for primality of prime |
5857 | | * and subPrime */ |
5858 | 0 | if (!KEA_PrimeCheck(&prime)) { |
5859 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5860 | 0 | goto done; |
5861 | 0 | } |
5862 | 0 | if (!KEA_PrimeCheck(&subPrime)) { |
5863 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5864 | 0 | goto done; |
5865 | 0 | } |
5866 | | /* if we aren't using a defined group, make sure base is in the |
5867 | | * subgroup. If it's not, then our key could fail or succeed sometimes. |
5868 | | * This makes the failure reliable */ |
5869 | 0 | if (!KEA_Verify(&base, &prime, &subPrime)) { |
5870 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5871 | 0 | } |
5872 | 0 | } |
5873 | 0 | subPrimePtr = &subPrime; |
5874 | 0 | } else { |
5875 | | /* we're using a known group, make sure we are using the known generator for that group */ |
5876 | 0 | if (SECITEM_CompareItem(&generator, &base) != 0) { |
5877 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5878 | 0 | goto done; |
5879 | 0 | } |
5880 | 0 | if (subPrime.len != 0) { |
5881 | | /* we have a known prime and a supplied subPrime, |
5882 | | * make sure the subPrime matches the subPrime for |
5883 | | * the known Prime */ |
5884 | 0 | if (SECITEM_CompareItem(subPrimePtr, &subPrime) != 0) { |
5885 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5886 | 0 | goto done; |
5887 | 0 | } |
5888 | 0 | } |
5889 | 0 | } |
5890 | 0 | if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) { |
5891 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
5892 | 0 | } |
5893 | 0 | done: |
5894 | 0 | SECITEM_ZfreeItem(&base, PR_FALSE); |
5895 | 0 | SECITEM_ZfreeItem(&subPrime, PR_FALSE); |
5896 | 0 | SECITEM_ZfreeItem(&prime, PR_FALSE); |
5897 | 0 | } |
5898 | | /* clean up before we return */ |
5899 | 16.5k | sftk_FreeAttribute(pubAttribute); |
5900 | 16.5k | if (crv != CKR_OK) { |
5901 | 0 | return crv; |
5902 | 0 | } |
5903 | 16.5k | } |
5904 | | |
5905 | 16.5k | isKEM = sftk_isTrue(privateKey, CKA_ENCAPSULATE); |
5906 | 16.5k | if (isKEM) { |
5907 | 0 | unsigned char *cipher_text = NULL; |
5908 | 0 | CK_ULONG cipher_text_length = 0; |
5909 | 0 | CK_OBJECT_HANDLE key1 = CK_INVALID_HANDLE; |
5910 | 0 | CK_OBJECT_HANDLE key2 = CK_INVALID_HANDLE; |
5911 | 0 | CK_KEY_TYPE genType = CKO_SECRET_KEY; |
5912 | 0 | CK_ATTRIBUTE template = { CKA_KEY_TYPE, NULL, 0 }; |
5913 | |
|
5914 | 0 | template.pValue = &genType; |
5915 | 0 | template.ulValueLen = sizeof(genType); |
5916 | 0 | crv = CKR_OK; |
5917 | 0 | switch (keyType) { |
5918 | 0 | case CKK_ML_KEM: |
5919 | 0 | cipher_text_length = MAX_ML_KEM_CIPHER_LENGTH; |
5920 | 0 | mech.mechanism = CKM_ML_KEM; |
5921 | 0 | break; |
5922 | 0 | default: |
5923 | 0 | return CKR_DEVICE_ERROR; |
5924 | 0 | } |
5925 | | /* Allocate space for kem cipher text. */ |
5926 | 0 | cipher_text = (unsigned char *)PORT_ZAlloc(cipher_text_length); |
5927 | 0 | if (cipher_text == NULL) { |
5928 | 0 | return CKR_HOST_MEMORY; |
5929 | 0 | } |
5930 | 0 | crv = NSC_Encapsulate(hSession, &mech, publicKey->handle, &template, 1, |
5931 | 0 | &key1, cipher_text, &cipher_text_length); |
5932 | 0 | if (crv != CKR_OK) { |
5933 | 0 | goto kem_done; |
5934 | 0 | } |
5935 | 0 | crv = NSC_Decapsulate(hSession, &mech, privateKey->handle, |
5936 | 0 | cipher_text, cipher_text_length, &template, 1, |
5937 | 0 | &key2); |
5938 | 0 | if (crv != CKR_OK) { |
5939 | 0 | goto kem_done; |
5940 | 0 | } |
5941 | 0 | if (!sftk_compareKeysEqual(hSession, key1, key2)) { |
5942 | 0 | crv = CKR_DEVICE_ERROR; |
5943 | 0 | goto kem_done; |
5944 | 0 | } |
5945 | 0 | kem_done: |
5946 | | /* PORT_Free already checks for NULL */ |
5947 | 0 | PORT_Free(cipher_text); |
5948 | 0 | if (key1 != CK_INVALID_HANDLE) { |
5949 | 0 | NSC_DestroyObject(hSession, key1); |
5950 | 0 | } |
5951 | 0 | if (key2 != CK_INVALID_HANDLE) { |
5952 | 0 | NSC_DestroyObject(hSession, key2); |
5953 | 0 | } |
5954 | 0 | if (crv != CKR_OK) { |
5955 | 0 | return CKR_DEVICE_ERROR; |
5956 | 0 | } |
5957 | 0 | } |
5958 | | |
5959 | 16.5k | return CKR_OK; |
5960 | 16.5k | } |
5961 | | |
5962 | | /* NSC_GenerateKeyPair generates a public-key/private-key pair, |
5963 | | * creating new key objects. */ |
5964 | | CK_RV |
5965 | | NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession, |
5966 | | CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, |
5967 | | CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, |
5968 | | CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, |
5969 | | CK_OBJECT_HANDLE_PTR phPrivateKey) |
5970 | 88.9k | { |
5971 | 88.9k | SFTKObject *publicKey, *privateKey; |
5972 | 88.9k | SFTKSession *session; |
5973 | 88.9k | CK_KEY_TYPE key_type; |
5974 | 88.9k | CK_RV crv = CKR_OK; |
5975 | 88.9k | CK_BBOOL cktrue = CK_TRUE; |
5976 | 88.9k | SECStatus rv; |
5977 | 88.9k | CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; |
5978 | 88.9k | CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; |
5979 | 88.9k | int i; |
5980 | 88.9k | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
5981 | 88.9k | unsigned int bitSize; |
5982 | | |
5983 | | /* RSA */ |
5984 | 88.9k | int public_modulus_bits = 0; |
5985 | 88.9k | SECItem pubExp; |
5986 | 88.9k | RSAPrivateKey *rsaPriv; |
5987 | | |
5988 | 88.9k | DHParams dhParam; |
5989 | 88.9k | #ifndef NSS_DISABLE_DSA |
5990 | | /* DSA */ |
5991 | 88.9k | PQGParams pqgParam; |
5992 | 88.9k | DSAPrivateKey *dsaPriv; |
5993 | 88.9k | #endif |
5994 | 88.9k | MLDSAPrivateKey mldsaPriv; |
5995 | 88.9k | MLDSAPublicKey mldsaPub; |
5996 | | |
5997 | | /* Diffie Hellman */ |
5998 | 88.9k | DHPrivateKey *dhPriv; |
5999 | | |
6000 | | /* Elliptic Curve Cryptography */ |
6001 | 88.9k | SECItem ecEncodedParams; /* DER Encoded parameters */ |
6002 | 88.9k | ECPrivateKey *ecPriv; |
6003 | 88.9k | ECParams *ecParams; |
6004 | | |
6005 | | /* parameter set, mostly pq keys */ |
6006 | 88.9k | CK_ULONG genParamSet = 0; |
6007 | | |
6008 | 88.9k | CHECK_FORK(); |
6009 | | |
6010 | 88.9k | if (!slot) { |
6011 | 0 | return CKR_SESSION_HANDLE_INVALID; |
6012 | 0 | } |
6013 | | /* |
6014 | | * now lets create an object to hang the attributes off of |
6015 | | */ |
6016 | 88.9k | publicKey = sftk_NewObject(slot); /* fill in the handle later */ |
6017 | 88.9k | if (publicKey == NULL) { |
6018 | 0 | return CKR_HOST_MEMORY; |
6019 | 0 | } |
6020 | | |
6021 | | /* |
6022 | | * load the template values into the publicKey |
6023 | | */ |
6024 | 719k | for (i = 0; i < (int)ulPublicKeyAttributeCount; i++) { |
6025 | 630k | if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) { |
6026 | 0 | public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue; |
6027 | 0 | continue; |
6028 | 0 | } |
6029 | | |
6030 | 630k | if ((pPublicKeyTemplate[i].type == CKA_PARAMETER_SET) || |
6031 | 630k | (pPublicKeyTemplate[i].type == CKA_NSS_PARAMETER_SET)) { |
6032 | 140 | genParamSet = *(CK_ULONG *)pPublicKeyTemplate[i].pValue; |
6033 | 140 | continue; |
6034 | 140 | } |
6035 | | |
6036 | 630k | crv = sftk_AddAttributeType(publicKey, |
6037 | 630k | sftk_attr_expand(&pPublicKeyTemplate[i])); |
6038 | 630k | if (crv != CKR_OK) |
6039 | 0 | break; |
6040 | 630k | } |
6041 | | |
6042 | 88.9k | if (crv != CKR_OK) { |
6043 | 0 | sftk_FreeObject(publicKey); |
6044 | 0 | return CKR_HOST_MEMORY; |
6045 | 0 | } |
6046 | | |
6047 | 88.9k | privateKey = sftk_NewObject(slot); /* fill in the handle later */ |
6048 | 88.9k | if (privateKey == NULL) { |
6049 | 0 | sftk_FreeObject(publicKey); |
6050 | 0 | return CKR_HOST_MEMORY; |
6051 | 0 | } |
6052 | | /* |
6053 | | * now load the private key template |
6054 | | */ |
6055 | 711k | for (i = 0; i < (int)ulPrivateKeyAttributeCount; i++) { |
6056 | 622k | if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) { |
6057 | 0 | continue; |
6058 | 0 | } |
6059 | | |
6060 | 622k | crv = sftk_AddAttributeType(privateKey, |
6061 | 622k | sftk_attr_expand(&pPrivateKeyTemplate[i])); |
6062 | 622k | if (crv != CKR_OK) |
6063 | 0 | break; |
6064 | 622k | } |
6065 | | |
6066 | 88.9k | if (crv != CKR_OK) { |
6067 | 0 | sftk_FreeObject(publicKey); |
6068 | 0 | sftk_FreeObject(privateKey); |
6069 | 0 | return CKR_HOST_MEMORY; |
6070 | 0 | } |
6071 | 88.9k | sftk_DeleteAttributeType(privateKey, CKA_CLASS); |
6072 | 88.9k | sftk_DeleteAttributeType(privateKey, CKA_KEY_TYPE); |
6073 | 88.9k | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
6074 | 88.9k | sftk_DeleteAttributeType(publicKey, CKA_CLASS); |
6075 | 88.9k | sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE); |
6076 | 88.9k | sftk_DeleteAttributeType(publicKey, CKA_VALUE); |
6077 | | |
6078 | | /* Now Set up the parameters to generate the key (based on mechanism) */ |
6079 | 88.9k | switch (pMechanism->mechanism) { |
6080 | 0 | case CKM_RSA_PKCS_KEY_PAIR_GEN: |
6081 | | /* format the keys */ |
6082 | 0 | sftk_DeleteAttributeType(publicKey, CKA_MODULUS); |
6083 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6084 | 0 | sftk_DeleteAttributeType(privateKey, CKA_MODULUS); |
6085 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIVATE_EXPONENT); |
6086 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PUBLIC_EXPONENT); |
6087 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME_1); |
6088 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME_2); |
6089 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_1); |
6090 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_2); |
6091 | 0 | sftk_DeleteAttributeType(privateKey, CKA_COEFFICIENT); |
6092 | 0 | key_type = CKK_RSA; |
6093 | 0 | if (public_modulus_bits == 0) { |
6094 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6095 | 0 | break; |
6096 | 0 | } |
6097 | 0 | if (public_modulus_bits < RSA_MIN_MODULUS_BITS) { |
6098 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
6099 | 0 | break; |
6100 | 0 | } |
6101 | 0 | if (public_modulus_bits % 2 != 0) { |
6102 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
6103 | 0 | break; |
6104 | 0 | } |
6105 | | |
6106 | | /* extract the exponent */ |
6107 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pubExp, publicKey, CKA_PUBLIC_EXPONENT); |
6108 | 0 | if (crv != CKR_OK) |
6109 | 0 | break; |
6110 | 0 | bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len); |
6111 | 0 | if (bitSize < 2) { |
6112 | 0 | crv = CKR_ATTRIBUTE_VALUE_INVALID; |
6113 | 0 | SECITEM_ZfreeItem(&pubExp, PR_FALSE); |
6114 | 0 | break; |
6115 | 0 | } |
6116 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PUBLIC_EXPONENT, |
6117 | 0 | sftk_item_expand(&pubExp)); |
6118 | 0 | if (crv != CKR_OK) { |
6119 | 0 | SECITEM_ZfreeItem(&pubExp, PR_FALSE); |
6120 | 0 | break; |
6121 | 0 | } |
6122 | | |
6123 | 0 | rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp); |
6124 | 0 | SECITEM_ZfreeItem(&pubExp, PR_FALSE); |
6125 | 0 | if (rsaPriv == NULL) { |
6126 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
6127 | 0 | sftk_fatalError = PR_TRUE; |
6128 | 0 | } |
6129 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6130 | 0 | break; |
6131 | 0 | } |
6132 | | /* now fill in the RSA dependent paramenters in the public key */ |
6133 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_MODULUS, |
6134 | 0 | sftk_item_expand(&rsaPriv->modulus)); |
6135 | 0 | if (crv != CKR_OK) |
6136 | 0 | goto kpg_done; |
6137 | | /* now fill in the RSA dependent paramenters in the private key */ |
6138 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6139 | 0 | sftk_item_expand(&rsaPriv->modulus)); |
6140 | 0 | if (crv != CKR_OK) |
6141 | 0 | goto kpg_done; |
6142 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_MODULUS, |
6143 | 0 | sftk_item_expand(&rsaPriv->modulus)); |
6144 | 0 | if (crv != CKR_OK) |
6145 | 0 | goto kpg_done; |
6146 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIVATE_EXPONENT, |
6147 | 0 | sftk_item_expand(&rsaPriv->privateExponent)); |
6148 | 0 | if (crv != CKR_OK) |
6149 | 0 | goto kpg_done; |
6150 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME_1, |
6151 | 0 | sftk_item_expand(&rsaPriv->prime1)); |
6152 | 0 | if (crv != CKR_OK) |
6153 | 0 | goto kpg_done; |
6154 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME_2, |
6155 | 0 | sftk_item_expand(&rsaPriv->prime2)); |
6156 | 0 | if (crv != CKR_OK) |
6157 | 0 | goto kpg_done; |
6158 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_1, |
6159 | 0 | sftk_item_expand(&rsaPriv->exponent1)); |
6160 | 0 | if (crv != CKR_OK) |
6161 | 0 | goto kpg_done; |
6162 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_2, |
6163 | 0 | sftk_item_expand(&rsaPriv->exponent2)); |
6164 | 0 | if (crv != CKR_OK) |
6165 | 0 | goto kpg_done; |
6166 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_COEFFICIENT, |
6167 | 0 | sftk_item_expand(&rsaPriv->coefficient)); |
6168 | 0 | kpg_done: |
6169 | | /* Should zeroize the contents first, since this func doesn't. */ |
6170 | 0 | PORT_FreeArena(rsaPriv->arena, PR_TRUE); |
6171 | 0 | break; |
6172 | 0 | #ifndef NSS_DISABLE_DSA |
6173 | 0 | case CKM_DSA_KEY_PAIR_GEN: |
6174 | 0 | sftk_DeleteAttributeType(publicKey, CKA_VALUE); |
6175 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6176 | 0 | sftk_DeleteAttributeType(privateKey, CKA_PRIME); |
6177 | 0 | sftk_DeleteAttributeType(privateKey, CKA_SUBPRIME); |
6178 | 0 | sftk_DeleteAttributeType(privateKey, CKA_BASE); |
6179 | 0 | key_type = CKK_DSA; |
6180 | | |
6181 | | /* extract the necessary parameters and copy them to the private key */ |
6182 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pqgParam.prime, publicKey, CKA_PRIME); |
6183 | 0 | if (crv != CKR_OK) |
6184 | 0 | break; |
6185 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pqgParam.subPrime, publicKey, |
6186 | 0 | CKA_SUBPRIME); |
6187 | 0 | if (crv != CKR_OK) { |
6188 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6189 | 0 | break; |
6190 | 0 | } |
6191 | 0 | crv = sftk_Attribute2SSecItem(NULL, &pqgParam.base, publicKey, CKA_BASE); |
6192 | 0 | if (crv != CKR_OK) { |
6193 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6194 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6195 | 0 | break; |
6196 | 0 | } |
6197 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PRIME, |
6198 | 0 | sftk_item_expand(&pqgParam.prime)); |
6199 | 0 | if (crv != CKR_OK) { |
6200 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6201 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6202 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6203 | 0 | break; |
6204 | 0 | } |
6205 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_SUBPRIME, |
6206 | 0 | sftk_item_expand(&pqgParam.subPrime)); |
6207 | 0 | if (crv != CKR_OK) { |
6208 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6209 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6210 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6211 | 0 | break; |
6212 | 0 | } |
6213 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_BASE, |
6214 | 0 | sftk_item_expand(&pqgParam.base)); |
6215 | 0 | if (crv != CKR_OK) { |
6216 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6217 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6218 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6219 | 0 | break; |
6220 | 0 | } |
6221 | | |
6222 | | /* |
6223 | | * these are checked by DSA_NewKey |
6224 | | */ |
6225 | 0 | bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data, |
6226 | 0 | pqgParam.subPrime.len); |
6227 | 0 | if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) { |
6228 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6229 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6230 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6231 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6232 | 0 | break; |
6233 | 0 | } |
6234 | 0 | bitSize = sftk_GetLengthInBits(pqgParam.prime.data, pqgParam.prime.len); |
6235 | 0 | if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) { |
6236 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6237 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6238 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6239 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6240 | 0 | break; |
6241 | 0 | } |
6242 | 0 | bitSize = sftk_GetLengthInBits(pqgParam.base.data, pqgParam.base.len); |
6243 | 0 | if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) { |
6244 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6245 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6246 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6247 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6248 | 0 | break; |
6249 | 0 | } |
6250 | | |
6251 | | /* Generate the key */ |
6252 | 0 | rv = DSA_NewKey(&pqgParam, &dsaPriv); |
6253 | |
|
6254 | 0 | SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE); |
6255 | 0 | SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE); |
6256 | 0 | SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE); |
6257 | |
|
6258 | 0 | if (rv != SECSuccess) { |
6259 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
6260 | 0 | sftk_fatalError = PR_TRUE; |
6261 | 0 | } |
6262 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6263 | 0 | break; |
6264 | 0 | } |
6265 | | |
6266 | | /* store the generated key into the attributes */ |
6267 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, |
6268 | 0 | sftk_item_expand(&dsaPriv->publicValue)); |
6269 | 0 | if (crv != CKR_OK) |
6270 | 0 | goto dsagn_done; |
6271 | | |
6272 | | /* now fill in the RSA dependent paramenters in the private key */ |
6273 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6274 | 0 | sftk_item_expand(&dsaPriv->publicValue)); |
6275 | 0 | if (crv != CKR_OK) |
6276 | 0 | goto dsagn_done; |
6277 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
6278 | 0 | sftk_item_expand(&dsaPriv->privateValue)); |
6279 | |
|
6280 | 0 | dsagn_done: |
6281 | | /* should zeroize, since this function doesn't. */ |
6282 | 0 | PORT_FreeArena(dsaPriv->params.arena, PR_TRUE); |
6283 | 0 | break; |
6284 | 0 | #endif |
6285 | 7.93k | case CKM_DH_PKCS_KEY_PAIR_GEN: |
6286 | 7.93k | sftk_DeleteAttributeType(privateKey, CKA_PRIME); |
6287 | 7.93k | sftk_DeleteAttributeType(privateKey, CKA_BASE); |
6288 | 7.93k | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
6289 | 7.93k | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6290 | 7.93k | key_type = CKK_DH; |
6291 | | |
6292 | | /* extract the necessary parameters and copy them to private keys */ |
6293 | 7.93k | crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey, |
6294 | 7.93k | CKA_PRIME); |
6295 | 7.93k | if (crv != CKR_OK) |
6296 | 0 | break; |
6297 | 7.93k | crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE); |
6298 | 7.93k | if (crv != CKR_OK) { |
6299 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
6300 | 0 | break; |
6301 | 0 | } |
6302 | 7.93k | crv = sftk_AddAttributeType(privateKey, CKA_PRIME, |
6303 | 7.93k | sftk_item_expand(&dhParam.prime)); |
6304 | 7.93k | if (crv != CKR_OK) { |
6305 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
6306 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
6307 | 0 | break; |
6308 | 0 | } |
6309 | 7.93k | crv = sftk_AddAttributeType(privateKey, CKA_BASE, |
6310 | 7.93k | sftk_item_expand(&dhParam.base)); |
6311 | 7.93k | if (crv != CKR_OK) { |
6312 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
6313 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
6314 | 0 | break; |
6315 | 0 | } |
6316 | 7.93k | bitSize = sftk_GetLengthInBits(dhParam.prime.data, dhParam.prime.len); |
6317 | 7.93k | if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) { |
6318 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6319 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
6320 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
6321 | 0 | break; |
6322 | 0 | } |
6323 | 7.93k | bitSize = sftk_GetLengthInBits(dhParam.base.data, dhParam.base.len); |
6324 | 7.93k | if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) { |
6325 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6326 | 0 | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
6327 | 0 | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
6328 | 0 | break; |
6329 | 0 | } |
6330 | | |
6331 | 7.93k | rv = DH_NewKey(&dhParam, &dhPriv); |
6332 | 7.93k | SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE); |
6333 | 7.93k | SECITEM_ZfreeItem(&dhParam.base, PR_FALSE); |
6334 | 7.93k | if (rv != SECSuccess) { |
6335 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
6336 | 0 | sftk_fatalError = PR_TRUE; |
6337 | 0 | } |
6338 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6339 | 0 | break; |
6340 | 0 | } |
6341 | | |
6342 | 7.93k | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, |
6343 | 7.93k | sftk_item_expand(&dhPriv->publicValue)); |
6344 | 7.93k | if (crv != CKR_OK) |
6345 | 0 | goto dhgn_done; |
6346 | | |
6347 | 7.93k | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6348 | 7.93k | sftk_item_expand(&dhPriv->publicValue)); |
6349 | 7.93k | if (crv != CKR_OK) |
6350 | 0 | goto dhgn_done; |
6351 | | |
6352 | 7.93k | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
6353 | 7.93k | sftk_item_expand(&dhPriv->privateValue)); |
6354 | | |
6355 | 7.93k | dhgn_done: |
6356 | | /* should zeroize, since this function doesn't. */ |
6357 | 7.93k | PORT_FreeArena(dhPriv->arena, PR_TRUE); |
6358 | 7.93k | break; |
6359 | | |
6360 | 9.16k | case CKM_EC_KEY_PAIR_GEN: |
6361 | 80.8k | case CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN: |
6362 | 80.8k | sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS); |
6363 | 80.8k | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
6364 | 80.8k | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6365 | 80.8k | key_type = CKK_EC; |
6366 | | |
6367 | | /* extract the necessary parameters and copy them to private keys */ |
6368 | 80.8k | crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, |
6369 | 80.8k | CKA_EC_PARAMS); |
6370 | 80.8k | if (crv != CKR_OK) |
6371 | 0 | break; |
6372 | | |
6373 | 80.8k | crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS, |
6374 | 80.8k | sftk_item_expand(&ecEncodedParams)); |
6375 | 80.8k | if (crv != CKR_OK) { |
6376 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
6377 | 0 | break; |
6378 | 0 | } |
6379 | | |
6380 | | /* Decode ec params before calling EC_NewKey */ |
6381 | 80.8k | rv = EC_DecodeParams(&ecEncodedParams, &ecParams); |
6382 | 80.8k | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
6383 | 80.8k | if (rv != SECSuccess) { |
6384 | 416 | crv = sftk_MapCryptError(PORT_GetError()); |
6385 | 416 | break; |
6386 | 416 | } |
6387 | 80.4k | rv = EC_NewKey(ecParams, &ecPriv); |
6388 | 80.4k | if (rv != SECSuccess) { |
6389 | 337 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
6390 | 0 | sftk_fatalError = PR_TRUE; |
6391 | 0 | } |
6392 | 337 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
6393 | 337 | crv = sftk_MapCryptError(PORT_GetError()); |
6394 | 337 | break; |
6395 | 337 | } |
6396 | | |
6397 | 80.1k | if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") || |
6398 | 80.1k | ecParams->type != ec_params_named) { |
6399 | 20.3k | PORT_FreeArena(ecParams->arena, PR_TRUE); |
6400 | 20.3k | crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
6401 | 20.3k | sftk_item_expand(&ecPriv->publicValue)); |
6402 | 59.7k | } else { |
6403 | 59.7k | PORT_FreeArena(ecParams->arena, PR_TRUE); |
6404 | 59.7k | SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, |
6405 | 59.7k | &ecPriv->publicValue, |
6406 | 59.7k | SEC_ASN1_GET(SEC_OctetStringTemplate)); |
6407 | 59.7k | if (!pubValue) { |
6408 | 0 | crv = CKR_ARGUMENTS_BAD; |
6409 | 0 | goto ecgn_done; |
6410 | 0 | } |
6411 | 59.7k | crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
6412 | 59.7k | sftk_item_expand(pubValue)); |
6413 | 59.7k | SECITEM_ZfreeItem(pubValue, PR_TRUE); |
6414 | 59.7k | } |
6415 | 80.1k | if (crv != CKR_OK) |
6416 | 0 | goto ecgn_done; |
6417 | | |
6418 | 80.1k | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
6419 | 80.1k | sftk_item_expand(&ecPriv->privateValue)); |
6420 | 80.1k | if (crv != CKR_OK) |
6421 | 0 | goto ecgn_done; |
6422 | | |
6423 | 80.1k | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6424 | 80.1k | sftk_item_expand(&ecPriv->publicValue)); |
6425 | 80.1k | ecgn_done: |
6426 | | /* should zeroize, since this function doesn't. */ |
6427 | 80.1k | PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); |
6428 | 80.1k | break; |
6429 | | |
6430 | 0 | #ifndef NSS_DISABLE_KYBER |
6431 | 0 | case CKM_NSS_KYBER_KEY_PAIR_GEN: |
6432 | 0 | key_type = CKK_NSS_KYBER; |
6433 | 0 | goto do_ml_kem; |
6434 | 0 | #endif |
6435 | 140 | case CKM_NSS_ML_KEM_KEY_PAIR_GEN: |
6436 | 140 | key_type = CKK_NSS_ML_KEM; |
6437 | 140 | goto do_ml_kem; |
6438 | | |
6439 | 0 | case CKM_ML_KEM_KEY_PAIR_GEN: |
6440 | 0 | key_type = CKK_ML_KEM; |
6441 | |
|
6442 | 140 | do_ml_kem: |
6443 | 140 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6444 | 140 | SECItem privKey = { siBuffer, NULL, 0 }; |
6445 | 140 | SECItem pubKey = { siBuffer, NULL, 0 }; |
6446 | 140 | KyberParams kyberParams = sftk_kyber_PK11ParamToInternal(genParamSet); |
6447 | 140 | if (!sftk_kyber_AllocPrivKeyItem(kyberParams, &privKey)) { |
6448 | 0 | crv = CKR_HOST_MEMORY; |
6449 | 0 | goto kyber_done; |
6450 | 0 | } |
6451 | 140 | if (!sftk_kyber_AllocPubKeyItem(kyberParams, &pubKey)) { |
6452 | 0 | crv = CKR_HOST_MEMORY; |
6453 | 0 | goto kyber_done; |
6454 | 0 | } |
6455 | 140 | rv = Kyber_NewKey(kyberParams, NULL, &privKey, &pubKey); |
6456 | 140 | if (rv != SECSuccess) { |
6457 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6458 | 0 | goto kyber_done; |
6459 | 0 | } |
6460 | | |
6461 | 140 | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, sftk_item_expand(&pubKey)); |
6462 | 140 | if (crv != CKR_OK) { |
6463 | 0 | goto kyber_done; |
6464 | 0 | } |
6465 | 140 | crv = sftk_AddAttributeType(publicKey, CKA_PARAMETER_SET, |
6466 | 140 | &genParamSet, |
6467 | 140 | sizeof(CK_ML_KEM_PARAMETER_SET_TYPE)); |
6468 | 140 | if (crv != CKR_OK) { |
6469 | 0 | goto kyber_done; |
6470 | 0 | } |
6471 | 140 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
6472 | 140 | sftk_item_expand(&privKey)); |
6473 | 140 | if (crv != CKR_OK) { |
6474 | 0 | goto kyber_done; |
6475 | 0 | } |
6476 | 140 | crv = sftk_AddAttributeType(privateKey, CKA_PARAMETER_SET, |
6477 | 140 | &genParamSet, |
6478 | 140 | sizeof(CK_ML_KEM_PARAMETER_SET_TYPE)); |
6479 | 140 | if (crv != CKR_OK) { |
6480 | 0 | goto kyber_done; |
6481 | 0 | } |
6482 | 140 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6483 | 140 | sftk_item_expand(&pubKey)); |
6484 | 140 | kyber_done: |
6485 | 140 | SECITEM_ZfreeItem(&privKey, PR_FALSE); |
6486 | 140 | SECITEM_FreeItem(&pubKey, PR_FALSE); |
6487 | 140 | break; |
6488 | | |
6489 | 0 | case CKM_ML_DSA_KEY_PAIR_GEN: |
6490 | 0 | sftk_DeleteAttributeType(publicKey, CKA_VALUE); |
6491 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6492 | 0 | sftk_DeleteAttributeType(privateKey, CKA_SEED); |
6493 | 0 | key_type = CKK_ML_DSA; |
6494 | | |
6495 | | /* |
6496 | | * the parameters are recognized by us |
6497 | | */ |
6498 | 0 | bitSize = sftk_MLDSAGetSigLen(genParamSet); |
6499 | 0 | if (bitSize == 0) { |
6500 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
6501 | 0 | break; |
6502 | 0 | } |
6503 | | |
6504 | | /* Generate the key */ |
6505 | 0 | rv = MLDSA_NewKey(genParamSet, NULL, &mldsaPriv, &mldsaPub); |
6506 | |
|
6507 | 0 | if (rv != SECSuccess) { |
6508 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
6509 | 0 | sftk_fatalError = PR_TRUE; |
6510 | 0 | } |
6511 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6512 | 0 | break; |
6513 | 0 | } |
6514 | | |
6515 | | /* store the generated key into the attributes */ |
6516 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_VALUE, |
6517 | 0 | mldsaPub.keyVal, mldsaPub.keyValLen); |
6518 | 0 | if (crv != CKR_OK) |
6519 | 0 | goto mldsagn_done; |
6520 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_PARAMETER_SET, |
6521 | 0 | &genParamSet, sizeof(CK_ML_DSA_PARAMETER_SET_TYPE)); |
6522 | 0 | if (crv != CKR_OK) { |
6523 | 0 | goto mldsagn_done; |
6524 | 0 | } |
6525 | | |
6526 | | /* now fill in the ML-DSA specfic paramenters in the private key */ |
6527 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6528 | 0 | mldsaPub.keyVal, mldsaPub.keyValLen); |
6529 | 0 | if (crv != CKR_OK) |
6530 | 0 | goto mldsagn_done; |
6531 | | |
6532 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
6533 | 0 | mldsaPriv.keyVal, |
6534 | 0 | mldsaPriv.keyValLen); |
6535 | 0 | if (crv != CKR_OK) |
6536 | 0 | goto mldsagn_done; |
6537 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_PARAMETER_SET, |
6538 | 0 | &genParamSet, sizeof(CK_ML_DSA_PARAMETER_SET_TYPE)); |
6539 | 0 | if (crv != CKR_OK) { |
6540 | 0 | goto mldsagn_done; |
6541 | 0 | } |
6542 | | |
6543 | 0 | if (mldsaPriv.seedLen != 0) { |
6544 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_SEED, |
6545 | 0 | mldsaPriv.seed, mldsaPriv.seedLen); |
6546 | 0 | if (crv != CKR_OK) { |
6547 | 0 | goto mldsagn_done; |
6548 | 0 | } |
6549 | | /* pseudo attribute that says the seed came with the key |
6550 | | * so don't try to regenerate the key in handleObject. |
6551 | | * it will be removed before the object sees the light of |
6552 | | * day. */ |
6553 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_SEED_OK, |
6554 | 0 | NULL, 0); |
6555 | | /* it was either this or a comment 'fall through' which would |
6556 | | * be cryptic to some users */ |
6557 | 0 | if (crv != CKR_OK) { |
6558 | 0 | goto mldsagn_done; |
6559 | 0 | } |
6560 | 0 | } |
6561 | 0 | mldsagn_done: |
6562 | 0 | PORT_SafeZero(&mldsaPriv, sizeof(mldsaPriv)); |
6563 | 0 | PORT_SafeZero(&mldsaPub, sizeof(mldsaPub)); |
6564 | 0 | break; |
6565 | | |
6566 | 0 | case CKM_EC_MONTGOMERY_KEY_PAIR_GEN: |
6567 | 0 | case CKM_EC_EDWARDS_KEY_PAIR_GEN: |
6568 | 0 | sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS); |
6569 | 0 | sftk_DeleteAttributeType(privateKey, CKA_VALUE); |
6570 | 0 | sftk_DeleteAttributeType(privateKey, CKA_NSS_DB); |
6571 | 0 | key_type = (pMechanism->mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN) ? CKK_EC_EDWARDS : CKK_EC_MONTGOMERY; |
6572 | | |
6573 | | /* extract the necessary parameters and copy them to private keys */ |
6574 | 0 | crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, |
6575 | 0 | CKA_EC_PARAMS); |
6576 | 0 | if (crv != CKR_OK) { |
6577 | 0 | break; |
6578 | 0 | } |
6579 | | |
6580 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS, |
6581 | 0 | sftk_item_expand(&ecEncodedParams)); |
6582 | 0 | if (crv != CKR_OK) { |
6583 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
6584 | 0 | break; |
6585 | 0 | } |
6586 | | |
6587 | | /* Decode ec params before calling EC_NewKey */ |
6588 | 0 | rv = EC_DecodeParams(&ecEncodedParams, &ecParams); |
6589 | 0 | SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE); |
6590 | 0 | if (rv != SECSuccess) { |
6591 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6592 | 0 | break; |
6593 | 0 | } |
6594 | | |
6595 | 0 | rv = EC_NewKey(ecParams, &ecPriv); |
6596 | 0 | if (rv != SECSuccess) { |
6597 | 0 | if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { |
6598 | 0 | sftk_fatalError = PR_TRUE; |
6599 | 0 | } |
6600 | 0 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
6601 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
6602 | 0 | break; |
6603 | 0 | } |
6604 | 0 | PORT_FreeArena(ecParams->arena, PR_TRUE); |
6605 | 0 | crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, |
6606 | 0 | sftk_item_expand(&ecPriv->publicValue)); |
6607 | 0 | if (crv != CKR_OK) |
6608 | 0 | goto edgn_done; |
6609 | | |
6610 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_VALUE, |
6611 | 0 | sftk_item_expand(&ecPriv->privateValue)); |
6612 | 0 | if (crv != CKR_OK) |
6613 | 0 | goto edgn_done; |
6614 | | |
6615 | 0 | crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB, |
6616 | 0 | sftk_item_expand(&ecPriv->publicValue)); |
6617 | 0 | edgn_done: |
6618 | | /* should zeroize, since this function doesn't. */ |
6619 | 0 | PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); |
6620 | 0 | break; |
6621 | | |
6622 | 0 | default: |
6623 | 0 | crv = CKR_MECHANISM_INVALID; |
6624 | 88.9k | } |
6625 | | |
6626 | 88.9k | if (crv != CKR_OK) { |
6627 | 753 | sftk_FreeObject(privateKey); |
6628 | 753 | sftk_FreeObject(publicKey); |
6629 | 753 | return crv; |
6630 | 753 | } |
6631 | | |
6632 | | /* Add the class, key_type The loop lets us check errors blow out |
6633 | | * on errors and clean up at the bottom */ |
6634 | 88.1k | session = NULL; /* make pedtantic happy... session cannot leave the*/ |
6635 | | /* loop below NULL unless an error is set... */ |
6636 | 88.1k | do { |
6637 | 88.1k | crv = sftk_AddAttributeType(privateKey, CKA_CLASS, &privClass, |
6638 | 88.1k | sizeof(CK_OBJECT_CLASS)); |
6639 | 88.1k | if (crv != CKR_OK) |
6640 | 0 | break; |
6641 | 88.1k | crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &pubClass, |
6642 | 88.1k | sizeof(CK_OBJECT_CLASS)); |
6643 | 88.1k | if (crv != CKR_OK) |
6644 | 0 | break; |
6645 | 88.1k | crv = sftk_AddAttributeType(privateKey, CKA_KEY_TYPE, &key_type, |
6646 | 88.1k | sizeof(CK_KEY_TYPE)); |
6647 | 88.1k | if (crv != CKR_OK) |
6648 | 0 | break; |
6649 | 88.1k | crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &key_type, |
6650 | 88.1k | sizeof(CK_KEY_TYPE)); |
6651 | 88.1k | if (crv != CKR_OK) |
6652 | 0 | break; |
6653 | 88.1k | session = sftk_SessionFromHandle(hSession); |
6654 | 88.1k | if (session == NULL) |
6655 | 0 | crv = CKR_SESSION_HANDLE_INVALID; |
6656 | 88.1k | } while (0); |
6657 | | |
6658 | 88.1k | if (crv != CKR_OK) { |
6659 | 0 | sftk_FreeObject(privateKey); |
6660 | 0 | sftk_FreeObject(publicKey); |
6661 | 0 | return crv; |
6662 | 0 | } |
6663 | | |
6664 | | /* |
6665 | | * handle the base object cleanup for the public Key |
6666 | | */ |
6667 | 88.1k | crv = sftk_handleObject(privateKey, session); |
6668 | 88.1k | if (crv != CKR_OK) { |
6669 | 0 | sftk_FreeSession(session); |
6670 | 0 | sftk_FreeObject(privateKey); |
6671 | 0 | sftk_FreeObject(publicKey); |
6672 | 0 | return crv; |
6673 | 0 | } |
6674 | | |
6675 | | /* |
6676 | | * handle the base object cleanup for the private Key |
6677 | | * If we have any problems, we destroy the public Key we've |
6678 | | * created and linked. |
6679 | | */ |
6680 | 88.1k | crv = sftk_handleObject(publicKey, session); |
6681 | 88.1k | sftk_FreeSession(session); |
6682 | 88.1k | if (crv != CKR_OK) { |
6683 | 524 | sftk_FreeObject(publicKey); |
6684 | 524 | NSC_DestroyObject(hSession, privateKey->handle); |
6685 | 524 | sftk_FreeObject(privateKey); |
6686 | 524 | return crv; |
6687 | 524 | } |
6688 | 87.6k | if (sftk_isTrue(privateKey, CKA_SENSITIVE)) { |
6689 | 3.60k | crv = sftk_forceAttribute(privateKey, CKA_ALWAYS_SENSITIVE, |
6690 | 3.60k | &cktrue, sizeof(CK_BBOOL)); |
6691 | 3.60k | } |
6692 | 87.6k | if (crv == CKR_OK && sftk_isTrue(publicKey, CKA_SENSITIVE)) { |
6693 | 0 | crv = sftk_forceAttribute(publicKey, CKA_ALWAYS_SENSITIVE, |
6694 | 0 | &cktrue, sizeof(CK_BBOOL)); |
6695 | 0 | } |
6696 | 87.6k | if (crv == CKR_OK && !sftk_isTrue(privateKey, CKA_EXTRACTABLE)) { |
6697 | 0 | crv = sftk_forceAttribute(privateKey, CKA_NEVER_EXTRACTABLE, |
6698 | 0 | &cktrue, sizeof(CK_BBOOL)); |
6699 | 0 | } |
6700 | 87.6k | if (crv == CKR_OK && !sftk_isTrue(publicKey, CKA_EXTRACTABLE)) { |
6701 | 87.6k | crv = sftk_forceAttribute(publicKey, CKA_NEVER_EXTRACTABLE, |
6702 | 87.6k | &cktrue, sizeof(CK_BBOOL)); |
6703 | 87.6k | } |
6704 | | |
6705 | 87.6k | if (crv == CKR_OK && |
6706 | 87.6k | pMechanism->mechanism != CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN) { |
6707 | | /* Perform FIPS 140-2 pairwise consistency check. */ |
6708 | 16.6k | crv = sftk_PairwiseConsistencyCheck(hSession, slot, |
6709 | 16.6k | publicKey, privateKey, key_type); |
6710 | 16.6k | if (crv != CKR_OK) { |
6711 | 0 | if (sftk_audit_enabled) { |
6712 | 0 | char msg[128]; |
6713 | 0 | PR_snprintf(msg, sizeof msg, |
6714 | 0 | "C_GenerateKeyPair(hSession=0x%08lX, " |
6715 | 0 | "pMechanism->mechanism=0x%08lX)=0x%08lX " |
6716 | 0 | "self-test: pair-wise consistency test failed", |
6717 | 0 | (PRUint32)hSession, (PRUint32)pMechanism->mechanism, |
6718 | 0 | (PRUint32)crv); |
6719 | 0 | sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg); |
6720 | 0 | } |
6721 | 0 | } |
6722 | 16.6k | } |
6723 | | |
6724 | 87.6k | if (crv != CKR_OK) { |
6725 | 0 | NSC_DestroyObject(hSession, publicKey->handle); |
6726 | 0 | sftk_FreeObject(publicKey); |
6727 | 0 | NSC_DestroyObject(hSession, privateKey->handle); |
6728 | 0 | sftk_FreeObject(privateKey); |
6729 | 0 | return crv; |
6730 | 0 | } |
6731 | 87.6k | *phPrivateKey = privateKey->handle; |
6732 | 87.6k | *phPublicKey = publicKey->handle; |
6733 | 87.6k | sftk_FreeObject(publicKey); |
6734 | 87.6k | sftk_FreeObject(privateKey); |
6735 | | |
6736 | 87.6k | return CKR_OK; |
6737 | 87.6k | } |
6738 | | |
6739 | | static SECItem * |
6740 | | sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp) |
6741 | 0 | { |
6742 | 0 | NSSLOWKEYPrivateKey *lk = NULL; |
6743 | 0 | NSSLOWKEYPrivateKeyInfo *pki = NULL; |
6744 | 0 | SFTKAttribute *attribute = NULL; |
6745 | 0 | PLArenaPool *arena = NULL; |
6746 | 0 | SECOidTag algorithm = SEC_OID_UNKNOWN; |
6747 | 0 | void *dummy, *param = NULL; |
6748 | 0 | SECStatus rv = SECSuccess; |
6749 | 0 | SECItem *encodedKey = NULL; |
6750 | | #ifdef EC_DEBUG |
6751 | | SECItem *fordebug; |
6752 | | #endif |
6753 | 0 | int savelen; |
6754 | |
|
6755 | 0 | if (!key) { |
6756 | 0 | *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */ |
6757 | 0 | return NULL; |
6758 | 0 | } |
6759 | | |
6760 | 0 | attribute = sftk_FindAttribute(key, CKA_KEY_TYPE); |
6761 | 0 | if (!attribute) { |
6762 | 0 | *crvp = CKR_KEY_TYPE_INCONSISTENT; |
6763 | 0 | return NULL; |
6764 | 0 | } |
6765 | | |
6766 | 0 | lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp); |
6767 | 0 | sftk_FreeAttribute(attribute); |
6768 | 0 | if (!lk) { |
6769 | 0 | return NULL; |
6770 | 0 | } |
6771 | | |
6772 | 0 | arena = PORT_NewArena(2048); /* XXX different size? */ |
6773 | 0 | if (!arena) { |
6774 | 0 | *crvp = CKR_HOST_MEMORY; |
6775 | 0 | rv = SECFailure; |
6776 | 0 | goto loser; |
6777 | 0 | } |
6778 | | |
6779 | 0 | pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena, |
6780 | 0 | sizeof(NSSLOWKEYPrivateKeyInfo)); |
6781 | 0 | if (!pki) { |
6782 | 0 | *crvp = CKR_HOST_MEMORY; |
6783 | 0 | rv = SECFailure; |
6784 | 0 | goto loser; |
6785 | 0 | } |
6786 | 0 | pki->arena = arena; |
6787 | |
|
6788 | 0 | param = NULL; |
6789 | 0 | switch (lk->keyType) { |
6790 | 0 | case NSSLOWKEYRSAKey: |
6791 | 0 | prepare_low_rsa_priv_key_for_asn1(lk); |
6792 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6793 | 0 | nsslowkey_RSAPrivateKeyTemplate); |
6794 | | |
6795 | | /* determine RSA key type from the CKA_PUBLIC_KEY_INFO if present */ |
6796 | 0 | attribute = sftk_FindAttribute(key, CKA_PUBLIC_KEY_INFO); |
6797 | 0 | if (attribute) { |
6798 | 0 | NSSLOWKEYSubjectPublicKeyInfo *publicKeyInfo; |
6799 | 0 | SECItem spki; |
6800 | |
|
6801 | 0 | spki.data = attribute->attrib.pValue; |
6802 | 0 | spki.len = attribute->attrib.ulValueLen; |
6803 | |
|
6804 | 0 | publicKeyInfo = PORT_ArenaZAlloc(arena, |
6805 | 0 | sizeof(NSSLOWKEYSubjectPublicKeyInfo)); |
6806 | 0 | if (!publicKeyInfo) { |
6807 | 0 | sftk_FreeAttribute(attribute); |
6808 | 0 | *crvp = CKR_HOST_MEMORY; |
6809 | 0 | rv = SECFailure; |
6810 | 0 | goto loser; |
6811 | 0 | } |
6812 | 0 | rv = SEC_QuickDERDecodeItem(arena, publicKeyInfo, |
6813 | 0 | nsslowkey_SubjectPublicKeyInfoTemplate, |
6814 | 0 | &spki); |
6815 | 0 | if (rv != SECSuccess) { |
6816 | 0 | sftk_FreeAttribute(attribute); |
6817 | 0 | *crvp = CKR_KEY_TYPE_INCONSISTENT; |
6818 | 0 | goto loser; |
6819 | 0 | } |
6820 | 0 | algorithm = SECOID_GetAlgorithmTag(&publicKeyInfo->algorithm); |
6821 | 0 | if (algorithm != SEC_OID_PKCS1_RSA_ENCRYPTION && |
6822 | 0 | algorithm != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { |
6823 | 0 | sftk_FreeAttribute(attribute); |
6824 | 0 | rv = SECFailure; |
6825 | 0 | *crvp = CKR_KEY_TYPE_INCONSISTENT; |
6826 | 0 | goto loser; |
6827 | 0 | } |
6828 | 0 | param = SECITEM_DupItem(&publicKeyInfo->algorithm.parameters); |
6829 | 0 | if (!param) { |
6830 | 0 | sftk_FreeAttribute(attribute); |
6831 | 0 | rv = SECFailure; |
6832 | 0 | *crvp = CKR_HOST_MEMORY; |
6833 | 0 | goto loser; |
6834 | 0 | } |
6835 | 0 | sftk_FreeAttribute(attribute); |
6836 | 0 | } else { |
6837 | | /* default to PKCS #1 */ |
6838 | 0 | algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; |
6839 | 0 | } |
6840 | 0 | break; |
6841 | 0 | case NSSLOWKEYDSAKey: |
6842 | 0 | prepare_low_dsa_priv_key_export_for_asn1(lk); |
6843 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6844 | 0 | nsslowkey_DSAPrivateKeyExportTemplate); |
6845 | 0 | prepare_low_pqg_params_for_asn1(&lk->u.dsa.params); |
6846 | 0 | param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params), |
6847 | 0 | nsslowkey_PQGParamsTemplate); |
6848 | 0 | algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE; |
6849 | 0 | break; |
6850 | 0 | case NSSLOWKEYECKey: |
6851 | 0 | prepare_low_ec_priv_key_for_asn1(lk); |
6852 | | /* Public value is encoded as a bit string so adjust length |
6853 | | * to be in bits before ASN encoding and readjust |
6854 | | * immediately after. |
6855 | | * |
6856 | | * Since the SECG specification recommends not including the |
6857 | | * parameters as part of ECPrivateKey, we zero out the curveOID |
6858 | | * length before encoding and restore it later. |
6859 | | */ |
6860 | 0 | lk->u.ec.publicValue.len <<= 3; |
6861 | 0 | savelen = lk->u.ec.ecParams.curveOID.len; |
6862 | 0 | lk->u.ec.ecParams.curveOID.len = 0; |
6863 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6864 | 0 | nsslowkey_ECPrivateKeyTemplate); |
6865 | 0 | lk->u.ec.ecParams.curveOID.len = savelen; |
6866 | 0 | lk->u.ec.publicValue.len >>= 3; |
6867 | |
|
6868 | | #ifdef EC_DEBUG |
6869 | | fordebug = &pki->privateKey; |
6870 | | SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType, |
6871 | | fordebug); |
6872 | | #endif |
6873 | |
|
6874 | 0 | param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding); |
6875 | |
|
6876 | 0 | algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY; |
6877 | 0 | break; |
6878 | 0 | case NSSLOWKEYMLDSAKey: { |
6879 | 0 | SECItem seed = { siBuffer, NULL, 0 }; |
6880 | 0 | SECItem keyVal = { siBuffer, NULL, 0 }; |
6881 | 0 | dummy = NULL; |
6882 | | |
6883 | | /* paramSet sets the algorithm */ |
6884 | 0 | switch (lk->u.mldsa.paramSet) { |
6885 | 0 | case CKP_ML_DSA_44: |
6886 | 0 | algorithm = SEC_OID_ML_DSA_44_PUBLIC_KEY; |
6887 | 0 | break; |
6888 | 0 | case CKP_ML_DSA_65: |
6889 | 0 | algorithm = SEC_OID_ML_DSA_65_PUBLIC_KEY; |
6890 | 0 | break; |
6891 | 0 | case CKP_ML_DSA_87: |
6892 | 0 | algorithm = SEC_OID_ML_DSA_87_PUBLIC_KEY; |
6893 | 0 | break; |
6894 | 0 | default: |
6895 | 0 | algorithm = SEC_OID_UNKNOWN; |
6896 | 0 | break; |
6897 | 0 | } |
6898 | 0 | if (algorithm == SEC_OID_UNKNOWN) { |
6899 | 0 | break; |
6900 | 0 | } |
6901 | | |
6902 | | /* if we have the seed, copy it */ |
6903 | 0 | if (lk->u.mldsa.seedLen != 0) { |
6904 | 0 | rv = SECITEM_MakeItem(arena, &seed, lk->u.mldsa.seed, |
6905 | 0 | lk->u.mldsa.seedLen); |
6906 | 0 | if (rv != SECSuccess) { |
6907 | 0 | break; |
6908 | 0 | } |
6909 | 0 | } |
6910 | 0 | rv = SECITEM_MakeItem(arena, &keyVal, lk->u.mldsa.keyVal, |
6911 | 0 | lk->u.mldsa.keyValLen); |
6912 | 0 | if (rv != SECSuccess) { |
6913 | 0 | break; |
6914 | 0 | } |
6915 | 0 | if (lk == key->objectInfo) { |
6916 | | /* we have a cached key, and we are about to |
6917 | | * overwrite it, let's get a duplicate first */ |
6918 | 0 | lk = nsslowkey_CopyPrivateKey(lk); |
6919 | 0 | if (lk == NULL) { |
6920 | 0 | break; |
6921 | 0 | } |
6922 | 0 | } |
6923 | | /* this overwrites the mldsa data, but we don't need it any |
6924 | | * more because we are discarding lk once we encode */ |
6925 | 0 | lk->u.genpq.seedItem = seed; |
6926 | 0 | lk->u.genpq.keyItem = keyVal; |
6927 | |
|
6928 | 0 | if (seed.len) { |
6929 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6930 | 0 | nsslowkey_PQBothSeedAndPrivateKeyTemplate); |
6931 | 0 | } else { |
6932 | 0 | dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, |
6933 | 0 | nsslowkey_PQPrivateKeyTemplate); |
6934 | 0 | } |
6935 | 0 | } break; |
6936 | | |
6937 | 0 | case NSSLOWKEYDHKey: |
6938 | 0 | default: |
6939 | 0 | dummy = NULL; |
6940 | 0 | break; |
6941 | 0 | } |
6942 | | |
6943 | 0 | if (!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) { |
6944 | 0 | *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
6945 | 0 | rv = SECFailure; |
6946 | 0 | goto loser; |
6947 | 0 | } |
6948 | | |
6949 | 0 | rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, |
6950 | 0 | (SECItem *)param); |
6951 | 0 | if (rv != SECSuccess) { |
6952 | 0 | *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
6953 | 0 | rv = SECFailure; |
6954 | 0 | goto loser; |
6955 | 0 | } |
6956 | | |
6957 | 0 | dummy = SEC_ASN1EncodeInteger(arena, &pki->version, |
6958 | 0 | NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); |
6959 | 0 | if (!dummy) { |
6960 | 0 | *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ |
6961 | 0 | rv = SECFailure; |
6962 | 0 | goto loser; |
6963 | 0 | } |
6964 | | |
6965 | 0 | encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, |
6966 | 0 | nsslowkey_PrivateKeyInfoTemplate); |
6967 | 0 | *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR; |
6968 | |
|
6969 | | #ifdef EC_DEBUG |
6970 | | fordebug = encodedKey; |
6971 | | SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType, |
6972 | | fordebug); |
6973 | | #endif |
6974 | 0 | loser: |
6975 | 0 | if (arena) { |
6976 | 0 | PORT_FreeArena(arena, PR_TRUE); |
6977 | 0 | } |
6978 | |
|
6979 | 0 | if (lk && (lk != key->objectInfo)) { |
6980 | 0 | nsslowkey_DestroyPrivateKey(lk); |
6981 | 0 | } |
6982 | |
|
6983 | 0 | if (param) { |
6984 | 0 | SECITEM_ZfreeItem((SECItem *)param, PR_TRUE); |
6985 | 0 | } |
6986 | |
|
6987 | 0 | if (rv != SECSuccess) { |
6988 | 0 | return NULL; |
6989 | 0 | } |
6990 | | |
6991 | 0 | return encodedKey; |
6992 | 0 | } |
6993 | | |
6994 | | /* it doesn't matter yet, since we colapse error conditions in the |
6995 | | * level above, but we really should map those few key error differences */ |
6996 | | static CK_RV |
6997 | | sftk_mapWrap(CK_RV crv) |
6998 | 99.4k | { |
6999 | 99.4k | switch (crv) { |
7000 | 0 | case CKR_ENCRYPTED_DATA_INVALID: |
7001 | 0 | crv = CKR_WRAPPED_KEY_INVALID; |
7002 | 0 | break; |
7003 | 99.4k | } |
7004 | 99.4k | return crv; |
7005 | 99.4k | } |
7006 | | |
7007 | | /* NSC_WrapKey wraps (i.e., encrypts) a key. */ |
7008 | | CK_RV |
7009 | | NSC_WrapKey(CK_SESSION_HANDLE hSession, |
7010 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, |
7011 | | CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, |
7012 | | CK_ULONG_PTR pulWrappedKeyLen) |
7013 | 65.1k | { |
7014 | 65.1k | SFTKSession *session; |
7015 | 65.1k | SFTKAttribute *attribute; |
7016 | 65.1k | SFTKObject *key; |
7017 | 65.1k | CK_RV crv; |
7018 | | |
7019 | 65.1k | CHECK_FORK(); |
7020 | | |
7021 | 65.1k | session = sftk_SessionFromHandle(hSession); |
7022 | 65.1k | if (session == NULL) { |
7023 | 0 | return CKR_SESSION_HANDLE_INVALID; |
7024 | 0 | } |
7025 | | |
7026 | 65.1k | key = sftk_ObjectFromHandle(hKey, session); |
7027 | 65.1k | if (key == NULL) { |
7028 | 0 | sftk_FreeSession(session); |
7029 | 0 | return CKR_KEY_HANDLE_INVALID; |
7030 | 0 | } |
7031 | | |
7032 | 65.1k | switch (key->objclass) { |
7033 | 65.1k | case CKO_SECRET_KEY: { |
7034 | 65.1k | SFTKSessionContext *context = NULL; |
7035 | 65.1k | SECItem pText; |
7036 | | |
7037 | 65.1k | attribute = sftk_FindAttribute(key, CKA_VALUE); |
7038 | | |
7039 | 65.1k | if (attribute == NULL) { |
7040 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7041 | 0 | break; |
7042 | 0 | } |
7043 | 65.1k | crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, |
7044 | 65.1k | CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); |
7045 | 65.1k | if (crv != CKR_OK) { |
7046 | 35 | sftk_FreeAttribute(attribute); |
7047 | 35 | break; |
7048 | 35 | } |
7049 | | |
7050 | 65.0k | pText.type = siBuffer; |
7051 | 65.0k | pText.data = (unsigned char *)attribute->attrib.pValue; |
7052 | 65.0k | pText.len = attribute->attrib.ulValueLen; |
7053 | | |
7054 | | /* Find out if this is a block cipher. */ |
7055 | 65.0k | crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, NULL); |
7056 | 65.0k | if (crv != CKR_OK || !context) |
7057 | 0 | break; |
7058 | 65.0k | if (context->blockSize > 1) { |
7059 | 51.5k | unsigned int remainder = pText.len % context->blockSize; |
7060 | 51.5k | if (!context->doPad && remainder) { |
7061 | | /* When wrapping secret keys with unpadded block ciphers, |
7062 | | ** the keys are zero padded, if necessary, to fill out |
7063 | | ** a full block. |
7064 | | */ |
7065 | 0 | pText.len += context->blockSize - remainder; |
7066 | 0 | pText.data = PORT_ZAlloc(pText.len); |
7067 | 0 | if (pText.data) |
7068 | 0 | memcpy(pText.data, attribute->attrib.pValue, |
7069 | 0 | attribute->attrib.ulValueLen); |
7070 | 0 | else { |
7071 | 0 | crv = CKR_HOST_MEMORY; |
7072 | 0 | break; |
7073 | 0 | } |
7074 | 0 | } |
7075 | 51.5k | } |
7076 | | |
7077 | 65.0k | crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data, |
7078 | 65.0k | pText.len, pWrappedKey, pulWrappedKeyLen); |
7079 | | /* always force a finalize, both on errors and when |
7080 | | * we are just getting the size */ |
7081 | 65.0k | if (crv != CKR_OK || pWrappedKey == NULL) { |
7082 | 0 | CK_RV lcrv; |
7083 | 0 | lcrv = sftk_GetContext(hSession, &context, |
7084 | 0 | SFTK_ENCRYPT, PR_FALSE, NULL); |
7085 | 0 | sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); |
7086 | 0 | if (lcrv == CKR_OK && context) { |
7087 | 0 | sftk_FreeContext(context); |
7088 | 0 | } |
7089 | 0 | } |
7090 | | |
7091 | 65.0k | if (pText.data != (unsigned char *)attribute->attrib.pValue) |
7092 | 0 | PORT_ZFree(pText.data, pText.len); |
7093 | 65.0k | sftk_FreeAttribute(attribute); |
7094 | 65.0k | break; |
7095 | 65.0k | } |
7096 | | |
7097 | 0 | case CKO_PRIVATE_KEY: { |
7098 | 0 | SECItem *bpki = sftk_PackagePrivateKey(key, &crv); |
7099 | 0 | SFTKSessionContext *context = NULL; |
7100 | |
|
7101 | 0 | if (!bpki) { |
7102 | 0 | break; |
7103 | 0 | } |
7104 | | |
7105 | 0 | crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, |
7106 | 0 | CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); |
7107 | 0 | if (crv != CKR_OK) { |
7108 | 0 | SECITEM_ZfreeItem(bpki, PR_TRUE); |
7109 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7110 | 0 | break; |
7111 | 0 | } |
7112 | | |
7113 | 0 | crv = NSC_Encrypt(hSession, bpki->data, bpki->len, |
7114 | 0 | pWrappedKey, pulWrappedKeyLen); |
7115 | | /* always force a finalize */ |
7116 | 0 | if (crv != CKR_OK || pWrappedKey == NULL) { |
7117 | 0 | CK_RV lcrv; |
7118 | 0 | lcrv = sftk_GetContext(hSession, &context, |
7119 | 0 | SFTK_ENCRYPT, PR_FALSE, NULL); |
7120 | 0 | sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); |
7121 | 0 | if (lcrv == CKR_OK && context) { |
7122 | 0 | sftk_FreeContext(context); |
7123 | 0 | } |
7124 | 0 | } |
7125 | 0 | SECITEM_ZfreeItem(bpki, PR_TRUE); |
7126 | 0 | break; |
7127 | 0 | } |
7128 | | |
7129 | 0 | default: |
7130 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7131 | 0 | break; |
7132 | 65.1k | } |
7133 | 65.1k | sftk_FreeObject(key); |
7134 | 65.1k | sftk_FreeSession(session); |
7135 | 65.1k | return sftk_mapWrap(crv); |
7136 | 65.1k | } |
7137 | | |
7138 | | /* |
7139 | | * import a pprivate key info into the desired slot |
7140 | | */ |
7141 | | static SECStatus |
7142 | | sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) |
7143 | 0 | { |
7144 | 0 | CK_BBOOL cktrue = CK_TRUE; |
7145 | 0 | CK_BBOOL ckfalse = CK_FALSE; |
7146 | 0 | CK_KEY_TYPE keyType = CKK_RSA; |
7147 | 0 | SECStatus rv = SECFailure; |
7148 | 0 | const SEC_ASN1Template *keyTemplate, *paramTemplate; |
7149 | 0 | void *paramDest = NULL; |
7150 | 0 | PLArenaPool *arena; |
7151 | 0 | NSSLOWKEYPrivateKey *lpk = NULL; |
7152 | 0 | NSSLOWKEYPrivateKeyInfo *pki = NULL; |
7153 | 0 | CK_RV crv = CKR_KEY_TYPE_INCONSISTENT; |
7154 | 0 | CK_ULONG paramSet = 0; |
7155 | |
|
7156 | 0 | arena = PORT_NewArena(2048); |
7157 | 0 | if (!arena) { |
7158 | 0 | return SECFailure; |
7159 | 0 | } |
7160 | | |
7161 | 0 | pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena, |
7162 | 0 | sizeof(NSSLOWKEYPrivateKeyInfo)); |
7163 | 0 | if (!pki) { |
7164 | 0 | PORT_FreeArena(arena, PR_FALSE); |
7165 | 0 | return SECFailure; |
7166 | 0 | } |
7167 | | |
7168 | 0 | if (SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) != SECSuccess) { |
7169 | 0 | PORT_FreeArena(arena, PR_TRUE); |
7170 | 0 | return SECFailure; |
7171 | 0 | } |
7172 | | |
7173 | 0 | lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena, |
7174 | 0 | sizeof(NSSLOWKEYPrivateKey)); |
7175 | 0 | if (lpk == NULL) { |
7176 | 0 | goto loser; |
7177 | 0 | } |
7178 | 0 | lpk->arena = arena; |
7179 | |
|
7180 | 0 | switch (SECOID_GetAlgorithmTag(&pki->algorithm)) { |
7181 | 0 | case SEC_OID_PKCS1_RSA_ENCRYPTION: |
7182 | 0 | case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: |
7183 | 0 | keyTemplate = nsslowkey_RSAPrivateKeyTemplate; |
7184 | 0 | paramTemplate = NULL; |
7185 | 0 | paramDest = NULL; |
7186 | 0 | lpk->keyType = NSSLOWKEYRSAKey; |
7187 | 0 | prepare_low_rsa_priv_key_for_asn1(lpk); |
7188 | 0 | break; |
7189 | 0 | case SEC_OID_ANSIX9_DSA_SIGNATURE: |
7190 | 0 | keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate; |
7191 | 0 | paramTemplate = nsslowkey_PQGParamsTemplate; |
7192 | 0 | paramDest = &(lpk->u.dsa.params); |
7193 | 0 | lpk->keyType = NSSLOWKEYDSAKey; |
7194 | 0 | prepare_low_dsa_priv_key_export_for_asn1(lpk); |
7195 | 0 | prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params); |
7196 | 0 | break; |
7197 | | /* case NSSLOWKEYDHKey: */ |
7198 | 0 | case SEC_OID_ANSIX962_EC_PUBLIC_KEY: |
7199 | 0 | keyTemplate = nsslowkey_ECPrivateKeyTemplate; |
7200 | 0 | paramTemplate = NULL; |
7201 | 0 | paramDest = &(lpk->u.ec.ecParams.DEREncoding); |
7202 | 0 | lpk->keyType = NSSLOWKEYECKey; |
7203 | 0 | prepare_low_ec_priv_key_for_asn1(lpk); |
7204 | 0 | prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams); |
7205 | 0 | break; |
7206 | 0 | case SEC_OID_ML_DSA_44_PUBLIC_KEY: |
7207 | 0 | paramSet = CKP_ML_DSA_44; |
7208 | 0 | goto mldsa_next; |
7209 | 0 | case SEC_OID_ML_DSA_65_PUBLIC_KEY: |
7210 | 0 | paramSet = CKP_ML_DSA_65; |
7211 | 0 | goto mldsa_next; |
7212 | 0 | case SEC_OID_ML_DSA_87_PUBLIC_KEY: |
7213 | 0 | paramSet = CKP_ML_DSA_87; |
7214 | 0 | mldsa_next: |
7215 | 0 | switch (pki->privateKey.data[0]) { |
7216 | 0 | case SEC_ASN1_CONTEXT_SPECIFIC | 0: |
7217 | 0 | keyTemplate = nsslowkey_PQSeedTemplate; |
7218 | 0 | break; |
7219 | 0 | case SEC_ASN1_OCTET_STRING: |
7220 | 0 | keyTemplate = nsslowkey_PQPrivateKeyTemplate; |
7221 | 0 | break; |
7222 | 0 | case SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE: |
7223 | 0 | keyTemplate = nsslowkey_PQBothSeedAndPrivateKeyTemplate; |
7224 | 0 | break; |
7225 | 0 | default: |
7226 | 0 | keyTemplate = NULL; |
7227 | 0 | break; |
7228 | 0 | } |
7229 | | |
7230 | 0 | paramTemplate = NULL; |
7231 | 0 | paramDest = NULL; |
7232 | 0 | lpk->keyType = NSSLOWKEYMLDSAKey; |
7233 | | /* genpq encodes ocect, not integer, so no need to prep it */ |
7234 | 0 | break; |
7235 | 0 | default: |
7236 | 0 | keyTemplate = NULL; |
7237 | 0 | paramTemplate = NULL; |
7238 | 0 | paramDest = NULL; |
7239 | 0 | break; |
7240 | 0 | } |
7241 | | |
7242 | 0 | if (!keyTemplate) { |
7243 | 0 | goto loser; |
7244 | 0 | } |
7245 | | |
7246 | | /* decode the private key and any algorithm parameters */ |
7247 | 0 | rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey); |
7248 | |
|
7249 | 0 | if (lpk->keyType == NSSLOWKEYECKey) { |
7250 | | /* convert length in bits to length in bytes */ |
7251 | 0 | lpk->u.ec.publicValue.len >>= 3; |
7252 | 0 | rv = SECITEM_CopyItem(arena, |
7253 | 0 | &(lpk->u.ec.ecParams.DEREncoding), |
7254 | 0 | &(pki->algorithm.parameters)); |
7255 | 0 | if (rv != SECSuccess) { |
7256 | 0 | goto loser; |
7257 | 0 | } |
7258 | 0 | } |
7259 | | |
7260 | 0 | if (rv != SECSuccess) { |
7261 | 0 | goto loser; |
7262 | 0 | } |
7263 | 0 | if (paramDest && paramTemplate) { |
7264 | 0 | rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate, |
7265 | 0 | &(pki->algorithm.parameters)); |
7266 | 0 | if (rv != SECSuccess) { |
7267 | 0 | goto loser; |
7268 | 0 | } |
7269 | 0 | } |
7270 | | |
7271 | 0 | rv = SECFailure; |
7272 | |
|
7273 | 0 | switch (lpk->keyType) { |
7274 | 0 | case NSSLOWKEYRSAKey: |
7275 | 0 | keyType = CKK_RSA; |
7276 | 0 | if (sftk_hasAttribute(key, CKA_NSS_DB)) { |
7277 | 0 | sftk_DeleteAttributeType(key, CKA_NSS_DB); |
7278 | 0 | } |
7279 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
7280 | 0 | sizeof(keyType)); |
7281 | 0 | if (crv != CKR_OK) |
7282 | 0 | break; |
7283 | 0 | crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue, |
7284 | 0 | sizeof(CK_BBOOL)); |
7285 | 0 | if (crv != CKR_OK) |
7286 | 0 | break; |
7287 | 0 | crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue, |
7288 | 0 | sizeof(CK_BBOOL)); |
7289 | 0 | if (crv != CKR_OK) |
7290 | 0 | break; |
7291 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
7292 | 0 | sizeof(CK_BBOOL)); |
7293 | 0 | if (crv != CKR_OK) |
7294 | 0 | break; |
7295 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, |
7296 | 0 | sizeof(CK_BBOOL)); |
7297 | 0 | if (crv != CKR_OK) |
7298 | 0 | break; |
7299 | 0 | crv = sftk_AddAttributeType(key, CKA_MODULUS, |
7300 | 0 | sftk_item_expand(&lpk->u.rsa.modulus)); |
7301 | 0 | if (crv != CKR_OK) |
7302 | 0 | break; |
7303 | 0 | crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT, |
7304 | 0 | sftk_item_expand(&lpk->u.rsa.publicExponent)); |
7305 | 0 | if (crv != CKR_OK) |
7306 | 0 | break; |
7307 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT, |
7308 | 0 | sftk_item_expand(&lpk->u.rsa.privateExponent)); |
7309 | 0 | if (crv != CKR_OK) |
7310 | 0 | break; |
7311 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME_1, |
7312 | 0 | sftk_item_expand(&lpk->u.rsa.prime1)); |
7313 | 0 | if (crv != CKR_OK) |
7314 | 0 | break; |
7315 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME_2, |
7316 | 0 | sftk_item_expand(&lpk->u.rsa.prime2)); |
7317 | 0 | if (crv != CKR_OK) |
7318 | 0 | break; |
7319 | 0 | crv = sftk_AddAttributeType(key, CKA_EXPONENT_1, |
7320 | 0 | sftk_item_expand(&lpk->u.rsa.exponent1)); |
7321 | 0 | if (crv != CKR_OK) |
7322 | 0 | break; |
7323 | 0 | crv = sftk_AddAttributeType(key, CKA_EXPONENT_2, |
7324 | 0 | sftk_item_expand(&lpk->u.rsa.exponent2)); |
7325 | 0 | if (crv != CKR_OK) |
7326 | 0 | break; |
7327 | 0 | crv = sftk_AddAttributeType(key, CKA_COEFFICIENT, |
7328 | 0 | sftk_item_expand(&lpk->u.rsa.coefficient)); |
7329 | 0 | break; |
7330 | 0 | case NSSLOWKEYDSAKey: |
7331 | 0 | keyType = CKK_DSA; |
7332 | 0 | crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT; |
7333 | 0 | if (crv != CKR_OK) |
7334 | 0 | break; |
7335 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
7336 | 0 | sizeof(keyType)); |
7337 | 0 | if (crv != CKR_OK) |
7338 | 0 | break; |
7339 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
7340 | 0 | sizeof(CK_BBOOL)); |
7341 | 0 | if (crv != CKR_OK) |
7342 | 0 | break; |
7343 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &ckfalse, |
7344 | 0 | sizeof(CK_BBOOL)); |
7345 | 0 | if (crv != CKR_OK) |
7346 | 0 | break; |
7347 | 0 | crv = sftk_AddAttributeType(key, CKA_PRIME, |
7348 | 0 | sftk_item_expand(&lpk->u.dsa.params.prime)); |
7349 | 0 | if (crv != CKR_OK) |
7350 | 0 | break; |
7351 | 0 | crv = sftk_AddAttributeType(key, CKA_SUBPRIME, |
7352 | 0 | sftk_item_expand(&lpk->u.dsa.params.subPrime)); |
7353 | 0 | if (crv != CKR_OK) |
7354 | 0 | break; |
7355 | 0 | crv = sftk_AddAttributeType(key, CKA_BASE, |
7356 | 0 | sftk_item_expand(&lpk->u.dsa.params.base)); |
7357 | 0 | if (crv != CKR_OK) |
7358 | 0 | break; |
7359 | 0 | crv = sftk_AddAttributeType(key, CKA_VALUE, |
7360 | 0 | sftk_item_expand(&lpk->u.dsa.privateValue)); |
7361 | 0 | if (crv != CKR_OK) |
7362 | 0 | break; |
7363 | 0 | break; |
7364 | 0 | case NSSLOWKEYMLDSAKey: |
7365 | 0 | keyType = CKK_ML_DSA; |
7366 | 0 | crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT; |
7367 | 0 | if (crv != CKR_OK) |
7368 | 0 | break; |
7369 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
7370 | 0 | sizeof(keyType)); |
7371 | 0 | if (crv != CKR_OK) |
7372 | 0 | break; |
7373 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
7374 | 0 | sizeof(CK_BBOOL)); |
7375 | 0 | if (crv != CKR_OK) |
7376 | 0 | break; |
7377 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &ckfalse, |
7378 | 0 | sizeof(CK_BBOOL)); |
7379 | 0 | if (crv != CKR_OK) |
7380 | 0 | break; |
7381 | 0 | crv = sftk_AddAttributeType(key, CKA_PARAMETER_SET, ¶mSet, |
7382 | 0 | sizeof(CK_ML_DSA_PARAMETER_SET_TYPE)); |
7383 | 0 | if (crv != CKR_OK) |
7384 | 0 | break; |
7385 | 0 | if (lpk->u.genpq.seedItem.len != 0) { |
7386 | 0 | crv = sftk_AddAttributeType(key, CKA_SEED, |
7387 | 0 | sftk_item_expand(&lpk->u.genpq.seedItem)); |
7388 | 0 | if (crv != CKR_OK) |
7389 | 0 | break; |
7390 | 0 | } |
7391 | | |
7392 | | /* if we were given just the seed, we'll regenerate the key |
7393 | | * from the seed in handleObject */ |
7394 | 0 | if (lpk->u.genpq.keyItem.len != 0) { |
7395 | 0 | crv = sftk_AddAttributeType(key, CKA_VALUE, |
7396 | 0 | sftk_item_expand(&lpk->u.genpq.keyItem)); |
7397 | | /* I know, this is redundant, but it would be too easy |
7398 | | * for someone to add another sftk_AddAttributeType after |
7399 | | * this without adding this check back because of the if */ |
7400 | 0 | if (crv != CKR_OK) |
7401 | 0 | break; |
7402 | 0 | } |
7403 | 0 | break; |
7404 | | #ifdef notdef |
7405 | | case NSSLOWKEYDHKey: |
7406 | | template = dhTemplate; |
7407 | | templateCount = sizeof(dhTemplate) / sizeof(CK_ATTRIBUTE); |
7408 | | keyType = CKK_DH; |
7409 | | break; |
7410 | | #endif |
7411 | | /* what about fortezza??? */ |
7412 | 0 | case NSSLOWKEYECKey: |
7413 | 0 | keyType = CKK_EC; |
7414 | 0 | crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT; |
7415 | 0 | if (crv != CKR_OK) |
7416 | 0 | break; |
7417 | 0 | crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, |
7418 | 0 | sizeof(keyType)); |
7419 | 0 | if (crv != CKR_OK) |
7420 | 0 | break; |
7421 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, |
7422 | 0 | sizeof(CK_BBOOL)); |
7423 | 0 | if (crv != CKR_OK) |
7424 | 0 | break; |
7425 | 0 | crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &ckfalse, |
7426 | 0 | sizeof(CK_BBOOL)); |
7427 | 0 | if (crv != CKR_OK) |
7428 | 0 | break; |
7429 | 0 | crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue, |
7430 | 0 | sizeof(CK_BBOOL)); |
7431 | 0 | if (crv != CKR_OK) |
7432 | 0 | break; |
7433 | 0 | crv = sftk_AddAttributeType(key, CKA_EC_PARAMS, |
7434 | 0 | sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding)); |
7435 | 0 | if (crv != CKR_OK) |
7436 | 0 | break; |
7437 | 0 | crv = sftk_AddAttributeType(key, CKA_VALUE, |
7438 | 0 | sftk_item_expand(&lpk->u.ec.privateValue)); |
7439 | 0 | if (crv != CKR_OK) |
7440 | 0 | break; |
7441 | | /* XXX Do we need to decode the EC Params here ?? */ |
7442 | 0 | break; |
7443 | 0 | default: |
7444 | 0 | crv = CKR_KEY_TYPE_INCONSISTENT; |
7445 | 0 | break; |
7446 | 0 | } |
7447 | | |
7448 | 0 | if (crv != CKR_OK) { |
7449 | 0 | goto loser; |
7450 | 0 | } |
7451 | | |
7452 | | /* For RSA-PSS, record the original algorithm parameters so |
7453 | | * they can be encrypted altoghether when wrapping */ |
7454 | 0 | if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { |
7455 | 0 | NSSLOWKEYSubjectPublicKeyInfo spki; |
7456 | 0 | NSSLOWKEYPublicKey pubk; |
7457 | 0 | SECItem *publicKeyInfo; |
7458 | |
|
7459 | 0 | memset(&spki, 0, sizeof(NSSLOWKEYSubjectPublicKeyInfo)); |
7460 | 0 | rv = SECOID_CopyAlgorithmID(arena, &spki.algorithm, &pki->algorithm); |
7461 | 0 | if (rv != SECSuccess) { |
7462 | 0 | crv = CKR_HOST_MEMORY; |
7463 | 0 | goto loser; |
7464 | 0 | } |
7465 | | |
7466 | 0 | prepare_low_rsa_pub_key_for_asn1(&pubk); |
7467 | |
|
7468 | 0 | rv = SECITEM_CopyItem(arena, &pubk.u.rsa.modulus, &lpk->u.rsa.modulus); |
7469 | 0 | if (rv != SECSuccess) { |
7470 | 0 | crv = CKR_HOST_MEMORY; |
7471 | 0 | goto loser; |
7472 | 0 | } |
7473 | 0 | rv = SECITEM_CopyItem(arena, &pubk.u.rsa.publicExponent, &lpk->u.rsa.publicExponent); |
7474 | 0 | if (rv != SECSuccess) { |
7475 | 0 | crv = CKR_HOST_MEMORY; |
7476 | 0 | goto loser; |
7477 | 0 | } |
7478 | | |
7479 | 0 | if (SEC_ASN1EncodeItem(arena, &spki.subjectPublicKey, |
7480 | 0 | &pubk, nsslowkey_RSAPublicKeyTemplate) == NULL) { |
7481 | 0 | crv = CKR_HOST_MEMORY; |
7482 | 0 | goto loser; |
7483 | 0 | } |
7484 | | |
7485 | 0 | publicKeyInfo = SEC_ASN1EncodeItem(arena, NULL, |
7486 | 0 | &spki, nsslowkey_SubjectPublicKeyInfoTemplate); |
7487 | 0 | if (!publicKeyInfo) { |
7488 | 0 | crv = CKR_HOST_MEMORY; |
7489 | 0 | goto loser; |
7490 | 0 | } |
7491 | 0 | crv = sftk_AddAttributeType(key, CKA_PUBLIC_KEY_INFO, |
7492 | 0 | sftk_item_expand(publicKeyInfo)); |
7493 | 0 | } |
7494 | | |
7495 | 0 | loser: |
7496 | 0 | if (lpk) { |
7497 | 0 | nsslowkey_DestroyPrivateKey(lpk); |
7498 | 0 | } |
7499 | |
|
7500 | 0 | if (crv != CKR_OK) { |
7501 | 0 | return SECFailure; |
7502 | 0 | } |
7503 | | |
7504 | 0 | return SECSuccess; |
7505 | 0 | } |
7506 | | |
7507 | | /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */ |
7508 | | CK_RV |
7509 | | NSC_UnwrapKey(CK_SESSION_HANDLE hSession, |
7510 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, |
7511 | | CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, |
7512 | | CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, |
7513 | | CK_OBJECT_HANDLE_PTR phKey) |
7514 | 37.2k | { |
7515 | 37.2k | SFTKObject *key = NULL; |
7516 | 37.2k | SFTKSession *session; |
7517 | 37.2k | CK_ULONG key_length = 0; |
7518 | 37.2k | unsigned char *buf = NULL; |
7519 | 37.2k | CK_RV crv = CKR_OK; |
7520 | 37.2k | int i; |
7521 | 37.2k | CK_ULONG bsize = ulWrappedKeyLen; |
7522 | 37.2k | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
7523 | 37.2k | SECItem bpki; |
7524 | 37.2k | CK_OBJECT_CLASS target_type = CKO_SECRET_KEY; |
7525 | | |
7526 | 37.2k | CHECK_FORK(); |
7527 | | |
7528 | 37.2k | if (!slot) { |
7529 | 0 | return CKR_SESSION_HANDLE_INVALID; |
7530 | 0 | } |
7531 | | /* |
7532 | | * now lets create an object to hang the attributes off of |
7533 | | */ |
7534 | 37.2k | key = sftk_NewObject(slot); /* fill in the handle later */ |
7535 | 37.2k | if (key == NULL) { |
7536 | 0 | return CKR_HOST_MEMORY; |
7537 | 0 | } |
7538 | | |
7539 | | /* |
7540 | | * load the template values into the object |
7541 | | */ |
7542 | 148k | for (i = 0; i < (int)ulAttributeCount; i++) { |
7543 | 111k | if (pTemplate[i].type == CKA_VALUE_LEN) { |
7544 | 0 | key_length = *(CK_ULONG *)pTemplate[i].pValue; |
7545 | 0 | continue; |
7546 | 0 | } |
7547 | 111k | if (pTemplate[i].type == CKA_CLASS) { |
7548 | 37.2k | target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; |
7549 | 37.2k | } |
7550 | 111k | crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); |
7551 | 111k | if (crv != CKR_OK) |
7552 | 0 | break; |
7553 | 111k | } |
7554 | 37.2k | if (crv != CKR_OK) { |
7555 | 0 | sftk_FreeObject(key); |
7556 | 0 | return crv; |
7557 | 0 | } |
7558 | | |
7559 | 37.2k | crv = sftk_CryptInit(hSession, pMechanism, hUnwrappingKey, CKA_UNWRAP, |
7560 | 37.2k | CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE); |
7561 | 37.2k | if (crv != CKR_OK) { |
7562 | 0 | sftk_FreeObject(key); |
7563 | 0 | return sftk_mapWrap(crv); |
7564 | 0 | } |
7565 | | |
7566 | | /* allocate the buffer to decrypt into |
7567 | | * this assumes the unwrapped key is never larger than the |
7568 | | * wrapped key. For all the mechanisms we support this is true */ |
7569 | 37.2k | buf = (unsigned char *)PORT_Alloc(ulWrappedKeyLen); |
7570 | 37.2k | bsize = ulWrappedKeyLen; |
7571 | | |
7572 | 37.2k | crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize); |
7573 | 37.2k | if (crv != CKR_OK) { |
7574 | 34.3k | sftk_FreeObject(key); |
7575 | 34.3k | PORT_Free(buf); |
7576 | 34.3k | return sftk_mapWrap(crv); |
7577 | 34.3k | } |
7578 | | |
7579 | 2.90k | switch (target_type) { |
7580 | 2.90k | case CKO_SECRET_KEY: |
7581 | 2.90k | if (!sftk_hasAttribute(key, CKA_KEY_TYPE)) { |
7582 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
7583 | 0 | break; |
7584 | 0 | } |
7585 | | |
7586 | 2.90k | if (key_length == 0 || key_length > bsize) { |
7587 | 2.90k | key_length = bsize; |
7588 | 2.90k | } |
7589 | 2.90k | if (key_length > MAX_KEY_LEN) { |
7590 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
7591 | 0 | break; |
7592 | 0 | } |
7593 | | |
7594 | | /* add the value */ |
7595 | 2.90k | crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length); |
7596 | 2.90k | break; |
7597 | 0 | case CKO_PRIVATE_KEY: |
7598 | 0 | bpki.data = (unsigned char *)buf; |
7599 | 0 | bpki.len = bsize; |
7600 | 0 | crv = CKR_OK; |
7601 | 0 | if (sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) { |
7602 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
7603 | 0 | } |
7604 | 0 | break; |
7605 | 0 | default: |
7606 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
7607 | 0 | break; |
7608 | 2.90k | } |
7609 | | |
7610 | 2.90k | PORT_ZFree(buf, bsize); |
7611 | 2.90k | if (crv != CKR_OK) { |
7612 | 0 | sftk_FreeObject(key); |
7613 | 0 | return crv; |
7614 | 0 | } |
7615 | | |
7616 | | /* get the session */ |
7617 | 2.90k | session = sftk_SessionFromHandle(hSession); |
7618 | 2.90k | if (session == NULL) { |
7619 | 0 | sftk_FreeObject(key); |
7620 | 0 | return CKR_SESSION_HANDLE_INVALID; |
7621 | 0 | } |
7622 | | |
7623 | | /* mark the key as FIPS if the previous operation was all FIPS */ |
7624 | 2.90k | sftk_setFIPS(key, session->lastOpWasFIPS); |
7625 | | /* |
7626 | | * handle the base object stuff |
7627 | | */ |
7628 | 2.90k | crv = sftk_handleObject(key, session); |
7629 | 2.90k | *phKey = key->handle; |
7630 | 2.90k | sftk_FreeSession(session); |
7631 | 2.90k | sftk_FreeObject(key); |
7632 | | |
7633 | 2.90k | return crv; |
7634 | 2.90k | } |
7635 | | |
7636 | | CK_RV |
7637 | | NSC_WrapKeyAuthenticated(CK_SESSION_HANDLE hSession, |
7638 | | CK_MECHANISM_PTR pMechanism, |
7639 | | CK_OBJECT_HANDLE hWrappingKey, |
7640 | | CK_OBJECT_HANDLE hKey, |
7641 | | CK_BYTE_PTR pAssociatedData, |
7642 | | CK_ULONG ulAssociatedDataLen, |
7643 | | CK_BYTE_PTR pWrappedKey, |
7644 | | CK_ULONG_PTR pulWrappedKeyLen) |
7645 | 0 | { |
7646 | 0 | CHECK_FORK(); |
7647 | |
|
7648 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
7649 | 0 | } |
7650 | | |
7651 | | CK_RV |
7652 | | NSC_UnwrapKeyAuthenticated(CK_SESSION_HANDLE hSession, |
7653 | | CK_MECHANISM_PTR pMechanism, |
7654 | | CK_OBJECT_HANDLE hUnwrappingKey, |
7655 | | CK_BYTE_PTR pWrappedKey, |
7656 | | CK_ULONG ulWrappedKeyLen, |
7657 | | CK_ATTRIBUTE_PTR pTemplate, |
7658 | | CK_ULONG ulAttributeCount, |
7659 | | CK_BYTE_PTR pAssociatedData, |
7660 | | CK_ULONG ulAssociatedDataLen, |
7661 | | CK_OBJECT_HANDLE_PTR phKey) |
7662 | 0 | { |
7663 | 0 | CHECK_FORK(); |
7664 | |
|
7665 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
7666 | 0 | } |
7667 | | |
7668 | | /* |
7669 | | * The SSL key gen mechanism create's lots of keys. This function handles the |
7670 | | * details of each of these key creation. |
7671 | | */ |
7672 | | static CK_RV |
7673 | | sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey, |
7674 | | PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize, |
7675 | | CK_OBJECT_HANDLE *keyHandle) |
7676 | 393k | { |
7677 | 393k | SFTKObject *key; |
7678 | 393k | SFTKSession *session; |
7679 | 393k | CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
7680 | 393k | CK_BBOOL cktrue = CK_TRUE; |
7681 | 393k | CK_BBOOL ckfalse = CK_FALSE; |
7682 | 393k | CK_RV crv = CKR_HOST_MEMORY; |
7683 | | |
7684 | | /* |
7685 | | * now lets create an object to hang the attributes off of |
7686 | | */ |
7687 | 393k | *keyHandle = CK_INVALID_HANDLE; |
7688 | 393k | key = sftk_NewObject(baseKey->slot); |
7689 | 393k | if (key == NULL) |
7690 | 0 | return CKR_HOST_MEMORY; |
7691 | 393k | sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE; |
7692 | | |
7693 | 393k | crv = sftk_CopyObject(key, baseKey); |
7694 | 393k | if (crv != CKR_OK) |
7695 | 0 | goto loser; |
7696 | 393k | if (isMacKey) { |
7697 | 207k | crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType)); |
7698 | 207k | if (crv != CKR_OK) |
7699 | 0 | goto loser; |
7700 | 207k | crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); |
7701 | 207k | if (crv != CKR_OK) |
7702 | 0 | goto loser; |
7703 | 207k | crv = sftk_forceAttribute(key, CKA_ENCRYPT, &ckfalse, sizeof(CK_BBOOL)); |
7704 | 207k | if (crv != CKR_OK) |
7705 | 0 | goto loser; |
7706 | 207k | crv = sftk_forceAttribute(key, CKA_DECRYPT, &ckfalse, sizeof(CK_BBOOL)); |
7707 | 207k | if (crv != CKR_OK) |
7708 | 0 | goto loser; |
7709 | 207k | crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); |
7710 | 207k | if (crv != CKR_OK) |
7711 | 0 | goto loser; |
7712 | 207k | crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); |
7713 | 207k | if (crv != CKR_OK) |
7714 | 0 | goto loser; |
7715 | 207k | crv = sftk_forceAttribute(key, CKA_WRAP, &ckfalse, sizeof(CK_BBOOL)); |
7716 | 207k | if (crv != CKR_OK) |
7717 | 0 | goto loser; |
7718 | 207k | crv = sftk_forceAttribute(key, CKA_UNWRAP, &ckfalse, sizeof(CK_BBOOL)); |
7719 | 207k | if (crv != CKR_OK) |
7720 | 0 | goto loser; |
7721 | 207k | } |
7722 | 393k | crv = sftk_forceAttribute(key, CKA_VALUE, keyBlock, keySize); |
7723 | 393k | if (crv != CKR_OK) |
7724 | 0 | goto loser; |
7725 | | |
7726 | | /* get the session */ |
7727 | 393k | crv = CKR_HOST_MEMORY; |
7728 | 393k | session = sftk_SessionFromHandle(hSession); |
7729 | 393k | if (session == NULL) { |
7730 | 0 | goto loser; |
7731 | 0 | } |
7732 | | |
7733 | 393k | crv = sftk_handleObject(key, session); |
7734 | 393k | sftk_FreeSession(session); |
7735 | 393k | *keyHandle = key->handle; |
7736 | 393k | loser: |
7737 | 393k | if (key) |
7738 | 393k | sftk_FreeObject(key); |
7739 | 393k | return crv; |
7740 | 393k | } |
7741 | | |
7742 | | /* |
7743 | | * if there is an error, we need to free the keys we already created in SSL |
7744 | | * This is the routine that will do it.. |
7745 | | */ |
7746 | | static void |
7747 | | sftk_freeSSLKeys(CK_SESSION_HANDLE session, |
7748 | | CK_SSL3_KEY_MAT_OUT *returnedMaterial) |
7749 | 0 | { |
7750 | 0 | if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) { |
7751 | 0 | NSC_DestroyObject(session, returnedMaterial->hClientMacSecret); |
7752 | 0 | } |
7753 | 0 | if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) { |
7754 | 0 | NSC_DestroyObject(session, returnedMaterial->hServerMacSecret); |
7755 | 0 | } |
7756 | 0 | if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) { |
7757 | 0 | NSC_DestroyObject(session, returnedMaterial->hClientKey); |
7758 | 0 | } |
7759 | 0 | if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) { |
7760 | 0 | NSC_DestroyObject(session, returnedMaterial->hServerKey); |
7761 | 0 | } |
7762 | 0 | } |
7763 | | |
7764 | | /* |
7765 | | * when deriving from sensitive and extractable keys, we need to preserve some |
7766 | | * of the semantics in the derived key. This helper routine maintains these |
7767 | | * semantics. |
7768 | | */ |
7769 | | static CK_RV |
7770 | | sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey, |
7771 | | PRBool canBeData) |
7772 | 676k | { |
7773 | 676k | PRBool hasSensitive; |
7774 | 676k | PRBool sensitive = PR_FALSE; |
7775 | 676k | CK_BBOOL bFalse = CK_FALSE; |
7776 | 676k | PRBool hasExtractable; |
7777 | 676k | PRBool extractable = PR_TRUE; |
7778 | 676k | CK_BBOOL bTrue = CK_TRUE; |
7779 | 676k | CK_RV crv = CKR_OK; |
7780 | 676k | SFTKAttribute *att; |
7781 | 676k | PRBool isData = PR_TRUE; |
7782 | | |
7783 | 676k | if (canBeData) { |
7784 | 565k | CK_OBJECT_CLASS objClass; |
7785 | | |
7786 | | /* if the target key is actually data, don't set the unexpected |
7787 | | * attributes */ |
7788 | 565k | crv = sftk_GetULongAttribute(destKey, CKA_CLASS, &objClass); |
7789 | 565k | if (crv != CKR_OK) { |
7790 | 0 | return crv; |
7791 | 0 | } |
7792 | 565k | if (objClass == CKO_DATA) { |
7793 | 169k | return CKR_OK; |
7794 | 169k | } |
7795 | | |
7796 | | /* if the base key is data, it doesn't have sensitive attributes, |
7797 | | * allow the destKey to get it's own */ |
7798 | 395k | crv = sftk_GetULongAttribute(baseKey, CKA_CLASS, &objClass); |
7799 | 395k | if (crv != CKR_OK) { |
7800 | 0 | return crv; |
7801 | 0 | } |
7802 | 395k | if (objClass == CKO_DATA) { |
7803 | 10.5k | isData = PR_TRUE; |
7804 | 10.5k | } |
7805 | 395k | } |
7806 | | |
7807 | 506k | hasSensitive = PR_FALSE; |
7808 | 506k | att = sftk_FindAttribute(destKey, CKA_SENSITIVE); |
7809 | 506k | if (att) { |
7810 | 0 | hasSensitive = PR_TRUE; |
7811 | 0 | sensitive = (PRBool) * (CK_BBOOL *)att->attrib.pValue; |
7812 | 0 | sftk_FreeAttribute(att); |
7813 | 0 | } |
7814 | | |
7815 | 506k | hasExtractable = PR_FALSE; |
7816 | 506k | att = sftk_FindAttribute(destKey, CKA_EXTRACTABLE); |
7817 | 506k | if (att) { |
7818 | 0 | hasExtractable = PR_TRUE; |
7819 | 0 | extractable = (PRBool) * (CK_BBOOL *)att->attrib.pValue; |
7820 | 0 | sftk_FreeAttribute(att); |
7821 | 0 | } |
7822 | | |
7823 | | /* don't make a key more accessible */ |
7824 | 506k | if (sftk_isTrue(baseKey, CKA_SENSITIVE) && hasSensitive && |
7825 | 0 | (sensitive == PR_FALSE)) { |
7826 | 0 | return CKR_KEY_FUNCTION_NOT_PERMITTED; |
7827 | 0 | } |
7828 | 506k | if (!sftk_isTrue(baseKey, CKA_EXTRACTABLE) && hasExtractable && |
7829 | 0 | (extractable == PR_TRUE)) { |
7830 | 0 | return CKR_KEY_FUNCTION_NOT_PERMITTED; |
7831 | 0 | } |
7832 | | |
7833 | | /* inherit parent's sensitivity */ |
7834 | 506k | if (!hasSensitive) { |
7835 | 506k | att = sftk_FindAttribute(baseKey, CKA_SENSITIVE); |
7836 | 506k | if (att != NULL) { |
7837 | 491k | crv = sftk_defaultAttribute(destKey, |
7838 | 491k | sftk_attr_expand(&att->attrib)); |
7839 | 491k | sftk_FreeAttribute(att); |
7840 | 491k | } else if (isData) { |
7841 | 14.1k | crv = sftk_defaultAttribute(destKey, CKA_SENSITIVE, |
7842 | 14.1k | &bFalse, sizeof(bFalse)); |
7843 | 14.1k | } else { |
7844 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
7845 | 0 | } |
7846 | 506k | if (crv != CKR_OK) |
7847 | 0 | return crv; |
7848 | 506k | } |
7849 | 506k | if (!hasExtractable) { |
7850 | 506k | att = sftk_FindAttribute(baseKey, CKA_EXTRACTABLE); |
7851 | 506k | if (att != NULL) { |
7852 | 491k | crv = sftk_defaultAttribute(destKey, |
7853 | 491k | sftk_attr_expand(&att->attrib)); |
7854 | 491k | sftk_FreeAttribute(att); |
7855 | 491k | } else if (isData) { |
7856 | 14.1k | crv = sftk_defaultAttribute(destKey, CKA_EXTRACTABLE, |
7857 | 14.1k | &bTrue, sizeof(bTrue)); |
7858 | 14.1k | } else { |
7859 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
7860 | 0 | } |
7861 | 506k | if (crv != CKR_OK) |
7862 | 0 | return crv; |
7863 | 506k | } |
7864 | | |
7865 | | /* we should inherit the parent's always extractable/ never sensitive info, |
7866 | | * but handleObject always forces this attributes, so we would need to do |
7867 | | * something special. */ |
7868 | 506k | return CKR_OK; |
7869 | 506k | } |
7870 | | |
7871 | | /* |
7872 | | * make known fixed PKCS #11 key types to their sizes in bytes |
7873 | | */ |
7874 | | unsigned long |
7875 | | sftk_MapKeySize(CK_KEY_TYPE keyType) |
7876 | 258k | { |
7877 | 258k | switch (keyType) { |
7878 | 0 | case CKK_CDMF: |
7879 | 0 | return 8; |
7880 | 8.66k | case CKK_DES: |
7881 | 8.66k | return 8; |
7882 | 0 | case CKK_DES2: |
7883 | 0 | return 16; |
7884 | 50.1k | case CKK_DES3: |
7885 | 50.1k | return 24; |
7886 | | /* IDEA and CAST need to be added */ |
7887 | 199k | default: |
7888 | 199k | break; |
7889 | 258k | } |
7890 | 199k | return 0; |
7891 | 258k | } |
7892 | | |
7893 | | /* Inputs: |
7894 | | * key_len: Length of derived key to be generated. |
7895 | | * SharedSecret: a shared secret that is the output of a key agreement primitive. |
7896 | | * SharedInfo: (Optional) some data shared by the entities computing the secret key. |
7897 | | * SharedInfoLen: the length in octets of SharedInfo |
7898 | | * Hash: The hash function to be used in the KDF |
7899 | | * HashLen: the length in octets of the output of Hash |
7900 | | * Output: |
7901 | | * key: Pointer to a buffer containing derived key, if return value is SECSuccess. |
7902 | | */ |
7903 | | static CK_RV |
7904 | | sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret, |
7905 | | CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, |
7906 | | SECStatus Hash(unsigned char *, const unsigned char *, PRUint32), |
7907 | | CK_ULONG HashLen) |
7908 | 0 | { |
7909 | 0 | unsigned char *buffer = NULL, *output_buffer = NULL; |
7910 | 0 | PRUint32 buffer_len, max_counter, i; |
7911 | 0 | SECStatus rv; |
7912 | 0 | CK_RV crv; |
7913 | | |
7914 | | /* Check that key_len isn't too long. The maximum key length could be |
7915 | | * greatly increased if the code below did not limit the 4-byte counter |
7916 | | * to a maximum value of 255. */ |
7917 | 0 | if (key_len > 254 * HashLen) |
7918 | 0 | return CKR_ARGUMENTS_BAD; |
7919 | | |
7920 | 0 | if (SharedInfo == NULL) |
7921 | 0 | SharedInfoLen = 0; |
7922 | |
|
7923 | 0 | buffer_len = SharedSecret->len + 4 + SharedInfoLen; |
7924 | 0 | buffer = (CK_BYTE *)PORT_Alloc(buffer_len); |
7925 | 0 | if (buffer == NULL) { |
7926 | 0 | crv = CKR_HOST_MEMORY; |
7927 | 0 | goto loser; |
7928 | 0 | } |
7929 | | |
7930 | 0 | max_counter = key_len / HashLen; |
7931 | 0 | if (key_len > max_counter * HashLen) |
7932 | 0 | max_counter++; |
7933 | |
|
7934 | 0 | output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen); |
7935 | 0 | if (output_buffer == NULL) { |
7936 | 0 | crv = CKR_HOST_MEMORY; |
7937 | 0 | goto loser; |
7938 | 0 | } |
7939 | | |
7940 | | /* Populate buffer with SharedSecret || Counter || [SharedInfo] |
7941 | | * where Counter is 0x00000001 */ |
7942 | 0 | PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len); |
7943 | 0 | buffer[SharedSecret->len] = 0; |
7944 | 0 | buffer[SharedSecret->len + 1] = 0; |
7945 | 0 | buffer[SharedSecret->len + 2] = 0; |
7946 | 0 | buffer[SharedSecret->len + 3] = 1; |
7947 | 0 | if (SharedInfo) { |
7948 | 0 | PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen); |
7949 | 0 | } |
7950 | |
|
7951 | 0 | for (i = 0; i < max_counter; i++) { |
7952 | 0 | rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len); |
7953 | 0 | if (rv != SECSuccess) { |
7954 | | /* 'Hash' should not fail. */ |
7955 | 0 | crv = CKR_FUNCTION_FAILED; |
7956 | 0 | goto loser; |
7957 | 0 | } |
7958 | | |
7959 | | /* Increment counter (assumes max_counter < 255) */ |
7960 | 0 | buffer[SharedSecret->len + 3]++; |
7961 | 0 | } |
7962 | | |
7963 | 0 | PORT_ZFree(buffer, buffer_len); |
7964 | 0 | if (key_len < max_counter * HashLen) { |
7965 | 0 | PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len); |
7966 | 0 | } |
7967 | 0 | *key = output_buffer; |
7968 | |
|
7969 | 0 | return CKR_OK; |
7970 | | |
7971 | 0 | loser: |
7972 | 0 | if (buffer) { |
7973 | 0 | PORT_ZFree(buffer, buffer_len); |
7974 | 0 | } |
7975 | 0 | if (output_buffer) { |
7976 | 0 | PORT_ZFree(output_buffer, max_counter * HashLen); |
7977 | 0 | } |
7978 | 0 | return crv; |
7979 | 0 | } |
7980 | | |
7981 | | static CK_RV |
7982 | | sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, |
7983 | | SECItem *SharedSecret, |
7984 | | CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, |
7985 | | CK_EC_KDF_TYPE kdf) |
7986 | 0 | { |
7987 | 0 | if (kdf == CKD_SHA1_KDF) |
7988 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7989 | 0 | SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH); |
7990 | 0 | else if (kdf == CKD_SHA224_KDF) |
7991 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7992 | 0 | SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH); |
7993 | 0 | else if (kdf == CKD_SHA256_KDF) |
7994 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7995 | 0 | SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH); |
7996 | 0 | else if (kdf == CKD_SHA384_KDF) |
7997 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
7998 | 0 | SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH); |
7999 | 0 | else if (kdf == CKD_SHA512_KDF) |
8000 | 0 | return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, |
8001 | 0 | SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH); |
8002 | 0 | else |
8003 | 0 | return CKR_MECHANISM_INVALID; |
8004 | 0 | } |
8005 | | |
8006 | | /* |
8007 | | * Handle the derive from a block encryption cipher |
8008 | | */ |
8009 | | CK_RV |
8010 | | sftk_DeriveEncrypt(SFTKCipher encrypt, void *cipherInfo, |
8011 | | int blockSize, SFTKObject *key, CK_ULONG keySize, |
8012 | | unsigned char *data, CK_ULONG len) |
8013 | 0 | { |
8014 | | /* large enough for a 512-bit key */ |
8015 | 0 | unsigned char tmpdata[SFTK_MAX_DERIVE_KEY_SIZE]; |
8016 | 0 | SECStatus rv; |
8017 | 0 | unsigned int outLen; |
8018 | 0 | CK_RV crv; |
8019 | |
|
8020 | 0 | if ((len % blockSize) != 0) { |
8021 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8022 | 0 | } |
8023 | 0 | if (len > SFTK_MAX_DERIVE_KEY_SIZE) { |
8024 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8025 | 0 | } |
8026 | 0 | if (keySize && (len < keySize)) { |
8027 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8028 | 0 | } |
8029 | 0 | if (keySize == 0) { |
8030 | 0 | keySize = len; |
8031 | 0 | } |
8032 | |
|
8033 | 0 | rv = (*encrypt)(cipherInfo, (unsigned char *)&tmpdata, &outLen, len, data, len); |
8034 | 0 | if (rv != SECSuccess) { |
8035 | 0 | crv = sftk_MapCryptError(PORT_GetError()); |
8036 | 0 | return crv; |
8037 | 0 | } |
8038 | | |
8039 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize); |
8040 | 0 | PORT_Memset(tmpdata, 0, sizeof tmpdata); |
8041 | 0 | return crv; |
8042 | 0 | } |
8043 | | |
8044 | | CK_RV |
8045 | | sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession, |
8046 | | SFTKObject *sourceKey, const unsigned char *sourceKeyBytes, |
8047 | | int sourceKeyLen, SFTKObject *key, unsigned char *outKeyBytes, |
8048 | | int keySize, PRBool canBeData, PRBool isFIPS) |
8049 | 565k | { |
8050 | 565k | SFTKSession *session; |
8051 | 565k | SFTKAttribute *saltKey_att = NULL; |
8052 | 565k | const SECHashObject *rawHash; |
8053 | 565k | unsigned hashLen; |
8054 | 565k | unsigned genLen = 0; |
8055 | 565k | unsigned char hashbuf[HASH_LENGTH_MAX]; |
8056 | 565k | unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH]; |
8057 | 565k | unsigned char *keyBlockAlloc = NULL; /* allocated keyBlock */ |
8058 | 565k | unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */ |
8059 | 565k | const unsigned char *prk; /* psuedo-random key */ |
8060 | 565k | CK_ULONG prkLen; |
8061 | 565k | const unsigned char *okm; /* output keying material */ |
8062 | 565k | HASH_HashType hashType = sftk_GetHashTypeFromMechanism(params->prfHashMechanism); |
8063 | 565k | SFTKObject *saltKey = NULL; |
8064 | 565k | CK_RV crv = CKR_OK; |
8065 | | |
8066 | | /* Spec says it should be the base hash, but also accept the HMAC */ |
8067 | 565k | if (hashType == HASH_AlgNULL) { |
8068 | 0 | hashType = sftk_HMACMechanismToHash(params->prfHashMechanism); |
8069 | 0 | } |
8070 | 565k | rawHash = HASH_GetRawHashObject(hashType); |
8071 | 565k | if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) { |
8072 | 0 | return CKR_MECHANISM_INVALID; |
8073 | 0 | } |
8074 | 565k | hashLen = rawHash->length; |
8075 | | |
8076 | 565k | if ((!params->bExpand && !params->bExtract) || |
8077 | 565k | (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) || |
8078 | 565k | (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) { |
8079 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8080 | 0 | } |
8081 | 565k | if ((params->bExpand && keySize == 0) || |
8082 | 565k | (!params->bExpand && keySize > hashLen) || |
8083 | 565k | (params->bExpand && keySize > 255 * hashLen)) { |
8084 | 0 | return CKR_TEMPLATE_INCONSISTENT; |
8085 | 0 | } |
8086 | | |
8087 | | /* sourceKey is NULL if we are called from the POST, skip the |
8088 | | * sensitiveCheck */ |
8089 | 565k | if (sourceKey != NULL) { |
8090 | 565k | crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData); |
8091 | 565k | if (crv != CKR_OK) |
8092 | 0 | return crv; |
8093 | 565k | } |
8094 | | |
8095 | | /* HKDF-Extract(salt, base key value) */ |
8096 | 565k | if (params->bExtract) { |
8097 | 37.2k | CK_BYTE *salt; |
8098 | 37.2k | CK_ULONG saltLen; |
8099 | 37.2k | HMACContext *hmac; |
8100 | 37.2k | unsigned int bufLen; |
8101 | | |
8102 | 37.2k | switch (params->ulSaltType) { |
8103 | 23.7k | case CKF_HKDF_SALT_NULL: |
8104 | 23.7k | saltLen = hashLen; |
8105 | 23.7k | salt = hashbuf; |
8106 | 23.7k | memset(salt, 0, saltLen); |
8107 | 23.7k | break; |
8108 | 0 | case CKF_HKDF_SALT_DATA: |
8109 | 0 | salt = params->pSalt; |
8110 | 0 | saltLen = params->ulSaltLen; |
8111 | 0 | if ((salt == NULL) || (params->ulSaltLen == 0)) { |
8112 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8113 | 0 | } |
8114 | 0 | break; |
8115 | 13.5k | case CKF_HKDF_SALT_KEY: |
8116 | | /* lookup key */ |
8117 | 13.5k | session = sftk_SessionFromHandle(hSession); |
8118 | 13.5k | if (session == NULL) { |
8119 | 0 | return CKR_SESSION_HANDLE_INVALID; |
8120 | 0 | } |
8121 | | |
8122 | 13.5k | saltKey = sftk_ObjectFromHandle(params->hSaltKey, session); |
8123 | 13.5k | sftk_FreeSession(session); |
8124 | 13.5k | if (saltKey == NULL) { |
8125 | 0 | return CKR_KEY_HANDLE_INVALID; |
8126 | 0 | } |
8127 | | /* if the base key is not fips, but the salt key is, the |
8128 | | * resulting key can be fips */ |
8129 | 13.5k | if (isFIPS && !sftk_hasFIPS(key) && sftk_hasFIPS(saltKey)) { |
8130 | 0 | CK_MECHANISM mech; |
8131 | 0 | mech.mechanism = CKM_HKDF_DERIVE; |
8132 | 0 | mech.pParameter = params; |
8133 | 0 | mech.ulParameterLen = sizeof(*params); |
8134 | 0 | sftk_setFIPS(key, sftk_operationIsFIPS(saltKey->slot, |
8135 | 0 | &mech, CKA_DERIVE, |
8136 | 0 | saltKey)); |
8137 | 0 | } |
8138 | 13.5k | saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE); |
8139 | 13.5k | if (saltKey_att == NULL) { |
8140 | 0 | sftk_FreeObject(saltKey); |
8141 | 0 | return CKR_KEY_HANDLE_INVALID; |
8142 | 0 | } |
8143 | | /* save the resulting salt */ |
8144 | 13.5k | salt = saltKey_att->attrib.pValue; |
8145 | 13.5k | saltLen = saltKey_att->attrib.ulValueLen; |
8146 | 13.5k | break; |
8147 | 0 | default: |
8148 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8149 | 0 | break; |
8150 | 37.2k | } |
8151 | | |
8152 | 37.2k | hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS); |
8153 | 37.2k | if (saltKey_att) { |
8154 | 13.5k | sftk_FreeAttribute(saltKey_att); |
8155 | 13.5k | } |
8156 | 37.2k | if (saltKey) { |
8157 | 13.5k | sftk_FreeObject(saltKey); |
8158 | 13.5k | } |
8159 | 37.2k | if (!hmac) { |
8160 | 0 | return CKR_HOST_MEMORY; |
8161 | 0 | } |
8162 | 37.2k | HMAC_Begin(hmac); |
8163 | 37.2k | HMAC_Update(hmac, sourceKeyBytes, sourceKeyLen); |
8164 | 37.2k | HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf)); |
8165 | 37.2k | HMAC_Destroy(hmac, PR_TRUE); |
8166 | 37.2k | PORT_Assert(bufLen == rawHash->length); |
8167 | 37.2k | prk = hashbuf; |
8168 | 37.2k | prkLen = bufLen; |
8169 | 527k | } else { |
8170 | | /* PRK = base key value */ |
8171 | 527k | prk = sourceKeyBytes; |
8172 | 527k | prkLen = sourceKeyLen; |
8173 | 527k | } |
8174 | | |
8175 | | /* HKDF-Expand */ |
8176 | 565k | if (!params->bExpand) { |
8177 | 37.2k | okm = prk; |
8178 | 37.2k | keySize = genLen = hashLen; |
8179 | 527k | } else { |
8180 | | /* T(1) = HMAC-Hash(prk, "" | info | 0x01) |
8181 | | * T(n) = HMAC-Hash(prk, T(n-1) | info | n |
8182 | | * key material = T(1) | ... | T(n) |
8183 | | */ |
8184 | 527k | HMACContext *hmac; |
8185 | 527k | CK_BYTE bi; |
8186 | 527k | unsigned iterations; |
8187 | | |
8188 | 527k | genLen = PR_ROUNDUP(keySize, hashLen); |
8189 | 527k | iterations = genLen / hashLen; |
8190 | | |
8191 | 527k | if (genLen > sizeof(keyBlock)) { |
8192 | 0 | keyBlockAlloc = PORT_Alloc(genLen); |
8193 | 0 | if (keyBlockAlloc == NULL) { |
8194 | 0 | return CKR_HOST_MEMORY; |
8195 | 0 | } |
8196 | 0 | keyBlockData = keyBlockAlloc; |
8197 | 0 | } |
8198 | 527k | hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS); |
8199 | 527k | if (hmac == NULL) { |
8200 | 0 | PORT_Free(keyBlockAlloc); |
8201 | 0 | return CKR_HOST_MEMORY; |
8202 | 0 | } |
8203 | 1.07M | for (bi = 1; bi <= iterations && bi > 0; ++bi) { |
8204 | 549k | unsigned len; |
8205 | 549k | HMAC_Begin(hmac); |
8206 | 549k | if (bi > 1) { |
8207 | 21.2k | HMAC_Update(hmac, &keyBlockData[(bi - 2) * hashLen], hashLen); |
8208 | 21.2k | } |
8209 | 549k | if (params->ulInfoLen != 0) { |
8210 | 526k | HMAC_Update(hmac, params->pInfo, params->ulInfoLen); |
8211 | 526k | } |
8212 | 549k | HMAC_Update(hmac, &bi, 1); |
8213 | 549k | HMAC_Finish(hmac, &keyBlockData[(bi - 1) * hashLen], &len, |
8214 | 549k | hashLen); |
8215 | 549k | PORT_Assert(len == hashLen); |
8216 | 549k | } |
8217 | 527k | HMAC_Destroy(hmac, PR_TRUE); |
8218 | 527k | okm = &keyBlockData[0]; |
8219 | 527k | } |
8220 | | /* key material = okm */ |
8221 | 565k | crv = CKR_OK; |
8222 | 565k | if (key) { |
8223 | 565k | crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize); |
8224 | 565k | } else { |
8225 | 0 | PORT_Assert(outKeyBytes != NULL); |
8226 | 0 | PORT_Memcpy(outKeyBytes, okm, keySize); |
8227 | 0 | } |
8228 | 565k | PORT_Memset(keyBlockData, 0, genLen); |
8229 | 565k | PORT_Memset(hashbuf, 0, sizeof(hashbuf)); |
8230 | 565k | PORT_Free(keyBlockAlloc); |
8231 | 565k | return crv; |
8232 | 565k | } |
8233 | | |
8234 | | /* |
8235 | | * SSL Key generation given pre master secret |
8236 | | */ |
8237 | 0 | #define NUM_MIXERS 9 |
8238 | | static const char *const mixers[NUM_MIXERS] = { |
8239 | | "A", |
8240 | | "BB", |
8241 | | "CCC", |
8242 | | "DDDD", |
8243 | | "EEEEE", |
8244 | | "FFFFFF", |
8245 | | "GGGGGGG", |
8246 | | "HHHHHHHH", |
8247 | | "IIIIIIIII" |
8248 | | }; |
8249 | 87.9k | #define SSL3_PMS_LENGTH 48 |
8250 | 380k | #define SSL3_MASTER_SECRET_LENGTH 48 |
8251 | 967k | #define SSL3_RANDOM_LENGTH 32 |
8252 | | |
8253 | | /* NSC_DeriveKey derives a key from a base key, creating a new key object. */ |
8254 | | CK_RV |
8255 | | NSC_DeriveKey(CK_SESSION_HANDLE hSession, |
8256 | | CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, |
8257 | | CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, |
8258 | | CK_OBJECT_HANDLE_PTR phKey) |
8259 | 892k | { |
8260 | 892k | SFTKSession *session; |
8261 | 892k | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
8262 | 892k | SFTKObject *key; |
8263 | 892k | SFTKObject *sourceKey; |
8264 | 892k | SFTKAttribute *att = NULL; |
8265 | 892k | SFTKAttribute *att2 = NULL; |
8266 | 892k | unsigned char *buf; |
8267 | 892k | SHA1Context *sha; |
8268 | 892k | MD5Context *md5; |
8269 | 892k | MD2Context *md2; |
8270 | 892k | CK_ULONG macSize; |
8271 | 892k | CK_ULONG tmpKeySize; |
8272 | 892k | CK_ULONG IVSize; |
8273 | 892k | CK_ULONG keySize = 0; |
8274 | 892k | CK_RV crv = CKR_OK; |
8275 | 892k | CK_BBOOL cktrue = CK_TRUE; |
8276 | 892k | CK_BBOOL ckfalse = CK_FALSE; |
8277 | 892k | CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
8278 | 892k | CK_OBJECT_CLASS classType = CKO_SECRET_KEY; |
8279 | 892k | CK_KEY_DERIVATION_STRING_DATA *stringPtr; |
8280 | 892k | PRBool isTLS = PR_FALSE; |
8281 | 892k | PRBool isDH = PR_FALSE; |
8282 | 892k | HASH_HashType tlsPrfHash = HASH_AlgNULL; |
8283 | 892k | SECStatus rv; |
8284 | 892k | int i; |
8285 | 892k | unsigned int outLen; |
8286 | 892k | unsigned char sha_out[SHA1_LENGTH]; |
8287 | 892k | unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH]; |
8288 | 892k | PRBool isFIPS; |
8289 | 892k | HASH_HashType hashType; |
8290 | 892k | CK_MECHANISM_TYPE hashMech; |
8291 | 892k | PRBool extractValue = PR_TRUE; |
8292 | 892k | CK_IKE1_EXTENDED_DERIVE_PARAMS ikeAppB; |
8293 | 892k | CK_IKE1_EXTENDED_DERIVE_PARAMS *pIkeAppB; |
8294 | | |
8295 | 892k | CHECK_FORK(); |
8296 | | |
8297 | 892k | if (!slot) { |
8298 | 0 | return CKR_SESSION_HANDLE_INVALID; |
8299 | 0 | } |
8300 | 892k | if (!pMechanism) { |
8301 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
8302 | 0 | } |
8303 | 892k | CK_MECHANISM_TYPE mechanism = pMechanism->mechanism; |
8304 | | |
8305 | | /* |
8306 | | * now lets create an object to hang the attributes off of |
8307 | | */ |
8308 | 892k | if (phKey) { |
8309 | 892k | *phKey = CK_INVALID_HANDLE; |
8310 | 892k | } |
8311 | | |
8312 | 892k | key = sftk_NewObject(slot); /* fill in the handle later */ |
8313 | 892k | if (key == NULL) { |
8314 | 0 | return CKR_HOST_MEMORY; |
8315 | 0 | } |
8316 | 892k | isFIPS = sftk_isFIPS(slot->slotID); |
8317 | | |
8318 | | /* |
8319 | | * load the template values into the object |
8320 | | */ |
8321 | 5.55M | for (i = 0; i < (int)ulAttributeCount; i++) { |
8322 | 4.66M | crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); |
8323 | 4.66M | if (crv != CKR_OK) |
8324 | 0 | break; |
8325 | | |
8326 | 4.66M | if (pTemplate[i].type == CKA_KEY_TYPE) { |
8327 | 892k | keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue; |
8328 | 892k | } |
8329 | 4.66M | if (pTemplate[i].type == CKA_VALUE_LEN) { |
8330 | 681k | keySize = *(CK_ULONG *)pTemplate[i].pValue; |
8331 | 681k | } |
8332 | 4.66M | } |
8333 | 892k | if (crv != CKR_OK) { |
8334 | 0 | sftk_FreeObject(key); |
8335 | 0 | return crv; |
8336 | 0 | } |
8337 | | |
8338 | 892k | if (keySize == 0) { |
8339 | 210k | keySize = sftk_MapKeySize(keyType); |
8340 | 210k | } |
8341 | | |
8342 | 892k | switch (mechanism) { |
8343 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */ |
8344 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */ |
8345 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */ |
8346 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA512: |
8347 | 0 | extractValue = PR_FALSE; |
8348 | 0 | classType = CKO_PRIVATE_KEY; |
8349 | 0 | break; |
8350 | 93 | case CKM_NSS_PUB_FROM_PRIV: |
8351 | 93 | extractValue = PR_FALSE; |
8352 | 93 | classType = CKO_PUBLIC_KEY; |
8353 | 93 | break; |
8354 | 169k | case CKM_HKDF_DATA: /* fall through */ |
8355 | 169k | case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */ |
8356 | 169k | case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */ |
8357 | 169k | case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: |
8358 | 169k | classType = CKO_DATA; |
8359 | 169k | break; |
8360 | 0 | case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */ |
8361 | 0 | case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */ |
8362 | 0 | case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */ |
8363 | 0 | case CKM_NSS_JPAKE_FINAL_SHA512: |
8364 | 0 | extractValue = PR_FALSE; |
8365 | | /* fall through */ |
8366 | 722k | default: |
8367 | 722k | classType = CKO_SECRET_KEY; |
8368 | 892k | } |
8369 | | |
8370 | 892k | crv = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType)); |
8371 | 892k | if (crv != CKR_OK) { |
8372 | 0 | sftk_FreeObject(key); |
8373 | 0 | return crv; |
8374 | 0 | } |
8375 | | |
8376 | | /* look up the base key we're deriving with */ |
8377 | 892k | session = sftk_SessionFromHandle(hSession); |
8378 | 892k | if (session == NULL) { |
8379 | 0 | sftk_FreeObject(key); |
8380 | 0 | return CKR_SESSION_HANDLE_INVALID; |
8381 | 0 | } |
8382 | | |
8383 | 892k | sourceKey = sftk_ObjectFromHandle(hBaseKey, session); |
8384 | 892k | sftk_FreeSession(session); |
8385 | | /* is this eventually succeeds, lastOpWasFIPS will be set the resulting key's |
8386 | | * FIPS state below. */ |
8387 | 892k | session->lastOpWasFIPS = PR_FALSE; |
8388 | 892k | if (sourceKey == NULL) { |
8389 | 0 | sftk_FreeObject(key); |
8390 | 0 | return CKR_KEY_HANDLE_INVALID; |
8391 | 0 | } |
8392 | | |
8393 | 892k | if (extractValue) { |
8394 | | /* get the value of the base key */ |
8395 | 892k | att = sftk_FindAttribute(sourceKey, CKA_VALUE); |
8396 | 892k | if (att == NULL) { |
8397 | 0 | sftk_FreeObject(key); |
8398 | 0 | sftk_FreeObject(sourceKey); |
8399 | 0 | return CKR_KEY_HANDLE_INVALID; |
8400 | 0 | } |
8401 | 892k | } |
8402 | 892k | sftk_setFIPS(key, sftk_operationIsFIPS(slot, pMechanism, |
8403 | 892k | CKA_DERIVE, sourceKey)); |
8404 | | |
8405 | 892k | switch (mechanism) { |
8406 | | /* get a public key from a private key. nsslowkey_ConvertToPublickey() |
8407 | | * will generate the public portion if it doesn't already exist. */ |
8408 | 93 | case CKM_NSS_PUB_FROM_PRIV: { |
8409 | 93 | NSSLOWKEYPrivateKey *privKey; |
8410 | 93 | NSSLOWKEYPublicKey *pubKey; |
8411 | 93 | int error; |
8412 | | |
8413 | 93 | crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType); |
8414 | 93 | if (crv != CKR_OK) { |
8415 | 0 | break; |
8416 | 0 | } |
8417 | | |
8418 | | /* privKey is stored in sourceKey and will be destroyed when |
8419 | | * the sourceKey is freed. */ |
8420 | 93 | privKey = sftk_GetPrivKey(sourceKey, keyType, &crv); |
8421 | 93 | if (privKey == NULL) { |
8422 | 0 | break; |
8423 | 0 | } |
8424 | 93 | pubKey = nsslowkey_ConvertToPublicKey(privKey); |
8425 | 93 | if (pubKey == NULL) { |
8426 | 2 | error = PORT_GetError(); |
8427 | 2 | crv = sftk_MapCryptError(error); |
8428 | 2 | break; |
8429 | 2 | } |
8430 | 91 | crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey); |
8431 | 91 | nsslowkey_DestroyPublicKey(pubKey); |
8432 | 91 | break; |
8433 | 93 | } |
8434 | 0 | case CKM_NSS_IKE_PRF_DERIVE: |
8435 | 0 | case CKM_IKE_PRF_DERIVE: |
8436 | 0 | if (pMechanism->ulParameterLen != |
8437 | 0 | sizeof(CK_IKE_PRF_DERIVE_PARAMS)) { |
8438 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8439 | 0 | break; |
8440 | 0 | } |
8441 | 0 | crv = sftk_ike_prf(hSession, att, |
8442 | 0 | (CK_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key); |
8443 | 0 | break; |
8444 | 0 | case CKM_NSS_IKE1_PRF_DERIVE: |
8445 | 0 | case CKM_IKE1_PRF_DERIVE: |
8446 | 0 | if (pMechanism->ulParameterLen != |
8447 | 0 | sizeof(CK_IKE1_PRF_DERIVE_PARAMS)) { |
8448 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8449 | 0 | break; |
8450 | 0 | } |
8451 | 0 | crv = sftk_ike1_prf(hSession, att, |
8452 | 0 | (CK_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter, |
8453 | 0 | key, keySize); |
8454 | 0 | break; |
8455 | 0 | case CKM_NSS_IKE1_APP_B_PRF_DERIVE: |
8456 | 0 | case CKM_IKE1_EXTENDED_DERIVE: |
8457 | 0 | pIkeAppB = (CK_IKE1_EXTENDED_DERIVE_PARAMS *)pMechanism->pParameter; |
8458 | 0 | if (pMechanism->ulParameterLen == |
8459 | 0 | sizeof(CK_MECHANISM_TYPE)) { |
8460 | 0 | ikeAppB.prfMechanism = *(CK_MECHANISM_TYPE *)pMechanism->pParameter; |
8461 | 0 | ikeAppB.bHasKeygxy = PR_FALSE; |
8462 | 0 | ikeAppB.hKeygxy = CK_INVALID_HANDLE; |
8463 | 0 | ikeAppB.pExtraData = NULL; |
8464 | 0 | ikeAppB.ulExtraDataLen = 0; |
8465 | 0 | pIkeAppB = &ikeAppB; |
8466 | 0 | } else if (pMechanism->ulParameterLen != |
8467 | 0 | sizeof(CK_IKE1_EXTENDED_DERIVE_PARAMS)) { |
8468 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8469 | 0 | break; |
8470 | 0 | } |
8471 | 0 | crv = sftk_ike1_appendix_b_prf(hSession, att, pIkeAppB, key, |
8472 | 0 | keySize); |
8473 | 0 | break; |
8474 | 0 | case CKM_NSS_IKE_PRF_PLUS_DERIVE: |
8475 | 0 | case CKM_IKE2_PRF_PLUS_DERIVE: |
8476 | 0 | if (pMechanism->ulParameterLen != |
8477 | 0 | sizeof(CK_IKE2_PRF_PLUS_DERIVE_PARAMS)) { |
8478 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8479 | 0 | break; |
8480 | 0 | } |
8481 | 0 | crv = sftk_ike_prf_plus(hSession, att, |
8482 | 0 | (CK_IKE2_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter, |
8483 | 0 | key, keySize); |
8484 | 0 | break; |
8485 | | /* |
8486 | | * generate the master secret |
8487 | | */ |
8488 | 70.4k | case CKM_TLS12_MASTER_KEY_DERIVE: |
8489 | 89.9k | case CKM_TLS12_MASTER_KEY_DERIVE_DH: |
8490 | 89.9k | case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256: |
8491 | 89.9k | case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256: |
8492 | 104k | case CKM_TLS_MASTER_KEY_DERIVE: |
8493 | 133k | case CKM_TLS_MASTER_KEY_DERIVE_DH: |
8494 | 133k | case CKM_SSL3_MASTER_KEY_DERIVE: |
8495 | 133k | case CKM_SSL3_MASTER_KEY_DERIVE_DH: { |
8496 | 133k | CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master; |
8497 | 133k | SSL3RSAPreMasterSecret *rsa_pms; |
8498 | 133k | unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; |
8499 | | |
8500 | 133k | if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) || |
8501 | 89.9k | (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { |
8502 | 89.9k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) { |
8503 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8504 | 0 | break; |
8505 | 0 | } |
8506 | 89.9k | CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master = |
8507 | 89.9k | (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter; |
8508 | 89.9k | tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_master->prfHashMechanism); |
8509 | 89.9k | if (tlsPrfHash == HASH_AlgNULL) { |
8510 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8511 | 0 | break; |
8512 | 0 | } |
8513 | 89.9k | } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) || |
8514 | 44.0k | (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) { |
8515 | 0 | tlsPrfHash = HASH_AlgSHA256; |
8516 | 0 | } |
8517 | | |
8518 | 133k | if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) && |
8519 | 133k | (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) { |
8520 | 133k | isTLS = PR_TRUE; |
8521 | 133k | } |
8522 | 133k | if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) || |
8523 | 133k | (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) || |
8524 | 104k | (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) || |
8525 | 104k | (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { |
8526 | 49.1k | isDH = PR_TRUE; |
8527 | 49.1k | } |
8528 | | |
8529 | | /* first do the consistency checks */ |
8530 | 133k | if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { |
8531 | 2.72k | crv = CKR_KEY_TYPE_INCONSISTENT; |
8532 | 2.72k | break; |
8533 | 2.72k | } |
8534 | 131k | att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); |
8535 | 131k | if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != |
8536 | 131k | CKK_GENERIC_SECRET)) { |
8537 | 0 | if (att2) |
8538 | 0 | sftk_FreeAttribute(att2); |
8539 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
8540 | 0 | break; |
8541 | 0 | } |
8542 | 131k | sftk_FreeAttribute(att2); |
8543 | 131k | if (keyType != CKK_GENERIC_SECRET) { |
8544 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
8545 | 0 | break; |
8546 | 0 | } |
8547 | 131k | if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { |
8548 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
8549 | 0 | break; |
8550 | 0 | } |
8551 | | |
8552 | | /* finally do the key gen */ |
8553 | 131k | ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) |
8554 | 131k | pMechanism->pParameter; |
8555 | | |
8556 | 131k | if (ssl3_master->pVersion) { |
8557 | 82.0k | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
8558 | 82.0k | rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue; |
8559 | | /* don't leak more key material then necessary for SSL to work */ |
8560 | 82.0k | if ((sessKey == NULL) || sessKey->wasDerived) { |
8561 | 0 | ssl3_master->pVersion->major = 0xff; |
8562 | 0 | ssl3_master->pVersion->minor = 0xff; |
8563 | 82.0k | } else { |
8564 | 82.0k | ssl3_master->pVersion->major = rsa_pms->client_version[0]; |
8565 | 82.0k | ssl3_master->pVersion->minor = rsa_pms->client_version[1]; |
8566 | 82.0k | } |
8567 | 82.0k | } |
8568 | 131k | if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) { |
8569 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8570 | 0 | break; |
8571 | 0 | } |
8572 | 131k | if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) { |
8573 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8574 | 0 | break; |
8575 | 0 | } |
8576 | 131k | PORT_Memcpy(crsrdata, |
8577 | 131k | ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); |
8578 | 131k | PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, |
8579 | 131k | ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); |
8580 | | |
8581 | 131k | if (isTLS) { |
8582 | 131k | SECStatus status; |
8583 | 131k | SECItem crsr = { siBuffer, NULL, 0 }; |
8584 | 131k | SECItem master = { siBuffer, NULL, 0 }; |
8585 | 131k | SECItem pms = { siBuffer, NULL, 0 }; |
8586 | | |
8587 | 131k | crsr.data = crsrdata; |
8588 | 131k | crsr.len = sizeof crsrdata; |
8589 | 131k | master.data = key_block; |
8590 | 131k | master.len = SSL3_MASTER_SECRET_LENGTH; |
8591 | 131k | pms.data = (unsigned char *)att->attrib.pValue; |
8592 | 131k | pms.len = att->attrib.ulValueLen; |
8593 | | |
8594 | 131k | if (tlsPrfHash != HASH_AlgNULL) { |
8595 | 87.6k | status = TLS_P_hash(tlsPrfHash, &pms, "master secret", |
8596 | 87.6k | &crsr, &master, isFIPS); |
8597 | 87.6k | } else { |
8598 | 43.6k | status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS); |
8599 | 43.6k | } |
8600 | 131k | if (status != SECSuccess) { |
8601 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
8602 | 0 | crv = CKR_FUNCTION_FAILED; |
8603 | 0 | break; |
8604 | 0 | } |
8605 | 131k | } else { |
8606 | | /* now allocate the hash contexts */ |
8607 | 0 | md5 = MD5_NewContext(); |
8608 | 0 | if (md5 == NULL) { |
8609 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
8610 | 0 | crv = CKR_HOST_MEMORY; |
8611 | 0 | break; |
8612 | 0 | } |
8613 | 0 | sha = SHA1_NewContext(); |
8614 | 0 | if (sha == NULL) { |
8615 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
8616 | 0 | PORT_Free(md5); |
8617 | 0 | crv = CKR_HOST_MEMORY; |
8618 | 0 | break; |
8619 | 0 | } |
8620 | 0 | for (i = 0; i < 3; i++) { |
8621 | 0 | SHA1_Begin(sha); |
8622 | 0 | SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i])); |
8623 | 0 | SHA1_Update(sha, (const unsigned char *)att->attrib.pValue, |
8624 | 0 | att->attrib.ulValueLen); |
8625 | 0 | SHA1_Update(sha, crsrdata, sizeof crsrdata); |
8626 | 0 | SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); |
8627 | 0 | PORT_Assert(outLen == SHA1_LENGTH); |
8628 | |
|
8629 | 0 | MD5_Begin(md5); |
8630 | 0 | MD5_Update(md5, (const unsigned char *)att->attrib.pValue, |
8631 | 0 | att->attrib.ulValueLen); |
8632 | 0 | MD5_Update(md5, sha_out, outLen); |
8633 | 0 | MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH); |
8634 | 0 | PORT_Assert(outLen == MD5_LENGTH); |
8635 | 0 | } |
8636 | 0 | PORT_Free(md5); |
8637 | 0 | PORT_Free(sha); |
8638 | 0 | PORT_Memset(crsrdata, 0, sizeof crsrdata); |
8639 | 0 | PORT_Memset(sha_out, 0, sizeof sha_out); |
8640 | 0 | } |
8641 | | |
8642 | | /* store the results */ |
8643 | 131k | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, SSL3_MASTER_SECRET_LENGTH); |
8644 | 131k | PORT_Memset(key_block, 0, sizeof key_block); |
8645 | 131k | if (crv != CKR_OK) |
8646 | 0 | break; |
8647 | 131k | keyType = CKK_GENERIC_SECRET; |
8648 | 131k | crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType)); |
8649 | 131k | if (isTLS) { |
8650 | | /* TLS's master secret is used to "sign" finished msgs with PRF. */ |
8651 | | /* XXX This seems like a hack. But SFTK_Derive only accepts |
8652 | | * one "operation" argument. */ |
8653 | 131k | crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); |
8654 | 131k | if (crv != CKR_OK) |
8655 | 0 | break; |
8656 | 131k | crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); |
8657 | 131k | if (crv != CKR_OK) |
8658 | 0 | break; |
8659 | | /* While we're here, we might as well force this, too. */ |
8660 | 131k | crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); |
8661 | 131k | if (crv != CKR_OK) |
8662 | 0 | break; |
8663 | 131k | } |
8664 | 131k | break; |
8665 | 131k | } |
8666 | | |
8667 | | /* Extended master key derivation [draft-ietf-tls-session-hash] */ |
8668 | 131k | case CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE: |
8669 | 7.29k | case CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE_DH: |
8670 | 7.29k | case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE: |
8671 | 7.29k | case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: { |
8672 | 7.29k | CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params; |
8673 | 7.29k | SSL3RSAPreMasterSecret *rsa_pms; |
8674 | 7.29k | SECStatus status; |
8675 | 7.29k | SECItem pms = { siBuffer, NULL, 0 }; |
8676 | 7.29k | SECItem seed = { siBuffer, NULL, 0 }; |
8677 | 7.29k | SECItem master = { siBuffer, NULL, 0 }; |
8678 | | |
8679 | 7.29k | ems_params = (CK_TLS12_EXTENDED_MASTER_KEY_DERIVE_PARAMS *) |
8680 | 7.29k | pMechanism->pParameter; |
8681 | | |
8682 | | /* First do the consistency checks */ |
8683 | 7.29k | if (((mechanism == CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE) || |
8684 | 4.15k | (mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE)) && |
8685 | 3.13k | (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { |
8686 | 63 | crv = CKR_KEY_TYPE_INCONSISTENT; |
8687 | 63 | break; |
8688 | 63 | } |
8689 | 7.23k | att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); |
8690 | 7.23k | if ((att2 == NULL) || |
8691 | 7.23k | (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) { |
8692 | 0 | if (att2) |
8693 | 0 | sftk_FreeAttribute(att2); |
8694 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
8695 | 0 | break; |
8696 | 0 | } |
8697 | 7.23k | sftk_FreeAttribute(att2); |
8698 | 7.23k | if (keyType != CKK_GENERIC_SECRET) { |
8699 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
8700 | 0 | break; |
8701 | 0 | } |
8702 | 7.23k | if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { |
8703 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
8704 | 0 | break; |
8705 | 0 | } |
8706 | | |
8707 | | /* Do the key derivation */ |
8708 | 7.23k | pms.data = (unsigned char *)att->attrib.pValue; |
8709 | 7.23k | pms.len = att->attrib.ulValueLen; |
8710 | 7.23k | seed.data = ems_params->pSessionHash; |
8711 | 7.23k | seed.len = ems_params->ulSessionHashLen; |
8712 | 7.23k | master.data = key_block; |
8713 | 7.23k | master.len = SSL3_MASTER_SECRET_LENGTH; |
8714 | 7.23k | if (ems_params->prfHashMechanism == CKM_TLS_PRF) { |
8715 | | /* |
8716 | | * In this case, the session hash is the concatenation of SHA-1 |
8717 | | * and MD5, so it should be 36 bytes long. |
8718 | | */ |
8719 | 1.61k | if (seed.len != MD5_LENGTH + SHA1_LENGTH) { |
8720 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8721 | 0 | break; |
8722 | 0 | } |
8723 | | |
8724 | 1.61k | status = TLS_PRF(&pms, "extended master secret", |
8725 | 1.61k | &seed, &master, isFIPS); |
8726 | 5.61k | } else { |
8727 | 5.61k | const SECHashObject *hashObj; |
8728 | | |
8729 | 5.61k | tlsPrfHash = sftk_GetHashTypeFromMechanism(ems_params->prfHashMechanism); |
8730 | 5.61k | if (tlsPrfHash == HASH_AlgNULL) { |
8731 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8732 | 0 | break; |
8733 | 0 | } |
8734 | | |
8735 | 5.61k | hashObj = HASH_GetRawHashObject(tlsPrfHash); |
8736 | 5.61k | if (seed.len != hashObj->length) { |
8737 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
8738 | 0 | break; |
8739 | 0 | } |
8740 | | |
8741 | 5.61k | status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret", |
8742 | 5.61k | &seed, &master, isFIPS); |
8743 | 5.61k | } |
8744 | 7.23k | if (status != SECSuccess) { |
8745 | 0 | crv = CKR_FUNCTION_FAILED; |
8746 | 0 | break; |
8747 | 0 | } |
8748 | | |
8749 | | /* Reflect the version if required */ |
8750 | 7.23k | if (ems_params->pVersion) { |
8751 | 3.07k | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
8752 | 3.07k | rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue; |
8753 | | /* don't leak more key material than necessary for SSL to work */ |
8754 | 3.07k | if ((sessKey == NULL) || sessKey->wasDerived) { |
8755 | 0 | ems_params->pVersion->major = 0xff; |
8756 | 0 | ems_params->pVersion->minor = 0xff; |
8757 | 3.07k | } else { |
8758 | 3.07k | ems_params->pVersion->major = rsa_pms->client_version[0]; |
8759 | 3.07k | ems_params->pVersion->minor = rsa_pms->client_version[1]; |
8760 | 3.07k | } |
8761 | 3.07k | } |
8762 | | |
8763 | | /* Store the results */ |
8764 | 7.23k | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, |
8765 | 7.23k | SSL3_MASTER_SECRET_LENGTH); |
8766 | 7.23k | PORT_Memset(key_block, 0, sizeof key_block); |
8767 | 7.23k | break; |
8768 | 7.23k | } |
8769 | | |
8770 | 64.8k | case CKM_TLS12_KEY_AND_MAC_DERIVE: |
8771 | 64.8k | case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: |
8772 | 103k | case CKM_TLS_KEY_AND_MAC_DERIVE: |
8773 | 103k | case CKM_SSL3_KEY_AND_MAC_DERIVE: { |
8774 | 103k | CK_SSL3_KEY_MAT_PARAMS *ssl3_keys; |
8775 | 103k | CK_SSL3_KEY_MAT_OUT *ssl3_keys_out; |
8776 | 103k | CK_ULONG effKeySize; |
8777 | 103k | unsigned int block_needed; |
8778 | 103k | unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; |
8779 | | |
8780 | 103k | if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) { |
8781 | 64.8k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) { |
8782 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8783 | 0 | break; |
8784 | 0 | } |
8785 | 64.8k | CK_TLS12_KEY_MAT_PARAMS *tls12_keys = |
8786 | 64.8k | (CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter; |
8787 | 64.8k | tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_keys->prfHashMechanism); |
8788 | 64.8k | if (tlsPrfHash == HASH_AlgNULL) { |
8789 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8790 | 0 | break; |
8791 | 0 | } |
8792 | 64.8k | } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) { |
8793 | 0 | tlsPrfHash = HASH_AlgSHA256; |
8794 | 0 | } |
8795 | | |
8796 | 103k | if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) { |
8797 | 103k | isTLS = PR_TRUE; |
8798 | 103k | } |
8799 | | |
8800 | 103k | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
8801 | 103k | if (crv != CKR_OK) |
8802 | 0 | break; |
8803 | | |
8804 | 103k | if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) { |
8805 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
8806 | 0 | break; |
8807 | 0 | } |
8808 | 103k | att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); |
8809 | 103k | if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != |
8810 | 103k | CKK_GENERIC_SECRET)) { |
8811 | 0 | if (att2) |
8812 | 0 | sftk_FreeAttribute(att2); |
8813 | 0 | crv = CKR_KEY_FUNCTION_NOT_PERMITTED; |
8814 | 0 | break; |
8815 | 0 | } |
8816 | 103k | sftk_FreeAttribute(att2); |
8817 | 103k | md5 = MD5_NewContext(); |
8818 | 103k | if (md5 == NULL) { |
8819 | 0 | crv = CKR_HOST_MEMORY; |
8820 | 0 | break; |
8821 | 0 | } |
8822 | 103k | sha = SHA1_NewContext(); |
8823 | 103k | if (sha == NULL) { |
8824 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
8825 | 0 | crv = CKR_HOST_MEMORY; |
8826 | 0 | break; |
8827 | 0 | } |
8828 | | |
8829 | 103k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_SSL3_KEY_MAT_PARAMS))) { |
8830 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
8831 | 0 | SHA1_DestroyContext(sha, PR_TRUE); |
8832 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8833 | 0 | break; |
8834 | 0 | } |
8835 | 103k | ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter; |
8836 | | |
8837 | 103k | PORT_Memcpy(srcrdata, |
8838 | 103k | ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); |
8839 | 103k | PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, |
8840 | 103k | ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); |
8841 | | |
8842 | | /* |
8843 | | * clear out our returned keys so we can recover on failure |
8844 | | */ |
8845 | 103k | ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial; |
8846 | 103k | ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE; |
8847 | 103k | ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE; |
8848 | 103k | ssl3_keys_out->hClientKey = CK_INVALID_HANDLE; |
8849 | 103k | ssl3_keys_out->hServerKey = CK_INVALID_HANDLE; |
8850 | | |
8851 | | /* |
8852 | | * How much key material do we need? |
8853 | | */ |
8854 | 103k | macSize = ssl3_keys->ulMacSizeInBits / 8; |
8855 | 103k | effKeySize = ssl3_keys->ulKeySizeInBits / 8; |
8856 | 103k | IVSize = ssl3_keys->ulIVSizeInBits / 8; |
8857 | 103k | if (keySize == 0) { |
8858 | 10.5k | effKeySize = keySize; |
8859 | 10.5k | } |
8860 | | |
8861 | | /* bIsExport must be false. */ |
8862 | 103k | if (ssl3_keys->bIsExport) { |
8863 | 0 | MD5_DestroyContext(md5, PR_TRUE); |
8864 | 0 | SHA1_DestroyContext(sha, PR_TRUE); |
8865 | 0 | PORT_Memset(srcrdata, 0, sizeof srcrdata); |
8866 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
8867 | 0 | break; |
8868 | 0 | } |
8869 | | |
8870 | 103k | block_needed = 2 * (macSize + effKeySize + IVSize); |
8871 | 103k | PORT_Assert(block_needed <= sizeof key_block); |
8872 | 103k | if (block_needed > sizeof key_block) |
8873 | 0 | block_needed = sizeof key_block; |
8874 | | |
8875 | | /* |
8876 | | * generate the key material: This looks amazingly similar to the |
8877 | | * PMS code, and is clearly crying out for a function to provide it. |
8878 | | */ |
8879 | 103k | if (isTLS) { |
8880 | 103k | SECStatus status; |
8881 | 103k | SECItem srcr = { siBuffer, NULL, 0 }; |
8882 | 103k | SECItem keyblk = { siBuffer, NULL, 0 }; |
8883 | 103k | SECItem master = { siBuffer, NULL, 0 }; |
8884 | | |
8885 | 103k | srcr.data = srcrdata; |
8886 | 103k | srcr.len = sizeof srcrdata; |
8887 | 103k | keyblk.data = key_block; |
8888 | 103k | keyblk.len = block_needed; |
8889 | 103k | master.data = (unsigned char *)att->attrib.pValue; |
8890 | 103k | master.len = att->attrib.ulValueLen; |
8891 | | |
8892 | 103k | if (tlsPrfHash != HASH_AlgNULL) { |
8893 | 64.8k | status = TLS_P_hash(tlsPrfHash, &master, "key expansion", |
8894 | 64.8k | &srcr, &keyblk, isFIPS); |
8895 | 64.8k | } else { |
8896 | 38.8k | status = TLS_PRF(&master, "key expansion", &srcr, &keyblk, |
8897 | 38.8k | isFIPS); |
8898 | 38.8k | } |
8899 | 103k | if (status != SECSuccess) { |
8900 | 0 | goto key_and_mac_derive_fail; |
8901 | 0 | } |
8902 | 103k | } else { |
8903 | 0 | unsigned int block_bytes = 0; |
8904 | | /* key_block = |
8905 | | * MD5(master_secret + SHA('A' + master_secret + |
8906 | | * ServerHello.random + ClientHello.random)) + |
8907 | | * MD5(master_secret + SHA('BB' + master_secret + |
8908 | | * ServerHello.random + ClientHello.random)) + |
8909 | | * MD5(master_secret + SHA('CCC' + master_secret + |
8910 | | * ServerHello.random + ClientHello.random)) + |
8911 | | * [...]; |
8912 | | */ |
8913 | 0 | for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) { |
8914 | 0 | SHA1_Begin(sha); |
8915 | 0 | SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i])); |
8916 | 0 | SHA1_Update(sha, (const unsigned char *)att->attrib.pValue, |
8917 | 0 | att->attrib.ulValueLen); |
8918 | 0 | SHA1_Update(sha, srcrdata, sizeof srcrdata); |
8919 | 0 | SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); |
8920 | 0 | PORT_Assert(outLen == SHA1_LENGTH); |
8921 | 0 | MD5_Begin(md5); |
8922 | 0 | MD5_Update(md5, (const unsigned char *)att->attrib.pValue, |
8923 | 0 | att->attrib.ulValueLen); |
8924 | 0 | MD5_Update(md5, sha_out, outLen); |
8925 | 0 | MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH); |
8926 | 0 | PORT_Assert(outLen == MD5_LENGTH); |
8927 | 0 | block_bytes += outLen; |
8928 | 0 | } |
8929 | 0 | PORT_Memset(sha_out, 0, sizeof sha_out); |
8930 | 0 | } |
8931 | | |
8932 | | /* |
8933 | | * Put the key material where it goes. |
8934 | | */ |
8935 | 103k | i = 0; /* now shows how much consumed */ |
8936 | | |
8937 | | /* |
8938 | | * The key_block is partitioned as follows: |
8939 | | * client_write_MAC_secret[CipherSpec.hash_size] |
8940 | | */ |
8941 | 103k | crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize, |
8942 | 103k | &ssl3_keys_out->hClientMacSecret); |
8943 | 103k | if (crv != CKR_OK) |
8944 | 0 | goto key_and_mac_derive_fail; |
8945 | | |
8946 | 103k | i += macSize; |
8947 | | |
8948 | | /* |
8949 | | * server_write_MAC_secret[CipherSpec.hash_size] |
8950 | | */ |
8951 | 103k | crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize, |
8952 | 103k | &ssl3_keys_out->hServerMacSecret); |
8953 | 103k | if (crv != CKR_OK) { |
8954 | 0 | goto key_and_mac_derive_fail; |
8955 | 0 | } |
8956 | 103k | i += macSize; |
8957 | | |
8958 | 103k | if (keySize) { |
8959 | | /* |
8960 | | ** Generate Domestic write keys and IVs. |
8961 | | ** client_write_key[CipherSpec.key_material] |
8962 | | */ |
8963 | 93.1k | crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i], |
8964 | 93.1k | keySize, &ssl3_keys_out->hClientKey); |
8965 | 93.1k | if (crv != CKR_OK) { |
8966 | 0 | goto key_and_mac_derive_fail; |
8967 | 0 | } |
8968 | 93.1k | i += keySize; |
8969 | | |
8970 | | /* |
8971 | | ** server_write_key[CipherSpec.key_material] |
8972 | | */ |
8973 | 93.1k | crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i], |
8974 | 93.1k | keySize, &ssl3_keys_out->hServerKey); |
8975 | 93.1k | if (crv != CKR_OK) { |
8976 | 0 | goto key_and_mac_derive_fail; |
8977 | 0 | } |
8978 | 93.1k | i += keySize; |
8979 | | |
8980 | | /* |
8981 | | ** client_write_IV[CipherSpec.IV_size] |
8982 | | */ |
8983 | 93.1k | if (IVSize > 0) { |
8984 | 90.9k | PORT_Memcpy(ssl3_keys_out->pIVClient, |
8985 | 90.9k | &key_block[i], IVSize); |
8986 | 90.9k | i += IVSize; |
8987 | 90.9k | } |
8988 | | |
8989 | | /* |
8990 | | ** server_write_IV[CipherSpec.IV_size] |
8991 | | */ |
8992 | 93.1k | if (IVSize > 0) { |
8993 | 90.9k | PORT_Memcpy(ssl3_keys_out->pIVServer, |
8994 | 90.9k | &key_block[i], IVSize); |
8995 | 90.9k | i += IVSize; |
8996 | 90.9k | } |
8997 | 93.1k | PORT_Assert(i <= sizeof key_block); |
8998 | 93.1k | } |
8999 | | |
9000 | 103k | crv = CKR_OK; |
9001 | | |
9002 | 103k | if (0) { |
9003 | 0 | key_and_mac_derive_fail: |
9004 | 0 | if (crv == CKR_OK) |
9005 | 0 | crv = CKR_FUNCTION_FAILED; |
9006 | 0 | sftk_freeSSLKeys(hSession, ssl3_keys_out); |
9007 | 0 | } |
9008 | 103k | PORT_Memset(srcrdata, 0, sizeof srcrdata); |
9009 | 103k | PORT_Memset(key_block, 0, sizeof key_block); |
9010 | 103k | MD5_DestroyContext(md5, PR_TRUE); |
9011 | 103k | SHA1_DestroyContext(sha, PR_TRUE); |
9012 | 103k | sftk_FreeObject(key); |
9013 | 103k | key = NULL; |
9014 | 103k | break; |
9015 | 103k | } |
9016 | | |
9017 | 0 | case CKM_DES3_ECB_ENCRYPT_DATA: |
9018 | 0 | case CKM_DES3_CBC_ENCRYPT_DATA: { |
9019 | 0 | void *cipherInfo; |
9020 | 0 | unsigned char des3key[MAX_DES3_KEY_SIZE]; |
9021 | 0 | CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr; |
9022 | 0 | int mode; |
9023 | 0 | unsigned char *iv; |
9024 | 0 | unsigned char *data; |
9025 | 0 | CK_ULONG len; |
9026 | |
|
9027 | 0 | if (mechanism == CKM_DES3_ECB_ENCRYPT_DATA) { |
9028 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9029 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9030 | 0 | break; |
9031 | 0 | } |
9032 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) |
9033 | 0 | pMechanism->pParameter; |
9034 | 0 | mode = NSS_DES_EDE3; |
9035 | 0 | iv = NULL; |
9036 | 0 | data = stringPtr->pData; |
9037 | 0 | len = stringPtr->ulLen; |
9038 | 0 | } else { |
9039 | 0 | mode = NSS_DES_EDE3_CBC; |
9040 | 0 | desEncryptPtr = |
9041 | 0 | (CK_DES_CBC_ENCRYPT_DATA_PARAMS *) |
9042 | 0 | pMechanism->pParameter; |
9043 | 0 | iv = desEncryptPtr->iv; |
9044 | 0 | data = desEncryptPtr->pData; |
9045 | 0 | len = desEncryptPtr->length; |
9046 | 0 | } |
9047 | 0 | if (att->attrib.ulValueLen == 16) { |
9048 | 0 | PORT_Memcpy(des3key, att->attrib.pValue, 16); |
9049 | 0 | PORT_Memcpy(des3key + 16, des3key, 8); |
9050 | 0 | } else if (att->attrib.ulValueLen == 24) { |
9051 | 0 | PORT_Memcpy(des3key, att->attrib.pValue, 24); |
9052 | 0 | } else { |
9053 | 0 | crv = CKR_KEY_SIZE_RANGE; |
9054 | 0 | break; |
9055 | 0 | } |
9056 | 0 | cipherInfo = DES_CreateContext(des3key, iv, mode, PR_TRUE); |
9057 | 0 | PORT_Memset(des3key, 0, 24); |
9058 | 0 | if (cipherInfo == NULL) { |
9059 | 0 | crv = CKR_HOST_MEMORY; |
9060 | 0 | break; |
9061 | 0 | } |
9062 | 0 | crv = sftk_DeriveEncrypt(SFTKCipher_DES_Encrypt, |
9063 | 0 | cipherInfo, 8, key, keySize, |
9064 | 0 | data, len); |
9065 | 0 | DES_DestroyContext(cipherInfo, PR_TRUE); |
9066 | 0 | break; |
9067 | 0 | } |
9068 | | |
9069 | 0 | case CKM_AES_ECB_ENCRYPT_DATA: |
9070 | 0 | case CKM_AES_CBC_ENCRYPT_DATA: { |
9071 | 0 | void *cipherInfo; |
9072 | 0 | CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; |
9073 | 0 | int mode; |
9074 | 0 | unsigned char *iv; |
9075 | 0 | unsigned char *data; |
9076 | 0 | CK_ULONG len; |
9077 | |
|
9078 | 0 | if (mechanism == CKM_AES_ECB_ENCRYPT_DATA) { |
9079 | 0 | mode = NSS_AES; |
9080 | 0 | iv = NULL; |
9081 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9082 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9083 | 0 | break; |
9084 | 0 | } |
9085 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
9086 | 0 | data = stringPtr->pData; |
9087 | 0 | len = stringPtr->ulLen; |
9088 | 0 | } else { |
9089 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) { |
9090 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9091 | 0 | break; |
9092 | 0 | } |
9093 | 0 | aesEncryptPtr = |
9094 | 0 | (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)pMechanism->pParameter; |
9095 | 0 | mode = NSS_AES_CBC; |
9096 | 0 | iv = aesEncryptPtr->iv; |
9097 | 0 | data = aesEncryptPtr->pData; |
9098 | 0 | len = aesEncryptPtr->length; |
9099 | 0 | } |
9100 | | |
9101 | 0 | cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue, |
9102 | 0 | iv, mode, PR_TRUE, |
9103 | 0 | att->attrib.ulValueLen, 16); |
9104 | 0 | if (cipherInfo == NULL) { |
9105 | 0 | crv = CKR_HOST_MEMORY; |
9106 | 0 | break; |
9107 | 0 | } |
9108 | 0 | crv = sftk_DeriveEncrypt(SFTKCipher_AES_Encrypt, |
9109 | 0 | cipherInfo, 16, key, keySize, |
9110 | 0 | data, len); |
9111 | 0 | AES_DestroyContext(cipherInfo, PR_TRUE); |
9112 | 0 | break; |
9113 | 0 | } |
9114 | | |
9115 | 0 | case CKM_CAMELLIA_ECB_ENCRYPT_DATA: |
9116 | 0 | case CKM_CAMELLIA_CBC_ENCRYPT_DATA: { |
9117 | 0 | void *cipherInfo; |
9118 | 0 | CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; |
9119 | 0 | int mode; |
9120 | 0 | unsigned char *iv; |
9121 | 0 | unsigned char *data; |
9122 | 0 | CK_ULONG len; |
9123 | |
|
9124 | 0 | if (mechanism == CKM_CAMELLIA_ECB_ENCRYPT_DATA) { |
9125 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9126 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9127 | 0 | break; |
9128 | 0 | } |
9129 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) |
9130 | 0 | pMechanism->pParameter; |
9131 | 0 | aesEncryptPtr = NULL; |
9132 | 0 | mode = NSS_CAMELLIA; |
9133 | 0 | data = stringPtr->pData; |
9134 | 0 | len = stringPtr->ulLen; |
9135 | 0 | iv = NULL; |
9136 | 0 | } else { |
9137 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) { |
9138 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9139 | 0 | break; |
9140 | 0 | } |
9141 | 0 | stringPtr = NULL; |
9142 | 0 | aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *) |
9143 | 0 | pMechanism->pParameter; |
9144 | 0 | mode = NSS_CAMELLIA_CBC; |
9145 | 0 | iv = aesEncryptPtr->iv; |
9146 | 0 | data = aesEncryptPtr->pData; |
9147 | 0 | len = aesEncryptPtr->length; |
9148 | 0 | } |
9149 | | |
9150 | 0 | cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue, |
9151 | 0 | iv, mode, PR_TRUE, |
9152 | 0 | att->attrib.ulValueLen); |
9153 | 0 | if (cipherInfo == NULL) { |
9154 | 0 | crv = CKR_HOST_MEMORY; |
9155 | 0 | break; |
9156 | 0 | } |
9157 | 0 | crv = sftk_DeriveEncrypt(SFTKCipher_Camellia_Encrypt, |
9158 | 0 | cipherInfo, 16, key, keySize, |
9159 | 0 | data, len); |
9160 | 0 | Camellia_DestroyContext(cipherInfo, PR_TRUE); |
9161 | 0 | break; |
9162 | 0 | } |
9163 | | |
9164 | 0 | #ifndef NSS_DISABLE_DEPRECATED_SEED |
9165 | 0 | case CKM_SEED_ECB_ENCRYPT_DATA: |
9166 | 0 | case CKM_SEED_CBC_ENCRYPT_DATA: { |
9167 | 0 | void *cipherInfo; |
9168 | 0 | CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr; |
9169 | 0 | int mode; |
9170 | 0 | unsigned char *iv; |
9171 | 0 | unsigned char *data; |
9172 | 0 | CK_ULONG len; |
9173 | |
|
9174 | 0 | if (mechanism == CKM_SEED_ECB_ENCRYPT_DATA) { |
9175 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9176 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9177 | 0 | break; |
9178 | 0 | } |
9179 | 0 | mode = NSS_SEED; |
9180 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) |
9181 | 0 | pMechanism->pParameter; |
9182 | 0 | aesEncryptPtr = NULL; |
9183 | 0 | data = stringPtr->pData; |
9184 | 0 | len = stringPtr->ulLen; |
9185 | 0 | iv = NULL; |
9186 | 0 | } else { |
9187 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) { |
9188 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9189 | 0 | break; |
9190 | 0 | } |
9191 | 0 | mode = NSS_SEED_CBC; |
9192 | 0 | aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *) |
9193 | 0 | pMechanism->pParameter; |
9194 | 0 | iv = aesEncryptPtr->iv; |
9195 | 0 | data = aesEncryptPtr->pData; |
9196 | 0 | len = aesEncryptPtr->length; |
9197 | 0 | } |
9198 | | |
9199 | 0 | cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue, |
9200 | 0 | iv, mode, PR_TRUE); |
9201 | 0 | if (cipherInfo == NULL) { |
9202 | 0 | crv = CKR_HOST_MEMORY; |
9203 | 0 | break; |
9204 | 0 | } |
9205 | 0 | crv = sftk_DeriveEncrypt(SFTKCipher_SEED_Encrypt, |
9206 | 0 | cipherInfo, 16, key, keySize, |
9207 | 0 | data, len); |
9208 | 0 | SEED_DestroyContext(cipherInfo, PR_TRUE); |
9209 | 0 | break; |
9210 | 0 | } |
9211 | 0 | #endif /* NSS_DISABLE_DEPRECATED_SEED */ |
9212 | | |
9213 | 166 | case CKM_CONCATENATE_BASE_AND_KEY: { |
9214 | 166 | SFTKObject *paramKey; |
9215 | | |
9216 | 166 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9217 | 166 | if (crv != CKR_OK) |
9218 | 0 | break; |
9219 | | |
9220 | 166 | session = sftk_SessionFromHandle(hSession); |
9221 | 166 | if (session == NULL) { |
9222 | 0 | crv = CKR_SESSION_HANDLE_INVALID; |
9223 | 0 | break; |
9224 | 0 | } |
9225 | | |
9226 | 166 | paramKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *) |
9227 | 166 | pMechanism->pParameter, |
9228 | 166 | session); |
9229 | 166 | sftk_FreeSession(session); |
9230 | 166 | if (paramKey == NULL) { |
9231 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
9232 | 0 | break; |
9233 | 0 | } |
9234 | | |
9235 | 166 | if (sftk_isTrue(paramKey, CKA_SENSITIVE)) { |
9236 | 0 | crv = sftk_forceAttribute(key, CKA_SENSITIVE, &cktrue, |
9237 | 0 | sizeof(CK_BBOOL)); |
9238 | 0 | if (crv != CKR_OK) { |
9239 | 0 | sftk_FreeObject(paramKey); |
9240 | 0 | break; |
9241 | 0 | } |
9242 | 0 | } |
9243 | | |
9244 | 166 | if (sftk_hasAttribute(paramKey, CKA_EXTRACTABLE) && !sftk_isTrue(paramKey, CKA_EXTRACTABLE)) { |
9245 | 0 | crv = sftk_forceAttribute(key, CKA_EXTRACTABLE, &ckfalse, sizeof(CK_BBOOL)); |
9246 | 0 | if (crv != CKR_OK) { |
9247 | 0 | sftk_FreeObject(paramKey); |
9248 | 0 | break; |
9249 | 0 | } |
9250 | 0 | } |
9251 | | |
9252 | 166 | att2 = sftk_FindAttribute(paramKey, CKA_VALUE); |
9253 | 166 | if (att2 == NULL) { |
9254 | 0 | sftk_FreeObject(paramKey); |
9255 | 0 | crv = CKR_KEY_HANDLE_INVALID; |
9256 | 0 | break; |
9257 | 0 | } |
9258 | 166 | tmpKeySize = att->attrib.ulValueLen + att2->attrib.ulValueLen; |
9259 | 166 | if (keySize == 0) |
9260 | 166 | keySize = tmpKeySize; |
9261 | 166 | if (keySize > tmpKeySize) { |
9262 | 0 | sftk_FreeObject(paramKey); |
9263 | 0 | sftk_FreeAttribute(att2); |
9264 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9265 | 0 | break; |
9266 | 0 | } |
9267 | 166 | buf = (unsigned char *)PORT_Alloc(tmpKeySize); |
9268 | 166 | if (buf == NULL) { |
9269 | 0 | sftk_FreeAttribute(att2); |
9270 | 0 | sftk_FreeObject(paramKey); |
9271 | 0 | crv = CKR_HOST_MEMORY; |
9272 | 0 | break; |
9273 | 0 | } |
9274 | | |
9275 | 166 | PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen); |
9276 | 166 | PORT_Memcpy(buf + att->attrib.ulValueLen, |
9277 | 166 | att2->attrib.pValue, att2->attrib.ulValueLen); |
9278 | | |
9279 | 166 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
9280 | 166 | PORT_ZFree(buf, tmpKeySize); |
9281 | 166 | sftk_FreeAttribute(att2); |
9282 | 166 | sftk_FreeObject(paramKey); |
9283 | 166 | break; |
9284 | 166 | } |
9285 | | |
9286 | 0 | case CKM_CONCATENATE_BASE_AND_DATA: |
9287 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9288 | 0 | if (crv != CKR_OK) |
9289 | 0 | break; |
9290 | | |
9291 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9292 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9293 | 0 | break; |
9294 | 0 | } |
9295 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
9296 | 0 | tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen; |
9297 | 0 | if (keySize == 0) |
9298 | 0 | keySize = tmpKeySize; |
9299 | 0 | if (keySize > tmpKeySize) { |
9300 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9301 | 0 | break; |
9302 | 0 | } |
9303 | 0 | buf = (unsigned char *)PORT_Alloc(tmpKeySize); |
9304 | 0 | if (buf == NULL) { |
9305 | 0 | crv = CKR_HOST_MEMORY; |
9306 | 0 | break; |
9307 | 0 | } |
9308 | | |
9309 | 0 | PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen); |
9310 | 0 | PORT_Memcpy(buf + att->attrib.ulValueLen, stringPtr->pData, |
9311 | 0 | stringPtr->ulLen); |
9312 | |
|
9313 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
9314 | 0 | PORT_ZFree(buf, tmpKeySize); |
9315 | 0 | break; |
9316 | 7.21k | case CKM_CONCATENATE_DATA_AND_BASE: |
9317 | 7.21k | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9318 | 7.21k | if (crv != CKR_OK) |
9319 | 0 | break; |
9320 | | |
9321 | 7.21k | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9322 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9323 | 0 | break; |
9324 | 0 | } |
9325 | 7.21k | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
9326 | 7.21k | tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen; |
9327 | 7.21k | if (keySize == 0) |
9328 | 7.21k | keySize = tmpKeySize; |
9329 | 7.21k | if (keySize > tmpKeySize) { |
9330 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9331 | 0 | break; |
9332 | 0 | } |
9333 | 7.21k | buf = (unsigned char *)PORT_Alloc(tmpKeySize); |
9334 | 7.21k | if (buf == NULL) { |
9335 | 0 | crv = CKR_HOST_MEMORY; |
9336 | 0 | break; |
9337 | 0 | } |
9338 | | |
9339 | 7.21k | PORT_Memcpy(buf, stringPtr->pData, stringPtr->ulLen); |
9340 | 7.21k | PORT_Memcpy(buf + stringPtr->ulLen, att->attrib.pValue, |
9341 | 7.21k | att->attrib.ulValueLen); |
9342 | | |
9343 | 7.21k | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
9344 | 7.21k | PORT_ZFree(buf, tmpKeySize); |
9345 | 7.21k | break; |
9346 | 0 | case CKM_XOR_BASE_AND_DATA: |
9347 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9348 | 0 | if (crv != CKR_OK) |
9349 | 0 | break; |
9350 | | |
9351 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) { |
9352 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9353 | 0 | break; |
9354 | 0 | } |
9355 | 0 | stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; |
9356 | 0 | tmpKeySize = PR_MIN(att->attrib.ulValueLen, stringPtr->ulLen); |
9357 | 0 | if (keySize == 0) |
9358 | 0 | keySize = tmpKeySize; |
9359 | 0 | if (keySize > tmpKeySize) { |
9360 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9361 | 0 | break; |
9362 | 0 | } |
9363 | 0 | buf = (unsigned char *)PORT_Alloc(keySize); |
9364 | 0 | if (buf == NULL) { |
9365 | 0 | crv = CKR_HOST_MEMORY; |
9366 | 0 | break; |
9367 | 0 | } |
9368 | | |
9369 | 0 | PORT_Memcpy(buf, att->attrib.pValue, keySize); |
9370 | 0 | for (i = 0; i < (int)keySize; i++) { |
9371 | 0 | buf[i] ^= stringPtr->pData[i]; |
9372 | 0 | } |
9373 | |
|
9374 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
9375 | 0 | PORT_ZFree(buf, keySize); |
9376 | 0 | break; |
9377 | | |
9378 | 0 | case CKM_EXTRACT_KEY_FROM_KEY: { |
9379 | 0 | if (BAD_PARAM_CAST(pMechanism, sizeof(CK_EXTRACT_PARAMS))) { |
9380 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9381 | 0 | break; |
9382 | 0 | } |
9383 | | /* the following assumes 8 bits per byte */ |
9384 | 0 | CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter; |
9385 | 0 | CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */ |
9386 | 0 | CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */ |
9387 | |
|
9388 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9389 | 0 | if (crv != CKR_OK) |
9390 | 0 | break; |
9391 | | |
9392 | 0 | if (keySize == 0) { |
9393 | 0 | crv = CKR_TEMPLATE_INCOMPLETE; |
9394 | 0 | break; |
9395 | 0 | } |
9396 | | /* make sure we have enough bits in the original key */ |
9397 | 0 | if (att->attrib.ulValueLen < |
9398 | 0 | (offset + keySize + ((shift != 0) ? 1 : 0))) { |
9399 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9400 | 0 | break; |
9401 | 0 | } |
9402 | 0 | buf = (unsigned char *)PORT_Alloc(keySize); |
9403 | 0 | if (buf == NULL) { |
9404 | 0 | crv = CKR_HOST_MEMORY; |
9405 | 0 | break; |
9406 | 0 | } |
9407 | | |
9408 | | /* copy the bits we need into the new key */ |
9409 | 0 | for (i = 0; i < (int)keySize; i++) { |
9410 | 0 | unsigned char *value = |
9411 | 0 | ((unsigned char *)att->attrib.pValue) + offset + i; |
9412 | 0 | if (shift) { |
9413 | 0 | buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift)); |
9414 | 0 | } else { |
9415 | 0 | buf[i] = value[0]; |
9416 | 0 | } |
9417 | 0 | } |
9418 | |
|
9419 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); |
9420 | 0 | PORT_ZFree(buf, keySize); |
9421 | 0 | break; |
9422 | 0 | } |
9423 | 0 | case CKM_MD2_KEY_DERIVATION: |
9424 | 0 | if (keySize == 0) |
9425 | 0 | keySize = MD2_LENGTH; |
9426 | 0 | if (keySize > MD2_LENGTH) { |
9427 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9428 | 0 | break; |
9429 | 0 | } |
9430 | | /* now allocate the hash contexts */ |
9431 | 0 | md2 = MD2_NewContext(); |
9432 | 0 | if (md2 == NULL) { |
9433 | 0 | crv = CKR_HOST_MEMORY; |
9434 | 0 | break; |
9435 | 0 | } |
9436 | 0 | MD2_Begin(md2); |
9437 | 0 | MD2_Update(md2, (const unsigned char *)att->attrib.pValue, |
9438 | 0 | att->attrib.ulValueLen); |
9439 | 0 | MD2_End(md2, key_block, &outLen, MD2_LENGTH); |
9440 | 0 | MD2_DestroyContext(md2, PR_TRUE); |
9441 | |
|
9442 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); |
9443 | 0 | PORT_Memset(key_block, 0, MD2_LENGTH); |
9444 | 0 | break; |
9445 | 0 | #define DERIVE_KEY_HASH(hash) \ |
9446 | 0 | case CKM_##hash##_KEY_DERIVATION: \ |
9447 | 0 | if (keySize == 0) \ |
9448 | 0 | keySize = hash##_LENGTH; \ |
9449 | 0 | if (keySize > hash##_LENGTH) { \ |
9450 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; \ |
9451 | 0 | break; \ |
9452 | 0 | } \ |
9453 | 0 | hash##_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, \ |
9454 | 0 | att->attrib.ulValueLen); \ |
9455 | 0 | crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); \ |
9456 | 0 | PORT_Memset(key_block, 0, hash##_LENGTH); \ |
9457 | 0 | break; |
9458 | 0 | DERIVE_KEY_HASH(MD5) |
9459 | 0 | DERIVE_KEY_HASH(SHA1) |
9460 | 0 | DERIVE_KEY_HASH(SHA224) |
9461 | 0 | DERIVE_KEY_HASH(SHA256) |
9462 | 0 | DERIVE_KEY_HASH(SHA384) |
9463 | 0 | DERIVE_KEY_HASH(SHA512) |
9464 | 0 | DERIVE_KEY_HASH(SHA3_224) |
9465 | 0 | DERIVE_KEY_HASH(SHA3_256) |
9466 | 0 | DERIVE_KEY_HASH(SHA3_384) |
9467 | 0 | DERIVE_KEY_HASH(SHA3_512) |
9468 | | |
9469 | 5.59k | case CKM_DH_PKCS_DERIVE: { |
9470 | 5.59k | SECItem derived, dhPublic; |
9471 | 5.59k | SECItem dhPrime, dhValue; |
9472 | 5.59k | const SECItem *subPrime; |
9473 | | /* sourceKey - values for the local existing low key */ |
9474 | | /* get prime and value attributes */ |
9475 | 5.59k | crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME); |
9476 | 5.59k | if (crv != CKR_OK) |
9477 | 0 | break; |
9478 | | |
9479 | 5.59k | dhPublic.data = pMechanism->pParameter; |
9480 | 5.59k | dhPublic.len = pMechanism->ulParameterLen; |
9481 | | |
9482 | | /* if the prime is an approved prime, we can skip all the other |
9483 | | * checks. */ |
9484 | 5.59k | subPrime = sftk_VerifyDH_Prime(&dhPrime, NULL, isFIPS); |
9485 | 5.59k | if (subPrime == NULL) { |
9486 | 8 | SECItem dhSubPrime; |
9487 | | /* If the caller set the subprime value, it means that |
9488 | | * either the caller knows the subprime value and wants us |
9489 | | * to validate the key against the subprime, or that the |
9490 | | * caller wants us to verify that the prime is a safe prime |
9491 | | * by passing in subprime = (prime-1)/2 */ |
9492 | 8 | dhSubPrime.data = NULL; |
9493 | 8 | dhSubPrime.len = 0; |
9494 | 8 | crv = sftk_Attribute2SecItem(NULL, &dhSubPrime, |
9495 | 8 | sourceKey, CKA_SUBPRIME); |
9496 | | /* we ignore the value of crv here, We treat a valid |
9497 | | * return of len = 0 and a failure to find a subrime the same |
9498 | | * NOTE: we free the subprime in both cases depending on |
9499 | | * PORT_Free of NULL to be a noop */ |
9500 | 8 | if (dhSubPrime.len != 0) { |
9501 | 0 | PRBool isSafe = PR_FALSE; |
9502 | | |
9503 | | /* Callers can set dhSubPrime to q=(p-1)/2 to force |
9504 | | * checks for safe primes. If so we only need to check |
9505 | | * q and p for primality and skip the group test. */ |
9506 | 0 | rv = sftk_IsSafePrime(&dhPrime, &dhSubPrime, &isSafe); |
9507 | 0 | if (rv != SECSuccess) { |
9508 | | /* either p or q was even and therefore not prime, |
9509 | | * we can stop processing here and fail now */ |
9510 | 0 | crv = CKR_ARGUMENTS_BAD; |
9511 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9512 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
9513 | 0 | break; |
9514 | 0 | } |
9515 | | |
9516 | | /* first make sure the primes are really prime */ |
9517 | 0 | if (!KEA_PrimeCheck(&dhPrime)) { |
9518 | 0 | crv = CKR_ARGUMENTS_BAD; |
9519 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9520 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
9521 | 0 | break; |
9522 | 0 | } |
9523 | 0 | if (!KEA_PrimeCheck(&dhSubPrime)) { |
9524 | 0 | crv = CKR_ARGUMENTS_BAD; |
9525 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9526 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
9527 | 0 | break; |
9528 | 0 | } |
9529 | 0 | if (isFIPS || !isSafe) { |
9530 | | /* With safe primes, there is only one other small |
9531 | | * subgroup. As long as y isn't 0, 1, or -1 mod p, |
9532 | | * any other y is safe. Only do the full check for |
9533 | | * non-safe primes, except in FIPS mode we need |
9534 | | * to do this check on all primes in which |
9535 | | * we receive the subprime value */ |
9536 | 0 | if (!KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime)) { |
9537 | 0 | crv = CKR_ARGUMENTS_BAD; |
9538 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9539 | 0 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
9540 | 0 | break; |
9541 | 0 | } |
9542 | 0 | } |
9543 | 8 | } else if (isFIPS) { |
9544 | | /* In FIPS mode we only accept approved primes, or |
9545 | | * primes with the full subprime value */ |
9546 | 0 | crv = CKR_ARGUMENTS_BAD; |
9547 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9548 | 0 | break; |
9549 | 0 | } |
9550 | | /* checks are complete, no need for the subPrime any longer */ |
9551 | 8 | SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE); |
9552 | 8 | } |
9553 | | |
9554 | | /* now that the prime is validated, get the private value */ |
9555 | 5.59k | crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE); |
9556 | 5.59k | if (crv != CKR_OK) { |
9557 | 0 | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9558 | 0 | break; |
9559 | 0 | } |
9560 | | |
9561 | | /* calculate private value - oct */ |
9562 | 5.59k | rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); |
9563 | | |
9564 | 5.59k | SECITEM_ZfreeItem(&dhPrime, PR_FALSE); |
9565 | 5.59k | SECITEM_ZfreeItem(&dhValue, PR_FALSE); |
9566 | | |
9567 | 5.59k | if (rv == SECSuccess) { |
9568 | 5.59k | sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len); |
9569 | 5.59k | SECITEM_ZfreeItem(&derived, PR_FALSE); |
9570 | 5.59k | crv = CKR_OK; |
9571 | 5.59k | } else |
9572 | 0 | crv = CKR_HOST_MEMORY; |
9573 | | |
9574 | 5.59k | break; |
9575 | 5.59k | } |
9576 | | |
9577 | 69.6k | case CKM_ECDH1_DERIVE: |
9578 | 69.6k | case CKM_ECDH1_COFACTOR_DERIVE: { |
9579 | 69.6k | SECItem ecScalar, ecPoint; |
9580 | 69.6k | SECItem tmp; |
9581 | 69.6k | PRBool withCofactor = PR_FALSE; |
9582 | 69.6k | unsigned char *secret; |
9583 | 69.6k | unsigned char *keyData = NULL; |
9584 | 69.6k | unsigned int secretlen, pubKeyLen; |
9585 | 69.6k | CK_ECDH1_DERIVE_PARAMS *mechParams; |
9586 | 69.6k | NSSLOWKEYPrivateKey *privKey; |
9587 | 69.6k | PLArenaPool *arena = NULL; |
9588 | | |
9589 | | /* Check mechanism parameters */ |
9590 | 69.6k | mechParams = (CK_ECDH1_DERIVE_PARAMS *)pMechanism->pParameter; |
9591 | 69.6k | if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) || |
9592 | 69.6k | ((mechParams->kdf == CKD_NULL) && |
9593 | 69.6k | ((mechParams->ulSharedDataLen != 0) || |
9594 | 69.6k | (mechParams->pSharedData != NULL)))) { |
9595 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9596 | 0 | break; |
9597 | 0 | } |
9598 | | |
9599 | 69.6k | privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv); |
9600 | 69.6k | if (privKey == NULL) { |
9601 | 0 | break; |
9602 | 0 | } |
9603 | | |
9604 | | /* Now we are working with a non-NULL private key */ |
9605 | 69.6k | SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue); |
9606 | | |
9607 | 69.6k | ecPoint.data = mechParams->pPublicData; |
9608 | 69.6k | ecPoint.len = mechParams->ulPublicDataLen; |
9609 | | |
9610 | 69.6k | pubKeyLen = EC_GetPointSize(&privKey->u.ec.ecParams); |
9611 | | |
9612 | | /* if the len is too large, might be an encoded point */ |
9613 | 69.6k | if (ecPoint.len > pubKeyLen) { |
9614 | 6.72k | SECItem newPoint; |
9615 | | |
9616 | 6.72k | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
9617 | 6.72k | if (arena == NULL) { |
9618 | 0 | goto ec_loser; |
9619 | 0 | } |
9620 | | |
9621 | 6.72k | rv = SEC_QuickDERDecodeItem(arena, &newPoint, |
9622 | 6.72k | SEC_ASN1_GET(SEC_OctetStringTemplate), |
9623 | 6.72k | &ecPoint); |
9624 | 6.72k | if (rv != SECSuccess) { |
9625 | 330 | goto ec_loser; |
9626 | 330 | } |
9627 | 6.39k | ecPoint = newPoint; |
9628 | 6.39k | } |
9629 | | |
9630 | 69.3k | if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) { |
9631 | 0 | withCofactor = PR_TRUE; |
9632 | 0 | } |
9633 | | |
9634 | 69.3k | rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar, |
9635 | 69.3k | withCofactor, &tmp); |
9636 | 69.3k | SECITEM_ZfreeItem(&ecScalar, PR_FALSE); |
9637 | 69.3k | ecScalar.data = NULL; |
9638 | 69.3k | if (privKey != sourceKey->objectInfo) { |
9639 | 0 | nsslowkey_DestroyPrivateKey(privKey); |
9640 | 0 | privKey = NULL; |
9641 | 0 | } |
9642 | 69.3k | if (arena) { |
9643 | 6.39k | PORT_FreeArena(arena, PR_FALSE); |
9644 | 6.39k | arena = NULL; |
9645 | 6.39k | } |
9646 | | |
9647 | 69.3k | if (rv != SECSuccess) { |
9648 | 12.9k | crv = sftk_MapCryptError(PORT_GetError()); |
9649 | 12.9k | break; |
9650 | 12.9k | } |
9651 | | |
9652 | | /* |
9653 | | * apply the kdf function. |
9654 | | */ |
9655 | 56.3k | if (mechParams->kdf == CKD_NULL) { |
9656 | | /* |
9657 | | * tmp is the raw data created by ECDH_Derive, |
9658 | | * secret and secretlen are the values we will |
9659 | | * eventually pass as our generated key. |
9660 | | */ |
9661 | 56.3k | secret = tmp.data; |
9662 | 56.3k | secretlen = tmp.len; |
9663 | 56.3k | } else { |
9664 | 0 | secretlen = keySize; |
9665 | 0 | crv = sftk_ANSI_X9_63_kdf(&secret, keySize, |
9666 | 0 | &tmp, mechParams->pSharedData, |
9667 | 0 | mechParams->ulSharedDataLen, mechParams->kdf); |
9668 | 0 | PORT_ZFree(tmp.data, tmp.len); |
9669 | 0 | if (crv != CKR_OK) { |
9670 | 0 | break; |
9671 | 0 | } |
9672 | 0 | tmp.data = secret; |
9673 | 0 | tmp.len = secretlen; |
9674 | 0 | } |
9675 | | |
9676 | | /* |
9677 | | * if keySize is supplied, then we are generating a key of a specific |
9678 | | * length. This is done by taking the least significant 'keySize' |
9679 | | * bytes from the unsigned value calculated by ECDH. Note: this may |
9680 | | * mean padding temp with extra leading zeros from what ECDH_Derive |
9681 | | * already returned (which itself may contain leading zeros). |
9682 | | */ |
9683 | 56.3k | if (keySize) { |
9684 | 56.3k | if (secretlen < keySize) { |
9685 | 1 | keyData = PORT_ZAlloc(keySize); |
9686 | 1 | if (!keyData) { |
9687 | 0 | PORT_ZFree(tmp.data, tmp.len); |
9688 | 0 | crv = CKR_HOST_MEMORY; |
9689 | 0 | break; |
9690 | 0 | } |
9691 | 1 | PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen); |
9692 | 1 | secret = keyData; |
9693 | 56.3k | } else { |
9694 | 56.3k | secret += (secretlen - keySize); |
9695 | 56.3k | } |
9696 | 56.3k | secretlen = keySize; |
9697 | 56.3k | } |
9698 | | |
9699 | 56.3k | sftk_forceAttribute(key, CKA_VALUE, secret, secretlen); |
9700 | 56.3k | PORT_ZFree(tmp.data, tmp.len); |
9701 | 56.3k | if (keyData) { |
9702 | 1 | PORT_ZFree(keyData, keySize); |
9703 | 1 | } |
9704 | 56.3k | break; |
9705 | | |
9706 | 330 | ec_loser: |
9707 | 330 | crv = CKR_ARGUMENTS_BAD; |
9708 | 330 | SECITEM_ZfreeItem(&ecScalar, PR_FALSE); |
9709 | 330 | if (privKey != sourceKey->objectInfo) |
9710 | 0 | nsslowkey_DestroyPrivateKey(privKey); |
9711 | 330 | if (arena) { |
9712 | 330 | PORT_FreeArena(arena, PR_TRUE); |
9713 | 330 | } |
9714 | 330 | break; |
9715 | 56.3k | } |
9716 | | /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */ |
9717 | 0 | case CKM_NSS_HKDF_SHA1: |
9718 | 0 | hashMech = CKM_SHA_1; |
9719 | 0 | goto hkdf; |
9720 | 0 | case CKM_NSS_HKDF_SHA256: |
9721 | 0 | hashMech = CKM_SHA256; |
9722 | 0 | goto hkdf; |
9723 | 0 | case CKM_NSS_HKDF_SHA384: |
9724 | 0 | hashMech = CKM_SHA384; |
9725 | 0 | goto hkdf; |
9726 | 0 | case CKM_NSS_HKDF_SHA512: |
9727 | 0 | hashMech = CKM_SHA512; |
9728 | 0 | goto hkdf; |
9729 | 0 | hkdf : { |
9730 | 0 | const CK_NSS_HKDFParams *params = |
9731 | 0 | (const CK_NSS_HKDFParams *)pMechanism->pParameter; |
9732 | 0 | CK_HKDF_PARAMS hkdfParams; |
9733 | |
|
9734 | 0 | if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams)) { |
9735 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9736 | 0 | break; |
9737 | 0 | } |
9738 | 0 | hkdfParams.bExtract = params->bExtract; |
9739 | 0 | hkdfParams.bExpand = params->bExpand; |
9740 | 0 | if (params->pSalt) { |
9741 | 0 | hkdfParams.ulSaltType = CKF_HKDF_SALT_DATA; |
9742 | 0 | } else { |
9743 | 0 | hkdfParams.ulSaltType = CKF_HKDF_SALT_NULL; |
9744 | 0 | } |
9745 | 0 | hkdfParams.pSalt = params->pSalt; |
9746 | 0 | hkdfParams.ulSaltLen = params->ulSaltLen; |
9747 | 0 | hkdfParams.hSaltKey = CK_INVALID_HANDLE; |
9748 | 0 | hkdfParams.pInfo = params->pInfo; |
9749 | 0 | hkdfParams.ulInfoLen = params->ulInfoLen; |
9750 | 0 | hkdfParams.prfHashMechanism = hashMech; |
9751 | |
|
9752 | 0 | crv = sftk_HKDF(&hkdfParams, hSession, sourceKey, |
9753 | 0 | att->attrib.pValue, att->attrib.ulValueLen, |
9754 | 0 | key, NULL, keySize, PR_FALSE, isFIPS); |
9755 | 0 | } break; |
9756 | 395k | case CKM_HKDF_DERIVE: |
9757 | 565k | case CKM_HKDF_DATA: /* only difference is the class of key */ |
9758 | 565k | if ((pMechanism->pParameter == NULL) || |
9759 | 565k | (pMechanism->ulParameterLen != sizeof(CK_HKDF_PARAMS))) { |
9760 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9761 | 0 | break; |
9762 | 0 | } |
9763 | 565k | crv = sftk_HKDF((CK_HKDF_PARAMS_PTR)pMechanism->pParameter, |
9764 | 565k | hSession, sourceKey, att->attrib.pValue, |
9765 | 565k | att->attrib.ulValueLen, key, NULL, keySize, PR_TRUE, |
9766 | 565k | isFIPS); |
9767 | 565k | break; |
9768 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA1: |
9769 | 0 | hashType = HASH_AlgSHA1; |
9770 | 0 | goto jpake2; |
9771 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA256: |
9772 | 0 | hashType = HASH_AlgSHA256; |
9773 | 0 | goto jpake2; |
9774 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA384: |
9775 | 0 | hashType = HASH_AlgSHA384; |
9776 | 0 | goto jpake2; |
9777 | 0 | case CKM_NSS_JPAKE_ROUND2_SHA512: |
9778 | 0 | hashType = HASH_AlgSHA512; |
9779 | 0 | goto jpake2; |
9780 | 0 | jpake2: |
9781 | 0 | if (pMechanism->pParameter == NULL || |
9782 | 0 | pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params)) |
9783 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9784 | 0 | if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN)) |
9785 | 0 | crv = CKR_TEMPLATE_INCONSISTENT; |
9786 | 0 | if (crv == CKR_OK) |
9787 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9788 | 0 | if (crv == CKR_OK) |
9789 | 0 | crv = jpake_Round2(hashType, |
9790 | 0 | (CK_NSS_JPAKERound2Params *)pMechanism->pParameter, |
9791 | 0 | sourceKey, key); |
9792 | 0 | break; |
9793 | | |
9794 | 0 | case CKM_NSS_JPAKE_FINAL_SHA1: |
9795 | 0 | hashType = HASH_AlgSHA1; |
9796 | 0 | goto jpakeFinal; |
9797 | 0 | case CKM_NSS_JPAKE_FINAL_SHA256: |
9798 | 0 | hashType = HASH_AlgSHA256; |
9799 | 0 | goto jpakeFinal; |
9800 | 0 | case CKM_NSS_JPAKE_FINAL_SHA384: |
9801 | 0 | hashType = HASH_AlgSHA384; |
9802 | 0 | goto jpakeFinal; |
9803 | 0 | case CKM_NSS_JPAKE_FINAL_SHA512: |
9804 | 0 | hashType = HASH_AlgSHA512; |
9805 | 0 | goto jpakeFinal; |
9806 | 0 | jpakeFinal: |
9807 | 0 | if (pMechanism->pParameter == NULL || |
9808 | 0 | pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams)) |
9809 | 0 | crv = CKR_MECHANISM_PARAM_INVALID; |
9810 | | /* We purposely do not do the derive sensitivity check; we want to be |
9811 | | able to derive non-sensitive keys while allowing the ROUND1 and |
9812 | | ROUND2 keys to be sensitive (which they always are, since they are |
9813 | | in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE |
9814 | | in the template in order for the resultant keyblock key to be |
9815 | | sensitive. |
9816 | | */ |
9817 | 0 | if (crv == CKR_OK) |
9818 | 0 | crv = jpake_Final(hashType, |
9819 | 0 | (CK_NSS_JPAKEFinalParams *)pMechanism->pParameter, |
9820 | 0 | sourceKey, key); |
9821 | 0 | break; |
9822 | | |
9823 | 0 | case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */ |
9824 | 0 | case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */ |
9825 | 0 | case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */ |
9826 | 0 | case CKM_SP800_108_COUNTER_KDF: /* fall through */ |
9827 | 0 | case CKM_SP800_108_FEEDBACK_KDF: /* fall through */ |
9828 | 0 | case CKM_SP800_108_DOUBLE_PIPELINE_KDF: |
9829 | 0 | crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE); |
9830 | 0 | if (crv != CKR_OK) { |
9831 | 0 | break; |
9832 | 0 | } |
9833 | | |
9834 | 0 | crv = kbkdf_Dispatch(mechanism, hSession, pMechanism, sourceKey, key, keySize); |
9835 | 0 | break; |
9836 | 0 | default: |
9837 | 0 | crv = CKR_MECHANISM_INVALID; |
9838 | 892k | } |
9839 | 892k | if (att) { |
9840 | 892k | sftk_FreeAttribute(att); |
9841 | 892k | } |
9842 | 892k | sftk_FreeObject(sourceKey); |
9843 | 892k | if (crv != CKR_OK) { |
9844 | 16.1k | if (key) |
9845 | 16.1k | sftk_FreeObject(key); |
9846 | 16.1k | return crv; |
9847 | 16.1k | } |
9848 | | |
9849 | | /* link the key object into the list */ |
9850 | 876k | if (key) { |
9851 | 772k | SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); |
9852 | 772k | PORT_Assert(sessKey); |
9853 | | /* get the session */ |
9854 | 772k | sessKey->wasDerived = PR_TRUE; |
9855 | 772k | session = sftk_SessionFromHandle(hSession); |
9856 | 772k | if (session == NULL) { |
9857 | 0 | sftk_FreeObject(key); |
9858 | 0 | return CKR_HOST_MEMORY; |
9859 | 0 | } |
9860 | | |
9861 | 772k | crv = sftk_handleObject(key, session); |
9862 | 772k | session->lastOpWasFIPS = sftk_hasFIPS(key); |
9863 | 772k | sftk_FreeSession(session); |
9864 | 772k | if (phKey) { |
9865 | 772k | *phKey = key->handle; |
9866 | 772k | } |
9867 | 772k | sftk_FreeObject(key); |
9868 | 772k | } |
9869 | 876k | return crv; |
9870 | 876k | } |
9871 | | |
9872 | | /* NSC_GetFunctionStatus obtains an updated status of a function running |
9873 | | * in parallel with an application. */ |
9874 | | CK_RV |
9875 | | NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession) |
9876 | 0 | { |
9877 | 0 | CHECK_FORK(); |
9878 | |
|
9879 | 0 | return CKR_FUNCTION_NOT_PARALLEL; |
9880 | 0 | } |
9881 | | |
9882 | | /* NSC_CancelFunction cancels a function running in parallel */ |
9883 | | CK_RV |
9884 | | NSC_CancelFunction(CK_SESSION_HANDLE hSession) |
9885 | 0 | { |
9886 | 0 | CHECK_FORK(); |
9887 | |
|
9888 | 0 | return CKR_FUNCTION_NOT_PARALLEL; |
9889 | 0 | } |
9890 | | |
9891 | | /* NSC_GetOperationState saves the state of the cryptographic |
9892 | | * operation in a session. |
9893 | | * NOTE: This code only works for digest functions for now. eventually need |
9894 | | * to add full flatten/resurect to our state stuff so that all types of state |
9895 | | * can be saved */ |
9896 | | CK_RV |
9897 | | NSC_GetOperationState(CK_SESSION_HANDLE hSession, |
9898 | | CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) |
9899 | 196k | { |
9900 | 196k | SFTKSessionContext *context; |
9901 | 196k | SFTKSession *session; |
9902 | 196k | CK_RV crv; |
9903 | 196k | CK_ULONG pOSLen = *pulOperationStateLen; |
9904 | | |
9905 | 196k | CHECK_FORK(); |
9906 | | |
9907 | | /* make sure we're legal */ |
9908 | 196k | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); |
9909 | 196k | if (crv != CKR_OK) |
9910 | 0 | return crv; |
9911 | | |
9912 | | /* a zero cipherInfoLen signals that this context cannot be serialized */ |
9913 | 196k | if (context->cipherInfoLen == 0) { |
9914 | 0 | return CKR_STATE_UNSAVEABLE; |
9915 | 0 | } |
9916 | | |
9917 | 196k | *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) + sizeof(SFTKContextType); |
9918 | 196k | if (pOperationState == NULL) { |
9919 | 22.3k | sftk_FreeSession(session); |
9920 | 22.3k | return CKR_OK; |
9921 | 174k | } else { |
9922 | 174k | if (pOSLen < *pulOperationStateLen) { |
9923 | 0 | return CKR_BUFFER_TOO_SMALL; |
9924 | 0 | } |
9925 | 174k | } |
9926 | 174k | PORT_Memcpy(pOperationState, &context->type, sizeof(SFTKContextType)); |
9927 | 174k | pOperationState += sizeof(SFTKContextType); |
9928 | 174k | PORT_Memcpy(pOperationState, &context->currentMech, |
9929 | 174k | sizeof(CK_MECHANISM_TYPE)); |
9930 | 174k | pOperationState += sizeof(CK_MECHANISM_TYPE); |
9931 | 174k | PORT_Memcpy(pOperationState, context->cipherInfo, context->cipherInfoLen); |
9932 | 174k | sftk_FreeSession(session); |
9933 | 174k | return CKR_OK; |
9934 | 196k | } |
9935 | | |
9936 | | #define sftk_Decrement(stateSize, len) \ |
9937 | 523k | stateSize = ((stateSize) > (CK_ULONG)(len)) ? ((stateSize) - (CK_ULONG)(len)) : 0; |
9938 | | |
9939 | | /* NSC_SetOperationState restores the state of the cryptographic |
9940 | | * operation in a session. This is coded like it can restore lots of |
9941 | | * states, but it only works for truly flat cipher structures. */ |
9942 | | CK_RV |
9943 | | NSC_SetOperationState(CK_SESSION_HANDLE hSession, |
9944 | | CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, |
9945 | | CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) |
9946 | 174k | { |
9947 | 174k | SFTKSessionContext *context; |
9948 | 174k | SFTKSession *session; |
9949 | 174k | SFTKContextType type; |
9950 | 174k | CK_MECHANISM mech; |
9951 | 174k | CK_RV crv = CKR_OK; |
9952 | | |
9953 | 174k | CHECK_FORK(); |
9954 | | |
9955 | 348k | while (ulOperationStateLen != 0) { |
9956 | | /* get what type of state we're dealing with... */ |
9957 | 174k | PORT_Memcpy(&type, pOperationState, sizeof(SFTKContextType)); |
9958 | | |
9959 | | /* fix up session contexts based on type */ |
9960 | 174k | session = sftk_SessionFromHandle(hSession); |
9961 | 174k | if (session == NULL) |
9962 | 0 | return CKR_SESSION_HANDLE_INVALID; |
9963 | 174k | context = sftk_ReturnContextByType(session, type); |
9964 | 174k | sftk_SetContextByType(session, type, NULL); |
9965 | 174k | if (context) { |
9966 | 22.3k | sftk_FreeContext(context); |
9967 | 22.3k | } |
9968 | 174k | pOperationState += sizeof(SFTKContextType); |
9969 | 174k | sftk_Decrement(ulOperationStateLen, sizeof(SFTKContextType)); |
9970 | | |
9971 | | /* get the mechanism structure */ |
9972 | 174k | PORT_Memcpy(&mech.mechanism, pOperationState, sizeof(CK_MECHANISM_TYPE)); |
9973 | 174k | pOperationState += sizeof(CK_MECHANISM_TYPE); |
9974 | 174k | sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE)); |
9975 | | /* should be filled in... but not necessary for hash */ |
9976 | 174k | mech.pParameter = NULL; |
9977 | 174k | mech.ulParameterLen = 0; |
9978 | 174k | switch (type) { |
9979 | 174k | case SFTK_HASH: |
9980 | 174k | crv = NSC_DigestInit(hSession, &mech); |
9981 | 174k | if (crv != CKR_OK) |
9982 | 0 | break; |
9983 | 174k | crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, |
9984 | 174k | NULL); |
9985 | 174k | if (crv != CKR_OK) |
9986 | 0 | break; |
9987 | 174k | if (context->cipherInfoLen == 0) { |
9988 | 0 | crv = CKR_SAVED_STATE_INVALID; |
9989 | 0 | break; |
9990 | 0 | } |
9991 | 174k | PORT_Memcpy(context->cipherInfo, pOperationState, |
9992 | 174k | context->cipherInfoLen); |
9993 | 174k | pOperationState += context->cipherInfoLen; |
9994 | 174k | sftk_Decrement(ulOperationStateLen, context->cipherInfoLen); |
9995 | 174k | break; |
9996 | 0 | default: |
9997 | | /* do sign/encrypt/decrypt later */ |
9998 | 0 | crv = CKR_SAVED_STATE_INVALID; |
9999 | 174k | } |
10000 | 174k | sftk_FreeSession(session); |
10001 | 174k | if (crv != CKR_OK) |
10002 | 0 | break; |
10003 | 174k | } |
10004 | 174k | return crv; |
10005 | 174k | } |
10006 | | |
10007 | | /* Dual-function cryptographic operations */ |
10008 | | |
10009 | | /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption |
10010 | | * operation. */ |
10011 | | CK_RV |
10012 | | NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
10013 | | CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
10014 | | CK_ULONG_PTR pulEncryptedPartLen) |
10015 | 0 | { |
10016 | 0 | CK_RV crv; |
10017 | |
|
10018 | 0 | CHECK_FORK(); |
10019 | |
|
10020 | 0 | crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, |
10021 | 0 | pulEncryptedPartLen); |
10022 | 0 | if (crv != CKR_OK) |
10023 | 0 | return crv; |
10024 | 0 | crv = NSC_DigestUpdate(hSession, pPart, ulPartLen); |
10025 | |
|
10026 | 0 | return crv; |
10027 | 0 | } |
10028 | | |
10029 | | /* NSC_DecryptDigestUpdate continues a multiple-part decryption and |
10030 | | * digesting operation. */ |
10031 | | CK_RV |
10032 | | NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, |
10033 | | CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, |
10034 | | CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) |
10035 | 0 | { |
10036 | 0 | CK_RV crv; |
10037 | |
|
10038 | 0 | CHECK_FORK(); |
10039 | |
|
10040 | 0 | crv = NSC_DecryptUpdate(hSession, pEncryptedPart, ulEncryptedPartLen, |
10041 | 0 | pPart, pulPartLen); |
10042 | 0 | if (crv != CKR_OK) |
10043 | 0 | return crv; |
10044 | 0 | crv = NSC_DigestUpdate(hSession, pPart, *pulPartLen); |
10045 | |
|
10046 | 0 | return crv; |
10047 | 0 | } |
10048 | | |
10049 | | /* NSC_SignEncryptUpdate continues a multiple-part signing and |
10050 | | * encryption operation. */ |
10051 | | CK_RV |
10052 | | NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, |
10053 | | CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, |
10054 | | CK_ULONG_PTR pulEncryptedPartLen) |
10055 | 0 | { |
10056 | 0 | CK_RV crv; |
10057 | |
|
10058 | 0 | CHECK_FORK(); |
10059 | |
|
10060 | 0 | crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, |
10061 | 0 | pulEncryptedPartLen); |
10062 | 0 | if (crv != CKR_OK) |
10063 | 0 | return crv; |
10064 | 0 | crv = NSC_SignUpdate(hSession, pPart, ulPartLen); |
10065 | |
|
10066 | 0 | return crv; |
10067 | 0 | } |
10068 | | |
10069 | | /* NSC_DecryptVerifyUpdate continues a multiple-part decryption |
10070 | | * and verify operation. */ |
10071 | | CK_RV |
10072 | | NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, |
10073 | | CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, |
10074 | | CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) |
10075 | 0 | { |
10076 | 0 | CK_RV crv; |
10077 | |
|
10078 | 0 | CHECK_FORK(); |
10079 | |
|
10080 | 0 | crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, |
10081 | 0 | pData, pulDataLen); |
10082 | 0 | if (crv != CKR_OK) |
10083 | 0 | return crv; |
10084 | 0 | crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen); |
10085 | |
|
10086 | 0 | return crv; |
10087 | 0 | } |
10088 | | |
10089 | | /* NSC_DigestKey continues a multi-part message-digesting operation, |
10090 | | * by digesting the value of a secret key as part of the data already digested. |
10091 | | */ |
10092 | | CK_RV |
10093 | | NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) |
10094 | 0 | { |
10095 | 0 | SFTKSession *session = NULL; |
10096 | 0 | SFTKObject *key = NULL; |
10097 | 0 | SFTKAttribute *att; |
10098 | 0 | CK_RV crv; |
10099 | |
|
10100 | 0 | CHECK_FORK(); |
10101 | |
|
10102 | 0 | session = sftk_SessionFromHandle(hSession); |
10103 | 0 | if (session == NULL) |
10104 | 0 | return CKR_SESSION_HANDLE_INVALID; |
10105 | | |
10106 | 0 | key = sftk_ObjectFromHandle(hKey, session); |
10107 | 0 | sftk_FreeSession(session); |
10108 | 0 | if (key == NULL) |
10109 | 0 | return CKR_KEY_HANDLE_INVALID; |
10110 | | |
10111 | | /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */ |
10112 | | |
10113 | | /* make sure it's a valid key for this operation */ |
10114 | 0 | if (key->objclass != CKO_SECRET_KEY) { |
10115 | 0 | sftk_FreeObject(key); |
10116 | 0 | return CKR_KEY_TYPE_INCONSISTENT; |
10117 | 0 | } |
10118 | | /* get the key value */ |
10119 | 0 | att = sftk_FindAttribute(key, CKA_VALUE); |
10120 | 0 | sftk_FreeObject(key); |
10121 | 0 | if (!att) { |
10122 | 0 | return CKR_KEY_HANDLE_INVALID; |
10123 | 0 | } |
10124 | 0 | crv = NSC_DigestUpdate(hSession, (CK_BYTE_PTR)att->attrib.pValue, |
10125 | 0 | att->attrib.ulValueLen); |
10126 | 0 | sftk_FreeAttribute(att); |
10127 | 0 | return crv; |
10128 | 0 | } |