File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libtpmtss / tpm_tss_quote_info.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:44 2020 UTC (4 years, 3 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>