1 | /********************************************************************************/
|
---|
2 | /* */
|
---|
3 | /* Implementation of cryptographic primitives for RSA */
|
---|
4 | /* Written by Ken Goldman */
|
---|
5 | /* IBM Thomas J. Watson Research Center */
|
---|
6 | /* $Id: CryptRsa.c 1658 2021-01-22 23:14:01Z 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 ([email protected]) 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 - 2021 */
|
---|
59 | /* */
|
---|
60 | /********************************************************************************/
|
---|
61 |
|
---|
62 | /* 10.2.17 CryptRsa.c */
|
---|
63 | /* 10.2.17.1 Introduction */
|
---|
64 | /* This file contains implementation of cryptographic primitives for RSA. Vendors may replace the
|
---|
65 | implementation in this file with their own library functions. */
|
---|
66 | /* 10.2.17.2 Includes */
|
---|
67 | /* Need this define to get the private defines for this function */
|
---|
68 | #define CRYPT_RSA_C
|
---|
69 | #include "Tpm.h"
|
---|
70 | #include "Helpers_fp.h" // libtpms added
|
---|
71 |
|
---|
72 | #include <openssl/rsa.h> // libtpms added
|
---|
73 |
|
---|
74 | #if ALG_RSA
|
---|
75 | /* 10.2.17.3 Obligatory Initialization Functions */
|
---|
76 | /* 10.2.17.3.1 CryptRsaInit() */
|
---|
77 | /* Function called at _TPM_Init(). */
|
---|
78 | BOOL
|
---|
79 | CryptRsaInit(
|
---|
80 | void
|
---|
81 | )
|
---|
82 | {
|
---|
83 | return TRUE;
|
---|
84 | }
|
---|
85 | /* 10.2.17.3.2 CryptRsaStartup() */
|
---|
86 | /* Function called at TPM2_Startup() */
|
---|
87 | BOOL
|
---|
88 | CryptRsaStartup(
|
---|
89 | void
|
---|
90 | )
|
---|
91 | {
|
---|
92 | return TRUE;
|
---|
93 | }
|
---|
94 | /* 10.2.17.4 Internal Functions */
|
---|
95 | void
|
---|
96 | RsaInitializeExponent(
|
---|
97 | privateExponent_t *pExp
|
---|
98 | )
|
---|
99 | {
|
---|
100 | #if CRT_FORMAT_RSA == NO
|
---|
101 | BN_INIT(pExp->D);
|
---|
102 | #else
|
---|
103 | BN_INIT(pExp->Q);
|
---|
104 | BN_INIT(pExp->dP);
|
---|
105 | BN_INIT(pExp->dQ);
|
---|
106 | BN_INIT(pExp->qInv);
|
---|
107 | #endif
|
---|
108 | }
|
---|
109 | /* 10.2.17.4.1 ComputePrivateExponent() */
|
---|
110 | /* This function computes the private exponent from the primes. */
|
---|
111 | /* Return Value Meaning */
|
---|
112 | /* TRUE(1) success */
|
---|
113 | /* FALSE(0) failure */
|
---|
114 | static BOOL
|
---|
115 | ComputePrivateExponent(
|
---|
116 | bigNum P, // IN: first prime (size is 1/2 of bnN)
|
---|
117 | bigNum Q, // IN: second prime (size is 1/2 of bnN)
|
---|
118 | bigNum E, // IN: the public exponent
|
---|
119 | bigNum N, // IN: the public modulus
|
---|
120 | privateExponent_t *pExp // OUT:
|
---|
121 | )
|
---|
122 | {
|
---|
123 | BOOL pOK;
|
---|
124 | BOOL qOK;
|
---|
125 | #if CRT_FORMAT_RSA == NO
|
---|
126 | BN_RSA(bnPhi);
|
---|
127 | //
|
---|
128 | RsaInitializeExponent(pExp);
|
---|
129 | // Get compute Phi = (p - 1)(q - 1) = pq - p - q + 1 = n - p - q + 1
|
---|
130 | pOK = BnCopy(bnPhi, N);
|
---|
131 | pOK = pOK && BnSub(bnPhi, bnPhi, P);
|
---|
132 | pOK = pOK && BnSub(bnPhi, bnPhi, Q);
|
---|
133 | pOK = pOK && BnAddWord(bnPhi, bnPhi, 1);
|
---|
134 | // Compute the multiplicative inverse d = 1/e mod Phi
|
---|
135 | pOK = pOK && BnModInverse((bigNum)&pExp->D, E, bnPhi);
|
---|
136 | qOK = pOK;
|
---|
137 | #else
|
---|
138 | BN_PRIME(temp);
|
---|
139 | bigNum pT;
|
---|
140 | //
|
---|
141 | NOT_REFERENCED(N);
|
---|
142 | RsaInitializeExponent(pExp);
|
---|
143 | BnCopy((bigNum)&pExp->Q, Q);
|
---|
144 | // make p the larger value so that m2 is always less than p
|
---|
145 | if(BnUnsignedCmp(P, Q) < 0)
|
---|
146 | {
|
---|
147 | pT = P;
|
---|
148 | P = Q;
|
---|
149 | Q = pT;
|
---|
150 | }
|
---|
151 | //dP = (1/e) mod (p-1) = d mod (p-1)
|
---|
152 | pOK = BnSubWord(temp, P, 1);
|
---|
153 | pOK = pOK && BnModInverse((bigNum)&pExp->dP, E, temp);
|
---|
154 | //dQ = (1/e) mod (q-1) = d mod (q-1)
|
---|
155 | qOK = BnSubWord(temp, Q, 1);
|
---|
156 | qOK = qOK && BnModInverse((bigNum)&pExp->dQ, E, temp);
|
---|
157 | // qInv = (1/q) mod p
|
---|
158 | if(pOK && qOK)
|
---|
159 | pOK = qOK = BnModInverse((bigNum)&pExp->qInv, Q, P);
|
---|
160 | #endif
|
---|
161 | if(!pOK)
|
---|
162 | BnSetWord(P, 0);
|
---|
163 | if(!qOK)
|
---|
164 | BnSetWord(Q, 0);
|
---|
165 | return pOK && qOK;
|
---|
166 | }
|
---|
167 | /* 10.2.17.4.2 RsaPrivateKeyOp() */
|
---|
168 | /* This function is called to do the exponentiation with the private key. Compile options allow use
|
---|
169 | of the simple (but slow) private exponent, or the more complex but faster CRT method. */
|
---|
170 | /* Return Value Meaning */
|
---|
171 | /* TRUE(1) success */
|
---|
172 | /* FALSE(0) failure */
|
---|
173 | static BOOL
|
---|
174 | RsaPrivateKeyOp(
|
---|
175 | bigNum inOut, // IN/OUT: number to be exponentiated
|
---|
176 | bigNum N, // IN: public modulus (can be NULL if CRT)
|
---|
177 | bigNum P, // IN: one of the primes (can be NULL if not CRT)
|
---|
178 | privateExponent_t *pExp
|
---|
179 | )
|
---|
180 | {
|
---|
181 | BOOL OK;
|
---|
182 | #if CRT_FORMAT_RSA == NO
|
---|
183 | (P);
|
---|
184 | OK = BnModExp(inOut, inOut, (bigNum)&pExp->D, N);
|
---|
185 | #else
|
---|
186 | BN_RSA(M1);
|
---|
187 | BN_RSA(M2);
|
---|
188 | BN_RSA(M);
|
---|
189 | BN_RSA(H);
|
---|
190 | bigNum Q = (bigNum)&pExp->Q;
|
---|
191 | NOT_REFERENCED(N);
|
---|
192 | // Make P the larger prime.
|
---|
193 | // NOTE that when the CRT form of the private key is created, dP will always
|
---|
194 | // be computed using the larger of p and q so the only thing needed here is that
|
---|
195 | // the primes be selected so that they agree with dP.
|
---|
196 | if(BnUnsignedCmp(P, Q) < 0)
|
---|
197 | {
|
---|
198 | bigNum T = P;
|
---|
199 | P = Q;
|
---|
200 | Q = T;
|
---|
201 | }
|
---|
202 | // m1 = cdP mod p
|
---|
203 | OK = BnModExp(M1, inOut, (bigNum)&pExp->dP, P);
|
---|
204 | // m2 = cdQ mod q
|
---|
205 | OK = OK && BnModExp(M2, inOut, (bigNum)&pExp->dQ, Q);
|
---|
206 | // h = qInv * (m1 - m2) mod p = qInv * (m1 + P - m2) mod P because Q < P
|
---|
207 | // so m2 < P
|
---|
208 | OK = OK && BnSub(H, P, M2);
|
---|
209 | OK = OK && BnAdd(H, H, M1);
|
---|
210 | OK = OK && BnModMult(H, H, (bigNum)&pExp->qInv, P);
|
---|
211 | // m = m2 + h * q
|
---|
212 | OK = OK && BnMult(M, H, Q);
|
---|
213 | OK = OK && BnAdd(inOut, M2, M);
|
---|
214 | #endif
|
---|
215 | return OK;
|
---|
216 | }
|
---|
217 | /* 10.2.17.4.3 RSAEP() */
|
---|
218 | /* This function performs the RSAEP operation defined in PKCS#1v2.1. It is an exponentiation of a
|
---|
219 | value (m) with the public exponent (e), modulo the public (n). */
|
---|
220 | /* Error Returns Meaning */
|
---|
221 | /* TPM_RC_VALUE number to exponentiate is larger than the modulus */
|
---|
222 | #if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added
|
---|
223 | static TPM_RC
|
---|
224 | RSAEP(
|
---|
225 | TPM2B *dInOut, // IN: size of the encrypted block and the size of
|
---|
226 | // the encrypted value. It must be the size of
|
---|
227 | // the modulus.
|
---|
228 | // OUT: the encrypted data. Will receive the
|
---|
229 | // decrypted value
|
---|
230 | OBJECT *key // IN: the key to use
|
---|
231 | )
|
---|
232 | {
|
---|
233 | TPM2B_TYPE(4BYTES, 4);
|
---|
234 | TPM2B_4BYTES(e) = {{4, {(BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT >> 24) & 0xff),
|
---|
235 | (BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT >> 16) & 0xff),
|
---|
236 | (BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT >> 8) & 0xff),
|
---|
237 | (BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT)& 0xff)}}};
|
---|
238 | //
|
---|
239 | if(key->publicArea.parameters.rsaDetail.exponent != 0)
|
---|
240 | UINT32_TO_BYTE_ARRAY(key->publicArea.parameters.rsaDetail.exponent,
|
---|
241 | e.t.buffer);
|
---|
242 | return ModExpB(dInOut->size, dInOut->buffer, dInOut->size, dInOut->buffer,
|
---|
243 | e.t.size, e.t.buffer, key->publicArea.unique.rsa.t.size,
|
---|
244 | key->publicArea.unique.rsa.t.buffer);
|
---|
245 | }
|
---|
246 | /* 10.2.17.4.4 RSADP() */
|
---|
247 | /* This function performs the RSADP operation defined in PKCS#1v2.1. It is an exponentiation of a
|
---|
248 | value (c) with the private exponent (d), modulo the public modulus (n). The decryption is in
|
---|
249 | place. */
|
---|
250 | /* This function also checks the size of the private key. If the size indicates that only a prime
|
---|
251 | value is present, the key is converted to being a private exponent. */
|
---|
252 | /* Error Returns Meaning */
|
---|
253 | /* TPM_RC_SIZE the value to decrypt is larger than the modulus */
|
---|
254 | static TPM_RC
|
---|
255 | RSADP(
|
---|
256 | TPM2B *inOut, // IN/OUT: the value to encrypt
|
---|
257 | OBJECT *key // IN: the key
|
---|
258 | )
|
---|
259 | {
|
---|
260 | BN_RSA_INITIALIZED(bnM, inOut);
|
---|
261 | BN_RSA_INITIALIZED(bnN, &key->publicArea.unique.rsa);
|
---|
262 | BN_RSA_INITIALIZED(bnP, &key->sensitive.sensitive.rsa);
|
---|
263 | if(BnUnsignedCmp(bnM, bnN) >= 0)
|
---|
264 | return TPM_RC_SIZE;
|
---|
265 | // private key operation requires that private exponent be loaded
|
---|
266 | // During self-test, this might not be the case so load it up if it hasn't
|
---|
267 | // already done
|
---|
268 | // been done
|
---|
269 | if(!key->attributes.privateExp)
|
---|
270 | CryptRsaLoadPrivateExponent(key);
|
---|
271 | if(!RsaPrivateKeyOp(bnM, bnN, bnP, &key->privateExponent))
|
---|
272 | FAIL(FATAL_ERROR_INTERNAL);
|
---|
273 | BnTo2B(bnM, inOut, inOut->size);
|
---|
274 | return TPM_RC_SUCCESS;
|
---|
275 | }
|
---|
276 | /* 10.2.17.4.5 OaepEncode() */
|
---|
277 | /* This function performs OAEP padding. The size of the buffer to receive the OAEP padded data must
|
---|
278 | equal the size of the modulus */
|
---|
279 | /* Error Returns Meaning */
|
---|
280 | /* TPM_RC_VALUE hashAlg is not valid or message size is too large */
|
---|
281 | static TPM_RC
|
---|
282 | OaepEncode(
|
---|
283 | TPM2B *padded, // OUT: the pad data
|
---|
284 | TPM_ALG_ID hashAlg, // IN: algorithm to use for padding
|
---|
285 | const TPM2B *label, // IN: null-terminated string (may be NULL)
|
---|
286 | TPM2B *message, // IN: the message being padded
|
---|
287 | RAND_STATE *rand // IN: the random number generator to use
|
---|
288 | )
|
---|
289 | {
|
---|
290 | INT32 padLen;
|
---|
291 | INT32 dbSize;
|
---|
292 | INT32 i;
|
---|
293 | BYTE mySeed[MAX_DIGEST_SIZE];
|
---|
294 | BYTE *seed = mySeed;
|
---|
295 | UINT16 hLen = CryptHashGetDigestSize(hashAlg);
|
---|
296 | BYTE mask[MAX_RSA_KEY_BYTES];
|
---|
297 | BYTE *pp;
|
---|
298 | BYTE *pm;
|
---|
299 | TPM_RC retVal = TPM_RC_SUCCESS;
|
---|
300 | pAssert(padded != NULL && message != NULL);
|
---|
301 | // A value of zero is not allowed because the KDF can't produce a result
|
---|
302 | // if the digest size is zero.
|
---|
303 | if(hLen == 0)
|
---|
304 | return TPM_RC_VALUE;
|
---|
305 | // Basic size checks
|
---|
306 | // make sure digest isn't too big for key size
|
---|
307 | if(padded->size < (2 * hLen) + 2)
|
---|
308 | ERROR_RETURN(TPM_RC_HASH);
|
---|
309 | // and that message will fit messageSize <= k - 2hLen - 2
|
---|
310 | if(message->size > (padded->size - (2 * hLen) - 2))
|
---|
311 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
312 | // Hash L even if it is null
|
---|
313 | // Offset into padded leaving room for masked seed and byte of zero
|
---|
314 | pp = &padded->buffer[hLen + 1];
|
---|
315 | if(CryptHashBlock(hashAlg, label->size, (BYTE *)label->buffer,
|
---|
316 | hLen, pp) != hLen)
|
---|
317 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
318 | // concatenate PS of k mLen 2hLen 2
|
---|
319 | padLen = padded->size - message->size - (2 * hLen) - 2;
|
---|
320 | MemorySet(&pp[hLen], 0, padLen);
|
---|
321 | pp[hLen + padLen] = 0x01;
|
---|
322 | padLen += 1;
|
---|
323 | memcpy(&pp[hLen + padLen], message->buffer, message->size);
|
---|
324 | // The total size of db = hLen + pad + mSize;
|
---|
325 | dbSize = hLen + padLen + message->size;
|
---|
326 | // If testing, then use the provided seed. Otherwise, use values
|
---|
327 | // from the RNG
|
---|
328 | CryptRandomGenerate(hLen, mySeed);
|
---|
329 | DRBG_Generate(rand, mySeed, (UINT16)hLen);
|
---|
330 | // mask = MGF1 (seed, nSize hLen 1)
|
---|
331 | CryptMGF_KDF(dbSize, mask, hashAlg, hLen, seed, 0);
|
---|
332 | // Create the masked db
|
---|
333 | pm = mask;
|
---|
334 | for(i = dbSize; i > 0; i--)
|
---|
335 | *pp++ ^= *pm++;
|
---|
336 | pp = &padded->buffer[hLen + 1];
|
---|
337 | // Run the masked data through MGF1
|
---|
338 | if(CryptMGF_KDF(hLen, &padded->buffer[1], hashAlg, dbSize, pp, 0) != (unsigned)hLen)
|
---|
339 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
340 | // Now XOR the seed to create masked seed
|
---|
341 | pp = &padded->buffer[1];
|
---|
342 | pm = seed;
|
---|
343 | for(i = hLen; i > 0; i--)
|
---|
344 | *pp++ ^= *pm++;
|
---|
345 | // Set the first byte to zero
|
---|
346 | padded->buffer[0] = 0x00;
|
---|
347 | Exit:
|
---|
348 | return retVal;
|
---|
349 | }
|
---|
350 | /* 10.2.17.4.6 OaepDecode() */
|
---|
351 | /* This function performs OAEP padding checking. The size of the buffer to receive the recovered
|
---|
352 | data. If the padding is not valid, the dSize size is set to zero and the function returns
|
---|
353 | TPM_RC_VALUE. */
|
---|
354 | /* The dSize parameter is used as an input to indicate the size available in the buffer. If
|
---|
355 | insufficient space is available, the size is not changed and the return code is TPM_RC_VALUE. */
|
---|
356 | /* Error Returns Meaning */
|
---|
357 | /* TPM_RC_VALUE the value to decode was larger than the modulus, or the padding is wrong or the
|
---|
358 | buffer to receive the results is too small */
|
---|
359 | static TPM_RC
|
---|
360 | OaepDecode(
|
---|
361 | TPM2B *dataOut, // OUT: the recovered data
|
---|
362 | TPM_ALG_ID hashAlg, // IN: algorithm to use for padding
|
---|
363 | const TPM2B *label, // IN: null-terminated string (may be NULL)
|
---|
364 | TPM2B *padded // IN: the padded data
|
---|
365 | )
|
---|
366 | {
|
---|
367 | UINT32 i;
|
---|
368 | BYTE seedMask[MAX_DIGEST_SIZE];
|
---|
369 | UINT32 hLen = CryptHashGetDigestSize(hashAlg);
|
---|
370 | BYTE mask[MAX_RSA_KEY_BYTES];
|
---|
371 | BYTE *pp;
|
---|
372 | BYTE *pm;
|
---|
373 | TPM_RC retVal = TPM_RC_SUCCESS;
|
---|
374 | // Strange size (anything smaller can't be an OAEP padded block)
|
---|
375 | // Also check for no leading 0
|
---|
376 | if((padded->size < (unsigned)((2 * hLen) + 2)) || (padded->buffer[0] != 0))
|
---|
377 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
378 | // Use the hash size to determine what to put through MGF1 in order
|
---|
379 | // to recover the seedMask
|
---|
380 | CryptMGF_KDF(hLen, seedMask, hashAlg, padded->size - hLen - 1,
|
---|
381 | &padded->buffer[hLen + 1], 0);
|
---|
382 | // Recover the seed into seedMask
|
---|
383 | pAssert(hLen <= sizeof(seedMask));
|
---|
384 | pp = &padded->buffer[1];
|
---|
385 | pm = seedMask;
|
---|
386 | for(i = hLen; i > 0; i--)
|
---|
387 | *pm++ ^= *pp++;
|
---|
388 | // Use the seed to generate the data mask
|
---|
389 | CryptMGF_KDF(padded->size - hLen - 1, mask, hashAlg, hLen, seedMask, 0);
|
---|
390 | // Use the mask generated from seed to recover the padded data
|
---|
391 | pp = &padded->buffer[hLen + 1];
|
---|
392 | pm = mask;
|
---|
393 | for(i = (padded->size - hLen - 1); i > 0; i--)
|
---|
394 | *pm++ ^= *pp++;
|
---|
395 | // Make sure that the recovered data has the hash of the label
|
---|
396 | // Put trial value in the seed mask
|
---|
397 | if((CryptHashBlock(hashAlg, label->size, (BYTE *)label->buffer,
|
---|
398 | hLen, seedMask)) != hLen)
|
---|
399 | FAIL(FATAL_ERROR_INTERNAL);
|
---|
400 | if(memcmp(seedMask, mask, hLen) != 0)
|
---|
401 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
402 | // find the start of the data
|
---|
403 | pm = &mask[hLen];
|
---|
404 | for(i = (UINT32)padded->size - (2 * hLen) - 1; i > 0; i--)
|
---|
405 | {
|
---|
406 | if(*pm++ != 0)
|
---|
407 | break;
|
---|
408 | }
|
---|
409 | // If we ran out of data or didn't end with 0x01, then return an error
|
---|
410 | if(i == 0 || pm[-1] != 0x01)
|
---|
411 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
412 | // pm should be pointing at the first part of the data
|
---|
413 | // and i is one greater than the number of bytes to move
|
---|
414 | i--;
|
---|
415 | if(i > dataOut->size)
|
---|
416 | // Special exit to preserve the size of the output buffer
|
---|
417 | return TPM_RC_VALUE;
|
---|
418 | memcpy(dataOut->buffer, pm, i);
|
---|
419 | dataOut->size = (UINT16)i;
|
---|
420 | Exit:
|
---|
421 | if(retVal != TPM_RC_SUCCESS)
|
---|
422 | dataOut->size = 0;
|
---|
423 | return retVal;
|
---|
424 | }
|
---|
425 | /* 10.2.17.4.7 PKCS1v1_5Encode() */
|
---|
426 | /* This function performs the encoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1 */
|
---|
427 | /* Error Returns Meaning */
|
---|
428 | /* TPM_RC_VALUE message size is too large */
|
---|
429 | static TPM_RC
|
---|
430 | RSAES_PKCS1v1_5Encode(
|
---|
431 | TPM2B *padded, // OUT: the pad data
|
---|
432 | TPM2B *message, // IN: the message being padded
|
---|
433 | RAND_STATE *rand
|
---|
434 | )
|
---|
435 | {
|
---|
436 | UINT32 ps = padded->size - message->size - 3;
|
---|
437 | //
|
---|
438 | if(message->size > padded->size - 11)
|
---|
439 | return TPM_RC_VALUE;
|
---|
440 | // move the message to the end of the buffer
|
---|
441 | memcpy(&padded->buffer[padded->size - message->size], message->buffer,
|
---|
442 | message->size);
|
---|
443 | // Set the first byte to 0x00 and the second to 0x02
|
---|
444 | padded->buffer[0] = 0;
|
---|
445 | padded->buffer[1] = 2;
|
---|
446 | // Fill with random bytes
|
---|
447 | DRBG_Generate(rand, &padded->buffer[2], (UINT16)ps);
|
---|
448 | // Set the delimiter for the random field to 0
|
---|
449 | padded->buffer[2 + ps] = 0;
|
---|
450 | // Now, the only messy part. Make sure that all the 'ps' bytes are non-zero
|
---|
451 | // In this implementation, use the value of the current index
|
---|
452 | for(ps++; ps > 1; ps--)
|
---|
453 | {
|
---|
454 | if(padded->buffer[ps] == 0)
|
---|
455 | padded->buffer[ps] = 0x55; // In the < 0.5% of the cases that the
|
---|
456 | // random value is 0, just pick a value to
|
---|
457 | // put into the spot.
|
---|
458 | }
|
---|
459 | return TPM_RC_SUCCESS;
|
---|
460 | }
|
---|
461 | /* 10.2.17.4.8 RSAES_Decode() */
|
---|
462 | /* This function performs the decoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1 */
|
---|
463 | /* Error Returns Meaning */
|
---|
464 | /* TPM_RC_FAIL decoding error or results would no fit into provided buffer */
|
---|
465 | static TPM_RC
|
---|
466 | RSAES_Decode(
|
---|
467 | TPM2B *message, // OUT: the recovered message
|
---|
468 | TPM2B *coded // IN: the encoded message
|
---|
469 | )
|
---|
470 | {
|
---|
471 | BOOL fail = FALSE;
|
---|
472 | UINT16 pSize;
|
---|
473 | fail = (coded->size < 11);
|
---|
474 | fail = (coded->buffer[0] != 0x00) | fail;
|
---|
475 | fail = (coded->buffer[1] != 0x02) | fail;
|
---|
476 | for(pSize = 2; pSize < coded->size; pSize++)
|
---|
477 | {
|
---|
478 | if(coded->buffer[pSize] == 0)
|
---|
479 | break;
|
---|
480 | }
|
---|
481 | pSize++;
|
---|
482 | // Make sure that pSize has not gone over the end and that there are at least 8
|
---|
483 | // bytes of pad data.
|
---|
484 | fail = (pSize > coded->size) | fail;
|
---|
485 | fail = ((pSize - 2) <= 8) | fail;
|
---|
486 | if((message->size < (UINT16)(coded->size - pSize)) || fail)
|
---|
487 | return TPM_RC_VALUE;
|
---|
488 | message->size = coded->size - pSize;
|
---|
489 | memcpy(message->buffer, &coded->buffer[pSize], coded->size - pSize);
|
---|
490 | return TPM_RC_SUCCESS;
|
---|
491 | }
|
---|
492 | #endif // libtpms added
|
---|
493 | /* 10.2.17.4.13 CryptRsaPssSaltSize() */
|
---|
494 | /* This function computes the salt size used in PSS. It is broken out so that the X509 code can get
|
---|
495 | the same value that is used by the encoding function in this module. */
|
---|
496 | INT16
|
---|
497 | CryptRsaPssSaltSize(
|
---|
498 | INT16 hashSize,
|
---|
499 | INT16 outSize
|
---|
500 | )
|
---|
501 | {
|
---|
502 | INT16 saltSize;
|
---|
503 | //
|
---|
504 | // (Mask Length) = (outSize - hashSize - 1);
|
---|
505 | // Max saltSize is (Mask Length) - 1
|
---|
506 | saltSize = (outSize - hashSize - 1) - 1;
|
---|
507 | // Use the maximum salt size allowed by FIPS 186-4
|
---|
508 | if (saltSize > hashSize)
|
---|
509 | saltSize = hashSize;
|
---|
510 | else if (saltSize < 0)
|
---|
511 | saltSize = 0;
|
---|
512 | return saltSize;
|
---|
513 | }
|
---|
514 |
|
---|
515 | #if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added
|
---|
516 | /* 10.2.17.4.9 PssEncode() */
|
---|
517 | /* This function creates an encoded block of data that is the size of modulus. The function uses the
|
---|
518 | maximum salt size that will fit in the encoded block. */
|
---|
519 | /* Returns TPM_RC_SUCCESS or goes into failure mode. */
|
---|
520 | static TPM_RC
|
---|
521 | PssEncode(
|
---|
522 | TPM2B *out, // OUT: the encoded buffer
|
---|
523 | TPM_ALG_ID hashAlg, // IN: hash algorithm for the encoding
|
---|
524 | TPM2B *digest, // IN: the digest
|
---|
525 | RAND_STATE *rand // IN: random number source
|
---|
526 | )
|
---|
527 | {
|
---|
528 | UINT32 hLen = CryptHashGetDigestSize(hashAlg);
|
---|
529 | BYTE salt[MAX_RSA_KEY_BYTES - 1];
|
---|
530 | UINT16 saltSize;
|
---|
531 | BYTE *ps = salt;
|
---|
532 | BYTE *pOut;
|
---|
533 | UINT16 mLen;
|
---|
534 | HASH_STATE hashState;
|
---|
535 | // These are fatal errors indicating bad TPM firmware
|
---|
536 | pAssert(out != NULL && hLen > 0 && digest != NULL);
|
---|
537 | // Get the size of the mask
|
---|
538 | mLen = (UINT16)(out->size - hLen - 1);
|
---|
539 | // Maximum possible salt size is mask length - 1
|
---|
540 | saltSize = mLen - 1;
|
---|
541 | // Use the maximum salt size allowed by FIPS 186-4
|
---|
542 | if(saltSize > hLen)
|
---|
543 | saltSize = (UINT16)hLen;
|
---|
544 | //using eOut for scratch space
|
---|
545 | // Set the first 8 bytes to zero
|
---|
546 | pOut = out->buffer;
|
---|
547 | memset(pOut, 0, 8);
|
---|
548 | // Get set the salt
|
---|
549 | DRBG_Generate(rand, salt, saltSize);
|
---|
550 | // Create the hash of the pad || input hash || salt
|
---|
551 | CryptHashStart(&hashState, hashAlg);
|
---|
552 | CryptDigestUpdate(&hashState, 8, pOut);
|
---|
553 | CryptDigestUpdate2B(&hashState, digest);
|
---|
554 | CryptDigestUpdate(&hashState, saltSize, salt);
|
---|
555 | CryptHashEnd(&hashState, hLen, &pOut[out->size - hLen - 1]);
|
---|
556 | // Create a mask
|
---|
557 | if(CryptMGF_KDF(mLen, pOut, hashAlg, hLen, &pOut[mLen], 0) != mLen)
|
---|
558 | FAIL(FATAL_ERROR_INTERNAL);
|
---|
559 | // Since this implementation uses key sizes that are all even multiples of
|
---|
560 | // 8, just need to make sure that the most significant bit is CLEAR
|
---|
561 | *pOut &= 0x7f;
|
---|
562 | // Before we mess up the pOut value, set the last byte to 0xbc
|
---|
563 | pOut[out->size - 1] = 0xbc;
|
---|
564 | // XOR a byte of 0x01 at the position just before where the salt will be XOR'ed
|
---|
565 | pOut = &pOut[mLen - saltSize - 1];
|
---|
566 | *pOut++ ^= 0x01;
|
---|
567 | // XOR the salt data into the buffer
|
---|
568 | for(; saltSize > 0; saltSize--)
|
---|
569 | *pOut++ ^= *ps++;
|
---|
570 | // and we are done
|
---|
571 | return TPM_RC_SUCCESS;
|
---|
572 | }
|
---|
573 | /* 10.2.17.4.10 PssDecode() */
|
---|
574 | /* This function checks that the PSS encoded block was built from the provided digest. If the check
|
---|
575 | is successful, TPM_RC_SUCCESS is returned. Any other value indicates an error. */
|
---|
576 | /* This implementation of PSS decoding is intended for the reference TPM implementation and is not
|
---|
577 | at all generalized. It is used to check signatures over hashes and assumptions are made about
|
---|
578 | the sizes of values. Those assumptions are enforce by this implementation. This implementation
|
---|
579 | does allow for a variable size salt value to have been used by the creator of the signature. */
|
---|
580 | /* Error Returns Meaning */
|
---|
581 | /* TPM_RC_SCHEME hashAlg is not a supported hash algorithm */
|
---|
582 | /* TPM_RC_VALUE decode operation failed */
|
---|
583 | static TPM_RC
|
---|
584 | PssDecode(
|
---|
585 | TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding
|
---|
586 | TPM2B *dIn, // In: the digest to compare
|
---|
587 | TPM2B *eIn // IN: the encoded data
|
---|
588 | )
|
---|
589 | {
|
---|
590 | UINT32 hLen = CryptHashGetDigestSize(hashAlg);
|
---|
591 | BYTE mask[MAX_RSA_KEY_BYTES];
|
---|
592 | BYTE *pm = mask;
|
---|
593 | BYTE *pe;
|
---|
594 | BYTE pad[8] = {0};
|
---|
595 | UINT32 i;
|
---|
596 | UINT32 mLen;
|
---|
597 | BYTE fail;
|
---|
598 | TPM_RC retVal = TPM_RC_SUCCESS;
|
---|
599 | HASH_STATE hashState;
|
---|
600 | // These errors are indicative of failures due to programmer error
|
---|
601 | pAssert(dIn != NULL && eIn != NULL);
|
---|
602 | pe = eIn->buffer;
|
---|
603 | // check the hash scheme
|
---|
604 | if(hLen == 0)
|
---|
605 | ERROR_RETURN(TPM_RC_SCHEME);
|
---|
606 | // most significant bit must be zero
|
---|
607 | fail = pe[0] & 0x80;
|
---|
608 | // last byte must be 0xbc
|
---|
609 | fail |= pe[eIn->size - 1] ^ 0xbc;
|
---|
610 | // Use the hLen bytes at the end of the buffer to generate a mask
|
---|
611 | // Doesn't start at the end which is a flag byte
|
---|
612 | mLen = eIn->size - hLen - 1;
|
---|
613 | CryptMGF_KDF(mLen, mask, hashAlg, hLen, &pe[mLen], 0);
|
---|
614 | // Clear the MSO of the mask to make it consistent with the encoding.
|
---|
615 | mask[0] &= 0x7F;
|
---|
616 | pAssert(mLen <= sizeof(mask));
|
---|
617 | // XOR the data into the mask to recover the salt. This sequence
|
---|
618 | // advances eIn so that it will end up pointing to the seed data
|
---|
619 | // which is the hash of the signature data
|
---|
620 | for(i = mLen; i > 0; i--)
|
---|
621 | *pm++ ^= *pe++;
|
---|
622 | // Find the first byte of 0x01 after a string of all 0x00
|
---|
623 | for(pm = mask, i = mLen; i > 0; i--)
|
---|
624 | {
|
---|
625 | if(*pm == 0x01)
|
---|
626 | break;
|
---|
627 | else
|
---|
628 | fail |= *pm++;
|
---|
629 | }
|
---|
630 | // i should not be zero
|
---|
631 | fail |= (i == 0);
|
---|
632 | // if we have failed, will continue using the entire mask as the salt value so
|
---|
633 | // that the timing attacks will not disclose anything (I don't think that this
|
---|
634 | // is a problem for TPM applications but, usually, we don't fail so this
|
---|
635 | // doesn't cost anything).
|
---|
636 | if(fail)
|
---|
637 | {
|
---|
638 | i = mLen;
|
---|
639 | pm = mask;
|
---|
640 | }
|
---|
641 | else
|
---|
642 | {
|
---|
643 | pm++;
|
---|
644 | i--;
|
---|
645 | }
|
---|
646 | // i contains the salt size and pm points to the salt. Going to use the input
|
---|
647 | // hash and the seed to recreate the hash in the lower portion of eIn.
|
---|
648 | CryptHashStart(&hashState, hashAlg);
|
---|
649 | // add the pad of 8 zeros
|
---|
650 | CryptDigestUpdate(&hashState, 8, pad);
|
---|
651 | // add the provided digest value
|
---|
652 | CryptDigestUpdate(&hashState, dIn->size, dIn->buffer);
|
---|
653 | // and the salt
|
---|
654 | CryptDigestUpdate(&hashState, i, pm);
|
---|
655 | // get the result
|
---|
656 | fail |= (CryptHashEnd(&hashState, hLen, mask) != hLen);
|
---|
657 | // Compare all bytes
|
---|
658 | for(pm = mask; hLen > 0; hLen--)
|
---|
659 | // don't use fail = because that could skip the increment and compare
|
---|
660 | // operations after the first failure and that gives away timing
|
---|
661 | // information.
|
---|
662 | fail |= *pm++ ^ *pe++;
|
---|
663 | retVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS;
|
---|
664 | Exit:
|
---|
665 | return retVal;
|
---|
666 | }
|
---|
667 | /* 10.2.17.4.16 MakeDerTag() */
|
---|
668 | /* Construct the DER value that is used in RSASSA */
|
---|
669 | /* Return Value Meaning */
|
---|
670 | /* > 0 size of value */
|
---|
671 | /* <= 0 no hash exists */
|
---|
672 | INT16
|
---|
673 | MakeDerTag(
|
---|
674 | TPM_ALG_ID hashAlg,
|
---|
675 | INT16 sizeOfBuffer,
|
---|
676 | BYTE *buffer
|
---|
677 | )
|
---|
678 | {
|
---|
679 | // 0x30, 0x31, // SEQUENCE (2 elements) 1st
|
---|
680 | // 0x30, 0x0D, // SEQUENCE (2 elements)
|
---|
681 | // 0x06, 0x09, // HASH OID
|
---|
682 | // 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
|
---|
683 | // 0x05, 0x00, // NULL
|
---|
684 | // 0x04, 0x20 // OCTET STRING
|
---|
685 | HASH_DEF *info = CryptGetHashDef(hashAlg);
|
---|
686 | INT16 oidSize;
|
---|
687 | // If no OID, can't do encode
|
---|
688 | VERIFY(info != NULL);
|
---|
689 | oidSize = 2 + (info->OID)[1];
|
---|
690 | // make sure this fits in the buffer
|
---|
691 | VERIFY(sizeOfBuffer >= (oidSize + 8));
|
---|
692 | *buffer++ = 0x30; // 1st SEQUENCE
|
---|
693 | // Size of the 1st SEQUENCE is 6 bytes + size of the hash OID + size of the
|
---|
694 | // digest size
|
---|
695 | *buffer++ = (BYTE)(6 + oidSize + info->digestSize); //
|
---|
696 | *buffer++ = 0x30; // 2nd SEQUENCE
|
---|
697 | // size is 4 bytes of overhead plus the side of the OID
|
---|
698 | *buffer++ = (BYTE)(2 + oidSize);
|
---|
699 | MemoryCopy(buffer, info->OID, oidSize);
|
---|
700 | buffer += oidSize;
|
---|
701 | *buffer++ = 0x05; // Add a NULL
|
---|
702 | *buffer++ = 0x00;
|
---|
703 |
|
---|
704 | *buffer++ = 0x04;
|
---|
705 | *buffer++ = (BYTE)(info->digestSize);
|
---|
706 | return oidSize + 8;
|
---|
707 | Error:
|
---|
708 | return 0;
|
---|
709 |
|
---|
710 | }
|
---|
711 |
|
---|
712 | /* 10.2.17.4.17 RSASSA_Encode() */
|
---|
713 | /* Encode a message using PKCS1v1.5 method. */
|
---|
714 | /* Error Returns Meaning */
|
---|
715 | /* TPM_RC_SCHEME hashAlg is not a supported hash algorithm */
|
---|
716 | /* TPM_RC_SIZE eOutSize is not large enough */
|
---|
717 | /* TPM_RC_VALUE hInSize does not match the digest size of hashAlg */
|
---|
718 | static TPM_RC
|
---|
719 | RSASSA_Encode(
|
---|
720 | TPM2B *pOut, // IN:OUT on in, the size of the public key
|
---|
721 | // on out, the encoded area
|
---|
722 | TPM_ALG_ID hashAlg, // IN: hash algorithm for PKCS1v1_5
|
---|
723 | TPM2B *hIn // IN: digest value to encode
|
---|
724 | )
|
---|
725 | {
|
---|
726 | BYTE DER[20];
|
---|
727 | BYTE *der = DER;
|
---|
728 | INT32 derSize = MakeDerTag(hashAlg, sizeof(DER), DER);
|
---|
729 | BYTE *eOut;
|
---|
730 | INT32 fillSize;
|
---|
731 | TPM_RC retVal = TPM_RC_SUCCESS;
|
---|
732 |
|
---|
733 | // Can't use this scheme if the algorithm doesn't have a DER string defined.
|
---|
734 | if(derSize == 0)
|
---|
735 | ERROR_RETURN(TPM_RC_SCHEME);
|
---|
736 |
|
---|
737 | // If the digest size of 'hashAl' doesn't match the input digest size, then
|
---|
738 | // the DER will misidentify the digest so return an error
|
---|
739 | if(CryptHashGetDigestSize(hashAlg) != hIn->size)
|
---|
740 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
741 | fillSize = pOut->size - derSize - hIn->size - 3;
|
---|
742 | eOut = pOut->buffer;
|
---|
743 |
|
---|
744 | // Make sure that this combination will fit in the provided space
|
---|
745 | if(fillSize < 8)
|
---|
746 | ERROR_RETURN(TPM_RC_SIZE);
|
---|
747 |
|
---|
748 | // Start filling
|
---|
749 | *eOut++ = 0; // initial byte of zero
|
---|
750 | *eOut++ = 1; // byte of 0x01
|
---|
751 | for(; fillSize > 0; fillSize--)
|
---|
752 | *eOut++ = 0xff; // bunch of 0xff
|
---|
753 | *eOut++ = 0; // another 0
|
---|
754 | for(; derSize > 0; derSize--)
|
---|
755 | *eOut++ = *der++; // copy the DER
|
---|
756 | der = hIn->buffer;
|
---|
757 | for(fillSize = hIn->size; fillSize > 0; fillSize--)
|
---|
758 | *eOut++ = *der++; // copy the hash
|
---|
759 | Exit:
|
---|
760 | return retVal;
|
---|
761 | }
|
---|
762 |
|
---|
763 | /* 10.2.17.4.18 RSASSA_Decode() */
|
---|
764 | /* This function performs the RSASSA decoding of a signature. */
|
---|
765 | /* Error Returns Meaning */
|
---|
766 | /* TPM_RC_VALUE decode unsuccessful */
|
---|
767 | /* TPM_RC_SCHEME haslAlg is not supported */
|
---|
768 | static TPM_RC
|
---|
769 | RSASSA_Decode(
|
---|
770 | TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding
|
---|
771 | TPM2B *hIn, // In: the digest to compare
|
---|
772 | TPM2B *eIn // IN: the encoded data
|
---|
773 | )
|
---|
774 | {
|
---|
775 | BYTE fail;
|
---|
776 | BYTE DER[20];
|
---|
777 | BYTE *der = DER;
|
---|
778 | INT32 derSize = MakeDerTag(hashAlg, sizeof(DER), DER);
|
---|
779 | BYTE *pe;
|
---|
780 | INT32 hashSize = CryptHashGetDigestSize(hashAlg);
|
---|
781 | INT32 fillSize;
|
---|
782 | TPM_RC retVal;
|
---|
783 | BYTE *digest;
|
---|
784 | UINT16 digestSize;
|
---|
785 |
|
---|
786 | pAssert(hIn != NULL && eIn != NULL);
|
---|
787 | pe = eIn->buffer;
|
---|
788 |
|
---|
789 | // Can't use this scheme if the algorithm doesn't have a DER string
|
---|
790 | // defined or if the provided hash isn't the right size
|
---|
791 | if(derSize == 0 || (unsigned)hashSize != hIn->size)
|
---|
792 | ERROR_RETURN(TPM_RC_SCHEME);
|
---|
793 |
|
---|
794 | // Make sure that this combination will fit in the provided space
|
---|
795 | // Since no data movement takes place, can just walk though this
|
---|
796 | // and accept nearly random values. This can only be called from
|
---|
797 | // CryptValidateSignature() so eInSize is known to be in range.
|
---|
798 | fillSize = eIn->size - derSize - hashSize - 3;
|
---|
799 |
|
---|
800 | // Start checking (fail will become non-zero if any of the bytes do not have
|
---|
801 | // the expected value.
|
---|
802 | fail = *pe++; // initial byte of zero
|
---|
803 | fail |= *pe++ ^ 1; // byte of 0x01
|
---|
804 | for(; fillSize > 0; fillSize--)
|
---|
805 | fail |= *pe++ ^ 0xff; // bunch of 0xff
|
---|
806 | fail |= *pe++; // another 0
|
---|
807 | for(; derSize > 0; derSize--)
|
---|
808 | fail |= *pe++ ^ *der++; // match the DER
|
---|
809 | digestSize = hIn->size;
|
---|
810 | digest = hIn->buffer;
|
---|
811 | for(; digestSize > 0; digestSize--)
|
---|
812 | fail |= *pe++ ^ *digest++; // match the hash
|
---|
813 | retVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS;
|
---|
814 | Exit:
|
---|
815 | return retVal;
|
---|
816 | }
|
---|
817 | #endif // libtpms added
|
---|
818 |
|
---|
819 | /* 10.2.17.4.13 CryptRsaSelectScheme() */
|
---|
820 | /* This function is used by TPM2_RSA_Decrypt() and TPM2_RSA_Encrypt(). It sets up the rules to
|
---|
821 | select a scheme between input and object default. This function assume the RSA object is
|
---|
822 | loaded. If a default scheme is defined in object, the default scheme should be chosen, otherwise,
|
---|
823 | the input scheme should be chosen. In the case that both the object and scheme are not
|
---|
824 | TPM_ALG_NULL, then if the schemes are the same, the input scheme will be chosen. if the scheme
|
---|
825 | are not compatible, a NULL pointer will be returned. */
|
---|
826 | /* The return pointer may point to a TPM_ALG_NULL scheme. */
|
---|
827 | TPMT_RSA_DECRYPT*
|
---|
828 | CryptRsaSelectScheme(
|
---|
829 | TPMI_DH_OBJECT rsaHandle, // IN: handle of an RSA key
|
---|
830 | TPMT_RSA_DECRYPT *scheme // IN: a sign or decrypt scheme
|
---|
831 | )
|
---|
832 | {
|
---|
833 | OBJECT *rsaObject;
|
---|
834 | TPMT_ASYM_SCHEME *keyScheme;
|
---|
835 | TPMT_RSA_DECRYPT *retVal = NULL;
|
---|
836 | // Get sign object pointer
|
---|
837 | rsaObject = HandleToObject(rsaHandle);
|
---|
838 | keyScheme = &rsaObject->publicArea.parameters.asymDetail.scheme;
|
---|
839 | // if the default scheme of the object is TPM_ALG_NULL, then select the
|
---|
840 | // input scheme
|
---|
841 | if(keyScheme->scheme == TPM_ALG_NULL)
|
---|
842 | {
|
---|
843 | retVal = scheme;
|
---|
844 | }
|
---|
845 | // if the object scheme is not TPM_ALG_NULL and the input scheme is
|
---|
846 | // TPM_ALG_NULL, then select the default scheme of the object.
|
---|
847 | else if(scheme->scheme == TPM_ALG_NULL)
|
---|
848 | {
|
---|
849 | // if input scheme is NULL
|
---|
850 | retVal = (TPMT_RSA_DECRYPT *)keyScheme;
|
---|
851 | }
|
---|
852 | // get here if both the object scheme and the input scheme are
|
---|
853 | // not TPM_ALG_NULL. Need to insure that they are the same.
|
---|
854 | // IMPLEMENTATION NOTE: This could cause problems if future versions have
|
---|
855 | // schemes that have more values than just a hash algorithm. A new function
|
---|
856 | // (IsSchemeSame()) might be needed then.
|
---|
857 | else if(keyScheme->scheme == scheme->scheme
|
---|
858 | && keyScheme->details.anySig.hashAlg == scheme->details.anySig.hashAlg)
|
---|
859 | {
|
---|
860 | retVal = scheme;
|
---|
861 | }
|
---|
862 | // two different, incompatible schemes specified will return NULL
|
---|
863 | return retVal;
|
---|
864 | }
|
---|
865 | /* 10.2.17.4.14 CryptRsaLoadPrivateExponent() */
|
---|
866 | /* Error Returns Meaning */
|
---|
867 | /* TPM_RC_BINDING public and private parts of rsaKey are not matched */
|
---|
868 | TPM_RC
|
---|
869 | CryptRsaLoadPrivateExponent(
|
---|
870 | OBJECT *rsaKey // IN: the RSA key object
|
---|
871 | )
|
---|
872 | {
|
---|
873 | BN_RSA_INITIALIZED(bnN, &rsaKey->publicArea.unique.rsa);
|
---|
874 | BN_PRIME_INITIALIZED(bnP, &rsaKey->sensitive.sensitive.rsa);
|
---|
875 | BN_RSA(bnQ);
|
---|
876 | BN_PRIME(bnQr);
|
---|
877 | BN_WORD_INITIALIZED(bnE, (rsaKey->publicArea.parameters.rsaDetail.exponent == 0)
|
---|
878 | ? RSA_DEFAULT_PUBLIC_EXPONENT
|
---|
879 | : rsaKey->publicArea.parameters.rsaDetail.exponent);
|
---|
880 | TPM_RC retVal = TPM_RC_SUCCESS;
|
---|
881 | if(!rsaKey->attributes.privateExp)
|
---|
882 | {
|
---|
883 | TEST(TPM_ALG_NULL);
|
---|
884 | // Make sure that the bigNum used for the exponent is properly initialized
|
---|
885 | RsaInitializeExponent(&rsaKey->privateExponent);
|
---|
886 | // Find the second prime by division
|
---|
887 | BnDiv(bnQ, bnQr, bnN, bnP);
|
---|
888 | if(!BnEqualZero(bnQr))
|
---|
889 | ERROR_RETURN(TPM_RC_BINDING);
|
---|
890 | // Compute the private exponent and return it if found
|
---|
891 | if(!ComputePrivateExponent(bnP, bnQ, bnE, bnN,
|
---|
892 | &rsaKey->privateExponent))
|
---|
893 | ERROR_RETURN(TPM_RC_BINDING);
|
---|
894 | }
|
---|
895 | Exit:
|
---|
896 | rsaKey->attributes.privateExp = (retVal == TPM_RC_SUCCESS);
|
---|
897 | return retVal;
|
---|
898 | }
|
---|
899 | #if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added
|
---|
900 | /* 10.2.17.4.15 CryptRsaEncrypt() */
|
---|
901 | /* This is the entry point for encryption using RSA. Encryption is use of the public exponent. The
|
---|
902 | padding parameter determines what padding will be used. */
|
---|
903 | /* The cOutSize parameter must be at least as large as the size of the key. */
|
---|
904 | /* If the padding is RSA_PAD_NONE, dIn is treated as a number. It must be lower in value than the
|
---|
905 | key modulus. */
|
---|
906 | /* NOTE: If dIn has fewer bytes than cOut, then we don't add low-order zeros to dIn to make it the
|
---|
907 | size of the RSA key for the call to RSAEP. This is because the high order bytes of dIn might have
|
---|
908 | a numeric value that is greater than the value of the key modulus. If this had low-order zeros
|
---|
909 | added, it would have a numeric value larger than the modulus even though it started out with a
|
---|
910 | lower numeric value. */
|
---|
911 | /* Error Returns Meaning */
|
---|
912 | /* TPM_RC_VALUE cOutSize is too small (must be the size of the modulus) */
|
---|
913 | /* TPM_RC_SCHEME padType is not a supported scheme */
|
---|
914 | LIB_EXPORT TPM_RC
|
---|
915 | CryptRsaEncrypt(
|
---|
916 | TPM2B_PUBLIC_KEY_RSA *cOut, // OUT: the encrypted data
|
---|
917 | TPM2B *dIn, // IN: the data to encrypt
|
---|
918 | OBJECT *key, // IN: the key used for encryption
|
---|
919 | TPMT_RSA_DECRYPT *scheme, // IN: the type of padding and hash
|
---|
920 | // if needed
|
---|
921 | const TPM2B *label, // IN: in case it is needed
|
---|
922 | RAND_STATE *rand // IN: random number generator
|
---|
923 | // state (mostly for testing)
|
---|
924 | )
|
---|
925 | {
|
---|
926 | TPM_RC retVal = TPM_RC_SUCCESS;
|
---|
927 | TPM2B_PUBLIC_KEY_RSA dataIn;
|
---|
928 | //
|
---|
929 | // if the input and output buffers are the same, copy the input to a scratch
|
---|
930 | // buffer so that things don't get messed up.
|
---|
931 | if(dIn == &cOut->b)
|
---|
932 | {
|
---|
933 | MemoryCopy2B(&dataIn.b, dIn, sizeof(dataIn.t.buffer));
|
---|
934 | dIn = &dataIn.b;
|
---|
935 | }
|
---|
936 | // All encryption schemes return the same size of data
|
---|
937 | cOut->t.size = key->publicArea.unique.rsa.t.size;
|
---|
938 | TEST(scheme->scheme);
|
---|
939 | switch(scheme->scheme)
|
---|
940 | {
|
---|
941 | case TPM_ALG_NULL: // 'raw' encryption
|
---|
942 | {
|
---|
943 | INT32 i;
|
---|
944 | INT32 dSize = dIn->size;
|
---|
945 | // dIn can have more bytes than cOut as long as the extra bytes
|
---|
946 | // are zero. Note: the more significant bytes of a number in a byte
|
---|
947 | // buffer are the bytes at the start of the array.
|
---|
948 | for(i = 0; (i < dSize) && (dIn->buffer[i] == 0); i++);
|
---|
949 | dSize -= i;
|
---|
950 | if(dSize > cOut->t.size)
|
---|
951 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
952 | // Pad cOut with zeros if dIn is smaller
|
---|
953 | memset(cOut->t.buffer, 0, cOut->t.size - dSize);
|
---|
954 | // And copy the rest of the value
|
---|
955 | memcpy(&cOut->t.buffer[cOut->t.size - dSize], &dIn->buffer[i], dSize);
|
---|
956 | // If the size of dIn is the same as cOut dIn could be larger than
|
---|
957 | // the modulus. If it is, then RSAEP() will catch it.
|
---|
958 | }
|
---|
959 | break;
|
---|
960 | case TPM_ALG_RSAES:
|
---|
961 | retVal = RSAES_PKCS1v1_5Encode(&cOut->b, dIn, rand);
|
---|
962 | break;
|
---|
963 | case TPM_ALG_OAEP:
|
---|
964 | retVal = OaepEncode(&cOut->b, scheme->details.oaep.hashAlg, label, dIn,
|
---|
965 | rand);
|
---|
966 | break;
|
---|
967 | default:
|
---|
968 | ERROR_RETURN(TPM_RC_SCHEME);
|
---|
969 | break;
|
---|
970 | }
|
---|
971 | // All the schemes that do padding will come here for the encryption step
|
---|
972 | // Check that the Encoding worked
|
---|
973 | if(retVal == TPM_RC_SUCCESS)
|
---|
974 | // Padding OK so do the encryption
|
---|
975 | retVal = RSAEP(&cOut->b, key);
|
---|
976 | Exit:
|
---|
977 | return retVal;
|
---|
978 | }
|
---|
979 | /* 10.2.17.4.16 CryptRsaDecrypt() */
|
---|
980 | /* This is the entry point for decryption using RSA. Decryption is use of the private exponent. The
|
---|
981 | padType parameter determines what padding was used. */
|
---|
982 | /* Error Returns Meaning */
|
---|
983 | /* TPM_RC_SIZE cInSize is not the same as the size of the public modulus of key; or numeric value of
|
---|
984 | the encrypted data is greater than the modulus */
|
---|
985 | /* TPM_RC_VALUE dOutSize is not large enough for the result */
|
---|
986 | /* TPM_RC_SCHEME padType is not supported */
|
---|
987 | LIB_EXPORT TPM_RC
|
---|
988 | CryptRsaDecrypt(
|
---|
989 | TPM2B *dOut, // OUT: the decrypted data
|
---|
990 | TPM2B *cIn, // IN: the data to decrypt
|
---|
991 | OBJECT *key, // IN: the key to use for decryption
|
---|
992 | TPMT_RSA_DECRYPT *scheme, // IN: the padding scheme
|
---|
993 | const TPM2B *label // IN: in case it is needed for the scheme
|
---|
994 | )
|
---|
995 | {
|
---|
996 | TPM_RC retVal;
|
---|
997 | // Make sure that the necessary parameters are provided
|
---|
998 | pAssert(cIn != NULL && dOut != NULL && key != NULL);
|
---|
999 | // Size is checked to make sure that the encrypted value is the right size
|
---|
1000 | if(cIn->size != key->publicArea.unique.rsa.t.size)
|
---|
1001 | ERROR_RETURN(TPM_RC_SIZE);
|
---|
1002 | TEST(scheme->scheme);
|
---|
1003 | // For others that do padding, do the decryption in place and then
|
---|
1004 | // go handle the decoding.
|
---|
1005 | retVal = RSADP(cIn, key);
|
---|
1006 | if(retVal == TPM_RC_SUCCESS)
|
---|
1007 | {
|
---|
1008 | // Remove padding
|
---|
1009 | switch(scheme->scheme)
|
---|
1010 | {
|
---|
1011 | case TPM_ALG_NULL:
|
---|
1012 | if(dOut->size < cIn->size)
|
---|
1013 | return TPM_RC_VALUE;
|
---|
1014 | MemoryCopy2B(dOut, cIn, dOut->size);
|
---|
1015 | break;
|
---|
1016 | case TPM_ALG_RSAES:
|
---|
1017 | retVal = RSAES_Decode(dOut, cIn);
|
---|
1018 | break;
|
---|
1019 | case TPM_ALG_OAEP:
|
---|
1020 | retVal = OaepDecode(dOut, scheme->details.oaep.hashAlg, label, cIn);
|
---|
1021 | break;
|
---|
1022 | default:
|
---|
1023 | retVal = TPM_RC_SCHEME;
|
---|
1024 | break;
|
---|
1025 | }
|
---|
1026 | }
|
---|
1027 | Exit:
|
---|
1028 | return retVal;
|
---|
1029 | }
|
---|
1030 | /* 10.2.17.4.17 CryptRsaSign() */
|
---|
1031 | /* This function is used to generate an RSA signature of the type indicated in scheme. */
|
---|
1032 | /* Error Returns Meaning */
|
---|
1033 | /* TPM_RC_SCHEME scheme or hashAlg are not supported */
|
---|
1034 | /* TPM_RC_VALUE hInSize does not match hashAlg (for RSASSA) */
|
---|
1035 | LIB_EXPORT TPM_RC
|
---|
1036 | CryptRsaSign(
|
---|
1037 | TPMT_SIGNATURE *sigOut,
|
---|
1038 | OBJECT *key, // IN: key to use
|
---|
1039 | TPM2B_DIGEST *hIn, // IN: the digest to sign
|
---|
1040 | RAND_STATE *rand // IN: the random number generator
|
---|
1041 | // to use (mostly for testing)
|
---|
1042 | )
|
---|
1043 | {
|
---|
1044 | TPM_RC retVal = TPM_RC_SUCCESS;
|
---|
1045 | UINT16 modSize;
|
---|
1046 | // parameter checks
|
---|
1047 | pAssert(sigOut != NULL && key != NULL && hIn != NULL);
|
---|
1048 | modSize = key->publicArea.unique.rsa.t.size;
|
---|
1049 | // for all non-null signatures, the size is the size of the key modulus
|
---|
1050 | sigOut->signature.rsapss.sig.t.size = modSize;
|
---|
1051 | TEST(sigOut->sigAlg);
|
---|
1052 | switch(sigOut->sigAlg)
|
---|
1053 | {
|
---|
1054 | case TPM_ALG_NULL:
|
---|
1055 | sigOut->signature.rsapss.sig.t.size = 0;
|
---|
1056 | return TPM_RC_SUCCESS;
|
---|
1057 | case TPM_ALG_RSAPSS:
|
---|
1058 | retVal = PssEncode(&sigOut->signature.rsapss.sig.b,
|
---|
1059 | sigOut->signature.rsapss.hash, &hIn->b, rand);
|
---|
1060 | break;
|
---|
1061 | case TPM_ALG_RSASSA:
|
---|
1062 | retVal = RSASSA_Encode(&sigOut->signature.rsassa.sig.b,
|
---|
1063 | sigOut->signature.rsassa.hash, &hIn->b);
|
---|
1064 | break;
|
---|
1065 | default:
|
---|
1066 | retVal = TPM_RC_SCHEME;
|
---|
1067 | }
|
---|
1068 | if(retVal == TPM_RC_SUCCESS)
|
---|
1069 | {
|
---|
1070 | // Do the encryption using the private key
|
---|
1071 | retVal = RSADP(&sigOut->signature.rsapss.sig.b, key);
|
---|
1072 | }
|
---|
1073 | return retVal;
|
---|
1074 | }
|
---|
1075 | /* 10.2.17.4.18 CryptRsaValidateSignature() */
|
---|
1076 | /* This function is used to validate an RSA signature. If the signature is valid TPM_RC_SUCCESS is
|
---|
1077 | returned. If the signature is not valid, TPM_RC_SIGNATURE is returned. Other return codes
|
---|
1078 | indicate either parameter problems or fatal errors. */
|
---|
1079 | /* Error Returns Meaning */
|
---|
1080 | /* TPM_RC_SIGNATURE the signature does not check */
|
---|
1081 | /* TPM_RC_SCHEME unsupported scheme or hash algorithm */
|
---|
1082 | LIB_EXPORT TPM_RC
|
---|
1083 | CryptRsaValidateSignature(
|
---|
1084 | TPMT_SIGNATURE *sig, // IN: signature
|
---|
1085 | OBJECT *key, // IN: public modulus
|
---|
1086 | TPM2B_DIGEST *digest // IN: The digest being validated
|
---|
1087 | )
|
---|
1088 | {
|
---|
1089 | TPM_RC retVal;
|
---|
1090 | //
|
---|
1091 | // Fatal programming errors
|
---|
1092 | pAssert(key != NULL && sig != NULL && digest != NULL);
|
---|
1093 | switch(sig->sigAlg)
|
---|
1094 | {
|
---|
1095 | case TPM_ALG_RSAPSS:
|
---|
1096 | case TPM_ALG_RSASSA:
|
---|
1097 | break;
|
---|
1098 | default:
|
---|
1099 | return TPM_RC_SCHEME;
|
---|
1100 | }
|
---|
1101 | // Errors that might be caused by calling parameters
|
---|
1102 | if(sig->signature.rsassa.sig.t.size != key->publicArea.unique.rsa.t.size)
|
---|
1103 | ERROR_RETURN(TPM_RC_SIGNATURE);
|
---|
1104 | TEST(sig->sigAlg);
|
---|
1105 | // Decrypt the block
|
---|
1106 | retVal = RSAEP(&sig->signature.rsassa.sig.b, key);
|
---|
1107 | if(retVal == TPM_RC_SUCCESS)
|
---|
1108 | {
|
---|
1109 | switch(sig->sigAlg)
|
---|
1110 | {
|
---|
1111 | case TPM_ALG_RSAPSS:
|
---|
1112 | retVal = PssDecode(sig->signature.any.hashAlg, &digest->b,
|
---|
1113 | &sig->signature.rsassa.sig.b);
|
---|
1114 | break;
|
---|
1115 | case TPM_ALG_RSASSA:
|
---|
1116 | retVal = RSASSA_Decode(sig->signature.any.hashAlg, &digest->b,
|
---|
1117 | &sig->signature.rsassa.sig.b);
|
---|
1118 | break;
|
---|
1119 | default:
|
---|
1120 | return TPM_RC_SCHEME;
|
---|
1121 | }
|
---|
1122 | }
|
---|
1123 | Exit:
|
---|
1124 | return (retVal != TPM_RC_SUCCESS) ? TPM_RC_SIGNATURE : TPM_RC_SUCCESS;
|
---|
1125 | }
|
---|
1126 | #endif // libtpms added
|
---|
1127 | #if SIMULATION && USE_RSA_KEY_CACHE
|
---|
1128 | extern int s_rsaKeyCacheEnabled;
|
---|
1129 | int GetCachedRsaKey(OBJECT *key, RAND_STATE *rand);
|
---|
1130 | #define GET_CACHED_KEY(key, rand) \
|
---|
1131 | (s_rsaKeyCacheEnabled && GetCachedRsaKey(key, rand))
|
---|
1132 | #else
|
---|
1133 | #define GET_CACHED_KEY(key, rand)
|
---|
1134 | #endif
|
---|
1135 | /* 10.2.17.4.19 CryptRsaGenerateKey() */
|
---|
1136 | /* Generate an RSA key from a provided seed */
|
---|
1137 | /* Error Returns Meaning */
|
---|
1138 | /* TPM_RC_CANCELED operation was canceled */
|
---|
1139 | /* TPM_RC_RANGE public exponent is not supported */
|
---|
1140 | /* TPM_RC_VALUE could not find a prime using the provided parameters */
|
---|
1141 | LIB_EXPORT TPM_RC
|
---|
1142 | CryptRsaGenerateKey(
|
---|
1143 | OBJECT *rsaKey, // IN/OUT: The object structure in which
|
---|
1144 | // the key is created.
|
---|
1145 | RAND_STATE *rand // IN: if not NULL, the deterministic
|
---|
1146 | // RNG state
|
---|
1147 | )
|
---|
1148 | {
|
---|
1149 | UINT32 i;
|
---|
1150 | BN_PRIME(bnP); // These four declarations initialize the number to 0
|
---|
1151 | BN_PRIME(bnQ);
|
---|
1152 | BN_RSA(bnD);
|
---|
1153 | BN_RSA(bnN);
|
---|
1154 | BN_WORD(bnE);
|
---|
1155 | UINT32 e;
|
---|
1156 | int keySizeInBits;
|
---|
1157 | TPMT_PUBLIC *publicArea = &rsaKey->publicArea;
|
---|
1158 | TPMT_SENSITIVE *sensitive = &rsaKey->sensitive;
|
---|
1159 | TPM_RC retVal = TPM_RC_NO_RESULT;
|
---|
1160 | //
|
---|
1161 | // Need to make sure that the caller did not specify an exponent that is
|
---|
1162 | // not supported
|
---|
1163 | e = publicArea->parameters.rsaDetail.exponent;
|
---|
1164 | if(e == 0)
|
---|
1165 | e = RSA_DEFAULT_PUBLIC_EXPONENT;
|
---|
1166 | if(e < 65537)
|
---|
1167 | ERROR_RETURN(TPM_RC_RANGE);
|
---|
1168 | if(e != RSA_DEFAULT_PUBLIC_EXPONENT && !IsPrimeInt(e))
|
---|
1169 | ERROR_RETURN(TPM_RC_RANGE);
|
---|
1170 | BnSetWord(bnE, e);
|
---|
1171 | // Check that e is prime
|
---|
1172 | // check for supported key size.
|
---|
1173 | keySizeInBits = publicArea->parameters.rsaDetail.keyBits;
|
---|
1174 | if(((keySizeInBits % 1024) != 0)
|
---|
1175 | || (keySizeInBits > MAX_RSA_KEY_BITS) // this might be redundant, but...
|
---|
1176 | || (keySizeInBits == 0))
|
---|
1177 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
1178 | // Set the prime size for instrumentation purposes
|
---|
1179 | INSTRUMENT_SET(PrimeIndex, PRIME_INDEX(keySizeInBits / 2));
|
---|
1180 | #if SIMULATION && USE_RSA_KEY_CACHE
|
---|
1181 | if(GET_CACHED_KEY(rsaKey, rand))
|
---|
1182 | return TPM_RC_SUCCESS;
|
---|
1183 | #endif
|
---|
1184 | // Make sure that key generation has been tested
|
---|
1185 | TEST(TPM_ALG_NULL);
|
---|
1186 | #if USE_OPENSSL_FUNCTIONS_RSA // libtpms added begin
|
---|
1187 | if (rand == NULL)
|
---|
1188 | return OpenSSLCryptRsaGenerateKey(rsaKey, e, keySizeInBits);
|
---|
1189 | #endif // libtpms added end
|
---|
1190 | // Need to initialize the privateExponent structure
|
---|
1191 | RsaInitializeExponent(&rsaKey->privateExponent);
|
---|
1192 | // The prime is computed in P. When a new prime is found, Q is checked to
|
---|
1193 | // see if it is zero. If so, P is copied to Q and a new P is found.
|
---|
1194 | // When both P and Q are non-zero, the modulus and
|
---|
1195 | // private exponent are computed and a trial encryption/decryption is
|
---|
1196 | // performed. If the encrypt/decrypt fails, assume that at least one of the
|
---|
1197 | // primes is composite. Since we don't know which one, set Q to zero and start
|
---|
1198 | // over and find a new pair of primes.
|
---|
1199 | for(i = 1; (retVal != TPM_RC_SUCCESS) && (i != 100); i++)
|
---|
1200 | {
|
---|
1201 | if(_plat__IsCanceled())
|
---|
1202 | ERROR_RETURN(TPM_RC_CANCELED);
|
---|
1203 | BnGeneratePrimeForRSA(bnP, keySizeInBits / 2, e, rand);
|
---|
1204 | INSTRUMENT_INC(PrimeCounts[PrimeIndex]);
|
---|
1205 | // If this is the second prime, make sure that it differs from the
|
---|
1206 | // first prime by at least 2^100
|
---|
1207 | if(BnEqualZero(bnQ))
|
---|
1208 | {
|
---|
1209 | // copy p to q and compute another prime in p
|
---|
1210 | BnCopy(bnQ, bnP);
|
---|
1211 | continue;
|
---|
1212 | }
|
---|
1213 | // Make sure that the difference is at least 100 bits. Need to do it this
|
---|
1214 | // way because the big numbers are only positive values
|
---|
1215 | if(BnUnsignedCmp(bnP, bnQ) < 0)
|
---|
1216 | BnSub(bnD, bnQ, bnP);
|
---|
1217 | else
|
---|
1218 | BnSub(bnD, bnP, bnQ);
|
---|
1219 | if(BnMsb(bnD) < 100)
|
---|
1220 | continue;
|
---|
1221 | //Form the public modulus and set the unique value
|
---|
1222 | BnMult(bnN, bnP, bnQ);
|
---|
1223 | BnTo2B(bnN, &publicArea->unique.rsa.b,
|
---|
1224 | (NUMBYTES)BITS_TO_BYTES(keySizeInBits));
|
---|
1225 | // And the prime to the sensitive area
|
---|
1226 | BnTo2B(bnP, &sensitive->sensitive.rsa.b,
|
---|
1227 | (NUMBYTES)BITS_TO_BYTES(keySizeInBits) / 2);
|
---|
1228 | // Make sure everything came out right. The MSb of the values must be
|
---|
1229 | // one
|
---|
1230 | if(((publicArea->unique.rsa.t.buffer[0] & 0x80) == 0)
|
---|
1231 | || ((sensitive->sensitive.rsa.t.buffer[0] & 0x80) == 0))
|
---|
1232 | FAIL(FATAL_ERROR_INTERNAL);
|
---|
1233 | // Make sure that we can form the private exponent values
|
---|
1234 | if(ComputePrivateExponent(bnP, bnQ, bnE, bnN, &rsaKey->privateExponent)
|
---|
1235 | != TRUE)
|
---|
1236 | {
|
---|
1237 | // If ComputePrivateExponent could not find an inverse for
|
---|
1238 | // Q, then copy P and recompute P. This might
|
---|
1239 | // cause both to be recomputed if P is also zero
|
---|
1240 | if(BnEqualZero(bnQ))
|
---|
1241 | BnCopy(bnQ, bnP);
|
---|
1242 | continue;
|
---|
1243 | }
|
---|
1244 | retVal = TPM_RC_SUCCESS;
|
---|
1245 | // Do a trial encryption decryption if this is a signing key
|
---|
1246 | if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
|
---|
1247 | {
|
---|
1248 | BN_RSA(temp1);
|
---|
1249 | BN_RSA(temp2);
|
---|
1250 | BnGenerateRandomInRange(temp1, bnN, rand);
|
---|
1251 | // Encrypt with public exponent...
|
---|
1252 | BnModExp(temp2, temp1, bnE, bnN);
|
---|
1253 | // ... then decrypt with private exponent
|
---|
1254 | RsaPrivateKeyOp(temp2, bnN, bnP, &rsaKey->privateExponent);
|
---|
1255 | // If the starting and ending values are not the same,
|
---|
1256 | // start over )-;
|
---|
1257 | if(BnUnsignedCmp(temp2, temp1) != 0)
|
---|
1258 | {
|
---|
1259 | BnSetWord(bnQ, 0);
|
---|
1260 | retVal = TPM_RC_NO_RESULT;
|
---|
1261 | }
|
---|
1262 | }
|
---|
1263 | }
|
---|
1264 | Exit:
|
---|
1265 | if(retVal == TPM_RC_SUCCESS)
|
---|
1266 | rsaKey->attributes.privateExp = SET;
|
---|
1267 | return retVal;
|
---|
1268 | }
|
---|
1269 |
|
---|
1270 | #if USE_OPENSSL_FUNCTIONS_RSA // libtpms added begin
|
---|
1271 | LIB_EXPORT TPM_RC
|
---|
1272 | CryptRsaEncrypt(
|
---|
1273 | TPM2B_PUBLIC_KEY_RSA *cOut, // OUT: the encrypted data
|
---|
1274 | TPM2B *dIn, // IN: the data to encrypt
|
---|
1275 | OBJECT *key, // IN: the key used for encryption
|
---|
1276 | TPMT_RSA_DECRYPT *scheme, // IN: the type of padding and hash
|
---|
1277 | // if needed
|
---|
1278 | const TPM2B *label, // IN: in case it is needed
|
---|
1279 | RAND_STATE *rand // IN: random number generator
|
---|
1280 | // state (mostly for testing)
|
---|
1281 | )
|
---|
1282 | {
|
---|
1283 | TPM_RC retVal;
|
---|
1284 | TPM2B_PUBLIC_KEY_RSA dataIn;
|
---|
1285 | TPM2B_PUBLIC_KEY_RSA scratch;
|
---|
1286 | size_t outlen;
|
---|
1287 | EVP_PKEY *pkey = NULL;
|
---|
1288 | EVP_PKEY_CTX *ctx = NULL;
|
---|
1289 | const EVP_MD *md;
|
---|
1290 | const char *digestname;
|
---|
1291 | unsigned char *tmp = NULL;
|
---|
1292 | //
|
---|
1293 | // if the input and output buffers are the same, copy the input to a scratch
|
---|
1294 | // buffer so that things don't get messed up.
|
---|
1295 | if(dIn == &cOut->b)
|
---|
1296 | {
|
---|
1297 | MemoryCopy2B(&dataIn.b, dIn, sizeof(dataIn.t.buffer));
|
---|
1298 | dIn = &dataIn.b;
|
---|
1299 | }
|
---|
1300 | // All encryption schemes return the same size of data
|
---|
1301 | pAssert(sizeof(cOut->t.buffer) >= key->publicArea.unique.rsa.t.size);
|
---|
1302 | cOut->t.size = key->publicArea.unique.rsa.t.size;
|
---|
1303 | TEST(scheme->scheme);
|
---|
1304 |
|
---|
1305 | retVal = InitOpenSSLRSAPublicKey(key, &pkey);
|
---|
1306 | if (retVal != TPM_RC_SUCCESS)
|
---|
1307 | return retVal;
|
---|
1308 |
|
---|
1309 | ctx = EVP_PKEY_CTX_new(pkey, NULL);
|
---|
1310 | if (ctx == NULL ||
|
---|
1311 | EVP_PKEY_encrypt_init(ctx) <= 0)
|
---|
1312 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1313 |
|
---|
1314 | switch(scheme->scheme)
|
---|
1315 | {
|
---|
1316 | case TPM_ALG_NULL: // 'raw' encryption
|
---|
1317 | {
|
---|
1318 | INT32 i;
|
---|
1319 | INT32 dSize = dIn->size;
|
---|
1320 | // dIn can have more bytes than cOut as long as the extra bytes
|
---|
1321 | // are zero. Note: the more significant bytes of a number in a byte
|
---|
1322 | // buffer are the bytes at the start of the array.
|
---|
1323 | for(i = 0; (i < dSize) && (dIn->buffer[i] == 0); i++);
|
---|
1324 | dSize -= i;
|
---|
1325 | scratch.t.size = cOut->t.size;
|
---|
1326 | pAssert(scratch.t.size <= sizeof(scratch.t.buffer));
|
---|
1327 | if(dSize > scratch.t.size)
|
---|
1328 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
1329 | // Pad cOut with zeros if dIn is smaller
|
---|
1330 | memset(scratch.t.buffer, 0, scratch.t.size - dSize);
|
---|
1331 | // And copy the rest of the value; value is then right-aligned
|
---|
1332 | memcpy(&scratch.t.buffer[scratch.t.size - dSize], &dIn->buffer[i], dSize);
|
---|
1333 |
|
---|
1334 | dIn = &scratch.b;
|
---|
1335 | }
|
---|
1336 | if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) <= 0)
|
---|
1337 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1338 | break;
|
---|
1339 | case TPM_ALG_RSAES:
|
---|
1340 | if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
|
---|
1341 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1342 | break;
|
---|
1343 | case TPM_ALG_OAEP:
|
---|
1344 | digestname = GetDigestNameByHashAlg(scheme->details.oaep.hashAlg);
|
---|
1345 | if (digestname == NULL)
|
---|
1346 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
1347 |
|
---|
1348 | md = EVP_get_digestbyname(digestname);
|
---|
1349 | if (md == NULL ||
|
---|
1350 | EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 ||
|
---|
1351 | EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0)
|
---|
1352 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1353 |
|
---|
1354 | if (label->size > 0) {
|
---|
1355 | tmp = malloc(label->size);
|
---|
1356 | if (tmp == NULL)
|
---|
1357 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1358 | memcpy(tmp, label->buffer, label->size);
|
---|
1359 | }
|
---|
1360 | // label->size == 0 is supported
|
---|
1361 | if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, tmp, label->size) <= 0)
|
---|
1362 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1363 | tmp = NULL;
|
---|
1364 | break;
|
---|
1365 | default:
|
---|
1366 | ERROR_RETURN(TPM_RC_SCHEME);
|
---|
1367 | break;
|
---|
1368 | }
|
---|
1369 |
|
---|
1370 | outlen = cOut->t.size;
|
---|
1371 |
|
---|
1372 | if (EVP_PKEY_encrypt(ctx, cOut->t.buffer, &outlen,
|
---|
1373 | dIn->buffer, dIn->size) <= 0)
|
---|
1374 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1375 |
|
---|
1376 | cOut->t.size = outlen;
|
---|
1377 |
|
---|
1378 | Exit:
|
---|
1379 | EVP_PKEY_free(pkey);
|
---|
1380 | EVP_PKEY_CTX_free(ctx);
|
---|
1381 | free(tmp);
|
---|
1382 |
|
---|
1383 | return retVal;
|
---|
1384 | }
|
---|
1385 |
|
---|
1386 | LIB_EXPORT TPM_RC
|
---|
1387 | CryptRsaDecrypt(
|
---|
1388 | TPM2B *dOut, // OUT: the decrypted data
|
---|
1389 | TPM2B *cIn, // IN: the data to decrypt
|
---|
1390 | OBJECT *key, // IN: the key to use for decryption
|
---|
1391 | TPMT_RSA_DECRYPT *scheme, // IN: the padding scheme
|
---|
1392 | const TPM2B *label // IN: in case it is needed for the scheme
|
---|
1393 | )
|
---|
1394 | {
|
---|
1395 | TPM_RC retVal;
|
---|
1396 | EVP_PKEY *pkey = NULL;
|
---|
1397 | EVP_PKEY_CTX *ctx = NULL;
|
---|
1398 | const EVP_MD *md = NULL;
|
---|
1399 | const char *digestname;
|
---|
1400 | size_t outlen;
|
---|
1401 | unsigned char *tmp = NULL;
|
---|
1402 | unsigned char buffer[MAX_RSA_KEY_BYTES];
|
---|
1403 |
|
---|
1404 | // Make sure that the necessary parameters are provided
|
---|
1405 | pAssert(cIn != NULL && dOut != NULL && key != NULL);
|
---|
1406 | // Size is checked to make sure that the encrypted value is the right size
|
---|
1407 | if(cIn->size != key->publicArea.unique.rsa.t.size)
|
---|
1408 | ERROR_RETURN(TPM_RC_SIZE);
|
---|
1409 | TEST(scheme->scheme);
|
---|
1410 |
|
---|
1411 | retVal = InitOpenSSLRSAPrivateKey(key, &pkey);
|
---|
1412 | if (retVal != TPM_RC_SUCCESS)
|
---|
1413 | return retVal;
|
---|
1414 |
|
---|
1415 | ctx = EVP_PKEY_CTX_new(pkey, NULL);
|
---|
1416 | if (ctx == NULL ||
|
---|
1417 | EVP_PKEY_decrypt_init(ctx) <= 0)
|
---|
1418 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1419 |
|
---|
1420 | switch(scheme->scheme)
|
---|
1421 | {
|
---|
1422 | case TPM_ALG_NULL: // 'raw' encryption
|
---|
1423 | if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) <= 0)
|
---|
1424 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1425 | break;
|
---|
1426 | case TPM_ALG_RSAES:
|
---|
1427 | if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
|
---|
1428 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1429 | break;
|
---|
1430 | case TPM_ALG_OAEP:
|
---|
1431 | digestname = GetDigestNameByHashAlg(scheme->details.oaep.hashAlg);
|
---|
1432 | if (digestname == NULL)
|
---|
1433 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
1434 |
|
---|
1435 | md = EVP_get_digestbyname(digestname);
|
---|
1436 | if (md == NULL ||
|
---|
1437 | EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 ||
|
---|
1438 | EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0)
|
---|
1439 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1440 |
|
---|
1441 | if (label->size > 0) {
|
---|
1442 | tmp = malloc(label->size);
|
---|
1443 | if (tmp == NULL)
|
---|
1444 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1445 | memcpy(tmp, label->buffer, label->size);
|
---|
1446 |
|
---|
1447 | if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, tmp, label->size) <= 0)
|
---|
1448 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1449 | tmp = NULL;
|
---|
1450 | }
|
---|
1451 | break;
|
---|
1452 | default:
|
---|
1453 | ERROR_RETURN(TPM_RC_SCHEME);
|
---|
1454 | break;
|
---|
1455 | }
|
---|
1456 |
|
---|
1457 | /* cannot use cOut->buffer */
|
---|
1458 | outlen = sizeof(buffer);
|
---|
1459 | if (EVP_PKEY_decrypt(ctx, buffer, &outlen,
|
---|
1460 | cIn->buffer, cIn->size) <= 0)
|
---|
1461 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1462 |
|
---|
1463 | if (outlen > dOut->size)
|
---|
1464 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1465 |
|
---|
1466 | memcpy(dOut->buffer, buffer, outlen);
|
---|
1467 | dOut->size = outlen;
|
---|
1468 |
|
---|
1469 | retVal = TPM_RC_SUCCESS;
|
---|
1470 |
|
---|
1471 | Exit:
|
---|
1472 | EVP_PKEY_free(pkey);
|
---|
1473 | EVP_PKEY_CTX_free(ctx);
|
---|
1474 | free(tmp);
|
---|
1475 |
|
---|
1476 | return retVal;
|
---|
1477 | }
|
---|
1478 |
|
---|
1479 | LIB_EXPORT TPM_RC
|
---|
1480 | CryptRsaSign(
|
---|
1481 | TPMT_SIGNATURE *sigOut,
|
---|
1482 | OBJECT *key, // IN: key to use
|
---|
1483 | TPM2B_DIGEST *hIn, // IN: the digest to sign
|
---|
1484 | RAND_STATE *rand // IN: the random number generator
|
---|
1485 | // to use (mostly for testing)
|
---|
1486 | )
|
---|
1487 | {
|
---|
1488 | TPM_RC retVal = TPM_RC_SUCCESS;
|
---|
1489 | UINT16 modSize;
|
---|
1490 | size_t outlen;
|
---|
1491 | int padding;
|
---|
1492 | EVP_PKEY *pkey = NULL;
|
---|
1493 | EVP_PKEY_CTX *ctx = NULL;
|
---|
1494 | const EVP_MD *md;
|
---|
1495 | const char *digestname;
|
---|
1496 | TPMI_ALG_HASH hashAlg;
|
---|
1497 |
|
---|
1498 | // parameter checks
|
---|
1499 | pAssert(sigOut != NULL && key != NULL && hIn != NULL);
|
---|
1500 | modSize = key->publicArea.unique.rsa.t.size;
|
---|
1501 | // for all non-null signatures, the size is the size of the key modulus
|
---|
1502 | sigOut->signature.rsapss.sig.t.size = modSize;
|
---|
1503 | TEST(sigOut->sigAlg);
|
---|
1504 |
|
---|
1505 | switch(sigOut->sigAlg)
|
---|
1506 | {
|
---|
1507 | case TPM_ALG_NULL:
|
---|
1508 | sigOut->signature.rsapss.sig.t.size = 0;
|
---|
1509 | return TPM_RC_SUCCESS;
|
---|
1510 | case TPM_ALG_RSAPSS:
|
---|
1511 | padding = RSA_PKCS1_PSS_PADDING;
|
---|
1512 | hashAlg = sigOut->signature.rsapss.hash;
|
---|
1513 | break;
|
---|
1514 | case TPM_ALG_RSASSA:
|
---|
1515 | padding = RSA_PKCS1_PADDING;
|
---|
1516 | hashAlg = sigOut->signature.rsassa.hash;
|
---|
1517 | break;
|
---|
1518 | default:
|
---|
1519 | ERROR_RETURN(TPM_RC_SCHEME);
|
---|
1520 | }
|
---|
1521 |
|
---|
1522 | digestname = GetDigestNameByHashAlg(hashAlg);
|
---|
1523 | if (digestname == NULL)
|
---|
1524 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
1525 |
|
---|
1526 | md = EVP_get_digestbyname(digestname);
|
---|
1527 | if (md == NULL)
|
---|
1528 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1529 |
|
---|
1530 | retVal = InitOpenSSLRSAPrivateKey(key, &pkey);
|
---|
1531 | if (retVal != TPM_RC_SUCCESS)
|
---|
1532 | return retVal;
|
---|
1533 |
|
---|
1534 | ctx = EVP_PKEY_CTX_new(pkey, NULL);
|
---|
1535 | if (ctx == NULL ||
|
---|
1536 | EVP_PKEY_sign_init(ctx) <= 0)
|
---|
1537 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1538 |
|
---|
1539 | if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
|
---|
1540 | EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0)
|
---|
1541 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1542 |
|
---|
1543 | /* careful with PSS padding: Use salt length = hash length (-1) if
|
---|
1544 | * length(digest) + length(hash-to-sign) + 2 <= modSize
|
---|
1545 | * otherwise use the max. possible salt length, which is the default (-2)
|
---|
1546 | * test case: 1024 bit key PSS signing sha512 hash
|
---|
1547 | */
|
---|
1548 | if (padding == RSA_PKCS1_PSS_PADDING &&
|
---|
1549 | EVP_MD_size(md) + hIn->b.size + 2 <= modSize && /* OSSL: RSA_padding_add_PKCS1_PSS_mgf1 */
|
---|
1550 | EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0)
|
---|
1551 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1552 |
|
---|
1553 | outlen = sigOut->signature.rsapss.sig.t.size;
|
---|
1554 | if (EVP_PKEY_sign(ctx,
|
---|
1555 | sigOut->signature.rsapss.sig.t.buffer, &outlen,
|
---|
1556 | hIn->b.buffer, hIn->b.size) <= 0)
|
---|
1557 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1558 |
|
---|
1559 | sigOut->signature.rsapss.sig.t.size = outlen;
|
---|
1560 |
|
---|
1561 | Exit:
|
---|
1562 | EVP_PKEY_free(pkey);
|
---|
1563 | EVP_PKEY_CTX_free(ctx);
|
---|
1564 |
|
---|
1565 | return retVal;
|
---|
1566 | }
|
---|
1567 |
|
---|
1568 | LIB_EXPORT TPM_RC
|
---|
1569 | CryptRsaValidateSignature(
|
---|
1570 | TPMT_SIGNATURE *sig, // IN: signature
|
---|
1571 | OBJECT *key, // IN: public modulus
|
---|
1572 | TPM2B_DIGEST *digest // IN: The digest being validated
|
---|
1573 | )
|
---|
1574 | {
|
---|
1575 | TPM_RC retVal;
|
---|
1576 | int padding;
|
---|
1577 | EVP_PKEY *pkey = NULL;
|
---|
1578 | EVP_PKEY_CTX *ctx = NULL;
|
---|
1579 | const EVP_MD *md;
|
---|
1580 | const char *digestname;
|
---|
1581 |
|
---|
1582 | //
|
---|
1583 | // Fatal programming errors
|
---|
1584 | pAssert(key != NULL && sig != NULL && digest != NULL);
|
---|
1585 | switch(sig->sigAlg)
|
---|
1586 | {
|
---|
1587 | case TPM_ALG_RSAPSS:
|
---|
1588 | padding = RSA_PKCS1_PSS_PADDING;
|
---|
1589 | break;
|
---|
1590 | case TPM_ALG_RSASSA:
|
---|
1591 | padding = RSA_PKCS1_PADDING;
|
---|
1592 | break;
|
---|
1593 | default:
|
---|
1594 | return TPM_RC_SCHEME;
|
---|
1595 | }
|
---|
1596 | // Errors that might be caused by calling parameters
|
---|
1597 | if(sig->signature.rsassa.sig.t.size != key->publicArea.unique.rsa.t.size)
|
---|
1598 | ERROR_RETURN(TPM_RC_SIGNATURE);
|
---|
1599 | TEST(sig->sigAlg);
|
---|
1600 |
|
---|
1601 | retVal = InitOpenSSLRSAPublicKey(key, &pkey);
|
---|
1602 | if (retVal != TPM_RC_SUCCESS)
|
---|
1603 | return retVal;
|
---|
1604 |
|
---|
1605 | digestname = GetDigestNameByHashAlg(sig->signature.any.hashAlg);
|
---|
1606 | if (digestname == NULL)
|
---|
1607 | ERROR_RETURN(TPM_RC_VALUE);
|
---|
1608 |
|
---|
1609 | md = EVP_get_digestbyname(digestname);
|
---|
1610 | ctx = EVP_PKEY_CTX_new(pkey, NULL);
|
---|
1611 | if (md == NULL || ctx == NULL ||
|
---|
1612 | EVP_PKEY_verify_init(ctx) <= 0)
|
---|
1613 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1614 |
|
---|
1615 | if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
|
---|
1616 | EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0)
|
---|
1617 | ERROR_RETURN(TPM_RC_FAILURE);
|
---|
1618 |
|
---|
1619 | if (EVP_PKEY_verify(ctx,
|
---|
1620 | sig->signature.rsassa.sig.t.buffer, sig->signature.rsassa.sig.t.size,
|
---|
1621 | digest->t.buffer, digest->t.size) <= 0)
|
---|
1622 | ERROR_RETURN(TPM_RC_SIGNATURE);
|
---|
1623 |
|
---|
1624 | retVal = TPM_RC_SUCCESS;
|
---|
1625 |
|
---|
1626 | Exit:
|
---|
1627 | EVP_PKEY_free(pkey);
|
---|
1628 | EVP_PKEY_CTX_free(ctx);
|
---|
1629 |
|
---|
1630 | return (retVal != TPM_RC_SUCCESS) ? TPM_RC_SIGNATURE : TPM_RC_SUCCESS;
|
---|
1631 | }
|
---|
1632 | #endif // USE_OPENSSL_FUNCTIONS_RSA libtpms added end
|
---|
1633 |
|
---|
1634 | #endif // TPM_ALG_RSA
|
---|