Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions test/integration/tests/getekcertificate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ tpm2 loadexternal -C e -u test_rsa_ek.pub -c rsa_key.ctx
tpm2 readpublic -c rsa_key.ctx -f pem -o test_rsa_ek.pem
openssl x509 -pubkey -in rsa_ek_cert.bin -noout -out test_ek.pem
diff test_rsa_ek.pem test_ek.pem
tpm2 flushcontext -t

# Sample ECC ek public from a real platform
echo "007a0023000b000300b20020837197674484b3f81a90cc8d46a5d724fd52
Expand All @@ -90,10 +91,13 @@ tpm2 loadexternal -C e -u test_ecc_ek.pub -c ecc_key.ctx
tpm2 readpublic -c ecc_key.ctx -f pem -o test_ecc_ek.pem
openssl x509 -pubkey -in ecc_ek_cert.bin -noout -out test_ek.pem
diff test_ecc_ek.pem test_ek.pem
tpm2 flushcontext -t

# Retrieve EK certificates from NV indices
RSA_EK_CERT_NV_INDEX=0x01C00002
ECC_EK_CERT_NV_INDEX=0x01C0000A
RSA_3072_EK_CERT_NV_INDEX=0x01C0001C
ECC_NIST_P384_EK_CERT_NV_INDEX=0x01C00016

define_ek_cert_nv_index() {
file_size=`ls -l $1 | awk {'print $5'}`
Expand Down Expand Up @@ -134,4 +138,49 @@ tpm2 getekcertificate -o nv_rsa_ek_cert.der -o nv_ecc_ek_cert.der
diff nv_rsa_ek_cert.der rsa_ek_cert.der
diff nv_ecc_ek_cert.der ecc_ek_cert.der

rm nv_rsa_ek_cert.der rsa_ek_cert.der nv_ecc_ek_cert.der ecc_ek_cert.der -f

## RSA & ECC self-signed EK certs stored in high range NV indexes
tpm2 nvundefine -C p $RSA_EK_CERT_NV_INDEX
tpm2 nvundefine -C p $ECC_EK_CERT_NV_INDEX

create_self_signed_ek_cert(){
case "$1" in
*rsa_3072)
openssl genpkey -algorithm RSA -out priv_key.pem \
-pkeyopt rsa_keygen_bits:3072 > /dev/null 2>&1
openssl req -new -key priv_key.pem -x509 -days 1 \
-subj "/" -outform DER -out $2
;;
*ecc_nist_p384)
openssl ecparam -name secp384r1 -genkey -out priv_key.pem > /dev/null 2>&1
openssl req -new -key priv_key.pem -x509 -days 1 \
-subj "/" -outform DER -out $2
;;
*) echo "Unsupported key type $1"; return 1;;
esac
}

create_self_signed_ek_cert rsa_3072 rsa_ek_cert.der
create_self_signed_ek_cert ecc_nist_p384 ecc_ek_cert.der

define_ek_cert_nv_index rsa_ek_cert.der $RSA_3072_EK_CERT_NV_INDEX
define_ek_cert_nv_index ecc_ek_cert.der $ECC_NIST_P384_EK_CERT_NV_INDEX

tpm2 getekcertificate -o nv_rsa_ek_cert.der -o nv_ecc_ek_cert.der

diff nv_rsa_ek_cert.der rsa_ek_cert.der
diff nv_ecc_ek_cert.der ecc_ek_cert.der

rm nv_rsa_ek_cert.der nv_ecc_ek_cert.der -f

## Make sure that if there are several certificates of the same type, then the one belonging to low range has priority
openssl x509 -in ecc_ek_cert.bin -out ecc_low_range_ek_cert.der -outform DER
define_ek_cert_nv_index ecc_low_range_ek_cert.der $ECC_EK_CERT_NV_INDEX

tpm2 getekcertificate -o nv_rsa_ek_cert.der -o nv_ecc_ek_cert.der

diff nv_ecc_ek_cert.der ecc_low_range_ek_cert.der
diff nv_rsa_ek_cert.der rsa_ek_cert.der

exit 0
117 changes: 93 additions & 24 deletions tools/tpm2_getekcertificate.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
#include "tpm2_tool.h"


/*
* Sourced from TCG Vendor ID Registry v1.06:
* https://trustedcomputinggroup.org/resource/vendor-id-registry/
*
*/

