1*5c591343SA. Cody Schuffelen /* Microsoft Reference Implementation for TPM 2.0
2*5c591343SA. Cody Schuffelen *
3*5c591343SA. Cody Schuffelen * The copyright in this software is being made available under the BSD License,
4*5c591343SA. Cody Schuffelen * included below. This software may be subject to other third party and
5*5c591343SA. Cody Schuffelen * contributor rights, including patent rights, and no such rights are granted
6*5c591343SA. Cody Schuffelen * under this license.
7*5c591343SA. Cody Schuffelen *
8*5c591343SA. Cody Schuffelen * Copyright (c) Microsoft Corporation
9*5c591343SA. Cody Schuffelen *
10*5c591343SA. Cody Schuffelen * All rights reserved.
11*5c591343SA. Cody Schuffelen *
12*5c591343SA. Cody Schuffelen * BSD License
13*5c591343SA. Cody Schuffelen *
14*5c591343SA. Cody Schuffelen * Redistribution and use in source and binary forms, with or without modification,
15*5c591343SA. Cody Schuffelen * are permitted provided that the following conditions are met:
16*5c591343SA. Cody Schuffelen *
17*5c591343SA. Cody Schuffelen * Redistributions of source code must retain the above copyright notice, this list
18*5c591343SA. Cody Schuffelen * of conditions and the following disclaimer.
19*5c591343SA. Cody Schuffelen *
20*5c591343SA. Cody Schuffelen * Redistributions in binary form must reproduce the above copyright notice, this
21*5c591343SA. Cody Schuffelen * list of conditions and the following disclaimer in the documentation and/or
22*5c591343SA. Cody Schuffelen * other materials provided with the distribution.
23*5c591343SA. Cody Schuffelen *
24*5c591343SA. Cody Schuffelen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25*5c591343SA. Cody Schuffelen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*5c591343SA. Cody Schuffelen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27*5c591343SA. Cody Schuffelen * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28*5c591343SA. Cody Schuffelen * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29*5c591343SA. Cody Schuffelen * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*5c591343SA. Cody Schuffelen * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31*5c591343SA. Cody Schuffelen * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*5c591343SA. Cody Schuffelen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*5c591343SA. Cody Schuffelen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*5c591343SA. Cody Schuffelen */
35*5c591343SA. Cody Schuffelen //** Introduction
36*5c591343SA. Cody Schuffelen // This file contains the functions to implement the RSA key cache that can be used
37*5c591343SA. Cody Schuffelen // to speed up simulation.
38*5c591343SA. Cody Schuffelen //
39*5c591343SA. Cody Schuffelen // Only one key is created for each supported key size and it is returned whenever
40*5c591343SA. Cody Schuffelen // a key of that size is requested.
41*5c591343SA. Cody Schuffelen //
42*5c591343SA. Cody Schuffelen // If desired, the key cache can be populated from a file. This allows multiple
43*5c591343SA. Cody Schuffelen // TPM to run with the same RSA keys. Also, when doing simulation, the DRBG will
44*5c591343SA. Cody Schuffelen // use preset sequences so it is not too hard to repeat sequences for debug or
45*5c591343SA. Cody Schuffelen // profile or stress.
46*5c591343SA. Cody Schuffelen //
47*5c591343SA. Cody Schuffelen // When the key cache is enabled, a call to CryptRsaGenerateKey() will call the
48*5c591343SA. Cody Schuffelen // GetCachedRsaKey(). If the cache is enabled and populated, then the cached key
49*5c591343SA. Cody Schuffelen // of the requested size is returned. If a key of the requested size is not
50*5c591343SA. Cody Schuffelen // available, the no key is loaded and the requested key will need to be generated.
51*5c591343SA. Cody Schuffelen // If the cache is not populated, the TPM will open a file that has the appropriate
52*5c591343SA. Cody Schuffelen // name for the type of keys required (CRT or no-CRT). If the file is the right
53*5c591343SA. Cody Schuffelen // size, it is used. If the file doesn't exist or the file does not have the correct
54*5c591343SA. Cody Schuffelen // size, the TMP will populate the cache with new keys of the required size and
55*5c591343SA. Cody Schuffelen // write the cache data to the file so that they will be available the next time.
56*5c591343SA. Cody Schuffelen //
57*5c591343SA. Cody Schuffelen // Currently, if two simulations are being run with TPM's that have different RSA
58*5c591343SA. Cody Schuffelen // key sizes (e.g,, one with 1024 and 2048 and another with 2048 and 3072, then the
59*5c591343SA. Cody Schuffelen // files will not match for the both of them and they will both try to overwrite
60*5c591343SA. Cody Schuffelen // the other's cache file. I may try to do something about this if necessary.
61*5c591343SA. Cody Schuffelen
62*5c591343SA. Cody Schuffelen //** Includes, Types, Locals, and Defines
63*5c591343SA. Cody Schuffelen
64*5c591343SA. Cody Schuffelen #include "Tpm.h"
65*5c591343SA. Cody Schuffelen
66*5c591343SA. Cody Schuffelen #if USE_RSA_KEY_CACHE
67*5c591343SA. Cody Schuffelen
68*5c591343SA. Cody Schuffelen #include <stdio.h>
69*5c591343SA. Cody Schuffelen #include "RsaKeyCache_fp.h"
70*5c591343SA. Cody Schuffelen
71*5c591343SA. Cody Schuffelen #if CRT_FORMAT_RSA == YES
72*5c591343SA. Cody Schuffelen #define CACHE_FILE_NAME "RsaKeyCacheCrt.data"
73*5c591343SA. Cody Schuffelen #else
74*5c591343SA. Cody Schuffelen #define CACHE_FILE_NAME "RsaKeyCacheNoCrt.data"
75*5c591343SA. Cody Schuffelen #endif
76*5c591343SA. Cody Schuffelen
77*5c591343SA. Cody Schuffelen typedef struct _RSA_KEY_CACHE_
78*5c591343SA. Cody Schuffelen {
79*5c591343SA. Cody Schuffelen TPM2B_PUBLIC_KEY_RSA publicModulus;
80*5c591343SA. Cody Schuffelen TPM2B_PRIVATE_KEY_RSA privateExponent;
81*5c591343SA. Cody Schuffelen } RSA_KEY_CACHE;
82*5c591343SA. Cody Schuffelen
83*5c591343SA. Cody Schuffelen // Determine the number of RSA key sizes for the cache
84*5c591343SA. Cody Schuffelen TPMI_RSA_KEY_BITS SupportedRsaKeySizes[] = {
85*5c591343SA. Cody Schuffelen #if RSA_1024
86*5c591343SA. Cody Schuffelen 1024,
87*5c591343SA. Cody Schuffelen #endif
88*5c591343SA. Cody Schuffelen #if RSA_2048
89*5c591343SA. Cody Schuffelen 2048,
90*5c591343SA. Cody Schuffelen #endif
91*5c591343SA. Cody Schuffelen #if RSA_3072
92*5c591343SA. Cody Schuffelen 3072,
93*5c591343SA. Cody Schuffelen #endif
94*5c591343SA. Cody Schuffelen #if RSA_4096
95*5c591343SA. Cody Schuffelen 4096,
96*5c591343SA. Cody Schuffelen #endif
97*5c591343SA. Cody Schuffelen 0
98*5c591343SA. Cody Schuffelen };
99*5c591343SA. Cody Schuffelen
100*5c591343SA. Cody Schuffelen #define RSA_KEY_CACHE_ENTRIES (RSA_1024 + RSA_2048 + RSA_3072 + RSA_4096)
101*5c591343SA. Cody Schuffelen
102*5c591343SA. Cody Schuffelen // The key cache holds one entry for each of the supported key sizes
103*5c591343SA. Cody Schuffelen RSA_KEY_CACHE s_rsaKeyCache[RSA_KEY_CACHE_ENTRIES];
104*5c591343SA. Cody Schuffelen // Indicates if the key cache is loaded. It can be loaded and enabled or disabled.
105*5c591343SA. Cody Schuffelen BOOL s_keyCacheLoaded = 0;
106*5c591343SA. Cody Schuffelen
107*5c591343SA. Cody Schuffelen // Indicates if the key cache is enabled
108*5c591343SA. Cody Schuffelen int s_rsaKeyCacheEnabled = FALSE;
109*5c591343SA. Cody Schuffelen
110*5c591343SA. Cody Schuffelen //*** RsaKeyCacheControl()
111*5c591343SA. Cody Schuffelen // Used to enable and disable the RSA key cache.
112*5c591343SA. Cody Schuffelen LIB_EXPORT void
RsaKeyCacheControl(int state)113*5c591343SA. Cody Schuffelen RsaKeyCacheControl(
114*5c591343SA. Cody Schuffelen int state
115*5c591343SA. Cody Schuffelen )
116*5c591343SA. Cody Schuffelen {
117*5c591343SA. Cody Schuffelen s_rsaKeyCacheEnabled = state;
118*5c591343SA. Cody Schuffelen }
119*5c591343SA. Cody Schuffelen
120*5c591343SA. Cody Schuffelen //*** InitializeKeyCache()
121*5c591343SA. Cody Schuffelen // This will initialize the key cache and attempt to write it to a file for later
122*5c591343SA. Cody Schuffelen // use.
123*5c591343SA. Cody Schuffelen // Return Type: BOOL
124*5c591343SA. Cody Schuffelen // TRUE(1) success
125*5c591343SA. Cody Schuffelen // FALSE(0) failure
126*5c591343SA. Cody Schuffelen static BOOL
InitializeKeyCache(TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,RAND_STATE * rand)127*5c591343SA. Cody Schuffelen InitializeKeyCache(
128*5c591343SA. Cody Schuffelen TPMT_PUBLIC *publicArea,
129*5c591343SA. Cody Schuffelen TPMT_SENSITIVE *sensitive,
130*5c591343SA. Cody Schuffelen RAND_STATE *rand // IN: if not NULL, the deterministic
131*5c591343SA. Cody Schuffelen // RNG state
132*5c591343SA. Cody Schuffelen )
133*5c591343SA. Cody Schuffelen {
134*5c591343SA. Cody Schuffelen int index;
135*5c591343SA. Cody Schuffelen TPM_KEY_BITS keySave = publicArea->parameters.rsaDetail.keyBits;
136*5c591343SA. Cody Schuffelen BOOL OK = TRUE;
137*5c591343SA. Cody Schuffelen //
138*5c591343SA. Cody Schuffelen s_rsaKeyCacheEnabled = FALSE;
139*5c591343SA. Cody Schuffelen for(index = 0; OK && index < RSA_KEY_CACHE_ENTRIES; index++)
140*5c591343SA. Cody Schuffelen {
141*5c591343SA. Cody Schuffelen publicArea->parameters.rsaDetail.keyBits
142*5c591343SA. Cody Schuffelen = SupportedRsaKeySizes[index];
143*5c591343SA. Cody Schuffelen OK = (CryptRsaGenerateKey(publicArea, sensitive, rand) == TPM_RC_SUCCESS);
144*5c591343SA. Cody Schuffelen if(OK)
145*5c591343SA. Cody Schuffelen {
146*5c591343SA. Cody Schuffelen s_rsaKeyCache[index].publicModulus = publicArea->unique.rsa;
147*5c591343SA. Cody Schuffelen s_rsaKeyCache[index].privateExponent = sensitive->sensitive.rsa;
148*5c591343SA. Cody Schuffelen }
149*5c591343SA. Cody Schuffelen }
150*5c591343SA. Cody Schuffelen publicArea->parameters.rsaDetail.keyBits = keySave;
151*5c591343SA. Cody Schuffelen s_keyCacheLoaded = OK;
152*5c591343SA. Cody Schuffelen #if SIMULATION && USE_RSA_KEY_CACHE && USE_KEY_CACHE_FILE
153*5c591343SA. Cody Schuffelen if(OK)
154*5c591343SA. Cody Schuffelen {
155*5c591343SA. Cody Schuffelen FILE *cacheFile;
156*5c591343SA. Cody Schuffelen const char *fn = CACHE_FILE_NAME;
157*5c591343SA. Cody Schuffelen
158*5c591343SA. Cody Schuffelen #if defined _MSC_VER
159*5c591343SA. Cody Schuffelen if(fopen_s(&cacheFile, fn, "w+b") != 0)
160*5c591343SA. Cody Schuffelen #else
161*5c591343SA. Cody Schuffelen cacheFile = fopen(fn, "w+b");
162*5c591343SA. Cody Schuffelen if(NULL == cacheFile)
163*5c591343SA. Cody Schuffelen #endif
164*5c591343SA. Cody Schuffelen {
165*5c591343SA. Cody Schuffelen printf("Can't open %s for write.\n", fn);
166*5c591343SA. Cody Schuffelen }
167*5c591343SA. Cody Schuffelen else
168*5c591343SA. Cody Schuffelen {
169*5c591343SA. Cody Schuffelen fseek(cacheFile, 0, SEEK_SET);
170*5c591343SA. Cody Schuffelen if(fwrite(s_rsaKeyCache, 1, sizeof(s_rsaKeyCache), cacheFile)
171*5c591343SA. Cody Schuffelen != sizeof(s_rsaKeyCache))
172*5c591343SA. Cody Schuffelen {
173*5c591343SA. Cody Schuffelen printf("Error writing cache to %s.", fn);
174*5c591343SA. Cody Schuffelen }
175*5c591343SA. Cody Schuffelen }
176*5c591343SA. Cody Schuffelen if(cacheFile)
177*5c591343SA. Cody Schuffelen fclose(cacheFile);
178*5c591343SA. Cody Schuffelen }
179*5c591343SA. Cody Schuffelen #endif
180*5c591343SA. Cody Schuffelen return s_keyCacheLoaded;
181*5c591343SA. Cody Schuffelen }
182*5c591343SA. Cody Schuffelen
183*5c591343SA. Cody Schuffelen //*** KeyCacheLoaded()
184*5c591343SA. Cody Schuffelen // Checks that key cache is loaded.
185*5c591343SA. Cody Schuffelen // Return Type: BOOL
186*5c591343SA. Cody Schuffelen // TRUE(1) cache loaded
187*5c591343SA. Cody Schuffelen // FALSE(0) cache not loaded
188*5c591343SA. Cody Schuffelen static BOOL
KeyCacheLoaded(TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,RAND_STATE * rand)189*5c591343SA. Cody Schuffelen KeyCacheLoaded(
190*5c591343SA. Cody Schuffelen TPMT_PUBLIC *publicArea,
191*5c591343SA. Cody Schuffelen TPMT_SENSITIVE *sensitive,
192*5c591343SA. Cody Schuffelen RAND_STATE *rand // IN: if not NULL, the deterministic
193*5c591343SA. Cody Schuffelen // RNG state
194*5c591343SA. Cody Schuffelen )
195*5c591343SA. Cody Schuffelen {
196*5c591343SA. Cody Schuffelen #if SIMULATION && USE_RSA_KEY_CACHE && USE_KEY_CACHE_FILE
197*5c591343SA. Cody Schuffelen if(!s_keyCacheLoaded)
198*5c591343SA. Cody Schuffelen {
199*5c591343SA. Cody Schuffelen FILE *cacheFile;
200*5c591343SA. Cody Schuffelen const char * fn = CACHE_FILE_NAME;
201*5c591343SA. Cody Schuffelen #if defined _MSC_VER && 1
202*5c591343SA. Cody Schuffelen if(fopen_s(&cacheFile, fn, "r+b") == 0)
203*5c591343SA. Cody Schuffelen #else
204*5c591343SA. Cody Schuffelen cacheFile = fopen(fn, "r+b");
205*5c591343SA. Cody Schuffelen if(NULL != cacheFile)
206*5c591343SA. Cody Schuffelen #endif
207*5c591343SA. Cody Schuffelen {
208*5c591343SA. Cody Schuffelen fseek(cacheFile, 0L, SEEK_END);
209*5c591343SA. Cody Schuffelen if(ftell(cacheFile) == sizeof(s_rsaKeyCache))
210*5c591343SA. Cody Schuffelen {
211*5c591343SA. Cody Schuffelen fseek(cacheFile, 0L, SEEK_SET);
212*5c591343SA. Cody Schuffelen s_keyCacheLoaded = (
213*5c591343SA. Cody Schuffelen fread(&s_rsaKeyCache, 1, sizeof(s_rsaKeyCache), cacheFile)
214*5c591343SA. Cody Schuffelen == sizeof(s_rsaKeyCache));
215*5c591343SA. Cody Schuffelen }
216*5c591343SA. Cody Schuffelen fclose(cacheFile);
217*5c591343SA. Cody Schuffelen }
218*5c591343SA. Cody Schuffelen }
219*5c591343SA. Cody Schuffelen #endif
220*5c591343SA. Cody Schuffelen if(!s_keyCacheLoaded)
221*5c591343SA. Cody Schuffelen s_rsaKeyCacheEnabled = InitializeKeyCache(publicArea, sensitive, rand);
222*5c591343SA. Cody Schuffelen return s_keyCacheLoaded;
223*5c591343SA. Cody Schuffelen }
224*5c591343SA. Cody Schuffelen
225*5c591343SA. Cody Schuffelen //*** GetCachedRsaKey()
226*5c591343SA. Cody Schuffelen // Return Type: BOOL
227*5c591343SA. Cody Schuffelen // TRUE(1) key loaded
228*5c591343SA. Cody Schuffelen // FALSE(0) key not loaded
229*5c591343SA. Cody Schuffelen BOOL
GetCachedRsaKey(TPMT_PUBLIC * publicArea,TPMT_SENSITIVE * sensitive,RAND_STATE * rand)230*5c591343SA. Cody Schuffelen GetCachedRsaKey(
231*5c591343SA. Cody Schuffelen TPMT_PUBLIC *publicArea,
232*5c591343SA. Cody Schuffelen TPMT_SENSITIVE *sensitive,
233*5c591343SA. Cody Schuffelen RAND_STATE *rand // IN: if not NULL, the deterministic
234*5c591343SA. Cody Schuffelen // RNG state
235*5c591343SA. Cody Schuffelen )
236*5c591343SA. Cody Schuffelen {
237*5c591343SA. Cody Schuffelen int keyBits = publicArea->parameters.rsaDetail.keyBits;
238*5c591343SA. Cody Schuffelen int index;
239*5c591343SA. Cody Schuffelen //
240*5c591343SA. Cody Schuffelen if(KeyCacheLoaded(publicArea, sensitive, rand))
241*5c591343SA. Cody Schuffelen {
242*5c591343SA. Cody Schuffelen for(index = 0; index < RSA_KEY_CACHE_ENTRIES; index++)
243*5c591343SA. Cody Schuffelen {
244*5c591343SA. Cody Schuffelen if((s_rsaKeyCache[index].publicModulus.t.size * 8) == keyBits)
245*5c591343SA. Cody Schuffelen {
246*5c591343SA. Cody Schuffelen publicArea->unique.rsa = s_rsaKeyCache[index].publicModulus;
247*5c591343SA. Cody Schuffelen sensitive->sensitive.rsa = s_rsaKeyCache[index].privateExponent;
248*5c591343SA. Cody Schuffelen return TRUE;
249*5c591343SA. Cody Schuffelen }
250*5c591343SA. Cody Schuffelen }
251*5c591343SA. Cody Schuffelen return FALSE;
252*5c591343SA. Cody Schuffelen }
253*5c591343SA. Cody Schuffelen return s_keyCacheLoaded;
254*5c591343SA. Cody Schuffelen }
255*5c591343SA. Cody Schuffelen #endif // defined SIMULATION && defined USE_RSA_KEY_CACHE
256