File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libtpmtss / tpm_tss_tss2_v2.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:20:08 2021 UTC (3 years, 5 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, HEAD
strongswan 5.9.2

    1: /*
    2:  * Copyright (C) 2018 Tobias Brunner
    3:  * Copyright (C) 2018-2020 Andreas Steffen
    4:  * HSR Hochschule fuer Technik Rapperswil
    5:  *
    6:  * This program is free software; you can redistribute it and/or modify it
    7:  * under the terms of the GNU General Public License as published by the
    8:  * Free Software Foundation; either version 2 of the License, or (at your
    9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
   10:  *
   11:  * This program is distributed in the hope that it will be useful, but
   12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14:  * for more details.
   15:  */
   16: 
   17: #include "tpm_tss_tss2.h"
   18: #include "tpm_tss_tss2_names.h"
   19: 
   20: #ifdef TSS_TSS2_V2
   21: 
   22: #include <asn1/asn1.h>
   23: #include <asn1/oid.h>
   24: #include <bio/bio_reader.h>
   25: #include <bio/bio_writer.h>
   26: #include <threading/mutex.h>
   27: 
   28: #include <tss2/tss2_sys.h>
   29: 
   30: #include <dlfcn.h>
   31: #include <sys/types.h>
   32: #include <sys/stat.h>
   33: #include <unistd.h>
   34: 
   35: #define LABEL	"TPM 2.0 -"
   36: 
   37: #define PLATFORM_PCR	24
   38: #define MAX_PCR_BANKS	 4
   39: 
   40: typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t;
   41: 
   42: /**
   43:  * Private data of an tpm_tss_tss2_t object.
   44:  */
   45: struct private_tpm_tss_tss2_t {
   46: 
   47: 	/**
   48: 	 * Public tpm_tss_tss2_t interface.
   49: 	 */
   50: 	tpm_tss_t public;
   51: 
   52: 	/**
   53: 	 * TCTI context
   54: 	 */
   55: 	TSS2_TCTI_CONTEXT *tcti_context;
   56: 
   57: 	/**
   58: 	 * SYS context
   59: 	 */
   60: 	TSS2_SYS_CONTEXT  *sys_context;
   61: 
   62: 	/**
   63: 	 * TPM version info
   64: 	 */
   65: 	chunk_t version_info;
   66: 
   67: 	/**
   68: 	 * Number of supported algorithms
   69: 	 */
   70: 	size_t supported_algs_count;
   71: 
   72: 	/**
   73: 	 * List of supported algorithms
   74: 	 */
   75: 	TPM2_ALG_ID supported_algs[TPM2_PT_ALGORITHM_SET];
   76: 
   77: 	/**
   78: 	 * Number of assigned PCR banks
   79: 	 */
   80: 	size_t assigned_pcrs_count;
   81: 
   82: 	/**
   83: 	 * List of assigned PCR banks
   84: 	 */
   85: 	TPM2_ALG_ID assigned_pcrs[MAX_PCR_BANKS];
   86: 
   87: 	/**
   88: 	 * Is TPM FIPS 186-4 compliant ?
   89: 	 */
   90: 	bool fips_186_4;
   91: 
   92: 	/**
   93: 	 * Does the TPM use the old TCG SHA1-only event digest format
   94: 	 */
   95: 	bool old_event_digest_format;
   96: 
   97: 	/**
   98: 	 * Mutex controlling access to the TPM 2.0 context
   99: 	 */
  100: 	mutex_t *mutex;
  101: 
  102: };
  103: 
  104: /**
  105:  * Global TCTI dynamic library handle and init function
  106:  */
  107: static void *tcti_handle;
  108: 
  109: static TSS2_TCTI_INIT_FUNC tcti_init;
  110: 
  111: static char *tcti_opts;
  112: 
  113: /**
  114:  * Empty AUTH_COMMAND
  115:  */
  116: static const TPMS_AUTH_COMMAND auth_cmd_empty;
  117: 
  118: /**
  119:  * Convert hash algorithm to TPM2_ALG_ID
  120:  */
  121: static TPM2_ALG_ID hash_alg_to_tpm_alg_id(hash_algorithm_t alg)
  122: {
  123: 	switch (alg)
  124: 	{
  125: 		case HASH_SHA1:
  126: 			return TPM2_ALG_SHA1;
  127: 		case HASH_SHA256:
  128: 			return TPM2_ALG_SHA256;
  129: 		case HASH_SHA384:
  130: 			return TPM2_ALG_SHA384;
  131: 		case HASH_SHA512:
  132: 			return TPM2_ALG_SHA512;
  133: 		case HASH_SHA3_256:
  134: 			return TPM2_ALG_SHA3_256;
  135: 		case HASH_SHA3_384:
  136: 			return TPM2_ALG_SHA3_384;
  137: 		case HASH_SHA3_512:
  138: 			return TPM2_ALG_SHA3_512;
  139: 		default:
  140: 			return TPM2_ALG_ERROR;
  141: 	}
  142: }
  143: 
  144: /**
  145:  * Convert TPM2_ALG_ID to hash algorithm
  146:  */
  147: static hash_algorithm_t hash_alg_from_tpm_alg_id(TPM2_ALG_ID alg)
  148: {
  149: 	switch (alg)
  150: 	{
  151: 		case TPM2_ALG_SHA1:
  152: 			return HASH_SHA1;
  153: 		case TPM2_ALG_SHA256:
  154: 			return HASH_SHA256;
  155: 		case TPM2_ALG_SHA384:
  156: 			return HASH_SHA384;
  157: 		case TPM2_ALG_SHA512:
  158: 			return HASH_SHA512;
  159: 		case TPM2_ALG_SHA3_256:
  160: 			return HASH_SHA3_256;
  161: 		case TPM2_ALG_SHA3_384:
  162: 			return HASH_SHA3_384;
  163: 		case TPM2_ALG_SHA3_512:
  164: 			return HASH_SHA3_512;
  165: 		default:
  166: 			return HASH_UNKNOWN;
  167: 	}
  168: }
  169: 
  170: /**
  171:  * Check if an algorithm given by its TPM2_ALG_ID is supported by the TPM
  172:  */
  173: static bool is_supported_alg(private_tpm_tss_tss2_t *this, TPM2_ALG_ID alg_id)
  174: {
  175: 	int i;
  176: 
  177: 	if (alg_id == TPM2_ALG_ERROR)
  178: 	{
  179: 		return FALSE;
  180: 	}
  181: 
  182: 	for (i = 0; i < this->supported_algs_count; i++)
  183: 	{
  184: 		if (this->supported_algs[i] == alg_id)
  185: 		{
  186: 			return TRUE;
  187: 		}
  188: 	}
  189: 
  190: 	return FALSE;
  191: }
  192: 
  193: /**
  194:  * Get the TPM version_info and a list of supported algorithms
  195:  *
  196:  *					   1				   2				   3
  197:  *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  198:  *
  199:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  200:  *  |  TPM 2.0 Version_Info Tag     |   Reserved    |   Locality    |
  201:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  202:  *  |                            Revision                           |
  203:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  204:  *  |                              Year                             |
  205:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  206:  *  |                             Vendor                            |
  207:  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  208:  */
  209: #define TPM2_VERSION_INFO_TAG       0x0200
  210: #define TPM2_VERSION_INFO_RESERVED  0x00
  211: #define TPM2_VERSION_INFO_SIZE      16
  212: #define TPM2_DEFAULT_LOCALITY       3
  213: 
  214: static bool get_algs_capability(private_tpm_tss_tss2_t *this)
  215: {
  216: 	TPMS_CAPABILITY_DATA cap_data;
  217: 	TPMS_TAGGED_PROPERTY tp;
  218: 	TPMI_YES_NO more_data;
  219: 	TPM2_ALG_ID alg;
  220: 	bio_writer_t *writer;
  221: 	bool fips_140_2 = FALSE;
  222: 	uint32_t rval, i, offset, revision = 0, year = 0, vendor = 0;
  223: 	uint8_t locality = TPM2_DEFAULT_LOCALITY;
  224: 	size_t len = BUF_LEN;
  225: 	char buf[BUF_LEN], manufacturer[5], vendor_string[17];
  226: 	char *pos = buf;
  227: 	int written;
  228: 
  229: 	/* get fixed properties */
  230: 	this->mutex->lock(this->mutex);
  231: 	rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_TPM_PROPERTIES,
  232: 								  TPM2_PT_FIXED, TPM2_MAX_TPM_PROPERTIES,
  233: 								  &more_data, &cap_data, 0);
  234: 	this->mutex->unlock(this->mutex);
  235: 	if (rval != TPM2_RC_SUCCESS)
  236: 	{
  237: 		DBG1(DBG_PTS, "%s GetCapability failed for TPM2_CAP_TPM_PROPERTIES: 0x%06x",
  238: 					   LABEL, rval);
  239: 		return FALSE;
  240: 	}
  241: 	memset(manufacturer,  '\0', sizeof(manufacturer));
  242: 	memset(vendor_string, '\0', sizeof(vendor_string));
  243: 
  244: 	/* print fixed properties */
  245: 	for (i = 0; i < cap_data.data.tpmProperties.count; i++)
  246: 	{
  247: 		tp = cap_data.data.tpmProperties.tpmProperty[i];
  248: 		switch (tp.property)
  249: 		{
  250: 			case TPM2_PT_REVISION:
  251: 				revision = tp.value;
  252: 				break;
  253: 			case TPM2_PT_YEAR:
  254: 				year = tp.value;
  255: 				break;
  256: 			case TPM2_PT_MANUFACTURER:
  257: 				vendor = tp.value;
  258: 				htoun32(manufacturer, tp.value);
  259: 				break;
  260: 			case TPM2_PT_VENDOR_STRING_1:
  261: 			case TPM2_PT_VENDOR_STRING_2:
  262: 			case TPM2_PT_VENDOR_STRING_3:
  263: 			case TPM2_PT_VENDOR_STRING_4:
  264: 				offset = 4 * (tp.property - TPM2_PT_VENDOR_STRING_1);
  265: 				htoun32(vendor_string + offset, tp.value);
  266: 				break;
  267: 			case TPM2_PT_MODES:
  268: 				if (tp.value & TPMA_MODES_FIPS_140_2)
  269: 				{
  270: 					this->fips_186_4 = fips_140_2 = TRUE;
  271: 				}
  272: 				break;
  273: 			default:
  274: 				break;
  275: 		}
  276: 	}
  277: 
  278: 	if (!fips_140_2)
  279: 	{
  280: 		this->fips_186_4 = lib->settings->get_bool(lib->settings,
  281: 					"%s.plugins.tpm.fips_186_4", FALSE, lib->ns);
  282: 	}
  283: 	DBG2(DBG_PTS, "%s manufacturer: %s (%s) rev: %05.2f %u %s", LABEL,
  284: 		 manufacturer, vendor_string, (float)revision/100, year,
  285: 		 fips_140_2 ? "FIPS 140-2" : (this->fips_186_4 ? "FIPS 186-4" : ""));
  286: 
  287: 	/* determine if TPM uses old event digest format and a different locality */
  288: 	if (streq(manufacturer, "INTC"))
  289: 	{
  290: 		locality = 0;
  291: 
  292: 		if (revision == 116 && year == 2016)
  293: 		{
  294: 			this->old_event_digest_format = TRUE;
  295: 		}
  296: 	}
  297: 
  298: 	/* construct TPM 2.0 version_info object */
  299: 	writer = bio_writer_create(  TPM2_VERSION_INFO_SIZE);
  300: 	writer->write_uint16(writer, TPM2_VERSION_INFO_TAG);
  301: 	writer->write_uint8(writer,  TPM2_VERSION_INFO_RESERVED);
  302: 	writer->write_uint8(writer,  locality);
  303: 	writer->write_uint32(writer, revision);
  304: 	writer->write_uint32(writer, year);
  305: 	writer->write_uint32(writer, vendor);
  306: 	this->version_info = writer->extract_buf(writer);
  307: 	writer->destroy(writer);
  308: 
  309: 	/* get supported algorithms */
  310: 	this->mutex->lock(this->mutex);
  311: 	rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_ALGS,
  312: 						0, TPM2_PT_ALGORITHM_SET, &more_data, &cap_data, 0);
  313: 	this->mutex->unlock(this->mutex);
  314: 	if (rval != TPM2_RC_SUCCESS)
  315: 	{
  316: 		DBG1(DBG_PTS, "%s GetCapability failed for TPM2_CAP_ALGS: 0x%06x",
  317: 					   LABEL, rval);
  318: 		return FALSE;
  319: 	}
  320: 
  321: 	/* Number of supported algorithms */
  322: 	this->supported_algs_count = cap_data.data.algorithms.count;
  323: 
  324: 	/* store and print supported algorithms */
  325: 	for (i = 0; i < this->supported_algs_count; i++)
  326: 	{
  327: 		alg = cap_data.data.algorithms.algProperties[i].alg;
  328: 		this->supported_algs[i] = alg;
  329: 
  330: 		written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
  331: 		if (written < 0 || written >= len)
  332: 		{
  333: 			break;
  334: 		}
  335: 		pos += written;
  336: 		len -= written;
  337: 	}
  338: 	DBG2(DBG_PTS, "%s algorithms:%s", LABEL, buf);
  339: 
  340: 	/* get supported ECC curves */
  341: 	this->mutex->lock(this->mutex);
  342: 	rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_ECC_CURVES,
  343: 						0, TPM2_PT_LOADED_CURVES, &more_data, &cap_data, 0);
  344: 	this->mutex->unlock(this->mutex);
  345: 	if (rval != TPM2_RC_SUCCESS)
  346: 	{
  347: 		DBG1(DBG_PTS, "%s GetCapability failed for TPM2_CAP_ECC_CURVES: 0x%06x",
  348: 					   LABEL, rval);
  349: 		return FALSE;
  350: 	}
  351: 
  352: 	/* reset print buffer */
  353: 	pos = buf;
  354: 	len = BUF_LEN;
  355: 
  356: 	/* print supported ECC curves */
  357: 	for (i = 0; i < cap_data.data.eccCurves.count; i++)
  358: 	{
  359: 		written = snprintf(pos, len, " %N", tpm_ecc_curve_names,
  360: 						   cap_data.data.eccCurves.eccCurves[i]);
  361: 		if (written < 0 || written >= len)
  362: 		{
  363: 			break;
  364: 		}
  365: 		pos += written;
  366: 		len -= written;
  367: 	}
  368: 	DBG2(DBG_PTS, "%s ECC curves:%s", LABEL, buf);
  369: 
  370: 	/* get assigned PCR banks */
  371: 	this->mutex->lock(this->mutex);
  372: 	rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_PCRS,
  373: 						0, MAX_PCR_BANKS, &more_data, &cap_data, 0);
  374: 	this->mutex->unlock(this->mutex);
  375: 	if (rval != TPM2_RC_SUCCESS)
  376: 	{
  377: 		DBG1(DBG_PTS, "%s GetCapability failed for TPM2_CAP_PCRS: 0x%06x",
  378: 					   LABEL, rval);
  379: 		return FALSE;
  380: 	}
  381: 
  382: 	/* Number of assigned PCR banks */
  383: 	this->assigned_pcrs_count = cap_data.data.assignedPCR.count;
  384: 
  385: 	/* reset print buffer */
  386: 	pos = buf;
  387: 	len = BUF_LEN;
  388: 
  389: 	/* store and print assigned PCR banks */
  390: 	for (i = 0; i < cap_data.data.assignedPCR.count; i++)
  391: 	{
  392: 		alg = cap_data.data.assignedPCR.pcrSelections[i].hash;
  393: 		this->assigned_pcrs[i] = alg;
  394: 		written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
  395: 		if (written < 0 || written >= len)
  396: 		{
  397: 			break;
  398: 		}
  399: 		pos += written;
  400: 		len -= written;
  401: 	}
  402: 	DBG2(DBG_PTS, "%s PCR banks:%s", LABEL, buf);
  403: 
  404: 	return TRUE;
  405: }
  406: 
  407: /**
  408:  * Initialize TSS2 TCTI context
  409:  */
  410: static bool initialize_tcti_context(private_tpm_tss_tss2_t *this)
  411: {
  412: 	size_t tcti_context_size;
  413: 	uint32_t rval;
  414: 
  415: 	if (!tcti_init)
  416: 	{
  417: 		return FALSE;
  418: 	}
  419: 
  420: 	/* determine size of tcti context */
  421: 	rval = tcti_init(NULL, &tcti_context_size, tcti_opts);
  422: 	if (rval != TSS2_RC_SUCCESS)
  423: 	{
  424: 		DBG1(DBG_PTS, "%s tcti init setup failed: 0x%06x",  LABEL, rval);
  425: 		return FALSE;
  426: 	}
  427: 
  428: 	/* allocate and initialize memory for tcti context */
  429: 	this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size);
  430: 	memset(this->tcti_context, 0x00, tcti_context_size);
  431: 
  432: 	/* initialize tcti context */
  433: 	rval = tcti_init(this->tcti_context, &tcti_context_size, tcti_opts);
  434: 	if (rval != TSS2_RC_SUCCESS)
  435: 	{
  436: 		DBG1(DBG_PTS, "%s tcti init allocation failed: 0x%06x", LABEL,rval);
  437: 		return FALSE;
  438: 	}
  439: 	return TRUE;
  440: }
  441: 
  442: /**
  443:  * Initialize TSS2 Sys context
  444:  */
  445: static bool initialize_sys_context(private_tpm_tss_tss2_t *this)
  446: {
  447: 	uint32_t sys_context_size;
  448: 	uint32_t rval;
  449: 
  450: 	TSS2_ABI_VERSION abi_version = {
  451: 		.tssCreator = 1,
  452:     	.tssFamily = 2,
  453:     	.tssLevel = 1,
  454:     	.tssVersion = 108
  455: 	};
  456: 
  457: 	/* determine size of sys context */
  458: 	sys_context_size = Tss2_Sys_GetContextSize(0);
  459: 
  460: 	/* allocate memory for sys context */
  461: 	this->sys_context = (TSS2_SYS_CONTEXT*)malloc(sys_context_size);
  462: 
  463: 	/* initialize sys context */
  464: 	rval = Tss2_Sys_Initialize(this->sys_context, sys_context_size,
  465: 							   this->tcti_context, &abi_version);
  466: 	if (rval != TSS2_RC_SUCCESS)
  467: 	{
  468: 		DBG1(DBG_PTS, "%s could not get sys_context: 0x%06x",
  469: 					   LABEL, rval);
  470: 		return FALSE;
  471: 	}
  472: 
  473: 	/* get a list of supported algorithms and ECC curves */
  474: 	return get_algs_capability(this);
  475: }
  476: 
  477: /**
  478:  * Finalize TSS context
  479:  */
  480: static void finalize_context(private_tpm_tss_tss2_t *this)
  481: {
  482: 	if (this->tcti_context)
  483: 	{
  484: 		Tss2_Tcti_Finalize(this->tcti_context);
  485: 		free(this->tcti_context);
  486: 	}
  487: 	if (this->sys_context)
  488: 	{
  489: 		Tss2_Sys_Finalize(this->sys_context);
  490: 		free(this->sys_context);
  491: 	}
  492: }
  493: 
  494: METHOD(tpm_tss_t, get_version, tpm_version_t,
  495: 	private_tpm_tss_tss2_t *this)
  496: {
  497: 	return TPM_VERSION_2_0;
  498: }
  499: 
  500: METHOD(tpm_tss_t, get_version_info, chunk_t,
  501: 	private_tpm_tss_tss2_t *this)
  502: {
  503: 	return this->version_info;
  504: }
  505: 
  506: /**
  507:  * read the public key portion of a TSS 2.0 key from NVRAM
  508:  */
  509: bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle,
  510: 	TPM2B_PUBLIC *public)
  511: {
  512: 	uint32_t rval;
  513: 
  514: 	TPM2B_NAME name = { sizeof(TPM2B_NAME)-2, };
  515: 	TPM2B_NAME qualified_name = { sizeof(TPM2B_NAME)-2, };
  516: 	TSS2L_SYS_AUTH_RESPONSE auth_rsp;
  517: 
  518: 
  519: 	/* read public key for a given object handle from TPM 2.0 NVRAM */
  520: 	this->mutex->lock(this->mutex);
  521: 	rval = Tss2_Sys_ReadPublic(this->sys_context, handle, 0, public, &name,
  522: 							   &qualified_name, &auth_rsp);
  523: 	this->mutex->unlock(this->mutex);
  524: 	if (rval != TPM2_RC_SUCCESS)
  525: 	{
  526: 		DBG1(DBG_PTS, "%s could not read public key from handle 0x%08x: 0x%06x",
  527: 					   LABEL, handle, rval);
  528: 		return FALSE;
  529: 	}
  530: 	return TRUE;
  531: }
  532: 
  533: METHOD(tpm_tss_t, generate_aik, bool,
  534: 	private_tpm_tss_tss2_t *this, chunk_t ca_modulus, chunk_t *aik_blob,
  535: 	chunk_t *aik_pubkey, chunk_t *identity_req)
  536: {
  537: 	return FALSE;
  538: }
  539: 
  540: METHOD(tpm_tss_t, get_public, chunk_t,
  541: 	private_tpm_tss_tss2_t *this, uint32_t handle)
  542: {
  543: 	TPM2B_PUBLIC public = { 0, };
  544: 	TPM2_ALG_ID sig_alg, digest_alg;
  545: 	chunk_t aik_pubkey = chunk_empty;
  546: 
  547: 	if (!read_public(this, handle, &public))
  548: 	{
  549: 		return chunk_empty;
  550: 	}
  551: 
  552: 	/* convert TSS 2.0 public key blot into PKCS#1 format */
  553: 	switch (public.publicArea.type)
  554: 	{
  555: 		case TPM2_ALG_RSA:
  556: 		{
  557: 			TPM2B_PUBLIC_KEY_RSA *rsa;
  558: 			TPMT_RSA_SCHEME *scheme;
  559: 			chunk_t aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
  560: 			chunk_t aik_modulus;
  561: 			uint32_t exponent;
  562: 
  563: 			scheme = &public.publicArea.parameters.rsaDetail.scheme;
  564: 			sig_alg   = scheme->scheme;
  565: 			digest_alg = scheme->details.anySig.hashAlg;
  566: 
  567: 			rsa = &public.publicArea.unique.rsa;
  568: 			aik_modulus = chunk_create(rsa->buffer, rsa->size);
  569: 			exponent = htonl(public.publicArea.parameters.rsaDetail.exponent);
  570: 			if (exponent)
  571: 			{
  572: 				aik_exponent = chunk_from_thing(exponent);
  573: 			}
  574: 
  575: 			/* subjectPublicKeyInfo encoding of RSA public key */
  576: 			if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
  577: 					NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
  578: 					CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
  579: 			{
  580: 				DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of public key "
  581: 							  "failed", LABEL);
  582: 				return chunk_empty;
  583: 			}
  584: 			break;
  585: 		}
  586: 		case TPM2_ALG_ECC:
  587: 		{
  588: 			TPMS_ECC_POINT *ecc;
  589: 			TPMT_ECC_SCHEME *scheme;
  590: 			chunk_t ecc_point;
  591: 			uint8_t *pos;
  592: 
  593: 			scheme = &public.publicArea.parameters.eccDetail.scheme;
  594: 			sig_alg   = scheme->scheme;
  595: 			digest_alg = scheme->details.anySig.hashAlg;
  596: 
  597: 			ecc = &public.publicArea.unique.ecc;
  598: 
  599: 			/* allocate space for bit string */
  600: 			pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING,
  601: 									2 + ecc->x.size + ecc->y.size);
  602: 			/* bit string length is a multiple of octets */
  603: 			*pos++ = 0x00;
  604: 			/* uncompressed ECC point format */
  605: 			*pos++ = 0x04;
  606: 			/* copy x coordinate of ECC point */
  607: 			memcpy(pos, ecc->x.buffer, ecc->x.size);
  608: 			pos += ecc->x.size;
  609: 			/* copy y coordinate of ECC point */
  610: 			memcpy(pos, ecc->y.buffer, ecc->y.size);
  611: 			/* subjectPublicKeyInfo encoding of ECC public key */
  612: 			aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
  613: 							asn1_wrap(ASN1_SEQUENCE, "mm",
  614: 								asn1_build_known_oid(OID_EC_PUBLICKEY),
  615: 								asn1_build_known_oid(ecc->x.size == 32 ?
  616: 										OID_PRIME256V1 : OID_SECT384R1)),
  617: 							ecc_point);
  618: 			break;
  619: 		}
  620: 		default:
  621: 			DBG1(DBG_PTS, "%s unsupported key type", LABEL);
  622: 			return chunk_empty;
  623: 	}
  624: 	DBG1(DBG_PTS, "signature algorithm is %N with %N hash",
  625: 		 tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg);
  626: 	return aik_pubkey;
  627: }
  628: 
  629: METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
  630: 	private_tpm_tss_tss2_t *this, uint32_t handle)
  631: {
  632: 	TPM2B_PUBLIC public = { 0, };
  633: 	hash_algorithm_t digest;
  634: 	signature_params_t supported_scheme;
  635: 
  636: 	if (!read_public(this, handle, &public))
  637: 	{
  638: 		return enumerator_create_empty();
  639: 	}
  640: 
  641: 	switch (public.publicArea.type)
  642: 	{
  643: 		case TPM2_ALG_RSA:
  644: 		{
  645: 			TPMS_RSA_PARMS *rsa;
  646: 			TPMT_RSA_SCHEME *scheme;
  647: 
  648: 			rsa = &public.publicArea.parameters.rsaDetail;
  649: 			scheme = &rsa->scheme;
  650: 			digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
  651: 
  652: 			switch (scheme->scheme)
  653: 			{
  654: 				case TPM2_ALG_RSAPSS:
  655: 				{
  656: 					ssize_t salt_len;
  657: 
  658: 					salt_len = this->fips_186_4 ? RSA_PSS_SALT_LEN_DEFAULT :
  659: 												  RSA_PSS_SALT_LEN_MAX;
  660: 					rsa_pss_params_t pss_params = {
  661: 						.hash = digest,
  662: 						.mgf1_hash = digest,
  663: 						.salt_len = salt_len,
  664: 					};
  665: 					supported_scheme = (signature_params_t){
  666: 						.scheme = SIGN_RSA_EMSA_PSS,
  667: 						.params = &pss_params,
  668: 					};
  669: 					if (!rsa_pss_params_set_salt_len(&pss_params, rsa->keyBits))
  670: 					{
  671: 						return enumerator_create_empty();
  672: 					}
  673: 					break;
  674: 				}
  675: 				case TPM2_ALG_RSASSA:
  676: 					supported_scheme = (signature_params_t){
  677: 						.scheme = signature_scheme_from_oid(
  678: 									hasher_signature_algorithm_to_oid(digest,
  679: 																	  KEY_RSA)),
  680: 					};
  681: 					break;
  682: 				default:
  683: 					return enumerator_create_empty();
  684: 			}
  685: 			break;
  686: 		}
  687: 		case TPM2_ALG_ECC:
  688: 		{
  689: 			TPMT_ECC_SCHEME *scheme;
  690: 
  691: 			scheme = &public.publicArea.parameters.eccDetail.scheme;
  692: 			digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
  693: 
  694: 			switch (scheme->scheme)
  695: 			{
  696: 				case TPM2_ALG_ECDSA:
  697: 					supported_scheme = (signature_params_t){
  698: 						.scheme = signature_scheme_from_oid(
  699: 									hasher_signature_algorithm_to_oid(digest,
  700: 																	KEY_ECDSA)),
  701: 					};
  702: 					break;
  703: 				default:
  704: 					return enumerator_create_empty();
  705: 			}
  706: 			break;
  707: 		}
  708: 		default:
  709: 			DBG1(DBG_PTS, "%s unsupported key type", LABEL);
  710: 			return enumerator_create_empty();
  711: 	}
  712: 	return enumerator_create_single(signature_params_clone(&supported_scheme),
  713: 									(void*)signature_params_destroy);
  714: }
  715: 
  716: METHOD(tpm_tss_t, has_pcr_bank, bool,
  717: 	private_tpm_tss_tss2_t *this, hash_algorithm_t alg)
  718: {
  719: 	TPM2_ALG_ID alg_id;
  720: 	int i;
  721: 
  722: 	alg_id = hash_alg_to_tpm_alg_id(alg);
  723: 
  724: 	for (i = 0; i < this->assigned_pcrs_count; i++)
  725: 	{
  726: 		if (this->assigned_pcrs[i] == alg_id)
  727: 		{
  728: 			return TRUE;
  729: 		}
  730: 	}
  731: 
  732: 	return FALSE;
  733: }
  734: 
  735: /**
  736:  * Configure a PCR Selection assuming a maximum of 24 registers
  737:  */
  738: static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs,
  739: 							   hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel)
  740: {
  741: 	uint32_t pcr;
  742: 
  743: 	/* check if there is an assigned PCR bank for this hash algorithm */
  744: 	if (!has_pcr_bank(this, alg))
  745: 	{
  746: 		DBG1(DBG_PTS, "%s %N hash algorithm not supported by any PCR bank",
  747: 			 LABEL, hash_algorithm_short_names, alg);
  748: 		return FALSE;
  749: 	}
  750: 
  751: 	/* initialize the PCR Selection structure,*/
  752: 	pcr_sel->count = 1;
  753: 	pcr_sel->pcrSelections[0].hash = hash_alg_to_tpm_alg_id(alg);
  754: ;
  755: 	pcr_sel->pcrSelections[0].sizeofSelect = 3;
  756: 	pcr_sel->pcrSelections[0].pcrSelect[0] = 0;
  757: 	pcr_sel->pcrSelections[0].pcrSelect[1] = 0;
  758: 	pcr_sel->pcrSelections[0].pcrSelect[2] = 0;
  759: 
  760: 	/* set the selected PCRs */
  761: 	for (pcr = 0; pcr < PLATFORM_PCR; pcr++)
  762: 	{
  763: 		if (pcrs & (1 << pcr))
  764: 		{
  765: 			pcr_sel->pcrSelections[0].pcrSelect[pcr / 8] |= ( 1 << (pcr % 8) );
  766: 		}
  767: 	}
  768: 	return TRUE;
  769: }
  770: 
  771: METHOD(tpm_tss_t, read_pcr, bool,
  772: 	private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
  773: 	hash_algorithm_t alg)
  774: {
  775: 	TPML_PCR_SELECTION pcr_selection;
  776: 	TPML_DIGEST pcr_values;
  777: 
  778: 	uint32_t pcr_update_counter, rval;
  779: 	uint8_t *pcr_value_ptr;
  780: 	size_t   pcr_value_len;
  781: 
  782: 	if (pcr_num >= PLATFORM_PCR)
  783: 	{
  784: 		DBG1(DBG_PTS, "%s maximum number of supported PCR is %d",
  785: 					   LABEL, PLATFORM_PCR);
  786: 		return FALSE;
  787: 	}
  788: 
  789: 	if (!init_pcr_selection(this, (1 << pcr_num), alg, &pcr_selection))
  790: 	{
  791: 		return FALSE;
  792: 	}
  793: 
  794: 	/* initialize the PCR Digest structure */
  795: 	memset(&pcr_values, 0, sizeof(TPML_DIGEST));
  796: 
  797: 	/* read the PCR value */
  798: 	this->mutex->lock(this->mutex);
  799: 	rval = Tss2_Sys_PCR_Read(this->sys_context, 0, &pcr_selection,
  800: 				&pcr_update_counter, &pcr_selection, &pcr_values, 0);
  801: 	this->mutex->unlock(this->mutex);
  802: 	if (rval != TPM2_RC_SUCCESS)
  803: 	{
  804: 		DBG1(DBG_PTS, "%s PCR bank could not be read: 0x%60x",
  805: 					   LABEL, rval);
  806: 		return FALSE;
  807: 	}
  808: 	pcr_value_ptr = (uint8_t *)pcr_values.digests[0].buffer;
  809: 	pcr_value_len = (size_t)   pcr_values.digests[0].size;
  810: 
  811: 	*pcr_value = chunk_clone(chunk_create(pcr_value_ptr, pcr_value_len));
  812: 
  813: 	return TRUE;
  814: }
  815: 
  816: METHOD(tpm_tss_t, extend_pcr, bool,
  817: 	private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
  818: 	chunk_t data, hash_algorithm_t alg)
  819: {
  820: 	uint32_t rval;
  821: 	TPML_DIGEST_VALUES digest_values;
  822: 	TSS2L_SYS_AUTH_COMMAND  auth_cmd = { 1, { auth_cmd_empty } };
  823: 	TSS2L_SYS_AUTH_RESPONSE auth_rsp;
  824: 
  825: 	auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
  826: 
  827: 	/* check if there is an assigned PCR bank for this hash algorithm */
  828: 	if (!has_pcr_bank(this, alg))
  829: 	{
  830: 		DBG1(DBG_PTS, "%s %N hash algorithm not supported by any PCR bank",
  831: 			 LABEL, hash_algorithm_short_names, alg);
  832: 		return FALSE;
  833: 	}
  834: 
  835: 	digest_values.count = 1;
  836: 	digest_values.digests[0].hashAlg = hash_alg_to_tpm_alg_id(alg);
  837: 
  838: 	switch (alg)
  839: 	{
  840: 		case HASH_SHA1:
  841: 			if (data.len != HASH_SIZE_SHA1)
  842: 			{
  843: 				return FALSE;
  844: 			}
  845: 			memcpy(digest_values.digests[0].digest.sha1, data.ptr,
  846: 				   HASH_SIZE_SHA1);
  847: 			break;
  848: 		case HASH_SHA256:
  849: 		case HASH_SHA3_256:
  850: 			if (data.len != HASH_SIZE_SHA256)
  851: 			{
  852: 				return FALSE;
  853: 			}
  854: 			memcpy(digest_values.digests[0].digest.sha256, data.ptr,
  855: 				    HASH_SIZE_SHA256);
  856: 			break;
  857: 		case HASH_SHA384:
  858: 		case HASH_SHA3_384:
  859: 			if (data.len != HASH_SIZE_SHA384)
  860: 			{
  861: 				return FALSE;
  862: 			}
  863: 			memcpy(digest_values.digests[0].digest.sha384, data.ptr,
  864: 				    HASH_SIZE_SHA384);
  865: 			break;
  866: 		case HASH_SHA512:
  867: 		case HASH_SHA3_512:
  868: 			if (data.len != HASH_SIZE_SHA512)
  869: 			{
  870: 				return FALSE;
  871: 			}
  872: 			memcpy(digest_values.digests[0].digest.sha512, data.ptr,
  873: 				    HASH_SIZE_SHA512);
  874: 			break;
  875: 		default:
  876: 			return FALSE;
  877: 	}
  878: 
  879: 	/* extend PCR */
  880: 	this->mutex->lock(this->mutex);
  881: 	rval = Tss2_Sys_PCR_Extend(this->sys_context, pcr_num, &auth_cmd,
  882: 							   &digest_values, &auth_rsp);
  883: 	this->mutex->unlock(this->mutex);
  884: 	if (rval != TPM2_RC_SUCCESS)
  885: 	{
  886: 		DBG1(DBG_PTS, "%s PCR %02u could not be extended: 0x%06x",
  887: 			 LABEL, pcr_num, rval);
  888: 		return FALSE;
  889: 	}
  890: 
  891: 	/* get updated PCR value */
  892: 	return read_pcr(this, pcr_num, pcr_value, alg);
  893: }
  894: 
  895: METHOD(tpm_tss_t, quote, bool,
  896: 	private_tpm_tss_tss2_t *this, uint32_t aik_handle, uint32_t pcr_sel,
  897: 	hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
  898: 	tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
  899: {
  900: 	chunk_t quoted_chunk, qualified_signer, extra_data, clock_info,
  901: 			firmware_version, pcr_select, pcr_digest;
  902: 	hash_algorithm_t pcr_digest_alg;
  903: 	bio_reader_t *reader;
  904: 	uint32_t rval;
  905: 
  906: 	TPM2B_DATA qualifying_data;
  907: 	TPML_PCR_SELECTION  pcr_selection;
  908: 	TPM2B_ATTEST quoted = { sizeof(TPM2B_ATTEST)-2, };
  909: 	TPMT_SIG_SCHEME scheme;
  910: 	TPMT_SIGNATURE sig;
  911: 	TPMI_ALG_HASH hash_alg;
  912: 	TSS2L_SYS_AUTH_COMMAND  auth_cmd = { 1, { auth_cmd_empty } };
  913: 	TSS2L_SYS_AUTH_RESPONSE auth_rsp;
  914: 
  915: 	auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
  916: 
  917: 	qualifying_data.size = data.len;
  918: 	memcpy(qualifying_data.buffer, data.ptr, data.len);
  919: 
  920: 	scheme.scheme = TPM2_ALG_NULL;
  921: 	memset(&sig, 0x00, sizeof(sig));
  922: 
  923: 	/* set Quote mode */
  924: 	*quote_mode = TPM_QUOTE_TPM2;
  925: 
  926: 	if (!init_pcr_selection(this, pcr_sel, alg, &pcr_selection))
  927: 	{
  928: 		return FALSE;
  929: 	}
  930: 
  931: 	this->mutex->lock(this->mutex);
  932: 	rval = Tss2_Sys_Quote(this->sys_context, aik_handle, &auth_cmd,
  933: 						  &qualifying_data, &scheme, &pcr_selection,  &quoted,
  934: 						  &sig, &auth_rsp);
  935: 	this->mutex->unlock(this->mutex);
  936: 	if (rval != TPM2_RC_SUCCESS)
  937: 	{
  938: 		DBG1(DBG_PTS,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL, rval);
  939: 		return FALSE;
  940: 	}
  941: 	quoted_chunk = chunk_create(quoted.attestationData, quoted.size);
  942: 
  943: 	reader = bio_reader_create(chunk_skip(quoted_chunk, 6));
  944: 	if (!reader->read_data16(reader, &qualified_signer) ||
  945: 		!reader->read_data16(reader, &extra_data) ||
  946: 		!reader->read_data  (reader, 17, &clock_info) ||
  947: 		!reader->read_data  (reader,  8, &firmware_version) ||
  948: 		!reader->read_data  (reader, 10, &pcr_select) ||
  949: 		!reader->read_data16(reader, &pcr_digest))
  950: 	{
  951: 		DBG1(DBG_PTS, "%s parsing of quoted struct failed", LABEL);
  952: 		reader->destroy(reader);
  953: 		return FALSE;
  954: 	}
  955: 	reader->destroy(reader);
  956: 
  957: 	DBG2(DBG_PTS, "PCR Composite digest: %B", &pcr_digest);
  958: 	DBG2(DBG_PTS, "TPM Quote Info: %B", &quoted_chunk);
  959: 	DBG2(DBG_PTS, "qualifiedSigner: %B", &qualified_signer);
  960: 	DBG2(DBG_PTS, "extraData: %B", &extra_data);
  961: 	DBG2(DBG_PTS, "clockInfo: %B", &clock_info);
  962: 	DBG2(DBG_PTS, "firmwareVersion: %B", &firmware_version);
  963: 	DBG2(DBG_PTS, "pcrSelect: %B", &pcr_select);
  964: 
  965: 	/* extract signature */
  966: 	switch (sig.sigAlg)
  967: 	{
  968: 		case TPM2_ALG_RSASSA:
  969: 		case TPM2_ALG_RSAPSS:
  970: 			*quote_sig = chunk_clone(
  971: 							chunk_create(
  972: 								sig.signature.rsassa.sig.buffer,
  973: 								sig.signature.rsassa.sig.size));
  974: 			hash_alg = sig.signature.rsassa.hash;
  975: 			break;
  976: 		case TPM2_ALG_ECDSA:
  977: 		case TPM2_ALG_ECDAA:
  978: 		case TPM2_ALG_SM2:
  979: 		case TPM2_ALG_ECSCHNORR:
  980: 			*quote_sig = chunk_cat("cc",
  981: 							chunk_create(
  982: 								sig.signature.ecdsa.signatureR.buffer,
  983: 								sig.signature.ecdsa.signatureR.size),
  984: 							chunk_create(
  985: 								sig.signature.ecdsa.signatureS.buffer,
  986: 								sig.signature.ecdsa.signatureS.size));
  987: 			hash_alg = sig.signature.ecdsa.hash;
  988: 			break;
  989: 		default:
  990: 			DBG1(DBG_PTS, "%s unsupported %N signature algorithm",
  991: 						   LABEL, tpm_alg_id_names, sig.sigAlg);
  992: 			return FALSE;
  993: 	}
  994: 
  995: 	DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg);
  996: 	pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg);
  997: 
  998: 	DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
  999: 
 1000: 	/* Create and initialize Quote Info object */
 1001: 	*quote_info = tpm_tss_quote_info_create(*quote_mode, pcr_digest_alg,
 1002: 														 pcr_digest);
 1003: 	(*quote_info)->set_tpm2_info(*quote_info, qualified_signer, clock_info,
 1004: 														 pcr_select);
 1005: 	(*quote_info)->set_version_info(*quote_info, firmware_version);
 1006: 
 1007: 	return TRUE;
 1008: }
 1009: 
 1010: METHOD(tpm_tss_t, sign, bool,
 1011: 	private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
 1012: 	signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin,
 1013: 	chunk_t *signature)
 1014: {
 1015: 	key_type_t key_type;
 1016: 	hash_algorithm_t hash_alg;
 1017: 	rsa_pss_params_t *rsa_pss_params;
 1018: 	uint32_t rval;
 1019: 
 1020: 	TPM2_ALG_ID alg_id;
 1021: 	TPM2B_MAX_BUFFER buffer;
 1022: 	TPM2B_DIGEST hash = { sizeof(TPM2B_DIGEST)-2, };
 1023: 	TPMT_TK_HASHCHECK validation;
 1024: 	TPM2B_PUBLIC public = { 0, };
 1025: 	TPMT_SIG_SCHEME sig_scheme;
 1026: 	TPMT_SIGNATURE sig;
 1027: 	TPMS_AUTH_COMMAND *cmd;
 1028: 	TSS2L_SYS_AUTH_COMMAND  auth_cmd = { 1, { auth_cmd_empty } };
 1029: 	TSS2L_SYS_AUTH_RESPONSE auth_rsp;
 1030: 
 1031: 	cmd = &auth_cmd.auths[0];
 1032: 	cmd->sessionHandle = TPM2_RS_PW;
 1033: 
 1034: 	if (pin.len > 0)
 1035: 	{
 1036: 		cmd->hmac.size = min(sizeof(cmd->hmac)-2, pin.len);
 1037: 		memcpy(cmd->hmac.buffer, pin.ptr, cmd->hmac.size);
 1038: 	}
 1039: 
 1040: 	if (scheme == SIGN_RSA_EMSA_PSS)
 1041: 	{
 1042: 		key_type = KEY_RSA;
 1043: 		rsa_pss_params = (rsa_pss_params_t *)params;
 1044: 		hash_alg = rsa_pss_params->hash;
 1045: 	}
 1046: 	else
 1047: 	{
 1048: 		key_type = key_type_from_signature_scheme(scheme);
 1049: 		hash_alg = hasher_from_signature_scheme(scheme, NULL);
 1050: 	}
 1051: 
 1052: 	/* Check if hash algorithm is supported by TPM */
 1053: 	alg_id = hash_alg_to_tpm_alg_id(hash_alg);
 1054: 	if (!is_supported_alg(this, alg_id))
 1055: 	{
 1056: 		DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
 1057: 			 LABEL, hash_algorithm_short_names, hash_alg);
 1058: 		return FALSE;
 1059: 	}
 1060: 
 1061: 	/* Get public key */
 1062: 	if (!read_public(this, handle, &public))
 1063: 	{
 1064: 		return FALSE;
 1065: 	}
 1066: 
 1067: 	if (key_type == KEY_RSA && public.publicArea.type == TPM2_ALG_RSA)
 1068: 	{
 1069: 		if (scheme == SIGN_RSA_EMSA_PSS)
 1070: 		{
 1071: 			sig_scheme.scheme = TPM2_ALG_RSAPSS;
 1072: 			sig_scheme.details.rsapss.hashAlg = alg_id;
 1073: 		}
 1074: 		else
 1075: 		{
 1076: 			sig_scheme.scheme = TPM2_ALG_RSASSA;
 1077: 			sig_scheme.details.rsassa.hashAlg = alg_id;
 1078: 		}
 1079: 	}
 1080: 	else if (key_type == KEY_ECDSA && public.publicArea.type == TPM2_ALG_ECC)
 1081: 	{
 1082: 		sig_scheme.scheme = TPM2_ALG_ECDSA;
 1083: 		sig_scheme.details.ecdsa.hashAlg = alg_id;
 1084: 
 1085: 	}
 1086: 	else
 1087: 	{
 1088: 		DBG1(DBG_PTS, "%s signature scheme %N not supported by TPM key",
 1089: 			 LABEL, signature_scheme_names, scheme);
 1090: 		return FALSE;
 1091: 	}
 1092: 
 1093: 	if (data.len <= TPM2_MAX_DIGEST_BUFFER)
 1094: 	{
 1095: 		memcpy(buffer.buffer, data.ptr, data.len);
 1096: 		buffer.size = data.len;
 1097: 
 1098: 		this->mutex->lock(this->mutex);
 1099: 		rval = Tss2_Sys_Hash(this->sys_context, 0, &buffer, alg_id, hierarchy,
 1100: 							 &hash, &validation, 0);
 1101: 		this->mutex->unlock(this->mutex);
 1102: 		if (rval != TPM2_RC_SUCCESS)
 1103: 		{
 1104: 			DBG1(DBG_PTS,"%s Tss2_Sys_Hash failed: 0x%06x", LABEL, rval);
 1105: 			return FALSE;
 1106: 		}
 1107: 	}
 1108: 	else
 1109: 	{
 1110: 	    TPMI_DH_OBJECT sequence_handle;
 1111: 	    TPM2B_AUTH null_auth;
 1112: 
 1113: 		null_auth.size = 0;
 1114: 		this->mutex->lock(this->mutex);
 1115: 		rval = Tss2_Sys_HashSequenceStart(this->sys_context, 0, &null_auth,
 1116: 										  alg_id, &sequence_handle, 0);
 1117: 		if (rval != TPM2_RC_SUCCESS)
 1118: 		{
 1119: 			DBG1(DBG_PTS,"%s Tss2_Sys_HashSequenceStart failed: 0x%06x",
 1120: 				 LABEL, rval);
 1121: 			this->mutex->unlock(this->mutex);
 1122: 			return FALSE;
 1123: 		}
 1124: 
 1125: 		while (data.len > 0)
 1126: 		{
 1127: 			buffer.size = min(data.len, TPM2_MAX_DIGEST_BUFFER);
 1128: 			memcpy(buffer.buffer, data.ptr, buffer.size);
 1129: 			data.ptr += buffer.size;
 1130: 			data.len -= buffer.size;
 1131: 
 1132: 			rval = Tss2_Sys_SequenceUpdate(this->sys_context, sequence_handle,
 1133: 										   &auth_cmd, &buffer, 0);
 1134: 			if (rval != TPM2_RC_SUCCESS)
 1135: 			{
 1136: 				DBG1(DBG_PTS,"%s Tss2_Sys_SequenceUpdate failed: 0x%06x",
 1137: 					 LABEL, rval);
 1138: 				this->mutex->unlock(this->mutex);
 1139: 				return FALSE;
 1140: 			}
 1141: 		}
 1142: 		buffer.size = 0;
 1143: 
 1144: 		rval = Tss2_Sys_SequenceComplete(this->sys_context, sequence_handle,
 1145: 										 &auth_cmd, &buffer, hierarchy,
 1146: 										 &hash, &validation, 0);
 1147: 		this->mutex->unlock(this->mutex);
 1148: 		if (rval != TPM2_RC_SUCCESS)
 1149: 		{
 1150: 			DBG1(DBG_PTS,"%s Tss2_Sys_SequenceComplete failed: 0x%06x",
 1151: 				 LABEL, rval);
 1152: 			return FALSE;
 1153: 		}
 1154: 	}
 1155: 
 1156: 	this->mutex->lock(this->mutex);
 1157: 	rval = Tss2_Sys_Sign(this->sys_context, handle, &auth_cmd, &hash,
 1158: 						 &sig_scheme, &validation, &sig, &auth_rsp);
 1159: 	this->mutex->unlock(this->mutex);
 1160: 	if (rval != TPM2_RC_SUCCESS)
 1161: 	{
 1162: 		DBG1(DBG_PTS,"%s Tss2_Sys_Sign failed: 0x%06x", LABEL, rval);
 1163: 		return FALSE;
 1164: 	}
 1165: 
 1166: 	/* extract signature */
 1167: 	switch (scheme)
 1168: 	{
 1169: 		case SIGN_RSA_EMSA_PKCS1_SHA1:
 1170: 		case SIGN_RSA_EMSA_PKCS1_SHA2_256:
 1171: 		case SIGN_RSA_EMSA_PKCS1_SHA2_384:
 1172: 		case SIGN_RSA_EMSA_PKCS1_SHA2_512:
 1173: 			*signature = chunk_clone(
 1174: 							chunk_create(
 1175: 								sig.signature.rsassa.sig.buffer,
 1176: 								sig.signature.rsassa.sig.size));
 1177: 			break;
 1178: 		case SIGN_RSA_EMSA_PSS:
 1179: 			*signature = chunk_clone(
 1180: 							chunk_create(
 1181: 								sig.signature.rsapss.sig.buffer,
 1182: 								sig.signature.rsapss.sig.size));
 1183: 			break;
 1184: 		case SIGN_ECDSA_256:
 1185: 		case SIGN_ECDSA_384:
 1186: 		case SIGN_ECDSA_521:
 1187: 			*signature = chunk_cat("cc",
 1188: 							chunk_create(
 1189: 								sig.signature.ecdsa.signatureR.buffer,
 1190: 								sig.signature.ecdsa.signatureR.size),
 1191: 							chunk_create(
 1192: 								sig.signature.ecdsa.signatureS.buffer,
 1193: 								sig.signature.ecdsa.signatureS.size));
 1194: 			break;
 1195: 		case SIGN_ECDSA_WITH_SHA256_DER:
 1196: 		case SIGN_ECDSA_WITH_SHA384_DER:
 1197: 		case SIGN_ECDSA_WITH_SHA512_DER:
 1198: 			*signature = asn1_wrap(ASN1_SEQUENCE, "mm",
 1199: 							asn1_integer("c",
 1200: 								chunk_create(
 1201: 									sig.signature.ecdsa.signatureR.buffer,
 1202: 									sig.signature.ecdsa.signatureR.size)),
 1203: 							asn1_integer("c",
 1204: 								chunk_create(
 1205: 									sig.signature.ecdsa.signatureS.buffer,
 1206: 									sig.signature.ecdsa.signatureS.size)));
 1207: 			break;
 1208: 		default:
 1209: 			DBG1(DBG_PTS, "%s unsupported %N signature scheme",
 1210: 						   LABEL, signature_scheme_names, scheme);
 1211: 			return FALSE;
 1212: 	}
 1213: 
 1214: 	return TRUE;
 1215: }
 1216: 
 1217: METHOD(tpm_tss_t, get_random, bool,
 1218: 	private_tpm_tss_tss2_t *this, size_t bytes, uint8_t *buffer)
 1219: {
 1220: 	size_t len, random_len= sizeof(TPM2B_DIGEST)-2;
 1221: 	TPM2B_DIGEST random = { random_len, };
 1222: 	uint8_t *pos = buffer;
 1223: 	uint32_t rval;
 1224: 
 1225: 	while (bytes > 0)
 1226: 	{
 1227: 		len = min(bytes, random_len);
 1228: 
 1229: 		this->mutex->lock(this->mutex);
 1230: 		rval = Tss2_Sys_GetRandom(this->sys_context, NULL, len, &random, NULL);
 1231: 		this->mutex->unlock(this->mutex);
 1232: 		if (rval != TSS2_RC_SUCCESS)
 1233: 		{
 1234: 			DBG1(DBG_PTS,"%s Tss2_Sys_GetRandom failed: 0x%06x", LABEL, rval);
 1235: 			return FALSE;
 1236: 	    }
 1237: 		memcpy(pos, random.buffer, random.size);
 1238: 		pos   += random.size;
 1239: 		bytes -= random.size;
 1240: 	}
 1241: 
 1242: 	return TRUE;
 1243: }
 1244: 
 1245: METHOD(tpm_tss_t, get_data, bool,
 1246: 	private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
 1247: 	chunk_t pin, chunk_t *data)
 1248: {
 1249: 	uint16_t max_data_size, nv_size, nv_offset = 0;
 1250: 	uint32_t rval;
 1251: 
 1252: 	TPMS_CAPABILITY_DATA cap_data;
 1253: 	TPMI_YES_NO more_data;
 1254: 	TPM2B_NAME nv_name = { sizeof(TPM2B_NAME)-2, };
 1255: 	TPM2B_NV_PUBLIC nv_public = { 0, };
 1256: 	TPM2B_MAX_NV_BUFFER nv_data = { TPM2_MAX_NV_BUFFER_SIZE, };
 1257: 	TPMS_AUTH_COMMAND *cmd;
 1258: 	TSS2L_SYS_AUTH_COMMAND  auth_cmd = { 1, { auth_cmd_empty } };
 1259: 	TSS2L_SYS_AUTH_RESPONSE auth_rsp;
 1260: 
 1261: 	/* query maximum TPM data transmission size */
 1262: 	this->mutex->lock(this->mutex);
 1263: 	rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_TPM_PROPERTIES,
 1264: 				TPM2_PT_NV_BUFFER_MAX, 1, &more_data, &cap_data, 0);
 1265: 	this->mutex->unlock(this->mutex);
 1266: 	if (rval != TPM2_RC_SUCCESS)
 1267: 	{
 1268: 		DBG1(DBG_PTS,"%s Tss2_Sys_GetCapability failed for "
 1269: 					 "TPM2_CAP_TPM_PROPERTIES: 0x%06x", LABEL, rval);
 1270: 		return FALSE;
 1271: 	}
 1272: 	max_data_size = min(cap_data.data.tpmProperties.tpmProperty[0].value,
 1273: 						TPM2_MAX_NV_BUFFER_SIZE);
 1274: 
 1275: 	/* get size of NV object */
 1276: 	this->mutex->lock(this->mutex);
 1277: 	rval = Tss2_Sys_NV_ReadPublic(this->sys_context, handle, 0, &nv_public,
 1278: 																&nv_name, 0);
 1279: 	this->mutex->unlock(this->mutex);
 1280: 	if (rval != TPM2_RC_SUCCESS)
 1281: 	{
 1282: 		DBG1(DBG_PTS,"%s Tss2_Sys_NV_ReadPublic failed: 0x%06x", LABEL, rval);
 1283: 		return FALSE;
 1284: 	}
 1285: 	nv_size = nv_public.nvPublic.dataSize;
 1286: 	*data = chunk_alloc(nv_size);
 1287: 
 1288: 	/* prepare NV read session */
 1289: 	cmd = &auth_cmd.auths[0];
 1290: 	cmd->sessionHandle = TPM2_RS_PW;
 1291: 
 1292: 	if (pin.len > 0)
 1293: 	{
 1294: 		cmd->hmac.size = min(sizeof(cmd->hmac)-2, pin.len);
 1295: 		memcpy(cmd->hmac.buffer, pin.ptr, cmd->hmac.size);
 1296: 	}
 1297: 
 1298: 	/* read NV data a maximum data size block at a time */
 1299: 	while (nv_size > 0)
 1300: 	{
 1301: 		this->mutex->lock(this->mutex);
 1302: 		rval = Tss2_Sys_NV_Read(this->sys_context, hierarchy, handle, &auth_cmd,
 1303: 					min(nv_size, max_data_size), nv_offset, &nv_data, &auth_rsp);
 1304: 		this->mutex->unlock(this->mutex);
 1305: 		if (rval != TPM2_RC_SUCCESS)
 1306: 		{
 1307: 			DBG1(DBG_PTS,"%s Tss2_Sys_NV_Read failed: 0x%06x", LABEL, rval);
 1308: 			chunk_free(data);
 1309: 			return FALSE;
 1310: 		}
 1311: 		memcpy(data->ptr + nv_offset, nv_data.buffer, nv_data.size);
 1312: 		nv_offset += nv_data.size;
 1313: 		nv_size   -= nv_data.size;
 1314: 	}
 1315: 
 1316: 	return TRUE;
 1317: }
 1318: 
 1319: METHOD(tpm_tss_t, get_event_digest, bool,
 1320: 	private_tpm_tss_tss2_t *this, int fd, hash_algorithm_t alg, chunk_t *digest)
 1321: {
 1322: 	uint8_t digest_buf[HASH_SIZE_SHA512];
 1323: 	uint32_t digest_count;
 1324: 	size_t digest_len = 0;
 1325: 	hash_algorithm_t hash_alg;
 1326: 	TPM2_ALG_ID alg_id;
 1327: 
 1328: 	if (this->old_event_digest_format)
 1329: 	{
 1330: 		if (alg != HASH_SHA1)
 1331: 		{
 1332: 			return FALSE;
 1333: 		}
 1334: 		digest_len = HASH_SIZE_SHA1;
 1335: 
 1336: 		*digest = chunk_alloc(digest_len);
 1337: 
 1338: 		if (read(fd, digest->ptr, digest_len) != digest_len)
 1339: 		{
 1340: 			return FALSE;
 1341: 		}
 1342: 	}
 1343: 	else
 1344: 	{
 1345: 		if (read(fd, &digest_count, 4) != 4)
 1346: 		{
 1347: 			return FALSE;
 1348: 		}
 1349: 		while (digest_count--)
 1350: 		{
 1351: 			if (read(fd, &alg_id, 2) != 2)
 1352: 			{
 1353: 				return FALSE;
 1354: 			}
 1355: 			hash_alg = hash_alg_from_tpm_alg_id(alg_id);
 1356: 
 1357: 			switch (hash_alg)
 1358: 			{
 1359: 				case HASH_SHA1:
 1360: 					digest_len = HASH_SIZE_SHA1;
 1361: 					break;
 1362: 				case HASH_SHA256:
 1363: 					digest_len = HASH_SIZE_SHA256;
 1364: 					break;
 1365: 				case HASH_SHA384:
 1366: 					digest_len = HASH_SIZE_SHA384;
 1367: 					break;
 1368: 				case HASH_SHA512:
 1369: 					digest_len = HASH_SIZE_SHA512;
 1370: 					break;
 1371: 				default:
 1372: 					DBG2(DBG_PTS, "alg_id: 0x%04x", alg_id);
 1373: 					return FALSE;
 1374: 			}
 1375: 			if (hash_alg == alg)
 1376: 			{
 1377: 				*digest = chunk_alloc(digest_len);
 1378: 				if (read(fd, digest->ptr, digest_len) != digest_len)
 1379: 				{
 1380: 				return FALSE;
 1381: 				}
 1382: 			}
 1383: 			else
 1384: 			{
 1385: 				/* read without storing */
 1386: 				if (read(fd, digest_buf, digest_len) != digest_len)
 1387: 				{
 1388: 					return FALSE;
 1389: 				}
 1390: 			}
 1391: 		}
 1392: 	}
 1393: 
 1394: 	return TRUE;
 1395: }
 1396: 
 1397: METHOD(tpm_tss_t, destroy, void,
 1398: 	private_tpm_tss_tss2_t *this)
 1399: {
 1400: 	finalize_context(this);
 1401: 	this->mutex->destroy(this->mutex);
 1402: 	free(this->version_info.ptr);
 1403: 	free(this);
 1404: }
 1405: 
 1406: /**
 1407:  * See header
 1408:  */
 1409: tpm_tss_t *tpm_tss_tss2_create()
 1410: {
 1411: 	private_tpm_tss_tss2_t *this;
 1412: 	bool available;
 1413: 
 1414: 	INIT(this,
 1415: 		.public = {
 1416: 			.get_version = _get_version,
 1417: 			.get_version_info = _get_version_info,
 1418: 			.generate_aik = _generate_aik,
 1419: 			.get_public = _get_public,
 1420: 			.supported_signature_schemes = _supported_signature_schemes,
 1421: 			.has_pcr_bank = _has_pcr_bank,
 1422: 			.read_pcr = _read_pcr,
 1423: 			.extend_pcr = _extend_pcr,
 1424: 			.quote = _quote,
 1425: 			.sign = _sign,
 1426: 			.get_random = _get_random,
 1427: 			.get_data = _get_data,
 1428: 			.get_event_digest = _get_event_digest,
 1429: 			.destroy = _destroy,
 1430: 		},
 1431: 		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
 1432: 	);
 1433: 
 1434: 	available = initialize_tcti_context(this);
 1435: 	if (available)
 1436: 	{
 1437: 		available = initialize_sys_context(this);
 1438: 	}
 1439: 	DBG1(DBG_PTS, "TPM 2.0 via TSS2 v2 %savailable", available ? "" : "not ");
 1440: 
 1441: 	if (!available)
 1442: 	{
 1443: 		destroy(this);
 1444: 		return NULL;
 1445: 	}
 1446: 	return &this->public;
 1447: }
 1448: 
 1449: /**
 1450:  * See header
 1451:  */
 1452: bool tpm_tss_tss2_init(void)
 1453: {
 1454: 	TSS2_TCTI_INFO_FUNC infofn;
 1455: 	const TSS2_TCTI_INFO *info;
 1456: 	char tcti_lib_format[] = "libtss2-tcti-%s.so.0";
 1457: 	char tcti_lib[BUF_LEN];
 1458: 	char *tcti_names[]   = { "device", "tabrmd", "mssim" };
 1459: 	char *tcti_options[] = { "/dev/tpmrm0", "", "" };
 1460: 	char *tcti_name;
 1461: 	bool match = FALSE;
 1462: 	struct stat st;
 1463: 	int i = 0;
 1464: 
 1465: 	/* check for the existence of an in-kernel TPM resource manager */
 1466: 	if (stat(tcti_options[i], &st))
 1467: 	{
 1468: 		i = 1;
 1469: 	}
 1470: 	DBG2(DBG_PTS, "%s \"%s\" in-kernel resource manager is %spresent",
 1471: 				   LABEL, tcti_options[0], i ? "not " : "");
 1472: 
 1473: 	/* select a dynamic TCTI library (device, tabrmd or mssim) */
 1474: 	tcti_name = lib->settings->get_str(lib->settings,
 1475: 					 "%s.plugins.tpm.tcti.name", tcti_names[i], lib->ns);
 1476: 	snprintf(tcti_lib, BUF_LEN, tcti_lib_format, tcti_name);
 1477: 
 1478: 	for (i = 0; i < countof(tcti_names); i++)
 1479: 	{
 1480: 		if (streq(tcti_name, tcti_names[i]))
 1481: 		{
 1482: 			match = TRUE;
 1483: 			break;
 1484: 		}
 1485: 	}
 1486: 	if (!match)
 1487: 	{
 1488: 		DBG1(DBG_PTS, "%s \"%s\" is not a valid TCTI library name",
 1489: 			 LABEL, tcti_lib);
 1490: 		return FALSE;
 1491: 	}
 1492: 
 1493: 	tcti_opts = lib->settings->get_str(lib->settings,
 1494: 					 "%s.plugins.tpm.tcti.opts", tcti_options[i], lib->ns);
 1495: 
 1496: 	/* open the selected dynamic TCTI library */
 1497: 	tcti_handle = dlopen(tcti_lib, RTLD_LAZY);
 1498: 	if (!tcti_handle)
 1499: 	{
 1500: 		DBG1(DBG_PTS, "%s could not load \"%s\"", LABEL, tcti_lib);
 1501: 		return FALSE;
 1502: 	}
 1503: 
 1504:  	infofn = (TSS2_TCTI_INFO_FUNC)dlsym(tcti_handle, TSS2_TCTI_INFO_SYMBOL);
 1505:     if (!infofn)
 1506: 	{
 1507:         DBG1(DBG_PTS, "%s symbol \"%s\" not found in \"%s\"", LABEL,
 1508: 					   TSS2_TCTI_INFO_SYMBOL, tcti_lib);
 1509: 		tpm_tss_tss2_deinit();
 1510: 
 1511: 		return FALSE;
 1512:     }
 1513: 	DBG2(DBG_PTS, "%s \"%s\" successfully loaded", LABEL, tcti_lib);
 1514: 	info = infofn();
 1515: 	tcti_init = info->init;
 1516: 
 1517: 	return TRUE;
 1518: }
 1519: 
 1520: /**
 1521:  * See header
 1522:  */
 1523: void tpm_tss_tss2_deinit(void)
 1524: {
 1525: 	dlclose(tcti_handle);
 1526: 	tcti_handle = NULL;
 1527: 	tcti_init   = NULL;
 1528: 	tcti_opts   = NULL;
 1529: }
 1530: 
 1531: #else /* TSS_TSS2_V2 */
 1532: 
 1533: /**
 1534:  * See header
 1535:  */
 1536: bool tpm_tss_tss2_init(void)
 1537: {
 1538: 	return TRUE;
 1539: }
 1540: 
 1541: /**
 1542:  * See header
 1543:  */
 1544: void tpm_tss_tss2_deinit(void)
 1545: {
 1546: 	/* empty */
 1547: }
 1548: 
 1549: #endif /* TSS_TSS2_V2 */
 1550: 

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