Comments (8)
You'd have to load the Activation Key from go-attestation from the same template into go-tpm-tools. You're now generating two distinct AKs.
I don't know how easy it is to get the go-attestation AK into go-tpm-tools. IDK if they store them in the same hierarchy for example. but it's probably possible with some masssaging.
Perhaps easier would be to try this PR which adds credential activation to this library
#98
from go-tpm-tools.
Main problem is that that this library only creates Primary keys and no child keys . So basically we'd have to wait for #98 to be merged; but at that point we don't need go-attestation libary in the firstp lace
from go-tpm-tools.
@arianvp
Thank you for your answer!
I was able to get around to it by using go-attestation's functions for boot measurement. But that makes me wonder. What's the relation between go-tpm-tools and go-attestation? At first I thought they did different things but now it seems that they have overlapping functionality. Is one of them going to be deprecated or I'm missing something important here?
I'll leave my solution here just for reference, but I still have to do some checks and add some policies to it:
//***client code***
config := &attest.OpenConfig{}
tpm, err := attest.OpenTPM(config)
if err != nil {
//handle error
return nil,err
}
defer tpm.Close()
ak, err := GetAK(tpm)
if err != nil {
//handle error
return nil,err
}
PlatformParameters, err := tpm.AttestPlatform(ak,nonce,nil)
if err != nil {
//handle error
return nil,err
}
//***server code***
AKPublic, err := attest.ParseAKPublic(attest.TPMVersion20, PlatformParameters.Public)
if err != nil {
//handle error
return false,err
}
if verified :=CompareAKs(TrustedAK,AKPublic.Public); verified != true {
//handle error
return false,err
}
err = AKPublic.VerifyAll(PlatformParameters.Quotes, PlatformParameters.PCRs, nonce)
if err != nil {
//handle error
return false,err
}
Eventlog,err := ParseEventLog(PlatformParameters.EventLog)
if err != nil {
//handle error
return false,err
}
Events, err := Eventlog.Verify(PlatformParameters.PCRs)
if err != nil {
//handle error
return false,err
}
from go-tpm-tools.
from go-tpm-tools.
Thank you for the link and your help! I'll be checking that for the answer!
from go-tpm-tools.
Here is an (untested). Activation + Attestation flow using just this library:
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/subtle"
"crypto/x509"
"log"
"github.com/google/go-tpm-tools/client"
"github.com/google/go-tpm-tools/server"
"github.com/google/go-tpm/tpm2"
"github.com/google/go-tpm/tpm2/credactivation"
)
func main() {
// BEGIN SERVER
attestationRootKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
log.Fatal(err)
}
attestationRootTemplate := &x509.Certificate{
IsCA: true,
}
attestationRoot, err := x509.CreateCertificate(rand.Reader, attestationRootTemplate, attestationRootTemplate, attestationRootKey.Public(), attestationRootKey)
if err != nil {
log.Fatal(err)
}
attestationRootCert, err := x509.ParseCertificate(attestationRoot)
if err != nil {
log.Fatal(err)
}
// END SERVER
// BEGIN CLIENT
tpm, err := tpm2.OpenTPM()
if err != nil {
log.Fatal(err)
}
defer tpm.Close()
ek, err := client.EndorsementKeyRSA(tpm)
if err != nil {
log.Fatal(err)
}
defer ek.Close()
ekCert := ek.Cert()
ak, err := client.AttestationKeyECC(tpm)
if err != nil {
log.Fatal(err)
}
defer ak.Close()
akCSRTemplate := &x509.CertificateRequest{}
akPrivateKey, err := ak.GetSigner()
if err != nil {
log.Fatal(err)
}
akCSRBytes, err := x509.CreateCertificateRequest(rand.Reader, akCSRTemplate, akPrivateKey)
if err != nil {
log.Fatal(err)
}
// END CLIENT
// BEGIN SERVER
// Check that th EK cert is trusted
_, err = ekCert.Verify(x509.VerifyOptions{})
if err != nil {
log.Fatal(err)
}
secret := make([]byte, 32)
if _, err := rand.Read(secret); err != nil {
log.Fatal(err)
}
// generate a challenge for the the client
credBlob, encryptedSecret, err := credactivation.Generate(ak.Name().Digest, ek.PublicKey(), 16, secret)
if err != nil {
log.Fatal(err)
}
// END SERVER
// BEGIN CLIENT
decryptedSecret, err := tpm2.ActivateCredential(tpm, ek.Handle(), ak.Handle(), "", "", credBlob, encryptedSecret)
if err != nil {
log.Fatal(err)
}
// END CLIENT
// BEGIN SERVER
// Check if the challenge is solved
if subtle.ConstantTimeCompare(secret, decryptedSecret) != 0 {
log.Fatal("Secrets did not match")
}
// decode the CSR
akCSR, err := x509.ParseCertificateRequest(akCSRBytes)
if err != nil {
log.Fatal(err)
}
if err := akCSR.CheckSignature(); err != nil {
log.Fatal(err)
}
// We know that the AK is backed by the EK and that the EK is trusted at
// this point! Lets issue a certificate for the AK
// NOTE: should be populated with the same fields as set on the CSR template In
// our case it's empty...
akCertTemplate := &x509.Certificate{}
akCertBytes, err := x509.CreateCertificate(rand.Reader, akCertTemplate, attestationRootCert, akCSR.PublicKey, attestationRootKey)
if err != nil {
log.Fatal(err)
}
// END SERVER
// BEGIN CLIENT
akCert, err := x509.ParseCertificate(akCertBytes)
if err != nil {
log.Fatal(err)
}
ak.SetCert(akCert)
// we can now generate an attestation
nonce := make([]byte, 32)
if _, err := rand.Read(nonce); err != nil {
log.Fatal(err)
}
attestation, err := ak.Attest(client.AttestOpts{
Nonce: nonce,
})
if err != nil {
log.Fatal(err)
}
// END CLIENT
// BEGIN SERVER
machineState, err := server.VerifyAttestation(attestation, server.VerifyOpts{
Nonce: nonce,
TrustedRootCerts: []*x509.Certificate{attestationRootCert},
})
if err != nil {
log.Fatal(err)
}
log.Print(machineState.String())
// END SERVER
}
from go-tpm-tools.
Two things about the above code dont work:
ActivateCredential needs to use ActivateCredentialUsingAuth.
and The CSR part needs to be skipped
I'll see if I can send a patch
from go-tpm-tools.
This one actually works:
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/subtle"
"crypto/x509"
"log"
"math/big"
"os"
"os/exec"
"time"
"github.com/google/go-tpm-tools/client"
"github.com/google/go-tpm-tools/server"
"github.com/google/go-tpm/tpm2"
"github.com/google/go-tpm/tpm2/credactivation"
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
// BEGIN SERVER
attestationRootKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
log.Fatal(err)
}
attestationRootTemplate := &x509.Certificate{
SerialNumber: big.NewInt(1),
NotBefore: time.Now(),
NotAfter: time.Now().Add(24 * time.Hour),
IsCA: true,
KeyUsage: x509.KeyUsageCertSign,
BasicConstraintsValid: true,
}
attestationRoot, err := x509.CreateCertificate(rand.Reader, attestationRootTemplate, attestationRootTemplate, attestationRootKey.Public(), attestationRootKey)
if err != nil {
log.Fatal(err)
}
attestationRootCert, err := x509.ParseCertificate(attestationRoot)
if err != nil {
log.Fatal(err)
}
rootCertPool := x509.NewCertPool()
rootCertPool.AddCert(attestationRootCert)
// END SERVER
// BEGIN CLIENT
if os.Getenv("CLOUD_SHELL") == "true" {
cmd := exec.Command("sudo", "chmod", "777", "/dev/tpmrm0")
if b, err := cmd.CombinedOutput(); err != nil {
log.Fatal(string(b))
}
}
tpm, err := tpm2.OpenTPM()
if err != nil {
log.Fatal(err)
}
defer tpm.Close()
ek, err := client.EndorsementKeyRSA(tpm)
if err != nil {
log.Fatal(err)
}
defer ek.Close()
ekCert := ek.Cert()
ak, err := client.AttestationKeyRSA(tpm)
if err != nil {
log.Fatal(err)
}
defer ak.Close()
// END CLIENT
// BEGIN SERVER
if ekCert != nil {
_, err = ekCert.Verify(x509.VerifyOptions{})
if err != nil {
log.Fatal(err)
}
}
secret := make([]byte, 32)
if _, err := rand.Read(secret); err != nil {
log.Fatal(err)
}
// generate a challenge for the the client
credBlob, encryptedSecret, err := credactivation.Generate(ak.Name().Digest, ek.PublicKey(), 16, secret)
if err != nil {
log.Fatal(err)
}
// END SERVER
// BEGIN CLIENT
// Had to hack this session in as. ek.Session is not exposed publicly
session, _, err := tpm2.StartAuthSession(
tpm,
/*tpmKey=*/ tpm2.HandleNull,
/*bindKey=*/ tpm2.HandleNull,
/*nonceCaller=*/ make([]byte, 16),
/*encryptedSalt=*/ nil,
/*sessionType=*/ tpm2.SessionPolicy,
/*symmetric=*/ tpm2.AlgNull,
/*authHash=*/ client.SessionHashAlgTpm)
if err != nil {
log.Fatal(err)
}
defer tpm2.FlushContext(tpm, session)
nullAuth := tpm2.AuthCommand{Session: tpm2.HandlePasswordSession, Attributes: tpm2.AttrContinueSession}
if _, _, err = tpm2.PolicySecret(tpm, tpm2.HandleEndorsement, nullAuth, session, nil, nil, nil, 0); err != nil {
log.Fatal(err)
}
ekAuth := tpm2.AuthCommand{Session: session, Attributes: tpm2.AttrContinueSession}
auth := []tpm2.AuthCommand{nullAuth, ekAuth}
decryptedSecret, err := tpm2.ActivateCredentialUsingAuth(tpm, auth, ak.Handle(), ek.Handle(), credBlob[2:], encryptedSecret[2:])
if err != nil {
log.Fatal(err)
}
// END CLIENT
// BEGIN SERVER
// Check if the challenge is solved
if subtle.ConstantTimeCompare(secret, decryptedSecret) != 1 {
log.Fatal("Secrets did not match")
}
// We know that the AK is backed by the EK and that the EK is trusted at
// this point! Lets issue a certificate for the AK
// NOTE: should be populated with the same fields as set on the CSR template In
// our case it's empty...
akCertTemplate := &x509.Certificate{
SerialNumber: big.NewInt(3),
NotBefore: time.Now(),
NotAfter: time.Now().Add(24 * time.Hour),
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
}
akCertBytes, err := x509.CreateCertificate(rand.Reader, akCertTemplate, attestationRootCert, ak.PublicKey(), attestationRootKey)
if err != nil {
log.Fatal(err)
}
// END SERVER
// BEGIN CLIENT
akCert, err := x509.ParseCertificate(akCertBytes)
if err != nil {
log.Fatal(err)
}
if _, err := akCert.Verify(x509.VerifyOptions{
Roots: rootCertPool,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsage(x509.ExtKeyUsageAny)},
}); err != nil {
log.Fatal(err)
}
ak.SetCert(akCert)
// we can now generate an attestation
nonce := make([]byte, 32)
if _, err := rand.Read(nonce); err != nil {
log.Fatal(err)
}
attestation, err := ak.Attest(client.AttestOpts{
Nonce: nonce,
})
if err != nil {
log.Fatal(err)
}
// END CLIENT
// BEGIN SERVER
machineState, err := server.VerifyAttestation(attestation, server.VerifyOpts{
Nonce: nonce,
TrustedRootCerts: []*x509.Certificate{attestationRootCert},
})
if err != nil {
log.Fatal(err)
}
log.Print(machineState.String())
// END SERVER
}
from go-tpm-tools.
Related Issues (20)
- Support loading cached key HOT 2
- Issue building on Ubuntu 2204 jammy HOT 3
- Surface gceInstanceInfo extension attributes for GCE issued AK/EK HOT 4
- Comapre Public Keys HOT 1
- Invalid PCR selection during `key.Attest()`
- Fix server.VerifyAttestation with server.VerifyOpts HOT 1
- launcher: Don't defer os.Exit
- using simulator in other project does not fetch ms-tpm-20-ref HOT 1
- Not able to Extract SHA256 PCR Bank Values HOT 5
- Simulator checks wrong path for `openssl` with Homebrew on Apple Silicon macOS
- Support "TSS2 PRIVATE KEY" PEM files
- Support importing AES or HMAC keys HOT 1
- GetGCEInstanceInfo should return error if not found
- README.md and go.mod: the go version number error
- Allow persistence `client.Key()` HOT 1
- SigningKeyImportBlob to support duplication policy
- Support linux userspace eventlog HOT 1
- Preferred way to get raw hardware attestation?
- Follow up on the TODOs in PR #375 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from go-tpm-tools.