/src/ibmswtpm2/src/AsymmetricCommands.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************************/ |
2 | | /* */ |
3 | | /* Asymmetric Commands */ |
4 | | /* Written by Ken Goldman */ |
5 | | /* IBM Thomas J. Watson Research Center */ |
6 | | /* $Id: AsymmetricCommands.c 1262 2018-07-11 21:03:43Z kgoldman $ */ |
7 | | /* */ |
8 | | /* Licenses and Notices */ |
9 | | /* */ |
10 | | /* 1. Copyright Licenses: */ |
11 | | /* */ |
12 | | /* - Trusted Computing Group (TCG) grants to the user of the source code in */ |
13 | | /* this specification (the "Source Code") a worldwide, irrevocable, */ |
14 | | /* nonexclusive, royalty free, copyright license to reproduce, create */ |
15 | | /* derivative works, distribute, display and perform the Source Code and */ |
16 | | /* derivative works thereof, and to grant others the rights granted herein. */ |
17 | | /* */ |
18 | | /* - The TCG grants to the user of the other parts of the specification */ |
19 | | /* (other than the Source Code) the rights to reproduce, distribute, */ |
20 | | /* display, and perform the specification solely for the purpose of */ |
21 | | /* developing products based on such documents. */ |
22 | | /* */ |
23 | | /* 2. Source Code Distribution Conditions: */ |
24 | | /* */ |
25 | | /* - Redistributions of Source Code must retain the above copyright licenses, */ |
26 | | /* this list of conditions and the following disclaimers. */ |
27 | | /* */ |
28 | | /* - Redistributions in binary form must reproduce the above copyright */ |
29 | | /* licenses, this list of conditions and the following disclaimers in the */ |
30 | | /* documentation and/or other materials provided with the distribution. */ |
31 | | /* */ |
32 | | /* 3. Disclaimers: */ |
33 | | /* */ |
34 | | /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ |
35 | | /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ |
36 | | /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ |
37 | | /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ |
38 | | /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ |
39 | | /* information on specification licensing rights available through TCG */ |
40 | | /* membership agreements. */ |
41 | | /* */ |
42 | | /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ |
43 | | /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ |
44 | | /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ |
45 | | /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ |
46 | | /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ |
47 | | /* */ |
48 | | /* - Without limitation, TCG and its members and licensors disclaim all */ |
49 | | /* liability, including liability for infringement of any proprietary */ |
50 | | /* rights, relating to use of information in this specification and to the */ |
51 | | /* implementation of this specification, and TCG disclaims all liability for */ |
52 | | /* cost of procurement of substitute goods or services, lost profits, loss */ |
53 | | /* of use, loss of data or any incidental, consequential, direct, indirect, */ |
54 | | /* or special damages, whether under contract, tort, warranty or otherwise, */ |
55 | | /* arising in any way out of use or reliance upon this specification or any */ |
56 | | /* information herein. */ |
57 | | /* */ |
58 | | /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ |
59 | | /* */ |
60 | | /********************************************************************************/ |
61 | | |
62 | | #include "Tpm.h" |
63 | | #include "RSA_Encrypt_fp.h" |
64 | | #if CC_RSA_Encrypt // Conditional expansion of this file |
65 | | #if ALG_RSA |
66 | | TPM_RC |
67 | | TPM2_RSA_Encrypt( |
68 | | RSA_Encrypt_In *in, // IN: input parameter list |
69 | | RSA_Encrypt_Out *out // OUT: output parameter list |
70 | | ) |
71 | 0 | { |
72 | 0 | TPM_RC result; |
73 | 0 | OBJECT *rsaKey; |
74 | 0 | TPMT_RSA_DECRYPT *scheme; |
75 | | // Input Validation |
76 | 0 | rsaKey = HandleToObject(in->keyHandle); |
77 | | // selected key must be an RSA key |
78 | 0 | if(rsaKey->publicArea.type != TPM_ALG_RSA) |
79 | 0 | return TPM_RCS_KEY + RC_RSA_Encrypt_keyHandle; |
80 | | // selected key must have the decryption attribute |
81 | 0 | if(!IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) |
82 | 0 | return TPM_RCS_ATTRIBUTES + RC_RSA_Encrypt_keyHandle; |
83 | | // Is there a label? |
84 | 0 | if(!IsLabelProperlyFormatted(&in->label.b)) |
85 | 0 | return TPM_RCS_VALUE + RC_RSA_Encrypt_label; |
86 | | // Command Output |
87 | | // Select a scheme for encryption |
88 | 0 | scheme = CryptRsaSelectScheme(in->keyHandle, &in->inScheme); |
89 | 0 | if(scheme == NULL) |
90 | 0 | return TPM_RCS_SCHEME + RC_RSA_Encrypt_inScheme; |
91 | | // Encryption. TPM_RC_VALUE, or TPM_RC_SCHEME errors my be returned buy |
92 | | // CryptEncyptRSA. |
93 | 0 | out->outData.t.size = sizeof(out->outData.t.buffer); |
94 | 0 | result = CryptRsaEncrypt(&out->outData, &in->message.b, rsaKey, scheme, |
95 | 0 | &in->label.b, NULL); |
96 | 0 | return result; |
97 | 0 | } |
98 | | #endif |
99 | | #endif // CC_RSA_Encrypt |
100 | | #include "Tpm.h" |
101 | | #include "RSA_Decrypt_fp.h" |
102 | | #if CC_RSA_Decrypt // Conditional expansion of this file |
103 | | #if ALG_RSA |
104 | | TPM_RC |
105 | | TPM2_RSA_Decrypt( |
106 | | RSA_Decrypt_In *in, // IN: input parameter list |
107 | | RSA_Decrypt_Out *out // OUT: output parameter list |
108 | | ) |
109 | 0 | { |
110 | 0 | TPM_RC result; |
111 | 0 | OBJECT *rsaKey; |
112 | 0 | TPMT_RSA_DECRYPT *scheme; |
113 | | // Input Validation |
114 | 0 | rsaKey = HandleToObject(in->keyHandle); |
115 | | // The selected key must be an RSA key |
116 | 0 | if(rsaKey->publicArea.type != TPM_ALG_RSA) |
117 | 0 | return TPM_RCS_KEY + RC_RSA_Decrypt_keyHandle; |
118 | | // The selected key must be an unrestricted decryption key |
119 | 0 | if(IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) |
120 | 0 | || !IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) |
121 | 0 | return TPM_RCS_ATTRIBUTES + RC_RSA_Decrypt_keyHandle; |
122 | | // NOTE: Proper operation of this command requires that the sensitive area |
123 | | // of the key is loaded. This is assured because authorization is required |
124 | | // to use the sensitive area of the key. In order to check the authorization, |
125 | | // the sensitive area has to be loaded, even if authorization is with policy. |
126 | | // If label is present, make sure that it is a NULL-terminated string |
127 | 0 | if(!IsLabelProperlyFormatted(&in->label.b)) |
128 | 0 | return TPM_RCS_VALUE + RC_RSA_Decrypt_label; |
129 | | // Command Output |
130 | | // Select a scheme for decrypt. |
131 | 0 | scheme = CryptRsaSelectScheme(in->keyHandle, &in->inScheme); |
132 | 0 | if(scheme == NULL) |
133 | 0 | return TPM_RCS_SCHEME + RC_RSA_Decrypt_inScheme; |
134 | | // Decryption. TPM_RC_VALUE, TPM_RC_SIZE, and TPM_RC_KEY error may be |
135 | | // returned by CryptRsaDecrypt. |
136 | | // NOTE: CryptRsaDecrypt can also return TPM_RC_ATTRIBUTES or TPM_RC_BINDING |
137 | | // when the key is not a decryption key but that was checked above. |
138 | 0 | out->message.t.size = sizeof(out->message.t.buffer); |
139 | 0 | result = CryptRsaDecrypt(&out->message.b, &in->cipherText.b, rsaKey, |
140 | 0 | scheme, &in->label.b); |
141 | 0 | return result; |
142 | 0 | } |
143 | | #endif |
144 | | #endif // CC_RSA_Decrypt |
145 | | #include "Tpm.h" |
146 | | #include "ECDH_KeyGen_fp.h" |
147 | | #if CC_ECDH_KeyGen // Conditional expansion of this file |
148 | | #if ALG_ECC |
149 | | TPM_RC |
150 | | TPM2_ECDH_KeyGen( |
151 | | ECDH_KeyGen_In *in, // IN: input parameter list |
152 | | ECDH_KeyGen_Out *out // OUT: output parameter list |
153 | | ) |
154 | 0 | { |
155 | 0 | OBJECT *eccKey; |
156 | 0 | TPM2B_ECC_PARAMETER sensitive; |
157 | 0 | TPM_RC result; |
158 | | // Input Validation |
159 | 0 | eccKey = HandleToObject(in->keyHandle); |
160 | | // Referenced key must be an ECC key |
161 | 0 | if(eccKey->publicArea.type != TPM_ALG_ECC) |
162 | 0 | return TPM_RCS_KEY + RC_ECDH_KeyGen_keyHandle; |
163 | | // Command Output |
164 | 0 | do |
165 | 0 | { |
166 | 0 | TPMT_PUBLIC *keyPublic = &eccKey->publicArea; |
167 | | // Create ephemeral ECC key |
168 | 0 | result = CryptEccNewKeyPair(&out->pubPoint.point, &sensitive, |
169 | 0 | keyPublic->parameters.eccDetail.curveID); |
170 | 0 | if(result == TPM_RC_SUCCESS) |
171 | 0 | { |
172 | | // Compute Z |
173 | 0 | result = CryptEccPointMultiply(&out->zPoint.point, |
174 | 0 | keyPublic->parameters.eccDetail.curveID, |
175 | 0 | &keyPublic->unique.ecc, |
176 | 0 | &sensitive, |
177 | 0 | NULL, NULL); |
178 | | // The point in the key is not on the curve. Indicate |
179 | | // that the key is bad. |
180 | 0 | if(result == TPM_RC_ECC_POINT) |
181 | 0 | return TPM_RCS_KEY + RC_ECDH_KeyGen_keyHandle; |
182 | | // The other possible error from CryptEccPointMultiply is |
183 | | // TPM_RC_NO_RESULT indicating that the multiplication resulted in |
184 | | // the point at infinity, so get a new random key and start over |
185 | | // BTW, this never happens. |
186 | 0 | } |
187 | 0 | } while(result == TPM_RC_NO_RESULT); |
188 | 0 | return result; |
189 | 0 | } |
190 | | #endif // ALG_ECC |
191 | | #endif // CC_ECDH_KeyGen |
192 | | #include "Tpm.h" |
193 | | #include "ECDH_ZGen_fp.h" |
194 | | #if CC_ECDH_ZGen // Conditional expansion of this file |
195 | | #if ALG_ECC |
196 | | TPM_RC |
197 | | TPM2_ECDH_ZGen( |
198 | | ECDH_ZGen_In *in, // IN: input parameter list |
199 | | ECDH_ZGen_Out *out // OUT: output parameter list |
200 | | ) |
201 | 0 | { |
202 | 0 | TPM_RC result; |
203 | 0 | OBJECT *eccKey; |
204 | | // Input Validation |
205 | 0 | eccKey = HandleToObject(in->keyHandle); |
206 | | // Selected key must be a non-restricted, decrypt ECC key |
207 | 0 | if(eccKey->publicArea.type != TPM_ALG_ECC) |
208 | 0 | return TPM_RCS_KEY + RC_ECDH_ZGen_keyHandle; |
209 | | // Selected key needs to be unrestricted with the 'decrypt' attribute |
210 | 0 | if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) |
211 | 0 | || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) |
212 | 0 | return TPM_RCS_ATTRIBUTES + RC_ECDH_ZGen_keyHandle; |
213 | | // Make sure the scheme allows this use |
214 | 0 | if(eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_ECDH |
215 | 0 | && eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_NULL) |
216 | 0 | return TPM_RCS_SCHEME + RC_ECDH_ZGen_keyHandle; |
217 | | // Command Output |
218 | | // Compute Z. TPM_RC_ECC_POINT or TPM_RC_NO_RESULT may be returned here. |
219 | 0 | result = CryptEccPointMultiply(&out->outPoint.point, |
220 | 0 | eccKey->publicArea.parameters.eccDetail.curveID, |
221 | 0 | &in->inPoint.point, |
222 | 0 | &eccKey->sensitive.sensitive.ecc, |
223 | 0 | NULL, NULL); |
224 | 0 | if(result != TPM_RC_SUCCESS) |
225 | 0 | return RcSafeAddToResult(result, RC_ECDH_ZGen_inPoint); |
226 | 0 | return result; |
227 | 0 | } |
228 | | #endif |
229 | | #endif // CC_ECDH_ZGen |
230 | | #include "Tpm.h" |
231 | | #include "ECC_Parameters_fp.h" |
232 | | #if CC_ECC_Parameters // Conditional expansion of this file |
233 | | #if ALG_ECC |
234 | | TPM_RC |
235 | | TPM2_ECC_Parameters( |
236 | | ECC_Parameters_In *in, // IN: input parameter list |
237 | | ECC_Parameters_Out *out // OUT: output parameter list |
238 | | ) |
239 | 0 | { |
240 | | // Command Output |
241 | | // Get ECC curve parameters |
242 | 0 | if(CryptEccGetParameters(in->curveID, &out->parameters)) |
243 | 0 | return TPM_RC_SUCCESS; |
244 | 0 | else |
245 | 0 | return TPM_RCS_VALUE + RC_ECC_Parameters_curveID; |
246 | 0 | } |
247 | | #endif |
248 | | #endif // CC_ECC_Parameters |
249 | | #include "Tpm.h" |
250 | | #include "ZGen_2Phase_fp.h" |
251 | | #if CC_ZGen_2Phase // Conditional expansion of this file |
252 | | TPM_RC |
253 | | TPM2_ZGen_2Phase( |
254 | | ZGen_2Phase_In *in, // IN: input parameter list |
255 | | ZGen_2Phase_Out *out // OUT: output parameter list |
256 | | ) |
257 | 0 | { |
258 | 0 | TPM_RC result; |
259 | 0 | OBJECT *eccKey; |
260 | 0 | TPM2B_ECC_PARAMETER r; |
261 | 0 | TPM_ALG_ID scheme; |
262 | | // Input Validation |
263 | 0 | eccKey = HandleToObject(in->keyA); |
264 | | // keyA must be an ECC key |
265 | 0 | if(eccKey->publicArea.type != TPM_ALG_ECC) |
266 | 0 | return TPM_RCS_KEY + RC_ZGen_2Phase_keyA; |
267 | | // keyA must not be restricted and must be a decrypt key |
268 | 0 | if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) |
269 | 0 | || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) |
270 | 0 | return TPM_RCS_ATTRIBUTES + RC_ZGen_2Phase_keyA; |
271 | | // if the scheme of keyA is TPM_ALG_NULL, then use the input scheme; otherwise |
272 | | // the input scheme must be the same as the scheme of keyA |
273 | 0 | scheme = eccKey->publicArea.parameters.asymDetail.scheme.scheme; |
274 | 0 | if(scheme != TPM_ALG_NULL) |
275 | 0 | { |
276 | 0 | if(scheme != in->inScheme) |
277 | 0 | return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; |
278 | 0 | } |
279 | 0 | else |
280 | 0 | scheme = in->inScheme; |
281 | 0 | if(scheme == TPM_ALG_NULL) |
282 | 0 | return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; |
283 | | // Input points must be on the curve of keyA |
284 | 0 | if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID, |
285 | 0 | &in->inQsB.point)) |
286 | 0 | return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQsB; |
287 | 0 | if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID, |
288 | 0 | &in->inQeB.point)) |
289 | 0 | return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQeB; |
290 | 0 | if(!CryptGenerateR(&r, &in->counter, |
291 | 0 | eccKey->publicArea.parameters.eccDetail.curveID, |
292 | 0 | NULL)) |
293 | 0 | return TPM_RCS_VALUE + RC_ZGen_2Phase_counter; |
294 | | // Command Output |
295 | 0 | result = CryptEcc2PhaseKeyExchange(&out->outZ1.point, |
296 | 0 | &out->outZ2.point, |
297 | 0 | eccKey->publicArea.parameters.eccDetail.curveID, |
298 | 0 | scheme, |
299 | 0 | &eccKey->sensitive.sensitive.ecc, |
300 | 0 | &r, |
301 | 0 | &in->inQsB.point, |
302 | 0 | &in->inQeB.point); |
303 | 0 | if(result == TPM_RC_SCHEME) |
304 | 0 | return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; |
305 | 0 | if(result == TPM_RC_SUCCESS) |
306 | 0 | CryptEndCommit(in->counter); |
307 | 0 | return result; |
308 | 0 | } |
309 | | #endif |