typedef enum tpm_manufacturer tpm_manufacturer;
enum tpm_manufacturer {
VENDOR_AMD = 0x414D4400,
Expand Down Expand Up @@ -57,6 +63,25 @@ enum pubkey_enc_mode {
ENC_AMD = 2,
};

/*
* Sourced from TCG PC Client Platform TPM Profile Specification v1.05 rev 14:
* https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
*
*/

typedef enum ek_nv_index ek_nv_index;
enum ek_nv_index {
RSA_EK_CERT_NV_INDEX = 0x01C00002,
ECC_EK_CERT_NV_INDEX = 0x01C0000A,
RSA_2048_EK_CERT_NV_INDEX = 0x01C00012,
RSA_3072_EK_CERT_NV_INDEX = 0x01C0001C,
RSA_4096_EK_CERT_NV_INDEX = 0x01C0001E,
ECC_NIST_P256_EK_CERT_NV_INDEX = 0x01C00014,
ECC_NIST_P384_EK_CERT_NV_INDEX = 0x01C00016,
ECC_NIST_P521_EK_CERT_NV_INDEX = 0x01C00018,
ECC_SM2_P256_EK_CERT_NV_INDEX = 0x01C0001A,
};

#define EK_SERVER_INTEL "https://ekop.intel.com/ekcertservice/"
#define EK_SERVER_AMD "https://ftpm.amd.com/pki/aia/"

Expand All @@ -68,6 +93,8 @@ struct tpm_getekcertificate_ctx {
tpm_manufacturer manufacturer;
bool is_rsa_ek_cert_nv_location_defined;
bool is_ecc_ek_cert_nv_location_defined;
ek_nv_index rsa_ek_cert_nv_location;
ek_nv_index ecc_ek_cert_nv_location;
bool is_tpmgeneratedeps;
// Certficate data handling
uint8_t cert_count;
Expand All @@ -90,18 +117,6 @@ struct tpm_getekcertificate_ctx {
TPM2B_PUBLIC *out_public;
};

/*
* Sourced from TCG Vendor ID Registry v1.06:
* https://trustedcomputinggroup.org/resource/vendor-id-registry/
*
*/

typedef enum ek_nv_index ek_nv_index;
enum ek_nv_index {
RSA_EK_CERT_NV_INDEX = 0x01C00002,
ECC_EK_CERT_NV_INDEX = 0x01C0000A
};

static tpm_getekcertificate_ctx ctx = {
.is_tpm2_device_active = true,
.is_cert_on_nv = true,
Expand All @@ -110,6 +125,46 @@ static tpm_getekcertificate_ctx ctx = {
};


typedef enum key_type key_type;
enum key_type {
KTYPE_RSA = 0,
KTYPE_ECC = 1,
};

typedef struct ek_index_map ek_index_map;
struct ek_index_map
{
const char *name;
key_type key_type;
ek_nv_index index;
TPMI_ALG_HASH hash_alg;
};

static ek_index_map ek_index_maps[] = {
{"rsa", KTYPE_RSA, RSA_EK_CERT_NV_INDEX, TPM2_ALG_SHA256},
{"rsa2048", KTYPE_RSA, RSA_2048_EK_CERT_NV_INDEX, TPM2_ALG_SHA256},
{"rsa3072", KTYPE_RSA, RSA_3072_EK_CERT_NV_INDEX, TPM2_ALG_SHA384},
{"rsa4096", KTYPE_RSA, RSA_4096_EK_CERT_NV_INDEX, TPM2_ALG_SHA512},
{"ecc", KTYPE_ECC, ECC_EK_CERT_NV_INDEX, TPM2_ALG_SHA256},
{"ecc_nist_p256", KTYPE_ECC, ECC_NIST_P256_EK_CERT_NV_INDEX, TPM2_ALG_SHA256},
{"ecc_nist_p384", KTYPE_ECC, ECC_NIST_P384_EK_CERT_NV_INDEX, TPM2_ALG_SHA384},
{"ecc_nist_p521", KTYPE_ECC, ECC_NIST_P521_EK_CERT_NV_INDEX, TPM2_ALG_SHA512},
{"ecc_sm2_p256", KTYPE_ECC, ECC_SM2_P256_EK_CERT_NV_INDEX, TPM2_ALG_SM3_256},
};

static const ek_index_map *lookup_ek_index_map(const TPMI_RH_NV_INDEX index) {
size_t i;

for (i = 0; i < ARRAY_LEN(ek_index_maps); i++)
{
if (index == ek_index_maps[i].index) {
return &ek_index_maps[i];
}
}
return NULL;
}


static char *get_ek_server_address(void) {
if (ctx.ek_server_addr) // set by CLI
{
Expand Down Expand Up @@ -610,14 +665,26 @@ tool_rc get_tpm_properties(ESYS_CONTEXT *ectx) {
goto get_tpm_properties_out;
}

ctx.rsa_ek_cert_nv_location = 0xffffffff;
ctx.ecc_ek_cert_nv_location = 0xffffffff;

UINT32 i;
for (i = 0; i < capability_data->data.handles.count; i++) {
TPMI_RH_NV_INDEX index = capability_data->data.handles.handle[i];
if (index == RSA_EK_CERT_NV_INDEX) {
const ek_index_map *m = lookup_ek_index_map(index);
if (!m) {
continue;
}

if (m->key_type == KTYPE_RSA && index < ctx.rsa_ek_cert_nv_location) {
LOG_INFO("Found pre-provisioned RSA EK certificate at %u [type=%s]", index, m->name);
ctx.is_rsa_ek_cert_nv_location_defined = true;
ctx.rsa_ek_cert_nv_location = m->index;
}
if (index == ECC_EK_CERT_NV_INDEX) {
if (m->key_type == KTYPE_ECC && index < ctx.ecc_ek_cert_nv_location) {
LOG_INFO("Found pre-provisioned ECC EK certificate at %u [type=%s]", index, m->name);
ctx.is_ecc_ek_cert_nv_location_defined = true;
ctx.ecc_ek_cert_nv_location = m->index;
}
}

Expand All @@ -638,13 +705,15 @@ static tool_rc nv_read(ESYS_CONTEXT *ectx, TPMI_RH_NV_INDEX nv_index) {
* with attributes:
* ppwrite|ppread|ownerread|authread|no_da|written|platformcreate
*/
const bool is_rsa = nv_index == RSA_EK_CERT_NV_INDEX;
char index_string[11];
if (is_rsa) {
strcpy(index_string, "0x01C00002");
} else {
strcpy(index_string, "0x01C0000A");
const ek_index_map *m = lookup_ek_index_map(nv_index);
if (!m) {
LOG_ERR("Unsupported NV INDEX, got \"%u\"", nv_index);
return tool_rc_unsupported;
}

const bool is_rsa = m->key_type == KTYPE_RSA;
char index_string[11];
snprintf(index_string, sizeof(index_string), "%u", m->index);
tpm2_loaded_object object;
tool_rc tmp_rc = tool_rc_success;
tool_rc rc = tpm2_util_object_load_auth(ectx, index_string, NULL, &object,
Expand All @@ -658,11 +727,11 @@ static tool_rc nv_read(ESYS_CONTEXT *ectx, TPMI_RH_NV_INDEX nv_index) {
uint16_t nv_buf_size = 0;
rc = is_rsa ?
tpm2_util_nv_read(ectx, nv_index, 0, 0, &object, &ctx.rsa_cert_buffer,
&nv_buf_size, &cp_hash, &rp_hash, TPM2_ALG_SHA256, 0,
&nv_buf_size, &cp_hash, &rp_hash, m->hash_alg, 0,
ESYS_TR_NONE, ESYS_TR_NONE, NULL) :

tpm2_util_nv_read(ectx, nv_index, 0, 0, &object, &ctx.ecc_cert_buffer,
&nv_buf_size, &cp_hash, &rp_hash, TPM2_ALG_SHA256, 0,
&nv_buf_size, &cp_hash, &rp_hash, m->hash_alg, 0,
ESYS_TR_NONE, ESYS_TR_NONE, NULL);
if (is_rsa) {
ctx.rsa_cert_buffer_size = nv_buf_size;
Expand Down Expand Up @@ -707,14 +776,14 @@ static tool_rc get_nv_ek_certificate(ESYS_CONTEXT *ectx) {

tool_rc rc = tool_rc_success;
if (ctx.is_rsa_ek_cert_nv_location_defined) {
rc = nv_read(ectx, RSA_EK_CERT_NV_INDEX);
rc = nv_read(ectx, ctx.rsa_ek_cert_nv_location);
if (rc != tool_rc_success) {
return rc;
}
}

if (ctx.is_ecc_ek_cert_nv_location_defined) {
rc = nv_read(ectx, ECC_EK_CERT_NV_INDEX);
rc = nv_read(ectx, ctx.ecc_ek_cert_nv_location);
}

return rc;
Expand Down
Loading