2 * Copyright (C) 2012 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
18 #include <utils/debug.h>
22 typedef struct private_pts_pcr_t private_pts_pcr_t
;
25 * Private data of a pts_pcr_t object.
28 struct private_pts_pcr_t
{
31 * Public pts_pcr_t interface.
36 * Shadow PCR registers
38 chunk_t pcrs
[PTS_PCR_MAX_NUM
];
41 * Number of extended PCR registers
46 * Highest extended PCR register
51 * Bitmap of extended PCR registers
53 uint8_t pcr_select
[PTS_PCR_MAX_NUM
/ 8];
56 * Hasher used to extend shadow PCRs
62 METHOD(pts_pcr_t
, get_count
, uint32_t,
63 private_pts_pcr_t
*this)
65 return this->pcr_count
;
68 METHOD(pts_pcr_t
, select_pcr
, bool,
69 private_pts_pcr_t
*this, uint32_t pcr
)
73 if (pcr
>= PTS_PCR_MAX_NUM
)
75 DBG1(DBG_PTS
, "PCR %2u: number is larger than maximum of %u",
76 pcr
, PTS_PCR_MAX_NUM
-1);
80 /* Determine PCR selection flag */
84 /* Has this PCR already been selected? */
85 if (!(this->pcr_select
[i
] & f
))
87 this->pcr_select
[i
] |= f
;
88 this->pcr_max
= max(this->pcr_max
, pcr
);
94 METHOD(pts_pcr_t
, get_selection_size
, size_t,
95 private_pts_pcr_t
*this)
99 * A TPM v1.2 has 24 PCR Registers so the bitmask field length
100 * used by TrouSerS is at least 3 bytes
102 return PTS_PCR_MAX_NUM
/ 8;
106 /** implements enumerator_t */
110 /** back reference to parent */
111 private_pts_pcr_t
*pcrs
;
114 METHOD(enumerator_t
, pcr_enumerator_enumerate
, bool,
115 pcr_enumerator_t
*this, va_list args
)
119 VA_ARGS_VGET(args
, pcr
);
121 while (this->pcr
<= this->pcrs
->pcr_max
)
123 /* Determine PCR selection flag */
125 f
= 1 << (this->pcr
- 8*i
);
127 /* Assign current PCR to output argument and increase */
130 /* return if PCR is selected */
131 if (this->pcrs
->pcr_select
[i
] & f
)
139 METHOD(pts_pcr_t
, create_enumerator
, enumerator_t
*,
140 private_pts_pcr_t
*this)
142 pcr_enumerator_t
*enumerator
;
146 .enumerate
= enumerator_enumerate_default
,
147 .venumerate
= _pcr_enumerator_enumerate
,
148 .destroy
= (void*)free
,
153 return (enumerator_t
*)enumerator
;
156 METHOD(pts_pcr_t
, get
, chunk_t
,
157 private_pts_pcr_t
*this, uint32_t pcr
)
159 return (pcr
< PTS_PCR_MAX_NUM
) ? this->pcrs
[pcr
] : chunk_empty
;
162 METHOD(pts_pcr_t
, set
, bool,
163 private_pts_pcr_t
*this, uint32_t pcr
, chunk_t value
)
165 if (value
.len
!= PTS_PCR_LEN
)
167 DBG1(DBG_PTS
, "PCR %2u: value does not fit", pcr
);
170 if (select_pcr(this, pcr
))
172 memcpy(this->pcrs
[pcr
].ptr
, value
.ptr
, PTS_PCR_LEN
);
178 METHOD(pts_pcr_t
, extend
, chunk_t
,
179 private_pts_pcr_t
*this, uint32_t pcr
, chunk_t measurement
)
181 if (measurement
.len
!= PTS_PCR_LEN
)
183 DBG1(DBG_PTS
, "PCR %2u: measurement does not fit", pcr
);
186 if (!select_pcr(this, pcr
))
190 if (!this->hasher
->get_hash(this->hasher
, this->pcrs
[pcr
] , NULL
) ||
191 !this->hasher
->get_hash(this->hasher
, measurement
, this->pcrs
[pcr
].ptr
))
193 DBG1(DBG_PTS
, "PCR %2u: not extended due to hasher problem", pcr
);
196 return this->pcrs
[pcr
];
199 METHOD(pts_pcr_t
, get_composite
, tpm_tss_pcr_composite_t
*,
200 private_pts_pcr_t
*this)
202 tpm_tss_pcr_composite_t
*pcr_composite
;
203 enumerator_t
*enumerator
;
204 uint16_t selection_size
;
205 uint32_t pcr_field_size
, pcr
;
208 selection_size
= get_selection_size(this);
209 pcr_field_size
= this->pcr_count
* PTS_PCR_LEN
;
212 .pcr_select
= chunk_alloc(selection_size
),
213 .pcr_composite
= chunk_alloc(pcr_field_size
),
216 memcpy(pcr_composite
->pcr_select
.ptr
, this->pcr_select
, selection_size
);
217 pos
= pcr_composite
->pcr_composite
.ptr
;
219 enumerator
= create_enumerator(this);
220 while (enumerator
->enumerate(enumerator
, &pcr
))
222 memcpy(pos
, this->pcrs
[pcr
].ptr
, PTS_PCR_LEN
);
225 enumerator
->destroy(enumerator
);
227 return pcr_composite
;
230 METHOD(pts_pcr_t
, destroy
, void,
231 private_pts_pcr_t
*this)
235 for (i
= 0; i
< PTS_PCR_MAX_NUM
; i
++)
237 free(this->pcrs
[i
].ptr
);
239 this->hasher
->destroy(this->hasher
);
246 pts_pcr_t
*pts_pcr_create(void)
248 private_pts_pcr_t
*this;
252 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
255 DBG1(DBG_PTS
, "%N hasher could not be created",
256 hash_algorithm_short_names
, HASH_SHA1
);
262 .get_count
= _get_count
,
263 .select_pcr
= _select_pcr
,
264 .get_selection_size
= _get_selection_size
,
265 .create_enumerator
= _create_enumerator
,
269 .get_composite
= _get_composite
,
275 for (i
= 0; i
< PTS_PCR_MAX_NUM
; i
++)
277 this->pcrs
[i
] = chunk_alloc(PTS_PCR_LEN
);
278 memset(this->pcrs
[i
].ptr
, 0x00, PTS_PCR_LEN
);
281 return &this->public;