1
2/*
3 * Licensed Materials - Property of IBM
4 *
5 * trousers - An open source TCG Software Stack
6 *
7 * (C) Copyright International Business Machines Corp. 2004-2006
8 *
9 */
10
11
12#include <stdlib.h>
13#include <stdio.h>
14#include <string.h>
15#include <time.h>
16#include <errno.h>
17
18#include "trousers/tss.h"
19#include "trousers/trousers.h"
20#include "trousers_types.h"
21#include "trousers_types.h"
22#include "spi_utils.h"
23#include "capabilities.h"
24#include "tsplog.h"
25#include "obj.h"
26#include "authsess.h"
27
28TSS_RESULT
29Tspi_ChangeAuth(TSS_HOBJECT hObjectToChange,	/* in */
30		TSS_HOBJECT hParentObject,	/* in */
31		TSS_HPOLICY hNewPolicy)		/* in */
32{
33	UINT32 keyToChangeHandle;
34	TSS_RESULT result;
35	TSS_HCONTEXT tspContext;
36
37	if ((result = obj_policy_get_tsp_context(hNewPolicy, &tspContext)))
38		return result;
39
40	/* if the object to change is the TPM object, then the parent should
41	 * be NULL.  If the object to change is not the TPM, then the parent
42	 * object must be either an rsakey or the TPM */
43	if (obj_is_tpm(hObjectToChange)) {
44		if (hParentObject != NULL_HOBJECT)
45			return TSPERR(TSS_E_BAD_PARAMETER);
46	} else if (!obj_is_rsakey(hParentObject) && !obj_is_tpm(hParentObject)) {
47		return TSPERR(TSS_E_INVALID_HANDLE);
48	}
49
50	if (obj_is_tpm(hObjectToChange)) {
51		if ((result = changeauth_owner(tspContext, hObjectToChange, NULL_HTPM, hNewPolicy)))
52			return result;
53	} else if (obj_is_rsakey(hObjectToChange)) {
54		if ((result = obj_rsakey_get_tcs_handle(hObjectToChange, &keyToChangeHandle)))
55			return result;
56
57		if (keyToChangeHandle == TPM_KEYHND_SRK) {
58			if ((result = changeauth_srk(tspContext, hObjectToChange, hParentObject,
59						     hNewPolicy)))
60				return result;
61		} else {
62			if ((result = changeauth_key(tspContext, hObjectToChange, hParentObject,
63						     hNewPolicy)))
64				return result;
65		}
66	} else if (obj_is_encdata(hObjectToChange)) {
67		if ((result = changeauth_encdata(tspContext, hObjectToChange, hParentObject,
68						 hNewPolicy)))
69			return result;
70	} else if (obj_is_policy(hObjectToChange) || obj_is_hash(hObjectToChange) ||
71		   obj_is_pcrs(hObjectToChange) || obj_is_context(hObjectToChange)) {
72		return TSPERR(TSS_E_BAD_PARAMETER);
73	} else {
74		return TSPERR(TSS_E_INVALID_HANDLE);
75	}
76
77	if ((result = obj_policy_set_type(hNewPolicy, TSS_POLICY_USAGE)))
78		return result;
79
80	return Tspi_Policy_AssignToObject(hNewPolicy, hObjectToChange);
81
82}
83
84TSS_RESULT
85Tspi_ChangeAuthAsym(TSS_HOBJECT hObjectToChange,	/* in */
86		    TSS_HOBJECT hParentObject,		/* in */
87		    TSS_HKEY hIdentKey,			/* in */
88		    TSS_HPOLICY hNewPolicy)		/* in */
89{
90#if 0
91	TPM_AUTH auth;
92	UINT64 offset;
93	BYTE hashBlob[0x1000];
94	TCPA_DIGEST digest;
95	TCPA_RESULT result;
96	UINT32 keyHandle;
97	UINT32 idHandle;
98	TSS_HPOLICY hPolicy;
99	TSS_HPOLICY hParentPolicy;
100	UINT32 keyToChangeHandle;
101	TCPA_NONCE antiReplay;
102	UINT32 bytesRequested;
103	UINT64 tempSize;
104	BYTE tempKey[512];
105	TCPA_KEY_PARMS keyParms;
106	/* XXX Wow... */
107	BYTE ephParms[] = { 0, 0, 0x08, 0, 0, 0, 0, 0x02, 0, 0, 0, 0 };
108	UINT32 KeySizeOut;
109	BYTE *KeyDataOut;
110	UINT32 CertifyInfoSize;
111	BYTE *CertifyInfo;
112	UINT32 sigSize;
113	BYTE *sig;
114	UINT32 ephHandle;
115	TPM_CHANGEAUTH_VALIDATE caValidate;
116	TCPA_SECRET newSecret, oldSecret;
117	BYTE seed[20];
118	BYTE a1[256];
119	UINT32 a1Size;
120	TSS_KEY ephemeralKey;
121	TCPA_DIGEST newAuthLink;
122	UINT32 encObjectSize;
123	BYTE *encObject = NULL;
124	UINT32 encDataSizeOut;
125	BYTE *encDataOut;
126	TCPA_NONCE saltNonce;
127	TCPA_DIGEST changeProof;
128	TSS_HPOLICY hOldPolicy;
129	UINT32 caValidSize;
130	UINT32 keyObjectSize;
131	BYTE *keyObject;
132	TSS_KEY keyContainer;
133	TCPA_STORED_DATA dataContainer;
134	BYTE *dataObject;
135	UINT32 dataObjectSize;
136	UINT16 entityType;
137	TSS_BOOL useAuth = TRUE; // XXX
138	TPM_AUTH *pAuth;
139	BYTE dataBlob[1024];
140	TSS_HCONTEXT tspContext;
141	Trspi_HashCtx hashCtx;
142
143	if ((result = obj_policy_get_tsp_context(hNewPolicy, &tspContext)))
144		return result;
145
146	/*  grab all of the needed handles */
147	if ((result = obj_rsakey_get_tcs_handle(hIdentKey, &idHandle)))
148		return result;
149
150	/*  get the secret for the parent */
151	if ((result = obj_rsakey_get_policy(hIdentKey, TSS_POLICY_USAGE, &hPolicy, &useAuth)))
152		return result;
153
154	/*  get the parent secret */
155	if ((result = Tspi_GetPolicyObject(hParentObject, TSS_POLICY_USAGE, &hParentPolicy)))
156		return result;
157
158	if (!obj_is_rsakey(hParentObject) && !obj_is_tpm(hParentObject))
159		return TSPERR(TSS_E_INVALID_HANDLE);
160
161	/*  get the keyObject  */
162	if ((result = obj_rsakey_get_tcs_handle(hParentObject, &keyHandle)))
163		return result;
164
165	if (obj_is_rsakey(hObjectToChange) ||
166	    obj_is_encdata(hObjectToChange)) {
167
168		if ((result = obj_rsakey_get_tcs_handle(hObjectToChange, &keyToChangeHandle)))
169			return result;
170
171		if (keyToChangeHandle == TPM_KEYHND_SRK) {
172			return TSPERR(TSS_E_BAD_PARAMETER);
173		} else {
174			/*  generate container for ephemeral key */
175			keyParms.algorithmID = 1;	/* rsa */
176			keyParms.encScheme = 3;
177			keyParms.sigScheme = 1;
178			keyParms.parmSize = 12;
179			keyParms.parms = malloc(12);
180			if (keyParms.parms == NULL) {
181				LogError("malloc of %d bytes failed.", 12);
182				return TSPERR(TSS_E_OUTOFMEMORY);
183			}
184			memcpy(keyParms.parms, ephParms, 12);
185
186			tempSize = 0;
187			Trspi_LoadBlob_KEY_PARMS(&tempSize, tempKey, &keyParms);
188
189			/*  generate antireplay nonce */
190			bytesRequested = 20;
191			if ((result = get_local_random(tspContext, FALSE, bytesRequested,
192						       (BYTE **)antiReplay.nonce)))
193				return result;
194
195			/* caluculate auth data */
196			result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
197			result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ChangeAuthAsymStart);
198			result |= Trspi_HashUpdate(&hashCtx, TCPA_SHA1_160_HASH_LEN,
199						   antiReplay.nonce);
200			result |= Trspi_Hash_KEY_PARMS(&hashCtx, &keyParms);
201			if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
202				return result;
203
204			if (useAuth) {
205				if ((result = secret_PerformAuth_OIAP(hIdentKey,
206								      TPM_ORD_ChangeAuthAsymStart,
207								      hPolicy, FALSE, &digest,
208								      &auth)))
209					return result;
210
211				pAuth = &auth;
212			} else {
213				pAuth = NULL;
214			}
215
216			if ((result = TCSP_ChangeAuthAsymStart(tspContext, idHandle, antiReplay,
217							       tempSize, tempKey, pAuth,
218							       &KeySizeOut, &KeyDataOut,
219							       &CertifyInfoSize, &CertifyInfo,
220							       &sigSize, &sig, &ephHandle)))
221				return result;
222
223			/* Validate the Auth's */
224			result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
225			result |= Trspi_Hash_UINT32(&hashCtx, result);
226			result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ChangeAuthAsymStart);
227			result |= Trspi_HashUpdate(&hashCtx, CertifyInfoSize, CertifyInfo);
228			result |= Trspi_Hash_UINT32(&hashCtx, sigSize);
229			result |= Trspi_HashUpdate(&hashCtx, sigSize, sig);
230			result |= Trspi_Hash_UINT32(&hashCtx, ephHandle);
231			result |= Trspi_HashUpdate(&hashCtx, KeySizeOut, KeyDataOut);
232			if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
233				return result;
234
235			if (useAuth) {
236				if ((result = obj_policy_validate_auth_oiap(hPolicy, &digest,
237									    &auth)))
238					return result;
239			}
240
241			/*  generate random data for asymfinish */
242			if ((result = get_local_random(tspContext, FALSE, bytesRequested,
243						       (BYTE **)&caValidate.n1.nonce)))
244				return result;
245
246			if ((result = get_local_random(tspContext, FALSE, bytesRequested,
247						       (BYTE **)&antiReplay.nonce)))
248				return result;
249
250			if ((result = get_local_random(tspContext, FALSE, bytesRequested,
251						       (BYTE **)&seed)))
252				return result;
253
254			if ((result = Tspi_GetPolicyObject(hObjectToChange, TSS_POLICY_USAGE,
255							  &hOldPolicy)))
256				return result;
257
258			if ((result = obj_policy_get_secret(hNewPolicy, TR_SECRET_CTX_NEW,
259							    &newSecret)))
260				return result;
261			if ((result = obj_policy_get_secret(hOldPolicy, TR_SECRET_CTX_NOT_NEW,
262							    &oldSecret)))
263				return result;
264
265			/* Encrypt the ChangeAuthValidate structure with the
266			 * ephemeral key */
267
268			memcpy(caValidate.newAuthSecret.authdata, newSecret.authdata, 20);
269
270			offset = 0;
271			Trspi_LoadBlob_CHANGEAUTH_VALIDATE(&offset, hashBlob, &caValidate);
272			caValidSize = offset;
273
274			offset = 0;
275			if ((result = UnloadBlob_TSS_KEY(&offset, KeyDataOut, &ephemeralKey)))
276				return result;
277
278			Trspi_RSA_Encrypt(hashBlob, caValidSize, a1, &a1Size,
279				       ephemeralKey.pubKey.key,
280				       ephemeralKey.pubKey.keyLength);
281
282			free_key_refs(&ephemeralKey);
283
284			Trspi_HMAC(TSS_HASH_SHA1, 20, oldSecret.authdata,
285					 20, newSecret.authdata,
286					 newAuthLink.digest);
287
288			if (obj_is_rsakey(hObjectToChange)) {
289				if ((result = obj_rsakey_get_blob(hObjectToChange,
290						   &keyObjectSize, &keyObject)))
291					return result;
292
293				__tspi_memset(&keyContainer, 0, sizeof(TSS_KEY));
294
295				offset = 0;
296				if ((result = UnloadBlob_TSS_KEY(&offset,
297								 keyObject,
298								 &keyContainer)))
299					return result;
300
301				encObjectSize = keyContainer.encSize;
302				encObject = malloc(encObjectSize);
303				if (encObject == NULL) {
304					LogError("malloc of %d bytes failed.",
305							encObjectSize);
306					free_key_refs(&keyContainer);
307					return TSPERR(TSS_E_OUTOFMEMORY);
308				}
309				memcpy(encObject, keyContainer.encData,
310						encObjectSize);
311				entityType = TCPA_ET_KEY;
312			} else {
313				if ((result = obj_encdata_get_data(hObjectToChange,
314						   &dataObjectSize, &dataObject)))
315					return result;
316
317				offset = 0;
318				if ((result = Trspi_UnloadBlob_STORED_DATA(&offset,
319									   dataObject,
320									   &dataContainer)))
321					return result;
322
323				encObjectSize = dataContainer.encDataSize;
324				encObject = malloc(encObjectSize);
325				if (encObject == NULL) {
326					LogError("malloc of %d bytes failed.", encObjectSize);
327					free(dataContainer.sealInfo);
328					free(dataContainer.encData);
329					return TSPERR(TSS_E_OUTOFMEMORY);
330				}
331				memcpy(encObject, dataContainer.encData,
332						encObjectSize);
333				entityType = TCPA_ET_DATA;
334			}
335
336			result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
337			result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ChangeAuthAsymFinish);
338			result |= Trspi_Hash_UINT16(&hashCtx, entityType);
339			result |= Trspi_HashUpdate(&hashCtx, TCPA_SHA1_160_HASH_LEN,
340						   newAuthLink.digest);
341			result |= Trspi_Hash_UINT32(&hashCtx, a1Size);
342			result |= Trspi_HashUpdate(&hashCtx, a1Size, a1);
343			result |= Trspi_Hash_UINT32(&hashCtx, encObjectSize);
344			result |= Trspi_HashUpdate(&hashCtx, encObjectSize, encObject);
345			if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
346				return result;
347
348			if (useAuth) {
349				if ((result = secret_PerformAuth_OIAP(hParentObject,
350								      TPM_ORD_ChangeAuthAsymFinish,
351								      hParentPolicy, FALSE,
352								      &digest, &auth))) {
353					free(encObject);
354					free_key_refs(&keyContainer);
355					return result;
356				}
357				pAuth = &auth;
358			} else {
359				pAuth = NULL;
360			}
361
362			if ((result = TCSP_ChangeAuthAsymFinish(tspContext, keyHandle, ephHandle,
363							       entityType, newAuthLink, a1Size, a1,
364							       encObjectSize, encObject, pAuth,
365							       &encDataSizeOut, &encDataOut,
366							       &saltNonce, &changeProof))) {
367				free_key_refs(&keyContainer);
368				free(encObject);
369				return result;
370			}
371
372			/* ---  Validate the Auth's */
373			result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1);
374			result |= Trspi_Hash_UINT32(&hashCtx, result);
375			result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_ChangeAuthAsymFinish);
376			result |= Trspi_Hash_UINT32(&hashCtx, encDataSizeOut);
377			result |= Trspi_HashUpdate(&hashCtx, encDataSizeOut, encDataOut);
378			result |= Trspi_HashUpdate(&hashCtx, TCPA_SHA1_160_HASH_LEN,
379						   saltNonce.nonce);
380			result |= Trspi_HashUpdate(&hashCtx, TCPA_SHA1_160_HASH_LEN,
381						   changeProof.digest);
382			if ((result |= Trspi_HashFinal(&hashCtx, digest.digest)))
383				return result;
384
385			if (useAuth) {
386				if ((result = obj_policy_validate_auth_oiap(hParentPolicy,
387									&digest,
388									&auth))) {
389					free_key_refs(&keyContainer);
390					free(encObject);
391					return result;
392				}
393			}
394
395			if (entityType == TCPA_ET_KEY ||
396			    entityType == TCPA_ET_KEYHANDLE) {
397				memcpy(keyContainer.encData, encDataOut, encDataSizeOut);
398				keyContainer.encSize = encDataSizeOut;
399
400				offset = 0;
401				LoadBlob_TSS_KEY(&offset, keyObject, &keyContainer);
402				free_key_refs(&keyContainer);
403				if ((result = obj_rsakey_set_tcpakey(hObjectToChange, offset,
404								     keyObject))) {
405					free(encObject);
406					return result;
407				}
408			}
409
410			if (entityType == TCPA_ET_DATA) {
411				memcpy(dataContainer.encData, encDataOut,
412						encDataSizeOut);
413				dataContainer.encDataSize = encDataSizeOut;
414
415				offset = 0;
416				Trspi_LoadBlob_STORED_DATA(&offset, dataBlob,
417							   &dataContainer);
418				free(dataContainer.sealInfo);
419				free(dataContainer.encData);
420				obj_encdata_set_data(hObjectToChange,
421						   offset, dataBlob);
422			}
423		}
424	} else
425		return TSPERR(TSS_E_BAD_PARAMETER);
426
427	free(encObject);
428
429	return Tspi_Policy_AssignToObject(hNewPolicy, hObjectToChange);
430#else
431	return TSPERR(TSS_E_NOTIMPL);
432#endif
433}
434
435