Annotation of embedaddon/strongswan/src/libimcv/pts/pts_pcr.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2012 Andreas Steffen
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include "pts_pcr.h"
17:
18: #include <utils/debug.h>
19:
20: #include <stdarg.h>
21:
22: typedef struct private_pts_pcr_t private_pts_pcr_t;
23:
24: /**
25: * Private data of a pts_pcr_t object.
26: *
27: */
28: struct private_pts_pcr_t {
29:
30: /**
31: * Public pts_pcr_t interface.
32: */
33: pts_pcr_t public;
34:
35: /**
36: * Shadow PCR registers
37: */
38: chunk_t pcrs[PTS_PCR_MAX_NUM];
39:
40: /**
41: * Number of extended PCR registers
42: */
43: uint32_t pcr_count;
44:
45: /**
46: * Highest extended PCR register
47: */
48: uint32_t pcr_max;
49:
50: /**
51: * Bitmap of extended PCR registers
52: */
53: uint8_t pcr_select[PTS_PCR_MAX_NUM / 8];
54:
55: /**
56: * Hasher used to extend shadow PCRs
57: */
58: hasher_t *hasher;
59:
60: };
61:
62: METHOD(pts_pcr_t, get_count, uint32_t,
63: private_pts_pcr_t *this)
64: {
65: return this->pcr_count;
66: }
67:
68: METHOD(pts_pcr_t, select_pcr, bool,
69: private_pts_pcr_t *this, uint32_t pcr)
70: {
71: uint32_t i, f;
72:
73: if (pcr >= PTS_PCR_MAX_NUM)
74: {
75: DBG1(DBG_PTS, "PCR %2u: number is larger than maximum of %u",
76: pcr, PTS_PCR_MAX_NUM-1);
77: return FALSE;
78: }
79:
80: /* Determine PCR selection flag */
81: i = pcr / 8;
82: f = 1 << (pcr - 8*i);
83:
84: /* Has this PCR already been selected? */
85: if (!(this->pcr_select[i] & f))
86: {
87: this->pcr_select[i] |= f;
88: this->pcr_max = max(this->pcr_max, pcr);
89: this->pcr_count++;
90: }
91: return TRUE;
92: }
93:
94: METHOD(pts_pcr_t, get_selection_size, size_t,
95: private_pts_pcr_t *this)
96: {
97:
98: /**
99: * A TPM v1.2 has 24 PCR Registers so the bitmask field length
100: * used by TrouSerS is at least 3 bytes
101: */
102: return PTS_PCR_MAX_NUM / 8;
103: }
104:
105: typedef struct {
106: /** implements enumerator_t */
107: enumerator_t public;
108: /** current PCR */
109: uint32_t pcr;
110: /** back reference to parent */
111: private_pts_pcr_t *pcrs;
112: } pcr_enumerator_t;
113:
114: METHOD(enumerator_t, pcr_enumerator_enumerate, bool,
115: pcr_enumerator_t *this, va_list args)
116: {
117: uint32_t i, f, *pcr;
118:
119: VA_ARGS_VGET(args, pcr);
120:
121: while (this->pcr <= this->pcrs->pcr_max)
122: {
123: /* Determine PCR selection flag */
124: i = this->pcr / 8;
125: f = 1 << (this->pcr - 8*i);
126:
127: /* Assign current PCR to output argument and increase */
128: *pcr = this->pcr++;
129:
130: /* return if PCR is selected */
131: if (this->pcrs->pcr_select[i] & f)
132: {
133: return TRUE;
134: }
135: }
136: return FALSE;
137: }
138:
139: METHOD(pts_pcr_t, create_enumerator, enumerator_t*,
140: private_pts_pcr_t *this)
141: {
142: pcr_enumerator_t *enumerator;
143:
144: INIT(enumerator,
145: .public = {
146: .enumerate = enumerator_enumerate_default,
147: .venumerate = _pcr_enumerator_enumerate,
148: .destroy = (void*)free,
149: },
150: .pcrs = this,
151: );
152:
153: return (enumerator_t*)enumerator;
154: }
155:
156: METHOD(pts_pcr_t, get, chunk_t,
157: private_pts_pcr_t *this, uint32_t pcr)
158: {
159: return (pcr < PTS_PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty;
160: }
161:
162: METHOD(pts_pcr_t, set, bool,
163: private_pts_pcr_t *this, uint32_t pcr, chunk_t value)
164: {
165: if (value.len != PTS_PCR_LEN)
166: {
167: DBG1(DBG_PTS, "PCR %2u: value does not fit", pcr);
168: return FALSE;
169: }
170: if (select_pcr(this, pcr))
171: {
172: memcpy(this->pcrs[pcr].ptr, value.ptr, PTS_PCR_LEN);
173: return TRUE;
174: }
175: return FALSE;
176: }
177:
178: METHOD(pts_pcr_t, extend, chunk_t,
179: private_pts_pcr_t *this, uint32_t pcr, chunk_t measurement)
180: {
181: if (measurement.len != PTS_PCR_LEN)
182: {
183: DBG1(DBG_PTS, "PCR %2u: measurement does not fit", pcr);
184: return chunk_empty;
185: }
186: if (!select_pcr(this, pcr))
187: {
188: return chunk_empty;
189: }
190: if (!this->hasher->get_hash(this->hasher, this->pcrs[pcr] , NULL) ||
191: !this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr))
192: {
193: DBG1(DBG_PTS, "PCR %2u: not extended due to hasher problem", pcr);
194: return chunk_empty;
195: }
196: return this->pcrs[pcr];
197: }
198:
199: METHOD(pts_pcr_t, get_composite, tpm_tss_pcr_composite_t*,
200: private_pts_pcr_t *this)
201: {
202: tpm_tss_pcr_composite_t *pcr_composite;
203: enumerator_t *enumerator;
204: uint16_t selection_size;
205: uint32_t pcr_field_size, pcr;
206: u_char *pos;
207:
208: selection_size = get_selection_size(this);
209: pcr_field_size = this->pcr_count * PTS_PCR_LEN;
210:
211: INIT(pcr_composite,
212: .pcr_select = chunk_alloc(selection_size),
213: .pcr_composite = chunk_alloc(pcr_field_size),
214: );
215:
216: memcpy(pcr_composite->pcr_select.ptr, this->pcr_select, selection_size);
217: pos = pcr_composite->pcr_composite.ptr;
218:
219: enumerator = create_enumerator(this);
220: while (enumerator->enumerate(enumerator, &pcr))
221: {
222: memcpy(pos, this->pcrs[pcr].ptr, PTS_PCR_LEN);
223: pos += PTS_PCR_LEN;
224: }
225: enumerator->destroy(enumerator);
226:
227: return pcr_composite;
228: }
229:
230: METHOD(pts_pcr_t, destroy, void,
231: private_pts_pcr_t *this)
232: {
233: uint32_t i;
234:
235: for (i = 0; i < PTS_PCR_MAX_NUM; i++)
236: {
237: free(this->pcrs[i].ptr);
238: }
239: this->hasher->destroy(this->hasher);
240: free(this);
241: }
242:
243: /**
244: * See header
245: */
246: pts_pcr_t *pts_pcr_create(void)
247: {
248: private_pts_pcr_t *this;
249: hasher_t *hasher;
250: uint32_t i;
251:
252: hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
253: if (!hasher)
254: {
255: DBG1(DBG_PTS, "%N hasher could not be created",
256: hash_algorithm_short_names, HASH_SHA1);
257: return NULL;
258: }
259:
260: INIT(this,
261: .public = {
262: .get_count = _get_count,
263: .select_pcr = _select_pcr,
264: .get_selection_size = _get_selection_size,
265: .create_enumerator = _create_enumerator,
266: .get = _get,
267: .set = _set,
268: .extend = _extend,
269: .get_composite = _get_composite,
270: .destroy = _destroy,
271: },
272: .hasher = hasher,
273: );
274:
275: for (i = 0; i < PTS_PCR_MAX_NUM; i++)
276: {
277: this->pcrs[i] = chunk_alloc(PTS_PCR_LEN);
278: memset(this->pcrs[i].ptr, 0x00, PTS_PCR_LEN);
279: }
280:
281: return &this->public;
282: }
283:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>