Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add support for creating IAK and IDevID keys and certificates #823

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
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
19 changes: 17 additions & 2 deletions man/man8/swtpm_cert.pod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ The following options are supported:

=over 4

=item B<--type {ek|platform}>
=item B<--type {ek|platform|iak|idevid}>

The type of certificate to create; by default an EK certificate is created.

Expand Down Expand Up @@ -114,6 +114,11 @@ The TPM model (part number).

The TPM's firmware version.

=item B<--tpm-serial-num <serial>>

The TPM's serial number. This option is required for creating IAK and IDevID
certificates.

=item B<--platform-manufacturer <name>>

The name of the platform manufacturer.
Expand Down Expand Up @@ -156,7 +161,9 @@ The output may contain the following:
"type": "swtpm_cert",
"features": [
"cmdarg-signkey-pwd",
"cmdarg-parentkey-pwd"
"cmdarg-parentkey-pwd",
"cmdarg-tpm-serial-num",
"supports-iak-idevid"
],
"version": "0.7.0"
}
Expand All @@ -175,6 +182,14 @@ The I<--signkey-pwd> option is supported.

The I<--parentkey-pwd> option is supported.

=item B<cmdarg-tpm-serial-num> (since v0.9)

The I<--tpm-serial-num> option is supported.

=item B<supports-iak-idevid> (since v0.9)

Creation of IAK and IDevID certificates is supported.

=back

=item B<--help, -h>
Expand Down
7 changes: 6 additions & 1 deletion man/man8/swtpm_localca.pod
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ The following options are supported:
=item B<--type type>

This parameter indicates the type of certificate to create. The type parameter may
be one of the following: I<ek>, or I<platform>
be one of the following: I<ek>, I<platform>, I<iak>, I<idevid>

=item B<--dir dir>

Expand Down Expand Up @@ -87,6 +87,11 @@ TPM specification parameters that describe the specification that was
followed for the TPM implementation. The parameters will be passed
to swtpm_cert for the creation of the EK certificate.

=item B<--tpm-serial-num>

The TPM's serial number that will become part of the certificate. This parameter
is necessary for IAK and IDevID certificates.

=item B<--tpm2>

Create TPM 2 compliant certificates.
Expand Down
13 changes: 12 additions & 1 deletion man/man8/swtpm_setup.pod
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ The output may contain the following:
"tpm2-rsa-keysize-2048",
"tpm2-rsa-keysize-3072",
"cmdarg-profile",
"cmdarg-profile-remove-disabled"
"cmdarg-profile-remove-disabled",
"cmdarg-no-iak"
],
"version": "0.7.0"
}
Expand Down Expand Up @@ -323,6 +324,12 @@ The I<--create-config-files> option is supported.
The I<--reconfigure> option is supported and allows the reconfiguration of
the active PCR banks.

=item B<cmdarg-no-iak> (since v0.9)

If I<--create-ek-cert> is given then swtpm_setup also creates IAK and IDevID
keys and certificates. When I<--no-iak> is passed then neither one of them is
created.

=item B<tpm2-rsa-keysize-2048, ...> (since v0.4)

The shown RSA key sizes are supported for a TPM 2's EK key. If none of the
Expand Down Expand Up @@ -401,6 +408,10 @@ systems this may be the case when a user is part of the 'tss' group. In
this case it is recommended that the user replace the swtpm-localca.conf
created with this command with a symbolic link to /etc/swtpm-localca.conf.

=item <--no-iak> (since v0.9)

Do not create IAK and IDevID keys and certificates.

=item B<--help, -h>

Display the help screen
Expand Down
110 changes: 107 additions & 3 deletions src/swtpm_cert/ek-cert.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ enum cert_type_t {
CERT_TYPE_EK = 1,
CERT_TYPE_PLATFORM,
CERT_TYPE_AIK,
CERT_TYPE_IAK,
CERT_TYPE_IDEVID,
};

/* some flags */
Expand Down Expand Up @@ -132,9 +134,11 @@ usage(const char *prg)
" -1 for no expiration\n"
"--pem : Write certificate in PEM format; default is DER\n"
"--type <platform|ek> : The type of certificate to create; default is ek\n"
" Other options are platform, iak, idevid\n"
"--tpm-manufacturer <name> : The name of the TPM manufacturer\n"
"--tpm-model <model> : The TPM model (part number)\n"
"--tpm-version <version> : The TPM version (firmware version)\n"
"--tpm-serial-num <s> : The TPM serial number; required for IAK and IDevID\n"
"--platform-manufacturer <name> : The name of the Platform manufacturer\n"
"--platform-model <model> : The Platform model (part number)\n"
"--platform-version <version> : The Platform version (firmware version)\n"
Expand Down Expand Up @@ -802,6 +806,59 @@ create_tpm_specification_info(const char *spec_family,
return err;
}

