diff --git a/attestation/rac/ractools/entity.go b/attestation/rac/ractools/entity.go new file mode 100644 index 0000000000000000000000000000000000000000..937fa7592a3da4a835299b52bf2e6224d2a1e431 --- /dev/null +++ b/attestation/rac/ractools/entity.go @@ -0,0 +1,79 @@ +package ractools + +import "github.com/google/go-tpm/tpm2" + +type Algorithm uint16 +type PcrValue string + +const EmptyPassword = "" + +var ( + // PCR7 is for SecureBoot. + PcrSelection0 = tpm2.PCRSelection{Hash: tpm2.AlgSHA1, PCRs: []int{0}} + PcrSelection1_17 = tpm2.PCRSelection{Hash: tpm2.AlgSHA1, PCRs: []int{1, 17}} + PcrSelection7 = tpm2.PCRSelection{Hash: tpm2.AlgSHA1, PCRs: []int{7}} + PcrSelectionAll = tpm2.PCRSelection{Hash: tpm2.AlgSHA1, PCRs: []int{0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}} + Params = tpm2.Public{ + Type: tpm2.AlgRSA, + NameAlg: tpm2.AlgSHA256, + Attributes: tpm2.FlagSignerDefault | tpm2.FlagNoDA, + RSAParameters: &tpm2.RSAParams{ + Sign: &tpm2.SigScheme{ + Alg: tpm2.AlgRSASSA, + Hash: tpm2.AlgSHA256, + }, + KeyBits: 2048, + }, + } + DefaultKeyParams = tpm2.Public{ + Type: tpm2.AlgRSA, + NameAlg: tpm2.AlgSHA1, + Attributes: tpm2.FlagStorageDefault, + RSAParameters: &tpm2.RSAParams{ + Symmetric: &tpm2.SymScheme{ + Alg: tpm2.AlgAES, + KeyBits: 128, + Mode: tpm2.AlgCFB, + }, + KeyBits: 2048, + ExponentRaw: 1<<16 + 1, + }, + } + MyPassword = "123456" + // The initial passwd is 123456, and user can modify it + // FIXME: we should consider passwd length constraints later + DefaultRsaSignerParams = tpm2.Public{ + Type: tpm2.AlgRSA, + NameAlg: tpm2.AlgSHA256, + Attributes: tpm2.FlagSign | tpm2.FlagSensitiveDataOrigin | tpm2.FlagUserWithAuth, + RSAParameters: &tpm2.RSAParams{ + Sign: &tpm2.SigScheme{ + Alg: tpm2.AlgRSASSA, + Hash: tpm2.AlgSHA256, + }, + KeyBits: 2048, + }, + } +) + +type PcrInfo struct { + pcrSelection tpm2.PCRSelection + pcrValues []PcrValue + pcrQuote []byte +} + +type Manifest struct { + pcr string + template_hash string + format string + filedata_hash string + filename_hint string +} + +type TrustReport struct { + pcrInfo PcrInfo + manifest []Manifest + clientId int64 + clientInfo map[string]string +} diff --git a/attestation/rac/ractools/main.go b/attestation/rac/ractools/main.go deleted file mode 100644 index fb7eb80ebd125577c85fcd400c9c66ecf0e77ecb..0000000000000000000000000000000000000000 --- a/attestation/rac/ractools/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "fmt" -) - -func main() { - fmt.Println("hello, this is ractools!") -} diff --git a/attestation/rac/ractools/ractools.go b/attestation/rac/ractools/ractools.go new file mode 100644 index 0000000000000000000000000000000000000000..28a639d5861624758791fc0aeb535336839343a0 --- /dev/null +++ b/attestation/rac/ractools/ractools.go @@ -0,0 +1,104 @@ +package ractools + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + + "github.com/google/go-tpm/tpm2" + "github.com/google/go-tpm/tpmutil" +) + +//FIXME: nonce is not used in functions +func CreateTrustReport(rw io.ReadWriter, pcrSelection tpm2.PCRSelection, imapath string, nonce, clientid int64, + clientinfo map[string]string) (report TrustReport, err error) { + + keyHandle, _, _, _, _, _, err := tpm2.CreatePrimaryEx(rw, tpm2.HandleEndorsement, + pcrSelection, EmptyPassword, EmptyPassword, Params) + if err != nil { + return TrustReport{}, err + } + + pcrmp, _ := tpm2.ReadPCRs(rw, pcrSelection) + if err != nil { + return TrustReport{}, err + } + + var pcrValues []PcrValue + for _, pcr := range pcrmp { + pcrValues = append(pcrValues, (PcrValue)(pcr)) + } + + qattestation, _, err := tpm2.Quote(rw, keyHandle, EmptyPassword, EmptyPassword, + nil, pcrSelection, tpm2.AlgNull) + if err != nil { + return TrustReport{}, err + } + + var pcrinfo PcrInfo = PcrInfo{pcrSelection, pcrValues, qattestation} + + //To construct the manifest + f, err := ioutil.ReadFile(imapath) + if err != nil { + return TrustReport{}, err + } + var mainfest []Manifest + s := make([]string, 5, 6) + var j int = 0 + for i, _ := range f { + if f[i] == ' ' { + j++ + continue + } else if f[i] == '\n' || f[i] == '\t' { + continue + } + s[j] = s[j] + (string)(f[i]) + } + ma := Manifest{s[0], s[1], s[2], s[3], s[4]} + mainfest = append(mainfest, ma) + + clientId := clientid + clientInfo := clientinfo + + var trust_report TrustReport = TrustReport{pcrinfo, mainfest, clientId, clientInfo} + + return trust_report, err +} + +func CreateAk(rw io.ReadWriter, parentHandle tpmutil.Handle, parentPassword string) ([]byte, []byte, []byte, error) { + + privateAk, publicAk, _, _, _, err := tpm2.CreateKey(rw, parentHandle, PcrSelection7, + parentPassword, EmptyPassword, DefaultKeyParams) + if err != nil { + return nil, nil, nil, err + } + + keyHandle, nameData, err := tpm2.Load(rw, parentHandle, parentPassword, publicAk, + privateAk) + if err != nil { + return nil, nil, nil, err + } + defer tpm2.FlushContext(rw, keyHandle) + + if _, err := tpm2.DecodeName(bytes.NewBuffer(nameData)); err != nil { + return nil, nil, nil, err + } + _, Akname, _, err := tpm2.ReadPublic(rw, keyHandle) + if err != nil { + return nil, nil, nil, err + } + + return Akname, privateAk, publicAk, nil +} + +func ActivateAC(rw io.ReadWriter, activeHandle, keyHandle tpmutil.Handle, activePassword, protectorPassword string, + credServer, encryptedSecret []byte, secret []byte) (rerecoveredCredential []byte, err error) { + + recoveredCredential, err := tpm2.ActivateCredential(rw, activeHandle, keyHandle, activePassword, + protectorPassword, credServer, encryptedSecret) + if err != nil { + fmt.Printf("ActivateCredential failed: %v \n", err) + } + return recoveredCredential, err +} diff --git a/attestation/rac/ractools/ractools_test.go b/attestation/rac/ractools/ractools_test.go new file mode 100644 index 0000000000000000000000000000000000000000..59e63d4952d071ef5964354d5e069ffce246dc04 --- /dev/null +++ b/attestation/rac/ractools/ractools_test.go @@ -0,0 +1,87 @@ +package ractools + +import ( + "flag" + "io" + "io/ioutil" + "testing" + + "github.com/google/go-tpm-tools/simulator" + "github.com/google/go-tpm/tpm2" + "github.com/google/go-tpm/tpmutil" +) + +const ( + HandleOwner tpmutil.Handle = 0x40000001 +) + +var ( + pcrSelection = PcrSelection7 + tpmPath = flag.String("tpm-path", "", `Path to TPM character device. Most Linux systems + expose it under /dev/tpm0. Empty value (default) will disable all integration tests.`) +) + +func openTPM(tb testing.TB) io.ReadWriteCloser { + tb.Helper() + if useDeviceTPM() { + return openDeviceTPM(tb) + } + simulator, err := simulator.Get() + if err != nil { + tb.Fatalf("Simulator initialization failed: %v", err) + } + return simulator +} + +func useDeviceTPM() bool { return *tpmPath != "" } + +func openDeviceTPM(tb testing.TB) io.ReadWriteCloser { + tb.Helper() + rw, err := tpm2.OpenTPM(*tpmPath) + if err != nil { + tb.Fatalf("Open TPM at %s failed: %s\n", *tpmPath, err) + } + return rw +} + +func TestCreateTrustReport(t *testing.T) { + rw := openTPM(t) + defer rw.Close() + + var ( + imaInfo = `10 1d8d532d463c9f8c205d0df7787669a85f93e260 ima-ng + sha1:0000000000000000000000000000000000000000 boot_aggregate` + imapath = "imapath" + nonce int64 = 1 + clientId int64 = 1 + clientInfo map[string]string + ) + clientInfo = make(map[string]string) + clientInfo["version"] = "0.0.1" + + ioutil.WriteFile(imapath, ([]byte)(imaInfo), 0777) + _, err := CreateTrustReport(rw, pcrSelection, imapath, nonce, clientId, clientInfo) + if err != nil { + t.Fatalf("CreateTrustReport failed: %s", err) + } + +} + +func TestCreateAk(t *testing.T) { + rw := openTPM(t) + defer rw.Close() + + ownerPassword := EmptyPassword + parentPassword := MyPassword + parentHandle, _, err := tpm2.CreatePrimary(rw, HandleOwner, pcrSelection, + ownerPassword, parentPassword, DefaultKeyParams) + if err != nil { + t.Fatalf("CreatePrimary failed: %s", err) + } + defer tpm2.FlushContext(rw, parentHandle) + + _, _, _, err = CreateAk(rw, parentHandle, parentPassword) + if err != nil { + t.Fatalf("CreateAk failed: %s", err) + } +}