diff --git a/command/ca/certificate.go b/command/ca/certificate.go index 78cdae403..e0124232e 100644 --- a/command/ca/certificate.go +++ b/command/ca/certificate.go @@ -173,6 +173,10 @@ multiple SANs. The '--san' flag and the '--token' flag are mutually exclusive.`, Usage: "The directory where TPM keys and certificates will be stored", Value: filepath.Join(step.Path(), "tpm"), }, + cli.StringFlag{ + Name: "tpm-device", + Usage: "The TPM device (name) to use", + }, flags.TemplateSet, flags.TemplateSetFile, flags.CaConfig, diff --git a/utils/cautils/acmeutils.go b/utils/cautils/acmeutils.go index 51b71eff8..b4f2fdfba 100644 --- a/utils/cautils/acmeutils.go +++ b/utils/cautils/acmeutils.go @@ -30,6 +30,8 @@ import ( "go.step.sm/cli-utils/ui" "go.step.sm/crypto/jose" "go.step.sm/crypto/keyutil" + "go.step.sm/crypto/kms/apiv1" + "go.step.sm/crypto/kms/uri" "go.step.sm/crypto/pemutil" "go.step.sm/crypto/tpm" tpmstorage "go.step.sm/crypto/tpm/storage" @@ -401,8 +403,19 @@ type attestationObject struct { // doDeviceAttestation performs `device-attest-01` challenge validation. func doDeviceAttestation(clictx *cli.Context, ac *ca.ACMEClient, ch *acme.Challenge, identifier string, af *acmeFlow) error { // TODO(hs): make TPM flow work with CreateAttestor()/Attest() too + // TODO: prepare the full attestation-uri: fill in missing data, fill in values from flags, + // get defaults (AK name, based on TPM presence); fail early if no TPM available. attestationURI := clictx.String("attestation-uri") if strings.HasPrefix(attestationURI, "tpmkms:") { + u, err := uri.ParseWithScheme(string(apiv1.TPMKMS), attestationURI) + if err != nil { + return fmt.Errorf("failed to parse %q: %w", attestationURI, err) + } + if device := clictx.String("tpm-device"); device != "" { + u.Values.Set("device", device) + clictx.Set("attestation-uri", u.String()) + } + return doTPMAttestation(clictx, ac, ch, identifier, af) } @@ -832,17 +845,20 @@ func (af *acmeFlow) GetCertificate() ([]*x509.Certificate, error) { if af.tpmSigner != nil { attestationURI := af.ctx.String("attestation-uri") tpmStorageDirectory := af.ctx.String("tpm-storage-directory") + tpmDevice := af.ctx.String("tpm-device") + + tpmOpts := []tpm.NewTPMOption{ + tpm.WithStore(tpmstorage.NewDirstore(tpmStorageDirectory)), + } keyName, attURI, err := parseTPMAttestationURI(attestationURI) if err != nil { return nil, fmt.Errorf("failed parsing --attestation-uri: %w", err) } - tpmOpts := []tpm.NewTPMOption{ - tpm.WithStore(tpmstorage.NewDirstore(tpmStorageDirectory)), - } - if device := attURI.Get("device"); device != "" { - tpmOpts = append(tpmOpts, tpm.WithDeviceName(device)) + if tpmDevice == "" { + tpmDevice := attURI.Get("device") + tpmOpts = append(tpmOpts, tpm.WithDeviceName(tpmDevice)) } t, err := tpm.New(tpmOpts...) diff --git a/utils/cautils/tpm.go b/utils/cautils/tpm.go index 49535c762..777bd23a6 100644 --- a/utils/cautils/tpm.go +++ b/utils/cautils/tpm.go @@ -39,11 +39,16 @@ import ( func doTPMAttestation(clictx *cli.Context, ac *ca.ACMEClient, ch *acme.Challenge, identifier string, af *acmeFlow) error { attestationURI := clictx.String("attestation-uri") tpmStorageDirectory := clictx.String("tpm-storage-directory") + tpmDevice := clictx.String("tpm-device") tpmAttestationCABaseURL := clictx.String("attestation-ca-url") tpmAttestationCARootFile := clictx.String("attestation-ca-root") tpmAttestationCAInsecure := clictx.Bool("attestation-ca-insecure") insecure := clictx.Bool("insecure") + tpmOpts := []tpm.NewTPMOption{ + tpm.WithStore(tpmstorage.NewDirstore(tpmStorageDirectory)), + } + keyName, attURI, err := parseTPMAttestationURI(attestationURI) if err != nil { return fmt.Errorf("failed parsing --attestation-uri: %w", err) @@ -56,11 +61,9 @@ func doTPMAttestation(clictx *cli.Context, ac *ca.ACMEClient, ch *acme.Challenge } } - tpmOpts := []tpm.NewTPMOption{ - tpm.WithStore(tpmstorage.NewDirstore(tpmStorageDirectory)), - } - if device := attURI.Get("device"); device != "" { - tpmOpts = append(tpmOpts, tpm.WithDeviceName(device)) + if tpmDevice == "" { + tpmDevice := attURI.Get("device") + tpmOpts = append(tpmOpts, tpm.WithDeviceName(tpmDevice)) } t, err := tpm.New(tpmOpts...)