static int
create_iak_info(gnutls_datum_t *asn1,
const char *hwSerialNum)
{
asn1_node at = NULL;
int err;

err = asn_init();
if (err != ASN1_SUCCESS) {
goto cleanup;
}

err = asn1_create_element(_tpm_asn, "TPM.TPMIAKSanInfo", &at);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "1cia. asn1_create_element error: %d\n", err);
goto cleanup;
}

err = asn1_write_value(at, "tpmIAKSanInfoSeq.id", "1.3.6.1.5.5.7.8.4", 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "2cia. asn1_write_value error: %d\n", err);
goto cleanup;
}

err = asn1_write_value(at, "tpmIAKSanInfoSeq.iakSanInfoSet.hwType", "2.23.133.1.2", 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "3cia. asn1_write_value error: %d\n", err);
goto cleanup;
}

err = asn1_write_value(at, "tpmIAKSanInfoSeq.iakSanInfoSet.hwSerialNum", hwSerialNum, 0);
if (err != ASN1_SUCCESS) {
fprintf(stderr, "4cia. asn1_write_value error: %d\n", err);
goto cleanup;
}

err = encode_asn1(asn1, at);

#if 0
fprintf(stderr, "size=%d\n", asn1->size);
unsigned int i = 0;
for (i = 0; i < asn1->size; i++) {
fprintf(stderr, "%02x ", asn1->data[i]);
}
fprintf(stderr, "\n");
#endif

cleanup:
asn1_delete_structure(&at);
return err;
}


static int
create_cert_extended_key_usage(const char *oid, gnutls_datum_t *asn1)
{
Expand Down Expand Up @@ -992,6 +1049,8 @@ static void capabilities_print_json(void)
"\"features\": [ "
"\"cmdarg-signkey-pwd\""
", \"cmdarg-parentkey-pwd\""
", \"cmdarg-tpm-serial-num\""
", \"supports-iak-idevid\""
" ], "
"\"version\": \"" VERSION "\" "
"}\n");
Expand Down Expand Up @@ -1041,6 +1100,7 @@ main(int argc, char *argv[])
const char *tpm_manufacturer = NULL;
const char *tpm_version = NULL;
const char *tpm_model = NULL;
const char *tpm_serial_num = NULL;
const char *platf_manufacturer = NULL;
const char *platf_version = NULL;
const char *platf_model = NULL;
Expand Down Expand Up @@ -1071,6 +1131,7 @@ main(int argc, char *argv[])
{"tpm-manufacturer", required_argument, NULL, '1'},
{"tpm-model", required_argument, NULL, '2'},
{"tpm-version", required_argument, NULL, '3'},
{"tpm-serial-num", required_argument, NULL, '0'},
{"platform-manufacturer", required_argument, NULL, '4'},
{"platform-model", required_argument, NULL, '5'},
{"platform-version", required_argument, NULL, '6'},
Expand Down Expand Up @@ -1190,6 +1251,10 @@ main(int argc, char *argv[])
certtype = CERT_TYPE_EK;
} else if (!strcasecmp(optarg, "platform")) {
certtype = CERT_TYPE_PLATFORM;
} else if (!strcasecmp(optarg, "iak")) {
certtype = CERT_TYPE_IAK;
} else if (!strcasecmp(optarg, "idevid")) {
certtype = CERT_TYPE_IDEVID;
} else {
fprintf(stderr, "Unknown certificate type '%s'.\n",
optarg);
Expand All @@ -1205,6 +1270,9 @@ main(int argc, char *argv[])
case '3': /* --tpm-version */
tpm_version = optarg;
break;
case '0': /* --tpm-serial-num */
tpm_serial_num = optarg;
break;
case '4': /* --platform-manufacturer */
platf_manufacturer = optarg;
break;
Expand Down Expand Up @@ -1317,6 +1385,13 @@ main(int argc, char *argv[])
break;
case CERT_TYPE_AIK:
break;
case CERT_TYPE_IAK:
case CERT_TYPE_IDEVID:
if (tpm_serial_num == NULL) {
fprintf(stderr, "--tpm-serial-num must be provided\n");
goto cleanup;
}
break;
}

switch (certtype) {
Expand All @@ -1340,6 +1415,8 @@ main(int argc, char *argv[])
}
break;
case CERT_TYPE_AIK:
case CERT_TYPE_IAK:
case CERT_TYPE_IDEVID:
break;
}

