Go-Attestation abstracts remote attestation operations across a variety of platforms and TPMs, enabling remote validation of machine identity and state. This project attempts to provide high level primitives for both client and server logic.
Talks on this project:
Go-Attestation is has reached initial maturity. It supports the initial design goals and is actively used at Google. It is still under development, and API changes may occur at any time. One caveat is that support for Windows is still relatively immature compared to support for Linux.
Please note that this is not an official Google product.
TPM 1.2 support is best effort, meaning we will accept fixes for TPM 1.2, but testing is not covered by CI.
The go-attestation package is installable using go get: go get github.com/google/go-attestation/attest
TPMs can be used to identify a device remotely and provision unique per-device hardware-bound keys.
TPMs are provisioned with a set of Endorsement Keys (EKs) by the manufacturer. These optionally include a certificate signed by the manufacturer and act as a TPM's identity. For privacy reasons the EK can't be used to sign or encrypt data directly, and is instead used to attest to the presence of a signing key, an Attestation Key (AK), on the same TPM. (Newer versions of the spec may allow the EK to sign directly.)
During attestation, a TPM generates an AK and proves to a certificate authority that the AK is on the same TPM as a EK. If the certificate authority trusts the EK, it can transitively trust the AK, for example by issuing a certificate for the AK.
To perform attestation, the client generates an AK and sends the EK and AK parameters to the server:
// Client generates an AK and sends it to the server
config := &attest.OpenConfig{}
tpm, err := attest.OpenTPM(config)
if err != nil {
// handle error
}
eks, err := tpm.EKs()
if err != nil {
// handle error
}
ek := eks[0]
akConfig := &attest.AKConfig{}
ak, err := tpm.NewAK(akConfig)
if err != nil {
// handle error
}
attestParams := ak.AttestationParameters()
akBytes, err := ak.Marshal()
if err != nil {
// handle error
}
if err := os.WriteFile("encrypted_aik.json", akBytes, 0600); err != nil {
// handle error
}
// send TPM version, EK, and attestParams to the server
The server uses the EK and AK parameters to generate a challenge encrypted to the EK, returning the challenge to the client. During this phase, the server determines if it trusts the EK, either by chaining its certificate to a known manufacturer and/or querying an inventory system.
// Server validates EK and/or EK certificate
params := attest.ActivationParameters{
TPMVersion: tpmVersion,
EK: ek.Public,
AK: attestParams,
}
secret, encryptedCredentials, err := params.Generate()
if err != nil {
// handle error
}
// return encrypted credentials to client
The client proves possession of the AK by decrypting the challenge and returning the same secret to the server.
// Client decrypts the credential
akBytes, err := os.ReadFile("encrypted_aik.json")
if err != nil {
// handle error
}
ak, err := tpm.LoadAK(akBytes)
if err != nil {
// handle error
}
secret, err := ak.ActivateCredential(tpm, encryptedCredentials)
if err != nil {
// handle error
}
// return secret to server
At this point, the server records the AK and EK association and allows the client to use its AK as a credential (e.g. by issuing it a client certificate).
(top 30 of 51)
Hacker News (1)
Go
100.0%
Go-Attestation abstracts remote attestation operations across a variety of platforms and TPMs, enabling remote validation of machine identity and state. This project attempts to provide high level primitives for both client and server logic.
Talks on this project:
Go-Attestation is has reached initial maturity. It supports the initial design goals and is actively used at Google. It is still under development, and API changes may occur at any time. One caveat is that support for Windows is still relatively immature compared to support for Linux.
Please note that this is not an official Google product.
TPM 1.2 support is best effort, meaning we will accept fixes for TPM 1.2, but testing is not covered by CI.
The go-attestation package is installable using go get: go get github.com/google/go-attestation/attest
TPMs can be used to identify a device remotely and provision unique per-device hardware-bound keys.
TPMs are provisioned with a set of Endorsement Keys (EKs) by the manufacturer. These optionally include a certificate signed by the manufacturer and act as a TPM's identity. For privacy reasons the EK can't be used to sign or encrypt data directly, and is instead used to attest to the presence of a signing key, an Attestation Key (AK), on the same TPM. (Newer versions of the spec may allow the EK to sign directly.)
During attestation, a TPM generates an AK and proves to a certificate authority that the AK is on the same TPM as a EK. If the certificate authority trusts the EK, it can transitively trust the AK, for example by issuing a certificate for the AK.
To perform attestation, the client generates an AK and sends the EK and AK parameters to the server:
// Client generates an AK and sends it to the server
config := &attest.OpenConfig{}
tpm, err := attest.OpenTPM(config)
if err != nil {
// handle error
}
eks, err := tpm.EKs()
if err != nil {
// handle error
}
ek := eks[0]
akConfig := &attest.AKConfig{}
ak, err := tpm.NewAK(akConfig)
if err != nil {
// handle error
}
attestParams := ak.AttestationParameters()
akBytes, err := ak.Marshal()
if err != nil {
// handle error
}
if err := os.WriteFile("encrypted_aik.json", akBytes, 0600); err != nil {
// handle error
}
// send TPM version, EK, and attestParams to the server
The server uses the EK and AK parameters to generate a challenge encrypted to the EK, returning the challenge to the client. During this phase, the server determines if it trusts the EK, either by chaining its certificate to a known manufacturer and/or querying an inventory system.
// Server validates EK and/or EK certificate
params := attest.ActivationParameters{
TPMVersion: tpmVersion,
EK: ek.Public,
AK: attestParams,
}
secret, encryptedCredentials, err := params.Generate()
if err != nil {
// handle error
}
// return encrypted credentials to client
The client proves possession of the AK by decrypting the challenge and returning the same secret to the server.
// Client decrypts the credential
akBytes, err := os.ReadFile("encrypted_aik.json")
if err != nil {
// handle error
}
ak, err := tpm.LoadAK(akBytes)
if err != nil {
// handle error
}
secret, err := ak.ActivateCredential(tpm, encryptedCredentials)
if err != nil {
// handle error
}
// return secret to server
At this point, the server records the AK and EK association and allows the client to use its AK as a credential (e.g. by issuing it a client certificate).
Hacker News (1)
(top 30 of 51)
Go
100.0%