Return to tpm_tss_quote_info.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libtpmtss |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2016 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 <tpm_tss_quote_info.h> ! 17: ! 18: #include <bio/bio_writer.h> ! 19: ! 20: #ifndef TPM_TAG_QUOTE_INFO2 ! 21: #define TPM_TAG_QUOTE_INFO2 0x0036 ! 22: #endif ! 23: #ifndef TPM_LOC_ZERO ! 24: #define TPM_LOC_ZERO 0x01 ! 25: #endif ! 26: ! 27: typedef struct private_tpm_tss_quote_info_t private_tpm_tss_quote_info_t; ! 28: ! 29: /** ! 30: * Private data of an tpm_tss_quote_info_t object. ! 31: */ ! 32: struct private_tpm_tss_quote_info_t { ! 33: ! 34: /** ! 35: * Public tpm_tss_quote_info_t interface. ! 36: */ ! 37: tpm_tss_quote_info_t public; ! 38: ! 39: /** ! 40: * TPM Quote Mode ! 41: */ ! 42: tpm_quote_mode_t quote_mode; ! 43: ! 44: /** ! 45: * TPM Qualified Signer ! 46: */ ! 47: chunk_t qualified_signer; ! 48: ! 49: /** ! 50: * TPM Clock Info ! 51: */ ! 52: chunk_t clock_info; ! 53: ! 54: /** ! 55: * TPM Version Info ! 56: */ ! 57: chunk_t version_info; ! 58: ! 59: /** ! 60: * TPM PCR Selection ! 61: */ ! 62: chunk_t pcr_select; ! 63: ! 64: /** ! 65: * TPM PCR Composite Hash ! 66: */ ! 67: chunk_t pcr_digest; ! 68: ! 69: /** ! 70: * TPM PCR Composite Hash algorithm ! 71: */ ! 72: hash_algorithm_t pcr_digest_alg; ! 73: ! 74: /** ! 75: * Reference count ! 76: */ ! 77: refcount_t ref; ! 78: ! 79: }; ! 80: ! 81: METHOD(tpm_tss_quote_info_t, get_quote_mode, tpm_quote_mode_t, ! 82: private_tpm_tss_quote_info_t *this) ! 83: { ! 84: return this->quote_mode; ! 85: } ! 86: ! 87: METHOD(tpm_tss_quote_info_t, get_pcr_digest_alg, hash_algorithm_t, ! 88: private_tpm_tss_quote_info_t *this) ! 89: { ! 90: return this->pcr_digest_alg; ! 91: } ! 92: ! 93: METHOD(tpm_tss_quote_info_t, get_pcr_digest, chunk_t, ! 94: private_tpm_tss_quote_info_t *this) ! 95: { ! 96: return this->pcr_digest; ! 97: } ! 98: ! 99: METHOD(tpm_tss_quote_info_t, get_quote, bool, ! 100: private_tpm_tss_quote_info_t *this, chunk_t nonce, ! 101: tpm_tss_pcr_composite_t *composite, chunk_t *quoted) ! 102: { ! 103: chunk_t pcr_composite, pcr_digest; ! 104: bio_writer_t *writer; ! 105: hasher_t *hasher; ! 106: bool equal_digests; ! 107: ! 108: /* Construct PCR Composite */ ! 109: writer = bio_writer_create(32); ! 110: ! 111: switch (this->quote_mode) ! 112: { ! 113: case TPM_QUOTE: ! 114: case TPM_QUOTE2: ! 115: case TPM_QUOTE2_VERSION_INFO: ! 116: writer->write_data16(writer, composite->pcr_select); ! 117: writer->write_data32(writer, composite->pcr_composite); ! 118: ! 119: break; ! 120: case TPM_QUOTE_TPM2: ! 121: writer->write_data(writer, composite->pcr_composite); ! 122: break; ! 123: case TPM_QUOTE_NONE: ! 124: break; ! 125: } ! 126: ! 127: pcr_composite = writer->extract_buf(writer); ! 128: writer->destroy(writer); ! 129: ! 130: DBG2(DBG_PTS, "constructed PCR Composite: %B", &pcr_composite); ! 131: ! 132: /* Compute PCR Composite Hash */ ! 133: hasher = lib->crypto->create_hasher(lib->crypto, this->pcr_digest_alg); ! 134: if (!hasher || !hasher->allocate_hash(hasher, pcr_composite, &pcr_digest)) ! 135: { ! 136: DESTROY_IF(hasher); ! 137: chunk_free(&pcr_composite); ! 138: return FALSE; ! 139: } ! 140: hasher->destroy(hasher); ! 141: chunk_free(&pcr_composite); ! 142: ! 143: DBG2(DBG_PTS, "constructed PCR Composite digest: %B", &pcr_digest); ! 144: ! 145: equal_digests = chunk_equals(pcr_digest, this->pcr_digest); ! 146: ! 147: /* Construct Quote Info */ ! 148: writer = bio_writer_create(32); ! 149: ! 150: switch (this->quote_mode) ! 151: { ! 152: case TPM_QUOTE: ! 153: /* Version number */ ! 154: writer->write_data(writer, chunk_from_chars(1, 1, 0, 0)); ! 155: ! 156: /* Magic QUOT value */ ! 157: writer->write_data(writer, chunk_from_str("QUOT")); ! 158: ! 159: /* PCR Composite Hash */ ! 160: writer->write_data(writer, pcr_digest); ! 161: ! 162: /* Secret assessment value 20 bytes (nonce) */ ! 163: writer->write_data(writer, nonce); ! 164: break; ! 165: case TPM_QUOTE2: ! 166: case TPM_QUOTE2_VERSION_INFO: ! 167: /* TPM Structure Tag */ ! 168: writer->write_uint16(writer, TPM_TAG_QUOTE_INFO2); ! 169: ! 170: /* Magic QUT2 value */ ! 171: writer->write_data(writer, chunk_from_str("QUT2")); ! 172: ! 173: /* Secret assessment value 20 bytes (nonce) */ ! 174: writer->write_data(writer, nonce); ! 175: ! 176: /* PCR selection */ ! 177: writer->write_data16(writer, composite->pcr_select); ! 178: ! 179: /* TPM Locality Selection */ ! 180: writer->write_uint8(writer, TPM_LOC_ZERO); ! 181: ! 182: /* PCR Composite Hash */ ! 183: writer->write_data(writer, pcr_digest); ! 184: ! 185: if (this->quote_mode == TPM_QUOTE2_VERSION_INFO) ! 186: { ! 187: /* TPM version Info */ ! 188: writer->write_data(writer, this->version_info); ! 189: } ! 190: break; ! 191: case TPM_QUOTE_TPM2: ! 192: /* Magic */ ! 193: writer->write_data(writer, chunk_from_chars(0xff,0x54,0x43,0x47)); ! 194: ! 195: /* Type */ ! 196: writer->write_uint16(writer, 0x8018); ! 197: ! 198: /* Qualified Signer */ ! 199: writer->write_data16(writer, this->qualified_signer); ! 200: ! 201: /* Extra Data */ ! 202: writer->write_data16(writer, nonce); ! 203: ! 204: /* Clock Info */ ! 205: writer->write_data(writer, this->clock_info); ! 206: ! 207: /* Firmware Version */ ! 208: writer->write_data(writer, this->version_info); ! 209: ! 210: /* PCR Selection */ ! 211: writer->write_data(writer, this->pcr_select); ! 212: ! 213: /* PCR Composite Hash */ ! 214: writer->write_data16(writer, pcr_digest); ! 215: break; ! 216: case TPM_QUOTE_NONE: ! 217: break; ! 218: } ! 219: chunk_free(&pcr_digest); ! 220: *quoted = writer->extract_buf(writer); ! 221: writer->destroy(writer); ! 222: ! 223: DBG2(DBG_PTS, "constructed TPM Quote Info: %B", quoted); ! 224: ! 225: if (!equal_digests) ! 226: { ! 227: DBG1(DBG_IMV, "received PCR Composite digest does not match " ! 228: "constructed one"); ! 229: chunk_free(quoted); ! 230: } ! 231: return equal_digests; ! 232: } ! 233: ! 234: METHOD(tpm_tss_quote_info_t, set_version_info, void, ! 235: private_tpm_tss_quote_info_t *this, chunk_t version_info) ! 236: { ! 237: chunk_free(&this->version_info); ! 238: this->version_info = chunk_clone(version_info); ! 239: } ! 240: ! 241: METHOD(tpm_tss_quote_info_t, get_version_info, chunk_t, ! 242: private_tpm_tss_quote_info_t *this) ! 243: { ! 244: return this->version_info; ! 245: } ! 246: ! 247: METHOD(tpm_tss_quote_info_t, set_tpm2_info, void, ! 248: private_tpm_tss_quote_info_t *this, chunk_t qualified_signer, ! 249: chunk_t clock_info, chunk_t pcr_select) ! 250: { ! 251: chunk_free(&this->qualified_signer); ! 252: this->qualified_signer = chunk_clone(qualified_signer); ! 253: ! 254: chunk_free(&this->clock_info); ! 255: this->clock_info = chunk_clone(clock_info); ! 256: ! 257: chunk_free(&this->pcr_select); ! 258: this->pcr_select = chunk_clone(pcr_select); ! 259: } ! 260: ! 261: METHOD(tpm_tss_quote_info_t, get_tpm2_info, void, ! 262: private_tpm_tss_quote_info_t *this, chunk_t *qualified_signer, ! 263: chunk_t *clock_info, chunk_t *pcr_select) ! 264: { ! 265: if (qualified_signer) ! 266: { ! 267: *qualified_signer = this->qualified_signer; ! 268: } ! 269: if (clock_info) ! 270: { ! 271: *clock_info = this->clock_info; ! 272: } ! 273: if (pcr_select) ! 274: { ! 275: *pcr_select = this->pcr_select; ! 276: } ! 277: } ! 278: ! 279: METHOD(tpm_tss_quote_info_t, get_ref, tpm_tss_quote_info_t*, ! 280: private_tpm_tss_quote_info_t *this) ! 281: { ! 282: ref_get(&this->ref); ! 283: ! 284: return &this->public; ! 285: } ! 286: ! 287: METHOD(tpm_tss_quote_info_t, destroy, void, ! 288: private_tpm_tss_quote_info_t *this) ! 289: { ! 290: if (ref_put(&this->ref)) ! 291: { ! 292: chunk_free(&this->qualified_signer); ! 293: chunk_free(&this->clock_info); ! 294: chunk_free(&this->version_info); ! 295: chunk_free(&this->pcr_select); ! 296: chunk_free(&this->pcr_digest); ! 297: free(this); ! 298: } ! 299: } ! 300: ! 301: /** ! 302: * See header ! 303: */ ! 304: tpm_tss_quote_info_t *tpm_tss_quote_info_create(tpm_quote_mode_t quote_mode, ! 305: hash_algorithm_t pcr_digest_alg, chunk_t pcr_digest) ! 306: ! 307: { ! 308: private_tpm_tss_quote_info_t *this; ! 309: ! 310: INIT(this, ! 311: .public = { ! 312: .get_quote_mode = _get_quote_mode, ! 313: .get_pcr_digest_alg = _get_pcr_digest_alg, ! 314: .get_pcr_digest = _get_pcr_digest, ! 315: .get_quote = _get_quote, ! 316: .set_version_info = _set_version_info, ! 317: .get_version_info = _get_version_info, ! 318: .set_tpm2_info = _set_tpm2_info, ! 319: .get_tpm2_info = _get_tpm2_info, ! 320: .get_ref = _get_ref, ! 321: .destroy = _destroy, ! 322: }, ! 323: .quote_mode = quote_mode, ! 324: .pcr_digest_alg = pcr_digest_alg, ! 325: .pcr_digest = chunk_clone(pcr_digest), ! 326: .ref = 1, ! 327: ); ! 328: ! 329: return &this->public; ! 330: }