forked from microsoft/TSS.MSR
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSample-KeyImport.cs
183 lines (145 loc) · 8.2 KB
/
Sample-KeyImport.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See the LICENSE file in the project root for full license information.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using Tpm2Lib;
using Tpm2Tester;
//
// This file contains examples of TPM 2.0 test routines
//
// Note that the names of the namespace and class(es) containing the tests can be any.
//
namespace Tpm2TestSuite
{
partial class Tpm2Tests
{
[Test(Profile.TPM20, Privileges.Admin, Category.Asym | Category.Dup | Category.Rsa)]
void DuplicateImportRsaSample(Tpm2 tpm, TestContext testCtx)
{
TpmAlgId nameAlg = Substrate.Random(TpmCfg.HashAlgs);
var policy = new PolicyTree(nameAlg);
policy.SetPolicyRoot(new TpmPolicyCommand(TpmCc.Duplicate));
var inPub = new TpmPublic(nameAlg,
ObjectAttr.Sign | ObjectAttr.AdminWithPolicy | ObjectAttr.SensitiveDataOrigin,
policy.GetPolicyDigest(),
new RsaParms(new SymDefObject(),
new SchemeRsassa(Substrate.Random(TpmCfg.HashAlgs)),
Substrate.Random(TpmCfg.RsaKeySizes), 0),
new Tpm2bPublicKeyRsa());
TpmHandle hKey = Substrate.CreateAndLoad(tpm, inPub, out TpmPublic pub);
// Duplicate
TpmPrivate priv = TpmHelper.GetPlaintextPrivate(tpm, hKey, policy);
tpm.FlushContext(hKey);
// Import
TpmPrivate privImp = tpm.Import(Substrate.LoadRsaPrimary(tpm), null, pub, priv, null, new SymDefObject());
} // SimpleDuplicateImportRsaSample
TssObject ImportExternalRsaKey(Tpm2 tpm, TpmHandle hParent,
int keySizeInBits, IAsymSchemeUnion scheme,
byte[] publicPart, byte[] privatePart,
ObjectAttr keyAttrs,
byte[] authVal = null, byte[] policyDigest = null)
{
TpmAlgId sigHashAlg = TpmHelper.GetSchemeHash(scheme),
nameAlg = sigHashAlg;
// TPM signing key template with the actual public key bits
var inPub = new TpmPublic(nameAlg,
keyAttrs,
policyDigest,
new RsaParms(new SymDefObject(), scheme as IAsymSchemeUnion,
(ushort)keySizeInBits, 0),
new Tpm2bPublicKeyRsa(publicPart));
// Wrap the key in a TSS helper class
TssObject swKey = TssObject.Create(inPub, authVal, privatePart);
// Get a key duplication blob in TPM 2.0 compatibale format
TpmPrivate dupBlob = swKey.GetPlaintextDuplicationBlob();
// Importing a duplication blob creates a new TPM private key blob protected
// with its new parent key.
swKey.Private = tpm.Import(hParent, null, swKey.Public, dupBlob, null, new SymDefObject());
return swKey;
} // ImportExternalRsaKey
[Test(Profile.TPM20, Privileges.Admin,
Category.Asym | Category.Dup | Category.Rsa)]
void ExternalKeyImportSample(Tpm2 tpm, TestContext testCtx)
{
// Create a software key (external to any TPM).
int keySize = 2048;
var externalRsaKey = new RawRsa(keySize);
// When an external key comes from a cert, one would need to extract the key size and
// byte buffers representing public and private parts of the key from the cert, an use
// them directly in the call to ImportExternalRsaKey() below (i.e. no RawRsa object is
// necessary).
// Signing scheme to use (it may come from the key's cert)
TpmAlgId sigHashAlg = Substrate.Random(TpmCfg.HashAlgs);
var sigScheme = new SchemeRsassa(sigHashAlg);
// An arbitrary external key would not have TPM key attributes associated with it.
// Yet some of them may be inferred from the cert based on the declared key purpose
// (ObjectAttr.Sign below). The others are defined by the intended TPM key usage
// scenarios, e.g. ObjectAttr.UserWithAuth tells TPM to allow key usage authorization
// using an auth value (random byte buffer) in a password or an HMAC session.
ObjectAttr keyAttrs = ObjectAttr.Sign | ObjectAttr.UserWithAuth;
// Generate an auth value for the imported matching in strength the signing scheme
byte[] authVal = Substrate.RandomAuth(sigHashAlg);
// We need a storage key to use as a parent of the imported key.
// The following helper creates an RSA primary storage key.
TpmHandle hParent = Substrate.CreateRsaPrimary(tpm);
TssObject importedKey = ImportExternalRsaKey(tpm, hParent,
keySize, sigScheme,
externalRsaKey.Public, externalRsaKey.Private,
keyAttrs, authVal);
// Now we can load the newly imported key into the TPM, ...
TpmHandle hImportedKey = tpm.Load(hParent, importedKey.Private, importedKey.Public);
// ... let the TSS know the auth value associated with this handle, ...
hImportedKey.SetAuth(authVal);
// ... and use it to sign something to check if import was OK
TpmHash toSign = TpmHash.FromRandom(sigHashAlg);
ISignatureUnion sig = tpm.Sign(hImportedKey, toSign, null, new TkHashcheck());
// Verify that the signature is correct using the public part of the imported key
bool sigOk = importedKey.Public.VerifySignatureOverHash(toSign, sig);
testCtx.Assert("Signature.OK", sigOk);
// Cleanup
tpm.FlushContext(hImportedKey);
// The parent key handle can be flushed immediately after it was used in the Load() command
tpm.FlushContext(hParent);
// Imported private/public key pair (in the TssObject) can be stored on disk, in the cloud,
// etc. (no additional protection is necessary), and loaded into the TPM as above whenever
// the key is needed.
// Alternatively the key can be persisted in the TPM using the EvictControl() command
} // ExternalKeyImportSample
[Test(Profile.TPM20, Privileges.Admin, Category.Asym | Category.Rsa)]
void LoadExternalFullRsaKeySample(Tpm2 tpm, TestContext testCtx)
{
var hashAlg = TpmAlgId.Sha256;
var inPub = new TpmPublic(hashAlg,
ObjectAttr.Decrypt | ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
null,
new RsaParms(new SymDefObject(), new SchemeOaep(hashAlg), 2048, 0),
new Tpm2bPublicKeyRsa());
// Create a software RSA key
var swKey = new AsymCryptoSystem(inPub);
// The crucial point in loading a software key is preparing the TPM-formatted private part of the key
Sensitive sens = swKey.GetSensitive();
TpmHandle extKey = tpm.LoadExternal(sens, swKey.GetPublicParms(), TpmRh.Null);
//
// Make sure that the key was loaded correctly
//
// This particular label is used by the TPM while doing OAEP for its internal protocols
// (though in n general any label can be used).
byte[] label = RawRsa.GetLabel("OaepLabel");
byte[] origMsg = Substrate.RandomBytes(64);
// Encrypt using software key (the paublic part is used)
byte[] encMsg = swKey.EncryptOaep(origMsg, label);
testCtx.AssertNotEqual("SwEnc", origMsg, encMsg);
// Decrypt using the TPM (the private part is used)
byte[] decMsg = tpm.RsaDecrypt(extKey, encMsg, null, label);
testCtx.AssertEqual("CrossEncDec", origMsg, decMsg);
tpm.FlushContext(extKey);
}
}
}