Annotation of embedaddon/strongswan/src/libimcv/pts/pts_pcr.c, revision 1.1.1.2
1.1 misho 1: /*
1.1.1.2 ! misho 2: * Copyright (C) 2012-2020 Andreas Steffen
1.1 misho 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: /**
1.1.1.2 ! misho 56: * Length in bytes of a PCR register (size of hash used)
! 57: */
! 58: size_t pcr_len;
! 59:
! 60: /**
! 61: * Hash algorithm of PCR bank
! 62: */
! 63: pts_meas_algorithms_t pcr_algo;
! 64:
! 65: /**
1.1 misho 66: * Hasher used to extend shadow PCRs
67: */
68: hasher_t *hasher;
69:
70: };
71:
1.1.1.2 ! misho 72: METHOD(pts_pcr_t, get_pcr_algo, pts_meas_algorithms_t,
! 73: private_pts_pcr_t *this)
! 74: {
! 75: return this->pcr_algo;
! 76: }
! 77:
1.1 misho 78: METHOD(pts_pcr_t, get_count, uint32_t,
79: private_pts_pcr_t *this)
80: {
81: return this->pcr_count;
82: }
83:
84: METHOD(pts_pcr_t, select_pcr, bool,
85: private_pts_pcr_t *this, uint32_t pcr)
86: {
87: uint32_t i, f;
88:
89: if (pcr >= PTS_PCR_MAX_NUM)
90: {
91: DBG1(DBG_PTS, "PCR %2u: number is larger than maximum of %u",
92: pcr, PTS_PCR_MAX_NUM-1);
93: return FALSE;
94: }
95:
96: /* Determine PCR selection flag */
97: i = pcr / 8;
98: f = 1 << (pcr - 8*i);
99:
100: /* Has this PCR already been selected? */
101: if (!(this->pcr_select[i] & f))
102: {
103: this->pcr_select[i] |= f;
104: this->pcr_max = max(this->pcr_max, pcr);
105: this->pcr_count++;
106: }
107: return TRUE;
108: }
109:
110: METHOD(pts_pcr_t, get_selection_size, size_t,
111: private_pts_pcr_t *this)
112: {
113:
114: /**
115: * A TPM v1.2 has 24 PCR Registers so the bitmask field length
116: * used by TrouSerS is at least 3 bytes
117: */
118: return PTS_PCR_MAX_NUM / 8;
119: }
120:
121: typedef struct {
122: /** implements enumerator_t */
123: enumerator_t public;
124: /** current PCR */
125: uint32_t pcr;
126: /** back reference to parent */
127: private_pts_pcr_t *pcrs;
128: } pcr_enumerator_t;
129:
130: METHOD(enumerator_t, pcr_enumerator_enumerate, bool,
131: pcr_enumerator_t *this, va_list args)
132: {
133: uint32_t i, f, *pcr;
134:
135: VA_ARGS_VGET(args, pcr);
136:
137: while (this->pcr <= this->pcrs->pcr_max)
138: {
139: /* Determine PCR selection flag */
140: i = this->pcr / 8;
141: f = 1 << (this->pcr - 8*i);
142:
143: /* Assign current PCR to output argument and increase */
144: *pcr = this->pcr++;
145:
146: /* return if PCR is selected */
147: if (this->pcrs->pcr_select[i] & f)
148: {
149: return TRUE;
150: }
151: }
152: return FALSE;
153: }
154:
155: METHOD(pts_pcr_t, create_enumerator, enumerator_t*,
156: private_pts_pcr_t *this)
157: {
158: pcr_enumerator_t *enumerator;
159:
160: INIT(enumerator,
161: .public = {
162: .enumerate = enumerator_enumerate_default,
163: .venumerate = _pcr_enumerator_enumerate,
164: .destroy = (void*)free,
165: },
166: .pcrs = this,
167: );
168:
169: return (enumerator_t*)enumerator;
170: }
171:
172: METHOD(pts_pcr_t, get, chunk_t,
173: private_pts_pcr_t *this, uint32_t pcr)
174: {
175: return (pcr < PTS_PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty;
176: }
177:
178: METHOD(pts_pcr_t, set, bool,
179: private_pts_pcr_t *this, uint32_t pcr, chunk_t value)
180: {
1.1.1.2 ! misho 181: if (value.len != this->pcr_len)
1.1 misho 182: {
183: DBG1(DBG_PTS, "PCR %2u: value does not fit", pcr);
184: return FALSE;
185: }
186: if (select_pcr(this, pcr))
187: {
1.1.1.2 ! misho 188: memcpy(this->pcrs[pcr].ptr, value.ptr, this->pcr_len);
1.1 misho 189: return TRUE;
190: }
191: return FALSE;
192: }
193:
194: METHOD(pts_pcr_t, extend, chunk_t,
195: private_pts_pcr_t *this, uint32_t pcr, chunk_t measurement)
196: {
1.1.1.2 ! misho 197: if (measurement.len != this->pcr_len)
1.1 misho 198: {
199: DBG1(DBG_PTS, "PCR %2u: measurement does not fit", pcr);
200: return chunk_empty;
201: }
202: if (!select_pcr(this, pcr))
203: {
204: return chunk_empty;
205: }
206: if (!this->hasher->get_hash(this->hasher, this->pcrs[pcr] , NULL) ||
207: !this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr))
208: {
209: DBG1(DBG_PTS, "PCR %2u: not extended due to hasher problem", pcr);
210: return chunk_empty;
211: }
212: return this->pcrs[pcr];
213: }
214:
215: METHOD(pts_pcr_t, get_composite, tpm_tss_pcr_composite_t*,
216: private_pts_pcr_t *this)
217: {
218: tpm_tss_pcr_composite_t *pcr_composite;
219: enumerator_t *enumerator;
220: uint16_t selection_size;
221: uint32_t pcr_field_size, pcr;
222: u_char *pos;
223:
224: selection_size = get_selection_size(this);
1.1.1.2 ! misho 225: pcr_field_size = this->pcr_count * this->pcr_len;
1.1 misho 226:
227: INIT(pcr_composite,
228: .pcr_select = chunk_alloc(selection_size),
229: .pcr_composite = chunk_alloc(pcr_field_size),
230: );
231:
232: memcpy(pcr_composite->pcr_select.ptr, this->pcr_select, selection_size);
233: pos = pcr_composite->pcr_composite.ptr;
234:
235: enumerator = create_enumerator(this);
236: while (enumerator->enumerate(enumerator, &pcr))
237: {
1.1.1.2 ! misho 238: memcpy(pos, this->pcrs[pcr].ptr, this->pcr_len);
! 239: pos += this->pcr_len;
1.1 misho 240: }
241: enumerator->destroy(enumerator);
242:
243: return pcr_composite;
244: }
245:
246: METHOD(pts_pcr_t, destroy, void,
247: private_pts_pcr_t *this)
248: {
249: uint32_t i;
250:
251: for (i = 0; i < PTS_PCR_MAX_NUM; i++)
252: {
253: free(this->pcrs[i].ptr);
254: }
255: this->hasher->destroy(this->hasher);
256: free(this);
257: }
258:
259: /**
260: * See header
261: */
1.1.1.2 ! misho 262: pts_pcr_t *pts_pcr_create(tpm_version_t tpm_version, pts_meas_algorithms_t algo,
! 263: uint8_t locality)
1.1 misho 264: {
265: private_pts_pcr_t *this;
1.1.1.2 ! misho 266: hash_algorithm_t hash_alg;
1.1 misho 267: hasher_t *hasher;
268: uint32_t i;
269:
1.1.1.2 ! misho 270: hash_alg = pts_meas_algo_to_hash(algo);
! 271: hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
1.1 misho 272: if (!hasher)
273: {
274: DBG1(DBG_PTS, "%N hasher could not be created",
1.1.1.2 ! misho 275: hash_algorithm_short_names, hash_alg);
1.1 misho 276: return NULL;
277: }
278:
279: INIT(this,
280: .public = {
1.1.1.2 ! misho 281: .get_pcr_algo = _get_pcr_algo,
1.1 misho 282: .get_count = _get_count,
283: .select_pcr = _select_pcr,
284: .get_selection_size = _get_selection_size,
285: .create_enumerator = _create_enumerator,
286: .get = _get,
287: .set = _set,
288: .extend = _extend,
289: .get_composite = _get_composite,
290: .destroy = _destroy,
291: },
1.1.1.2 ! misho 292: .pcr_algo = algo,
! 293: .pcr_len = pts_meas_algo_hash_size(algo),
1.1 misho 294: .hasher = hasher,
295: );
296:
297: for (i = 0; i < PTS_PCR_MAX_NUM; i++)
298: {
1.1.1.2 ! misho 299: this->pcrs[i] = chunk_alloc(this->pcr_len);
! 300: memset(this->pcrs[i].ptr, 0x00, this->pcr_len);
! 301: }
! 302:
! 303: /* Set locality indicator in PCR[0] */
! 304: if (tpm_version == TPM_VERSION_2_0)
! 305: {
! 306: DBG2(DBG_PTS, "TPM 2.0 - locality indicator set to %u",
! 307: (uint32_t)locality);
! 308: this->pcrs[0].ptr[this->pcr_len - 1] = locality;
1.1 misho 309: }
310:
311: return &this->public;
312: }
313:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>