xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tcs/tcs_caps.c (revision 2d5f7628c5531eb583b9313ac2fd1cf8582b4479)
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 <unistd.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/mman.h>
19 #include <fcntl.h>
20 #include <errno.h>
21 
22 #include "trousers/tss.h"
23 #include "trousers_types.h"
24 #include "tcs_tsp.h"
25 #include "tcs_utils.h"
26 #include "tcs_int_literals.h"
27 #include "capabilities.h"
28 #include "tcsps.h"
29 #include "tcslog.h"
30 #include "tddl.h"
31 #include "req_mgr.h"
32 
33 
34 TSS_RESULT
get_current_version(TPM_VERSION * version)35 get_current_version(TPM_VERSION *version)
36 {
37 	TCPA_CAPABILITY_AREA capArea = TPM_CAP_VERSION_VAL;
38 	UINT32 respSize;
39 	BYTE *resp;
40 	TSS_RESULT result;
41 	UINT64 offset;
42 
43 	/* try the 1.2 way first */
44 	result = TCSP_GetCapability_Internal(InternalContext, capArea, 0, NULL, &respSize, &resp);
45 	if (result == TSS_SUCCESS) {
46 		offset = sizeof(UINT16); // XXX hack
47 		UnloadBlob_VERSION(&offset, resp, version);
48 		free(resp);
49 	} else if (result == TCPA_E_BAD_MODE) {
50 		/* if the TPM doesn't understand VERSION_VAL, try the 1.1 way */
51 		capArea = TCPA_CAP_VERSION;
52 		result = TCSP_GetCapability_Internal(InternalContext, capArea, 0, NULL, &respSize,
53 						     &resp);
54 		if (result == TSS_SUCCESS) {
55 			offset = 0;
56 			UnloadBlob_VERSION(&offset, resp, version);
57 			free(resp);
58 		}
59 	}
60 
61 	return result;
62 }
63 
64 TSS_RESULT
get_cap_uint32(TCPA_CAPABILITY_AREA capArea,BYTE * subCap,UINT32 subCapSize,UINT32 * v)65 get_cap_uint32(TCPA_CAPABILITY_AREA capArea, BYTE *subCap, UINT32 subCapSize, UINT32 *v)
66 {
67 	UINT32 respSize;
68 	BYTE *resp;
69 	TSS_RESULT result;
70 	UINT64 offset;
71 
72 	result = TCSP_GetCapability_Internal(InternalContext, capArea, subCapSize, subCap,
73 					     &respSize, &resp);
74 	if (!result) {
75 		offset = 0;
76 		switch (respSize) {
77 			case 1:
78 				UnloadBlob_BYTE(&offset, (BYTE *)v, resp);
79 				break;
80 			case sizeof(UINT16):
81 				UnloadBlob_UINT16(&offset, (UINT16 *)v, resp);
82 				break;
83 			case sizeof(UINT32):
84 				UnloadBlob_UINT32(&offset, v, resp);
85 				break;
86 			default:
87 				LogDebug("TCSP_GetCapability_Internal returned"
88 					  " %u bytes", respSize);
89 				result = TCSERR(TSS_E_FAIL);
90 				break;
91 		}
92 		free(resp);
93 	}
94 
95 	return result;
96 }
97 
98 
99 TSS_RESULT
get_max_auths(UINT32 * auths)100 get_max_auths(UINT32 *auths)
101 {
102 	TCS_AUTHHANDLE handles[TSS_MAX_AUTHS_CAP];
103 	TCPA_NONCE nonce;
104 	UINT32 subCap;
105 	TSS_RESULT result;
106 	int i;
107 
108 	if (TPM_VERSION_IS(1,2)) {
109 		UINT32ToArray(TPM_CAP_PROP_MAX_AUTHSESS, (BYTE *)(&subCap));
110 		result = get_cap_uint32(TPM_CAP_PROPERTY, (BYTE *)&subCap, sizeof(subCap), auths);
111 	} else if (TPM_VERSION_IS(1,1)) {
112 		/* open auth sessions until we get a failure */
113 		for (i = 0; i < TSS_MAX_AUTHS_CAP; i++) {
114 			result = TCSP_OIAP_Internal(InternalContext, &(handles[i]), &nonce);
115 			if (result != TSS_SUCCESS) {
116 				/* this is not off by one since we're 0 indexed */
117 				*auths = i;
118 				break;
119 			}
120 		}
121 
122 		if (i == TSS_MAX_AUTHS_CAP)
123 			*auths = TSS_MAX_AUTHS_CAP;
124 
125 		/* close the auth sessions */
126 		for (i = 0; (UINT32)i < *auths; i++) {
127 			internal_TerminateHandle(handles[i]);
128 		}
129 	} else {
130 		result = TCSERR(TSS_E_INTERNAL_ERROR);
131 		*auths = 0;
132 	}
133 
134 	if (*auths < 2) {
135 		LogError("%s reported only %u auth available!", __FUNCTION__, *auths);
136 		LogError("Your TPM must be reset before the TCSD can be started.");
137 	} else {
138 		LogDebug("get_max_auths reports %u auth contexts found", *auths);
139 		result = TSS_SUCCESS;
140 	}
141 
142 	return result;
143 }
144 
145 /* This is only called from init paths, so printing an error message is
146  * appropriate if something goes wrong */
147 TSS_RESULT
get_tpm_metrics(struct tpm_properties * p)148 get_tpm_metrics(struct tpm_properties *p)
149 {
150 	TSS_RESULT result;
151 	UINT32 subCap, rv = 0;
152 
153 	if ((result = get_current_version(&p->version)))
154 		goto err;
155 
156 	UINT32ToArray(TPM_ORD_SaveKeyContext, (BYTE *)&subCap);
157 	if ((result = get_cap_uint32(TCPA_CAP_ORD, (BYTE *)&subCap, sizeof(UINT32), &rv)))
158 		goto err;
159 	p->keyctx_swap = rv ? TRUE : FALSE;
160 
161 	rv = 0;
162 	UINT32ToArray(TPM_ORD_SaveAuthContext, (BYTE *)&subCap);
163 	if ((result = get_cap_uint32(TCPA_CAP_ORD, (BYTE *)&subCap, sizeof(UINT32), &rv)))
164 		goto err;
165 	p->authctx_swap = rv ? TRUE : FALSE;
166 
167 	UINT32ToArray(TPM_CAP_PROP_PCR, (BYTE *)&subCap);
168 	if ((result = get_cap_uint32(TCPA_CAP_PROPERTY, (BYTE *)&subCap, sizeof(UINT32),
169 					&p->num_pcrs)))
170 		goto err;
171 
172 	UINT32ToArray(TPM_CAP_PROP_DIR, (BYTE *)&subCap);
173 	if ((result = get_cap_uint32(TCPA_CAP_PROPERTY, (BYTE *)&subCap, sizeof(UINT32),
174 					&p->num_dirs)))
175 		goto err;
176 
177 	UINT32ToArray(TPM_CAP_PROP_SLOTS, (BYTE *)&subCap);
178 	if ((result = get_cap_uint32(TCPA_CAP_PROPERTY, (BYTE *)&subCap, sizeof(UINT32),
179 					&p->num_keys)))
180 		goto err;
181 
182 	UINT32ToArray(TPM_CAP_PROP_MANUFACTURER, (BYTE *)&subCap);
183 	if ((result = get_cap_uint32(TCPA_CAP_PROPERTY, (BYTE *)&subCap, sizeof(UINT32),
184 					(UINT32 *)&p->manufacturer)))
185 		goto err;
186 
187 	result = get_max_auths(&(p->num_auths));
188 
189 err:
190 	if (result)
191 		LogError("TCS GetCapability failed with result = 0x%x", result);
192 
193 	return result;
194 }
195 
196