Expand Down Expand Up @@ -1501,6 +1578,10 @@ if (_err != GNUTLS_E_SUCCESS) { \
case CERT_TYPE_AIK:
oid = "1.2.840.113549.1.1.1";
break;
case CERT_TYPE_IAK:
case CERT_TYPE_IDEVID:
oid = NULL;
break;
default:
fprintf(stderr, "Internal error: unhandle case in line %d\n",
__LINE__);
Expand Down Expand Up @@ -1551,16 +1632,33 @@ if (_err != GNUTLS_E_SUCCESS) { \
break;
case CERT_TYPE_AIK:
break;
case CERT_TYPE_IAK:
case CERT_TYPE_IDEVID:
err = create_iak_info(&datum, tpm_serial_num);
if (err) {
fprintf(stderr, "Could not create IAK info");
goto cleanup;
}
break;
default:
fprintf(stderr, "Internal error: unhandle case in line %d\n",
__LINE__);
goto cleanup;
}

if (datum.size > 0) {
err = prepend_san_asn1_header(&datum);
CHECK_GNUTLS_ERROR(err, "Could not prepend SAN ASN.1 header: %s\n",
gnutls_strerror(err))
switch (certtype) {
case CERT_TYPE_EK:
case CERT_TYPE_PLATFORM:
err = prepend_san_asn1_header(&datum);
CHECK_GNUTLS_ERROR(err, "Could not prepend SAN ASN.1 header: %s\n",
gnutls_strerror(err))
break;
case CERT_TYPE_AIK:
case CERT_TYPE_IAK:
case CERT_TYPE_IDEVID:
break;
}

err = gnutls_x509_crt_set_extension_by_oid(crt, GNUTLS_X509EXT_OID_SAN,
datum.data, datum.size,
Expand Down Expand Up @@ -1589,6 +1687,8 @@ if (_err != GNUTLS_E_SUCCESS) { \
break;
case CERT_TYPE_PLATFORM:
case CERT_TYPE_AIK:
case CERT_TYPE_IAK:
case CERT_TYPE_IDEVID:
break;
default:
fprintf(stderr, "Internal error: unhandled case in line %d\n",
Expand Down Expand Up @@ -1641,6 +1741,8 @@ if (_err != GNUTLS_E_SUCCESS) { \
}
break;
case CERT_TYPE_AIK:
case CERT_TYPE_IAK:
case CERT_TYPE_IDEVID:
key_usage = GNUTLS_KEY_DIGITAL_SIGNATURE;
break;
default:
Expand All @@ -1663,6 +1765,8 @@ if (_err != GNUTLS_E_SUCCESS) { \
oid = "2.23.133.8.2";
break;
case CERT_TYPE_AIK:
case CERT_TYPE_IAK:
case CERT_TYPE_IDEVID:
break;
default:
fprintf(stderr, "Internal error: unhandled case in line %d\n",
Expand Down
16 changes: 16 additions & 0 deletions src/swtpm_cert/tpm.asn
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,20 @@ TPMEKCertExtendedKeyUsage ::= SEQUENCE {
id OBJECT IDENTIFIER
}

-- IAK --

TPMIAKSanInfo ::= SEQUENCE {
tpmIAKSanInfoSeq [0] IMPLICIT TPMIAKSanInfoSeq
}

TPMIAKSanInfoSeq ::= SEQUENCE {
id OBJECT IDENTIFIER,
iakSanInfoSet [0] EXPLICIT IAKHardwareModuleName
}

IAKHardwareModuleName ::= SEQUENCE {
hwType OBJECT IDENTIFIER,
hwSerialNum OCTET STRING
}

END
12 changes: 11 additions & 1 deletion src/swtpm_cert/tpm_asn1.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,17 @@ const asn1_static_node tpm_asn1_tab[] = {
{ "version", 34, NULL },
{ "PlatformCertificateSAN", 1610612747, NULL },
{ NULL, 13, NULL },
{ "TPMEKCertExtendedKeyUsage", 536870917, NULL },
{ "TPMEKCertExtendedKeyUsage", 1610612741, NULL },
{ "id", 12, NULL },
{ "TPMIAKSanInfo", 1610612741, NULL },
{ "tpmIAKSanInfoSeq", 536879106, "TPMIAKSanInfoSeq"},
{ NULL, 4104, "0"},
{ "TPMIAKSanInfoSeq", 1610612741, NULL },
{ "id", 1073741836, NULL },
{ "iakSanInfoSet", 536879106, "IAKHardwareModuleName"},
{ NULL, 2056, "0"},
{ "IAKHardwareModuleName", 536870917, NULL },
{ "hwType", 1073741836, NULL },
{ "hwSerialNum", 7, NULL },
{ NULL, 0, NULL }
};
Loading