Updates to allow for TPM 2.0 quote.

This commit is contained in:
apldev4 2019-02-14 12:39:21 -05:00 committed by apldev2
parent aeebd068f5
commit efbd22812d
8 changed files with 151 additions and 20 deletions

View File

@ -9,6 +9,7 @@ CERTS_DIR="/etc/hirs/provisioner/certs/"
HIRS_SITE_CONFIG="/etc/hirs/hirs-site.config"
HIRS_PROVISIONER_CONFIG="/etc/hirs/provisioner/hirs-provisioner-config.sh"
HIRS_PROVISIONER_SCRIPT="/usr/share/hirs/provisioner/bin/HIRS_Provisioner"
HIRS_PROVISIONER_2_0_SCRIPT="/usr/local/bin/hirs-provisioner-tpm2"
HIRS_PROVISIONER_PROPERTIES="/etc/hirs/provisioner/provisioner.properties"
if [ "$EUID" != "0" ]; then
@ -105,10 +106,16 @@ function CheckProvisionPrereqsAndDoProvisioning {
function Provision {
# Provisioner will only retain one {uuid}.cer credential; remove any existing *.cer files.
echo "----> Removing old provisioner scripts, if any"
rm -f $CERTS_DIR/*.cer
echo "----> Removing old attestation credentials, if any"
rm -f $CERTS_DIR/*.cer /etc/hirs/ak.cer
echo "----> Provisioning TPM"
if [ -f $HIRS_PROVISIONER_2_0_SCRIPT ]
then
$HIRS_PROVISIONER_2_0_SCRIPT provision || { echo "----> Failed to provision TPM 2.0"; exit 1; }
else
$HIRS_PROVISIONER_SCRIPT $CLIENT_HOSTNAME || { echo "----> Failed to provision TPM"; exit 1; }
fi
}

View File

@ -140,11 +140,11 @@ list(APPEND REQUIRED_LIBS ${PROTOBUF_LIBRARY})
# Define the TPM 2.0 Provisioner Library
add_subdirectory(src)
# Set Project Header/Source files
set(EXECUTABLE_SOURCE_FILES src/TPM2_Provisioner.cpp)
# Create project executable
add_executable(${PROJECT_NAME} ${EXECUTABLE_SOURCE_FILES} ${PROJECT_CONFIG_FILES})
add_executable(${PROJECT_NAME} src/TPM2_Provisioner.cpp ${PROJECT_CONFIG_FILES})
# In TPM 2.0 land, there is currently not a way to fetch the TPM version info
add_executable(tpm_version src/tpm_version.cpp)
# Link necessary libraries
target_link_libraries(${PROJECT_NAME} TPM2_PROVISIONER_LIBRARY)
@ -159,13 +159,25 @@ if(CMAKE_THREAD_LIBS_INIT)
endif()
# Set commands for installation of project on target system (i.e. "make install")
install(TARGETS ${PROJECT_NAME}
install(TARGETS ${PROJECT_NAME} tpm_version
DESTINATION "bin")
install(FILES config/log4cplus_config.ini DESTINATION /etc/hirs/TPM2_Provisioner)
install(FILES scripts/tpm_aca_provision DESTINATION /usr/local/bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
install(DIRECTORY DESTINATION ${/var/log/hirs/provisioner}
DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
install(DIRECTORY DESTINATION ${/etc/hirs/provisioner}
DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
install(FILES ../HIRS_Provisioner/src/main/resources/defaults.properties DESTINATION /etc/hirs/provisioner RENAME provisioner.properties)
install(FILES ../HIRS_Provisioner/hirs-provisioner-config.sh DESTINATION /etc/hirs/provisioner
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
install(FILES ../HIRS_Provisioner/scripts/install/hirs-provisioner.sh DESTINATION /etc/hirs/provisioner
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
execute_process(COMMAND cp ../HIRS_Utils/src/main/resources/logging.properties ./config/
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})

View File

@ -1,8 +1,10 @@
HIRS_SITE_CONFIG="/etc/hirs/hirs-site.config"
mkdir -p /var/log/hirs/provisioner
mkdir -p /etc/hirs/provisioner/certs
ln -s -f /usr/local/bin/hirs-provisioner-tpm2 /usr/sbin/hirs-provisioner-tpm2
ln -s -f /usr/local/bin/tpm_aca_provision /usr/sbin/tpm_aca_provision
ln -s -f /usr/local/bin/tpm_version /usr/sbin/tpm_version
if [ ! -f $HIRS_SITE_CONFIG ]; then
# Create template site config if it does not exist
@ -29,3 +31,4 @@ DEFAULT_SITE_CONFIG_FILE
echo "$HIRS_SITE_CONFIG not found - a template has been created"
echo "Set your site configuration manually in $HIRS_SITE_CONFIG, then run 'hirs-provisioner-tpm2 provision' to provision this system"
fi
ln -s -f /etc/hirs/provisioner/hirs-provisioner.sh /usr/sbin/hirs-provisioner

View File

@ -8,8 +8,10 @@ fi
HIRS_SITE_CONFIG="/etc/hirs/hirs-site.config"
mkdir -p /var/log/hirs/provisioner
mkdir -p /etc/hirs/provisioner/certs
ln -s -f /usr/local/bin/hirs-provisioner-tpm2 /usr/sbin/hirs-provisioner-tpm2
ln -s -f /usr/local/bin/tpm_aca_provision /usr/sbin/tpm_aca_provision
ln -s -f /usr/local/bin/tpm_version /usr/sbin/tpm_version
if [ ! -f $HIRS_SITE_CONFIG ]; then
# Create template site config if it does not exist
@ -36,3 +38,4 @@ DEFAULT_SITE_CONFIG_FILE
echo "$HIRS_SITE_CONFIG not found - a template has been created"
echo "Set your site configuration manually in $HIRS_SITE_CONFIG, then run 'hirs-provisioner-tpm2 provision' to provision this system"
fi
ln -s -f /etc/hirs/provisioner/hirs-provisioner.sh /usr/sbin/hirs-provisioner

View File

@ -0,0 +1,11 @@
#include <iostream>
using std::cout;
using std::endl;
int main(void) {
cout << "Chip Version: 2.0.0.0" << endl;
cout << "TPM Vendor ID: UNKN" << endl;
return 0;
}

View File

@ -61,9 +61,6 @@ public final class TPMMeasurementRecord extends ExaminableRecord {
LOGGER.error("null hash value");
throw new NullPointerException("hash");
}
if (hash.getAlgorithm() != DigestAlgorithm.SHA1) {
throw new IllegalArgumentException("hash algorithm is not SHA-1");
}
this.pcrId = pcrId;
this.hash = hash;

View File

@ -1,5 +1,7 @@
package hirs.data.persist.tpm;
import hirs.data.persist.Digest;
import hirs.data.persist.DigestAlgorithm;
import hirs.data.persist.TPMMeasurementRecord;
import javax.persistence.AttributeOverride;
@ -21,6 +23,8 @@ import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* Java class for PcrInfoShort complex type, which was modified from code
@ -200,16 +204,31 @@ public class PcrInfoShort {
}
/**
* Calculates the digest of the PCR values the same way a TPM computes the digest contained in
* the quote. Useful for TPM appraisal and for ensuring the digest of the collected PCR values
* match the digest in the quote.
* Calculates the SHA-1 or SHA-256 digest of the PCR values the same way a TPM computes the
* digest contained in the quote. Useful for TPM appraisal and for ensuring the digest of the
* collected PCR values match the digest in the quote.
*
* @return byte array containing the digest
* @throws NoSuchAlgorithmException
* if MessageDigest doesn't recognize "SHA-1"
* if MessageDigest doesn't recognize "SHA-1" or "SHA-256"
*/
public final byte[] getCalculatedDigest() throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
if (this.isTpm1()) {
return getCalculatedDigestTpmV1p2(MessageDigest.getInstance("SHA-1"));
} else {
return getCalculatedDigestTpmV2p0(MessageDigest.getInstance("SHA-256"));
}
}
/**
* Calculates the SHA-1 digest of the PCR values the same way a TPM computes the digest
* contained in the quote. Useful for TPM appraisal and for ensuring the digest of the
* collected PCR values match the digest in the quote.
*
* @param messageDigest message digest algorithm to use
* @return byte array containing the digest
*/
private byte[] getCalculatedDigestTpmV1p2(final MessageDigest messageDigest) {
byte[] computedDigest;
final int sizeOfInt = 4;
@ -235,6 +254,32 @@ public class PcrInfoShort {
return computedDigest;
}
/**
* Calculates the digest of the PCR values the same way a TPM computes the digest contained in
* the quote. Useful for TPM appraisal and for ensuring the digest of the collected PCR values
* match the digest in the quote.
*
* @param messageDigest message digest algorithm to use
* @return byte array containing the digest
*/
private byte[] getCalculatedDigestTpmV2p0(final MessageDigest messageDigest) {
int sizeOfByteBuffer = pcrComposite.getValueSize();
ByteBuffer byteBuffer = ByteBuffer.allocate(sizeOfByteBuffer);
LOGGER.debug("Size of the buffer allocated to hash: {}", sizeOfByteBuffer);
Iterator iter = pcrComposite.getPcrValueList().iterator();
while (iter.hasNext()) {
TPMMeasurementRecord record = (TPMMeasurementRecord) iter.next();
byteBuffer.put(record.getHash().getDigest());
}
LOGGER.debug("PCR composite buffer to be hashed: {}",
Hex.encodeHexString(byteBuffer.array()));
byte[] computedDigest = messageDigest.digest(byteBuffer.array());
LOGGER.debug("Calculated digest: {}", Hex.encodeHexString(computedDigest));
return computedDigest;
}
/**
* Returns the value of PcrInfoShort flattened into a byte array. The array contains the value
* of PCR selection, the locality at release, and the composite hash.
@ -250,4 +295,22 @@ public class PcrInfoShort {
return byteBuffer.array();
}
/**
* Determines whether the TPM used to generate this pcr info is version 1.2 or not.
*
* @return whether the TPM used to generate this pcr info is version 1.2 or not
*/
public boolean isTpm1() {
// need to get an individual PCR and measure length to determine SHA1 v SHA 256
List<TPMMeasurementRecord> pcrs = this.getPcrComposite().getPcrValueList();
if (pcrs.size() == 0) {
// it's the case of an empty pcrmask, so it doesn't matter
return false;
}
Digest hash = pcrs.get(0).getHash();
// check if the hash algorithm is SHA 1, if so it's TPM 1.2, if not it's TPM 2.0
return hash.getAlgorithm() == DigestAlgorithm.SHA1;
}
}

View File

@ -52,11 +52,15 @@ import java.util.Arrays;
name = "QuoteSignature",
namespace = "http://www.trustedcomputinggroup.org/XML/SCHEMA/"
+ "Integrity_Report_v1_0#",
propOrder = {"signatureValue" })
propOrder = {"rawQuote", "signatureValue" })
@Embeddable
public class QuoteSignature {
private static final int SIGNATURE_LENGTH = 10000;
@XmlElement(name = "RawQuote", required = false)
@Column(length = SIGNATURE_LENGTH)
private final byte[] rawQuote;
@XmlElement(name = "SignatureValue", required = true)
@Column(length = SIGNATURE_LENGTH)
private final byte[] signatureValue;
@ -65,6 +69,7 @@ public class QuoteSignature {
* Default constructor necessary for marshalling/unmarshalling xml.
*/
protected QuoteSignature() {
this.rawQuote = new byte[0];
this.signatureValue = new byte[0];
}
@ -76,6 +81,23 @@ public class QuoteSignature {
* SignatureValue that contains the Quote2 signature, may be null
*/
public QuoteSignature(final byte[] signatureValue) {
this(signatureValue, null);
}
/**
* Constructor used to create a QuoteSignature. The signature value may be
* null.
*
* @param signatureValue
* SignatureValue that contains the Quote2 signature, may be null
* @param rawQuote
* Value that was signed, may be null
*/
public QuoteSignature(final byte[] signatureValue, final byte[] rawQuote) {
if (rawQuote == null) {
this.rawQuote = null;
} else {
this.rawQuote = rawQuote.clone();
}
if (signatureValue == null) {
this.signatureValue = null;
} else {
@ -90,11 +112,24 @@ public class QuoteSignature {
*
*/
public final byte[] getSignatureValue() {
if (signatureValue == null) {
return null;
} else {
if (signatureValue != null) {
return signatureValue.clone();
}
return null;
}
/**
* Gets the value of the rawQuote property.
*
* @return possible object is a byte array containing the raw quote value, may return null
*
*/
public byte[] getRawQuote() {
if (rawQuote != null) {
return rawQuote.clone();
}
return null;
}
@Override