From 65df104084eb5c255371caf922a228fc9f7dbd83 Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Tue, 17 Jan 2023 16:30:46 +0100 Subject: [PATCH 01/14] WIP: pkg/intel/metadata: debug manifest codegen Signed-off-by: Daniel Maslowski --- .../common/manifestcodegen/cmd/manifestcodegen/main.go | 6 ++++++ .../metadata/common/manifestcodegen/pkg/analyze/scan.go | 1 + 2 files changed, 7 insertions(+) diff --git a/pkg/intel/metadata/common/manifestcodegen/cmd/manifestcodegen/main.go b/pkg/intel/metadata/common/manifestcodegen/cmd/manifestcodegen/main.go index fc6b2e0c..820c19c2 100644 --- a/pkg/intel/metadata/common/manifestcodegen/cmd/manifestcodegen/main.go +++ b/pkg/intel/metadata/common/manifestcodegen/cmd/manifestcodegen/main.go @@ -87,6 +87,12 @@ func processPath(path string, isCheck, enableTracing bool, packageName string) e goPaths = append(goPaths, filepath.Join(homeDir, "go")) } + cwd, err := os.Getwd() + if err != nil { + return fmt.Errorf("unable to determine working directory: %w", err) + } + goPaths = append(goPaths, cwd) + dirInfo, err := analyze.Scan(path, goPaths) if err != nil { return fmt.Errorf("unable to analyze path '%s': %w", path, err) diff --git a/pkg/intel/metadata/common/manifestcodegen/pkg/analyze/scan.go b/pkg/intel/metadata/common/manifestcodegen/pkg/analyze/scan.go index 3bbf6713..0e7a076c 100644 --- a/pkg/intel/metadata/common/manifestcodegen/pkg/analyze/scan.go +++ b/pkg/intel/metadata/common/manifestcodegen/pkg/analyze/scan.go @@ -43,6 +43,7 @@ func getRawPkg( buildCtx := build.Default buildCtx.GOPATH = strings.Join(goPaths, string(filepath.ListSeparator)) buildCtx.BuildTags = append(buildCtx.BuildTags, `manifestcodegen`) + fmt.Printf("search for `%v` in `%v` (%v) \n\n", path, goPaths, buildCtx.GOPATH) dirRaw, err := gosrc.OpenDirectoryByPkgPath(&buildCtx, path, false, false, false, nil) if err != nil { return nil, fmt.Errorf("unable to open go directory: %w", err) From f8670ba8ac93dcba778ae948301f4f79a538d030 Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Sat, 7 Jan 2023 00:25:22 +0100 Subject: [PATCH 02/14] Draft intelmeta command manifest v2.1 Test images: https://www.gigabyte.com/Motherboard/H410M-H-V3-rev-10-12/support#support-dl-bios Key leakage test images: https://www.msi.com/Laptop/Pulse-GL76-12UX/support?sub_product=Pulse-GL76-12UEK https://download.msi.com/bos_exe/nb/E17L3IMS.10D.zip https://download.msi.com/bos_exe/nb/E17L3IMS.10E.zip Signed-off-by: Daniel Maslowski --- cmds/intelmeta/main.go | 166 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 cmds/intelmeta/main.go diff --git a/cmds/intelmeta/main.go b/cmds/intelmeta/main.go new file mode 100644 index 00000000..81a47bf6 --- /dev/null +++ b/cmds/intelmeta/main.go @@ -0,0 +1,166 @@ +// Copyright 2023 the LinuxBoot Authors. All rights reserved +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "flag" + "fmt" + "os" + + "github.com/linuxboot/fiano/pkg/intel/metadata/bg/bgbootpolicy" + "github.com/linuxboot/fiano/pkg/intel/metadata/bg/bgkey" + "github.com/linuxboot/fiano/pkg/intel/metadata/cbnt/cbntbootpolicy" + "github.com/linuxboot/fiano/pkg/intel/metadata/cbnt/cbntkey" + "github.com/linuxboot/fiano/pkg/intel/metadata/fit" + "github.com/linuxboot/fiano/pkg/log" +) + +var ( + flagJSON = flag.Bool("j", false, "Output as JSON") +) + +func getLeakedKeys() [10][]byte { + var keys = [10]string{ + // https://github.com/binarly-io/SupplyChainAttacks/blob/main/MSI/MsiImpactedDevices.md + "77304b5179d0924e55060188495c80135da6be5a357234809e04a50c9629be6832f2d71be5e720a71bc9103b62413f91f98bf35723a358c5a24530fd46f6c89e6b3c22b77cd364b252bb0190cbc5ef6dd91811bfeff9a7308a6b5d60a4297dcfab6302d5d9db78103d4467d097bacce456b54c983f175c44bfd150b5121a589fa642308fd522471b6216afa0a9dbf8f158b0f7a787c0c6a58e70f2ebbff73708a880ae929bdc6097d6bc6463ab524c4ee6e9aa208ac845211b0e04fe8f2dca3799641af550e4740498ed7c3b4e9ceaf8e9256a30623cba4799ba8198cb3d53e28492c49ce3512856dfd4577992c6c7867eee353bbb38424ac83dcfc7dfba902bb41b180ded8026ac9591f3575cc4e2a6e228c4f12e978996984cb48bfd982067c00baa789447f56d63f52f4bc210025b239b92141592eb0734088647c14ff3df646bd0e629ccb0ec57bec4372700d1041cdd44ecf4e4067cc363e76af1d52fbffc8a6164b25d4c7611b57169c76717a940f387959916aa259a1064596bbc76a7", + "af3a5bee87e8cfa1bc040c7dab318d74278c453f7fc750e1f9de642bb1e467dd36f84f548acb4270a58bdbcb54584c55a60466ea54d34053de06526ff32f1aafd1d8c4c92dae8d2bb097e7d36de9f0b41431de36e543386dbc6c8f674195bd8f5b6d0b39546c728e76075127d27adb1dc1d9e4ead47aae51812ba7655136d5be5b670f083505c5eec58ff77892e519220ab579bfdd7031d2a7f9534279424901cffe30ee1e585ba3e1f5faa8e5ad99f39fa87f27c39b854abcf3e0b7f6330439ce82074beb1d0b90ad13bf29463695cea80d5e1deb12ac58c946deac0de5393258dd545bd9fbf5fb55a052a7c2fcc181af9595fff110248e2eb1814cddf5fb6f8765019c6eb21bfa2b5e3826ec801cd7828a831cdcbdc8b3479b4109e86421af509b9c15bea0dd52af5ea5320258f326bf8116cf1a665f96a30eec72e9c75a1972f3b28b83a0060b8fd819fc898a967580c3ce027b6c3fa94ec7dfe125973a9a275762bbc799ff2d8184974de74cce78cb530f6009432e951dbf37d5ac966abb", + "b54d2b7c8a5be3023b7de2a7e75b2b8e927359c893c4977027f957f6ac7c580f78fec3eae65b7a34915bb2029404fba8c562ffe193fc2a469e995ff947f23029ccd8bea9843fe28901ebc1ac99f0a2be6284257248b213e4d83f755ac29faa1bf22d1eee0ff04f7645b87c66aecb6253c094a0bcf4b305d8567b6d5a80daf2b720ea966a198b6830095fac5ec386537b0dee6d222225abebdadd15a991080429566ae3b132c6678ad0697d0045d389cef8e965ebc2a165ce37311cb2bbf57512ac7aedfee9266b20b0d767992a0d6cae757793e058a24ead0d0335aa2b0118b8db60cfceb2c737706e62c6b4ac98a676c52150762659a2ca60125d774ac40413120477501fb18155619cc14fddef8e322f3a9fffdbeefaa4989043890d1f1bc67a9bc7657a5cc409435daf84fd39776e62ee583778f12062ab613aeaf6e62b32b415759cbc93c223fb45b8c87c9f0bf1bd9e749858350c4c7c26cf6c7e6d9ca1fd6d56d66450feb38ce3a25aa44c1bdc978641e02affb76cba8684a326845bdd", + "fdc427b39f77949c8c657a09484ee2fda4378cbece0d3651202e4fa62d0cf7916b9ae0592d1d8687f312406fc7e37504a80740eddf788a20a4d2ad3fad9105956ac27ed48e60acef4cc70092348676649e44b371772ca1a5225dd966ca955a5a8dd713c1ed31876f3846b1efce5734d7833ee3db9acb4c123cf3a79be142aa97603ba853d4cbe44c14bb10db27233a7db7fe5e57d3ea34cd9a6413d0d33dbf569238d314f9f3c7e93372cd6554ce15126ff4aa3819b4b28a645fa8fc4186110ddc1bc4dcc6bf11ecec639976424459bc6f817ae4364002062a59e3509b928f2b659b193b6f453f68ea82863ea2b2de1f4c19324d217e4830a6dd2cebd6192aaf646e3066e3991346428ef834fa06897446d9b507a6035cb8067e7ab3d621c012566d687748e60dcd0782772dcb805fc55c4b83d9c12b0e43c03583f894b51453f5fcaa16ba54abf90e8bb6e49b4999727228f4c437aef223e34964e30ab360357282d8187b4cf8a36a946ab35540df41f2f45ea8a00e64603da4fa2b56ba4bdd", + // https://github.com/binarly-io/SupplyChainAttacks/blob/main/Lenovo:LCFC/IntelKeysImpactedDevices.md + "53450ff591470c7dc3d7430b3f99780d3d6c87b54b32224d6a1ca88394c4c0831393d9d6bd5f9c2c2edf86959caaa36917c05ef42b9e0fc16c966e0fdf968014fe51a7886313ea804815d5ed249e7dfe177c518c023b280fcf62d713e04895fc3be67c5fdee26fd3f502a60c8be9ccadefe632d53807ee7e67875905239bc88b84c02faa4e095c778e5087794ec6c36f39f950c8935ca62c4c2e3f2ac3025a9c6d0d4e3e5b3cf85dc78dafc7eaadcd2f1337ff4f8cf3fae48bc7b631e464a923dd1f602f17a22289c2f4ec5657289d801831eec84cf8a79087e47a7afbf3f085ae42b054d4a3fd2c4f87827946ea4fa24581b7cd7633496e5db89385a947e2c07b24eb7fd9bda266f6abe60789e1deee1a27c9cc33cb86e0a62ad8e5fcf2a0cc52368bc73b2dc209cf2a6ad380e597dec884051af8883042675d95617a8b9902446948e896c1a1375b64fbce46f0b3927f77d1b1b6b3d6e0069df307afc7e6d60e113996038c348bbf0ea8dab5025a61a140349957e8a00589a6e7b9cb5043e3", + "13158420e2d1fb847e49a7994df957efdfcc975b8238aa2191e98c24620db163b9d34ba8f1e96b408ec8173291324c25ade38a3f2c77081e4f19550112fb5c9055e2e57642ecc0411fe7ec965f1eab8f9c24d62690a84e3a51e514931c86049b6574438d997c79503136e9979192c66ba8aa4f7db77a760fba352174b6048bf5a0820c0b3087e32f75d72ef27ddc70e8b2807d39f1c49140ec125e7a445cc722c7809e563f990935ce33f8e4b25c4433fdd73d31ec2136fd1206f19678cbcea8b64c58c2b7a8ddea5daee54a289b5f6c8ab8f8698d977a241cbf74c5b102ea0e650bd0d5405f6bdc9bcfec40d1dd6af2c7294eb880a16bcf8e3b1c284069e0e4", + "ff849b32ff8a956b5949868d619101651a35ae51182a8f550592a82ff14e96403f35c2fad403c8f91310f0e4adcf747c62a0805d40d8802e474024dffd02288991086ad818afb83a967dbee073a94b20fa095751e6be3d4378c99429f5af93b1b303a5886bc7d728f451eff0f23a0af9812eb6c55b9b1275faebd16acedb9f52b08a5ce7802e0971126fa6910ace7a70b13284e9a12e3f4f953de93ec0b1941a2b7e6f47c714e2d5cb481a4230c8b8032815183aa32e5b1997145063176dda642485c271649d6fe2900760b527c86f516de73f5c777a29aa54173a2f3b51d0713c4f4c8ceeb8b0bc3869d5aba0743796d8f65001371eea7bb1a1472d67ce5dbf", + "ddd5d1efba0b586e933c3dfbf7aa84deaba6716c57747c517b8243884f0fa5dc57ebb2ede50c1f3dfe5b07c9c32c8f463fcb73856674b7996df5673666be1a4e989084f3a519b03f1a4ad2975166ff4c75097f300b328fd61e879a38fbf341c1b34f896b1a82dfc51bb2857d64a8e052621ef57ed6a9e6d3939fe968826ddc69e2a12e293a569fd5043ce33bb0926979fa24071bb174858d941f50390fdbc414fd4669434c76419978dd019b0c5496377641cccf13675ac573db0e525c47d4c875ed8a7374f325609f7c571a95e9ea0d144fadcfd6a57c013b9daeddd06e156831fca833e8b3fd941b280d595589427f9a3e331e9f47b15027be6c960f82feca", + "d903fc44ebad1579bfb1a54522f2afa86ebdb862f54b59fe6b97a69af0745989e2352700747e8b10dfef1584d0d9a777e8aff37ede4a2a1a185f50ed01b74da4bdb465a57488108a22f6b0c6e6a1ba645ed85e8ffc9137effa886656401d9a604391dc0b6d8b01284a5b4db71ffc0f798e92b4030b02b83b16bad3a7f47072d84ee7c00c5257b10574c724d26bc6b75aba356e810fca0c46cf8fbbf48dfc5b3d8559b0357b30c2104e933c6ecc66cc2dd14f5a5ece734c2578f1734ce2253325189c639b21581fc56faa4036582578a4a86dc5ca5f9511d2036e00fa74619d2b1816410a3ccf84e8bbb4a776d3d9862b4268f31e31314ead28ecf66653e5269fc6fa396d1704bf5bd33e55240eb11f2090608d97c5b3b7eddc9f469f2f625d10e980e84ccc0d64e01ab211d6034424aa411407280de3a8a6e7271723658846ed9bde9ac237e22f4f143d322ae20e2c41367ad69bf1a4ea8d26a9a885f0566900658847ca3b7d17f67be9cb5a49398b41f0f65bd01130c892c89851afc64a76d8", + } + + var bkeys [10][]byte + var err error + + for i, k := range keys { + bkeys[i], err = hex.DecodeString(k) + if err != nil { + fmt.Fprintf(os.Stderr, "cannot decode key\n") + } + } + + return bkeys +} + +type Manifest interface{} + +type Meta struct { + Keym Manifest + Polm Manifest +} + +func main() { + flag.Parse() + if flag.Arg(0) == "" { + log.Fatalf("missing file name") + } + filePath := flag.Arg(0) + data, err := os.ReadFile(filePath) + if err != nil { + log.Fatalf("cannot read input file: %v", err) + } + + entries, err := fit.GetEntries(data) + if err != nil { + log.Fatalf("cannot parse input file: %v", err) + } + + var bme fit.Entry + var kme fit.Entry + for idx, entry := range entries { + // if entry.GetEntryBase().Headers.Type() == fit.EntryTypeStartupACModuleEntry { + if entry.GetEntryBase().Headers.Type() == fit.EntryTypeKeyManifestRecord { + kme = entry + fmt.Fprintf(os.Stderr, "key manifest @ %v\n", idx) + } + if entry.GetEntryBase().Headers.Type() == fit.EntryTypeBootPolicyManifest { + bme = entry + fmt.Fprintf(os.Stderr, "boot policy manifest @ %v\n", idx) + } + } + + var meta Meta + + if bme == nil { + fmt.Fprintf(os.Stderr, "no boot manifest entry\n") + } else { + bpm := bgbootpolicy.Manifest{} + _, err = bpm.ReadFrom(bytes.NewReader(bme.GetEntryBase().DataSegmentBytes)) + if err == nil { + if !*flagJSON { + fmt.Print(bpm.PrettyString(0, true)) + } + meta.Polm = bpm + } else { + // log.Fatalf("%v", err) + bpm := cbntbootpolicy.Manifest{} + _, err = bpm.ReadFrom(bytes.NewReader(bme.GetEntryBase().DataSegmentBytes)) + if err == nil { + if !*flagJSON { + fmt.Print(bpm.PrettyString(0, true)) + } + meta.Polm = bpm + } else { + // log.Fatalf("%v", err) + } + } + } + + if kme == nil { + fmt.Fprintf(os.Stderr, "no key manifest entry\n") + } else { + km := bgkey.Manifest{} + _, err = km.ReadFrom(bytes.NewReader(kme.GetEntryBase().DataSegmentBytes)) + if err == nil { + if !*flagJSON { + fmt.Print(km.PrettyString(0, true)) + } + meta.Keym = km + } else { + // log.Fatalf("%v", err) + km := cbntkey.Manifest{} + _, err = km.ReadFrom(bytes.NewReader(kme.GetEntryBase().DataSegmentBytes)) + if err == nil { + if !*flagJSON { + fmt.Print(km.PrettyString(0, true)) + } + meta.Keym = km + } else { + // log.Fatalf("%v", err) + } + } + } + + if *flagJSON { + j, err := json.MarshalIndent(meta, "", " ") + if err != nil { + log.Fatalf("cannot marshal JSON: %v", err) + } + if err != nil { + log.Fatalf("cannot marshal JSON: %v", err) + } + fmt.Println(string(j)) + } + + leakedKeys := getLeakedKeys() + if meta.Polm != nil { + p := meta.Polm.(cbntbootpolicy.Manifest) + k := p.PMSE.Key.Data[4:] + // fmt.Fprintf(os.Stderr, "%v\n", k) + for _, lk := range leakedKeys { + if bytes.Equal(k, lk) { + fmt.Fprintf(os.Stderr, "LEAKED BG KEY USED: %x\n", lk[:8]) + } + } + } +} From f1e8c5d71382cb51943ca930309f82e79929d092 Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Tue, 17 Jan 2023 16:38:13 +0100 Subject: [PATCH 03/14] Draft km and bginfo commands (to be discarded) Signed-off-by: Daniel Maslowski --- cmds/bginfo/main.go | 56 +++++++++++++++++++++++++++++++++++++++++++++ cmds/km/main.go | 55 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 cmds/bginfo/main.go create mode 100644 cmds/km/main.go diff --git a/cmds/bginfo/main.go b/cmds/bginfo/main.go new file mode 100644 index 00000000..c0475042 --- /dev/null +++ b/cmds/bginfo/main.go @@ -0,0 +1,56 @@ +// Copyright 2017-2018 the LinuxBoot Authors. All rights reserved +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// fspinfo prints FSP header information. + +package main + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "os" + + "github.com/linuxboot/fiano/pkg/intel/metadata/bg/bgbootpolicy" + "github.com/linuxboot/fiano/pkg/log" +) + +var ( + flagJSON = flag.Bool("j", false, "Output as JSON") +) + +func main() { + flag.Parse() + if flag.Arg(0) == "" { + log.Fatalf("missing file name") + } + data, err := os.ReadFile(flag.Arg(0)) + if err != nil { + log.Fatalf("cannot read input file: %x", err) + } + + ACBPMagic := []byte("__ACBP__") + // __IBBS__ also seen in the next 16 bytes; not sure what that is + offset := bytes.Index(data, ACBPMagic) + if offset == -1 { + log.Fatalf("no %v (%x) magic found", string(ACBPMagic), ACBPMagic) + } + + m := bgbootpolicy.Manifest{} + _, err = m.ReadFrom(bytes.NewReader(data[offset:])) + if err != nil { + log.Fatalf("%v", err) + } + + j, err := json.MarshalIndent(m, "", " ") + if err != nil { + log.Fatalf("cannot marshal JSON: %v", err) + } + if *flagJSON { + fmt.Println(string(j)) + } else { + fmt.Print(m.PrettyString(0, true)) + } +} diff --git a/cmds/km/main.go b/cmds/km/main.go new file mode 100644 index 00000000..111bb889 --- /dev/null +++ b/cmds/km/main.go @@ -0,0 +1,55 @@ +// Copyright 2017-2018 the LinuxBoot Authors. All rights reserved +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// fspinfo prints FSP header information. + +package main + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "os" + + "github.com/linuxboot/fiano/pkg/intel/metadata/cbnt/cbntkey" + "github.com/linuxboot/fiano/pkg/log" +) + +var ( + flagJSON = flag.Bool("j", false, "Output as JSON") +) + +func main() { + flag.Parse() + if flag.Arg(0) == "" { + log.Fatalf("missing file name") + } + data, err := os.ReadFile(flag.Arg(0)) + if err != nil { + log.Fatalf("cannot read input file: %v", err) + } + + KEYMMagic := []byte("__KEYM__") + offset := bytes.Index(data, KEYMMagic) + if offset == -1 { + log.Fatalf("no %v magic (%x) found", string(KEYMMagic), KEYMMagic) + } + + m := cbntkey.Manifest{} + _, err = m.ReadFrom(bytes.NewReader(data)) + if err != nil { + log.Fatalf("%v", err) + } + + j, err := json.MarshalIndent(m, "", " ") + if err != nil { + log.Fatalf("cannot marshal JSON: %v", err) + } + if *flagJSON { + fmt.Println(string(j)) + } else { + fmt.Print(m.PrettyString(0, true)) + } +} From 4897ae69888bf17eb432f7bdee5efd35d9e04eb3 Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Mon, 15 May 2023 21:44:18 +0200 Subject: [PATCH 04/14] intelmeta: get the whole FIT Signed-off-by: Daniel Maslowski --- cmds/intelmeta/main.go | 59 ++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/cmds/intelmeta/main.go b/cmds/intelmeta/main.go index 81a47bf6..4056b550 100644 --- a/cmds/intelmeta/main.go +++ b/cmds/intelmeta/main.go @@ -24,7 +24,7 @@ var ( flagJSON = flag.Bool("j", false, "Output as JSON") ) -func getLeakedKeys() [10][]byte { +func getLeakedKeys() ([10][]byte, error) { var keys = [10]string{ // https://github.com/binarly-io/SupplyChainAttacks/blob/main/MSI/MsiImpactedDevices.md "77304b5179d0924e55060188495c80135da6be5a357234809e04a50c9629be6832f2d71be5e720a71bc9103b62413f91f98bf35723a358c5a24530fd46f6c89e6b3c22b77cd364b252bb0190cbc5ef6dd91811bfeff9a7308a6b5d60a4297dcfab6302d5d9db78103d4467d097bacce456b54c983f175c44bfd150b5121a589fa642308fd522471b6216afa0a9dbf8f158b0f7a787c0c6a58e70f2ebbff73708a880ae929bdc6097d6bc6463ab524c4ee6e9aa208ac845211b0e04fe8f2dca3799641af550e4740498ed7c3b4e9ceaf8e9256a30623cba4799ba8198cb3d53e28492c49ce3512856dfd4577992c6c7867eee353bbb38424ac83dcfc7dfba902bb41b180ded8026ac9591f3575cc4e2a6e228c4f12e978996984cb48bfd982067c00baa789447f56d63f52f4bc210025b239b92141592eb0734088647c14ff3df646bd0e629ccb0ec57bec4372700d1041cdd44ecf4e4067cc363e76af1d52fbffc8a6164b25d4c7611b57169c76717a940f387959916aa259a1064596bbc76a7", @@ -45,18 +45,20 @@ func getLeakedKeys() [10][]byte { for i, k := range keys { bkeys[i], err = hex.DecodeString(k) if err != nil { - fmt.Fprintf(os.Stderr, "cannot decode key\n") + return bkeys, err } } - return bkeys + return bkeys, nil } type Manifest interface{} type Meta struct { - Keym Manifest - Polm Manifest + Keym Manifest + Polm Manifest + Fit []fit.Entry + LeakedKey string } func main() { @@ -90,6 +92,7 @@ func main() { } var meta Meta + meta.Fit = entries if bme == nil { fmt.Fprintf(os.Stderr, "no boot manifest entry\n") @@ -141,26 +144,44 @@ func main() { } } + leakedKeys, err := getLeakedKeys() + if err != nil { + fmt.Fprintf(os.Stderr, "[ERR]: cannot decode list of presumably hex-encoded leaked keys\n") + } + if meta.Polm != nil { + // https://go.dev/tour/methods/15 + _, ok := meta.Polm.(cbntbootpolicy.Manifest) + if ok == true { + pol := meta.Polm.(cbntbootpolicy.Manifest) + k := pol.PMSE.Key.Data[4:] + for _, lk := range leakedKeys { + if bytes.Equal(k, lk) { + meta.LeakedKey = hex.EncodeToString(lk[:8]) + } + } + } + if ok == false { + p, ok := meta.Polm.(bgbootpolicy.Manifest) + if ok == true { + k := p.PMSE.Key.Data[4:] + for _, lk := range leakedKeys { + if bytes.Equal(k, lk) { + meta.LeakedKey = hex.EncodeToString(lk[:8]) + } + } + } + } + } + if *flagJSON { j, err := json.MarshalIndent(meta, "", " ") if err != nil { - log.Fatalf("cannot marshal JSON: %v", err) - } - if err != nil { - log.Fatalf("cannot marshal JSON: %v", err) + log.Fatalf("cannot marshal to JSON: %v", err) } fmt.Println(string(j)) } - leakedKeys := getLeakedKeys() - if meta.Polm != nil { - p := meta.Polm.(cbntbootpolicy.Manifest) - k := p.PMSE.Key.Data[4:] - // fmt.Fprintf(os.Stderr, "%v\n", k) - for _, lk := range leakedKeys { - if bytes.Equal(k, lk) { - fmt.Fprintf(os.Stderr, "LEAKED BG KEY USED: %x\n", lk[:8]) - } - } + if meta.LeakedKey != "" { + fmt.Fprintf(os.Stderr, "LEAKED BG KEY USED: %x\n", meta.LeakedKey) } } From 22a1ed43aa5d842ee719c3371e3823cda3862f01 Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Tue, 16 May 2023 00:55:22 +0200 Subject: [PATCH 05/14] intel/metadata/fit: spell out SACM to StartupACM This makes it easier to grasp. Intel docs also spell it out. See: https://www.intel.com/content/dam/develop/external/us/en/documents/firmware-interface-table-bios-specification-r1p2p1.pdf Signed-off-by: Daniel Maslowski --- .../fit/ent_startup_ac_module_entry.go | 272 +++++++++--------- pkg/intel/metadata/fit/entry_type.go | 2 +- 2 files changed, 139 insertions(+), 135 deletions(-) diff --git a/pkg/intel/metadata/fit/ent_startup_ac_module_entry.go b/pkg/intel/metadata/fit/ent_startup_ac_module_entry.go index 15969900..9919b790 100644 --- a/pkg/intel/metadata/fit/ent_startup_ac_module_entry.go +++ b/pkg/intel/metadata/fit/ent_startup_ac_module_entry.go @@ -17,12 +17,12 @@ import ( "github.com/xaionaro-go/bytesextra" ) -// EntrySACM represents a FIT entry of type "Startup AC Module Entry" (0x02) -type EntrySACM struct{ EntryBase } +// EntryStartupACM represents a FIT entry of type "Startup AC Module Entry" (0x02) +type EntryStartupACM struct{ EntryBase } -var _ EntryCustomGetDataSegmentSizer = (*EntrySACM)(nil) +var _ EntryCustomGetDataSegmentSizer = (*EntryStartupACM)(nil) -func (entry *EntrySACM) CustomGetDataSegmentSize(firmware io.ReadSeeker) (uint64, error) { +func (entry *EntryStartupACM) CustomGetDataSegmentSize(firmware io.ReadSeeker) (uint64, error) { offset, err := entry.Headers.getDataSegmentOffset(firmware) if err != nil { return 0, fmt.Errorf("unable to detect data segment offset: %w", err) @@ -31,16 +31,16 @@ func (entry *EntrySACM) CustomGetDataSegmentSize(firmware io.ReadSeeker) (uint64 // See point "7" of "2.7" of the specification: the size field is // always zero. So we parsing the size from it's data right now: var size uint32 - size, err = EntrySACMParseSizeFrom(firmware, offset) + size, err = EntryStartupACMParseSizeFrom(firmware, offset) if err != nil { return 0, fmt.Errorf("unable to detect data segment size: %w", err) } return uint64(size), nil } -var _ EntryCustomRecalculateHeaderser = (*EntrySACM)(nil) +var _ EntryCustomRecalculateHeaderser = (*EntryStartupACM)(nil) -func (entry *EntrySACM) CustomRecalculateHeaders() error { +func (entry *EntryStartupACM) CustomRecalculateHeaders() error { // See 4.4.7 of the FIT specification. entry.Headers.Size.SetUint32(0) return nil @@ -50,9 +50,9 @@ func (entry *EntrySACM) CustomRecalculateHeaders() error { // "Intel ® Trusted Execution Technology (Intel ® TXT)" // https://www.intel.com/content/www/us/en/software-developers/txt-software-development-guide.html -// EntrySACMDataInterface is the interface of a startup AC module +// EntryStartupACMDataInterface is the interface of a startup AC module // data (of any version) -type EntrySACMDataInterface interface { +type EntryStartupACMDataInterface interface { io.ReadWriter io.ReaderFrom io.WriterTo @@ -168,9 +168,9 @@ type SegSel uint32 // EntryPoint is the authenticated code entry point offset (bytes) type EntryPoint uint32 -// EntrySACMDataCommon is the common part from the beginning of a startup AC module +// EntryStartupACMDataCommon is the common part from the beginning of a startup AC module // entry of any version. -type EntrySACMDataCommon struct { +type EntryStartupACMDataCommon struct { ModuleType ACModuleType ModuleSubType ACModuleSubType HeaderLen SizeM4 @@ -193,159 +193,163 @@ type EntrySACMDataCommon struct { ScratchSize SizeM4 } -var entrySACMDataCommonSize = uint(binary.Size(EntrySACMDataCommon{})) +var entryStartupACMDataCommonSize = uint(binary.Size(EntryStartupACMDataCommon{})) // Read parses the ACM common headers -func (entryData *EntrySACMDataCommon) Read(b []byte) (int, error) { +func (entryData *EntryStartupACMDataCommon) Read(b []byte) (int, error) { n, err := entryData.ReadFrom(bytesextra.NewReadWriteSeeker(b)) return int(n), err } // ReadFrom parses the ACM common headers -func (entryData *EntrySACMDataCommon) ReadFrom(r io.Reader) (int64, error) { +func (entryData *EntryStartupACMDataCommon) ReadFrom(r io.Reader) (int64, error) { err := binary.Read(r, binary.LittleEndian, entryData) if err != nil { return -1, err } - return int64(entrySACMDataCommonSize), nil + return int64(entryStartupACMDataCommonSize), nil } -// Write compiles the SACM common headers into a binary representation -func (entryData *EntrySACMDataCommon) Write(b []byte) (int, error) { +// Write compiles the ACM common headers into a binary representation +func (entryData *EntryStartupACMDataCommon) Write(b []byte) (int, error) { n, err := entryData.WriteTo(bytesextra.NewReadWriteSeeker(b)) return int(n), err } -// WriteTo compiles the SACM common headers into a binary representation -func (entryData *EntrySACMDataCommon) WriteTo(w io.Writer) (int64, error) { +// WriteTo compiles the ACM common headers into a binary representation +func (entryData *EntryStartupACMDataCommon) WriteTo(w io.Writer) (int64, error) { err := binary.Write(w, binary.LittleEndian, entryData) if err != nil { return -1, err } - return int64(entrySACMDataCommonSize), nil + return int64(entryStartupACMDataCommonSize), nil } // GetModuleType returns the type of AC module -func (entryData *EntrySACMDataCommon) GetModuleType() ACModuleType { return entryData.ModuleType } +func (entryData *EntryStartupACMDataCommon) GetModuleType() ACModuleType { return entryData.ModuleType } // GetModuleSubType returns the subtype of AC module (0 - TXT ACM; 1 - S-ACM) -func (entryData *EntrySACMDataCommon) GetModuleSubType() ACModuleSubType { +func (entryData *EntryStartupACMDataCommon) GetModuleSubType() ACModuleSubType { return entryData.ModuleSubType } // GetHeaderLen returns HeaderLen field value -func (entryData *EntrySACMDataCommon) GetHeaderLen() SizeM4 { return entryData.HeaderLen } +func (entryData *EntryStartupACMDataCommon) GetHeaderLen() SizeM4 { return entryData.HeaderLen } // GetHeaderVersion returns module format version: // * 0.0 – for SINIT ACM before 2017 // * 3.0 – for SINIT ACM of converge of BtG and TXT -func (entryData *EntrySACMDataCommon) GetHeaderVersion() ACModuleHeaderVersion { +func (entryData *EntryStartupACMDataCommon) GetHeaderVersion() ACModuleHeaderVersion { return entryData.HeaderVersion } // GetChipsetID returns ChipsetID field value -func (entryData *EntrySACMDataCommon) GetChipsetID() ACChipsetID { return entryData.ChipsetID } +func (entryData *EntryStartupACMDataCommon) GetChipsetID() ACChipsetID { return entryData.ChipsetID } // GetFlags returns Flags field value (the module-specific flags) -func (entryData *EntrySACMDataCommon) GetFlags() ACFlags { return entryData.Flags } +func (entryData *EntryStartupACMDataCommon) GetFlags() ACFlags { return entryData.Flags } // GetModuleVendor returns ModuleVendor field value -func (entryData *EntrySACMDataCommon) GetModuleVendor() ACModuleVendor { return entryData.ModuleVendor } +func (entryData *EntryStartupACMDataCommon) GetModuleVendor() ACModuleVendor { + return entryData.ModuleVendor +} // GetDate returns Date field value ("year.month.day") -func (entryData *EntrySACMDataCommon) GetDate() BCDDate { return entryData.Date } +func (entryData *EntryStartupACMDataCommon) GetDate() BCDDate { return entryData.Date } // GetSize returns Size field value (the size in multiples of four bytes) -func (entryData *EntrySACMDataCommon) GetSize() SizeM4 { return entryData.Size } +func (entryData *EntryStartupACMDataCommon) GetSize() SizeM4 { return entryData.Size } // GetTXTSVN returns TXT security version number -func (entryData *EntrySACMDataCommon) GetTXTSVN() TXTSVN { return entryData.TXTSVN } +func (entryData *EntryStartupACMDataCommon) GetTXTSVN() TXTSVN { return entryData.TXTSVN } // GetSESVN returns Software Guard Extensions (Secure Enclaves) Security Version Number -func (entryData *EntrySACMDataCommon) GetSESVN() SESVN { return entryData.SESVN } +func (entryData *EntryStartupACMDataCommon) GetSESVN() SESVN { return entryData.SESVN } // GetCodeControl returns the authenticated code control flags -func (entryData *EntrySACMDataCommon) GetCodeControl() CodeControl { return entryData.CodeControl } +func (entryData *EntryStartupACMDataCommon) GetCodeControl() CodeControl { + return entryData.CodeControl +} // GetErrorEntryPoint returns error entry point field value -func (entryData *EntrySACMDataCommon) GetErrorEntryPoint() ErrorEntryPoint { +func (entryData *EntryStartupACMDataCommon) GetErrorEntryPoint() ErrorEntryPoint { return entryData.ErrorEntryPoint } // GetGDTLimit returns GDTLimit field value -func (entryData *EntrySACMDataCommon) GetGDTLimit() GDTLimit { return entryData.GDTLimit } +func (entryData *EntryStartupACMDataCommon) GetGDTLimit() GDTLimit { return entryData.GDTLimit } // GetGDTBasePtr returns the GDT base pointer offset (bytes) -func (entryData *EntrySACMDataCommon) GetGDTBasePtr() GDTBasePtr { return entryData.GDTBasePtr } +func (entryData *EntryStartupACMDataCommon) GetGDTBasePtr() GDTBasePtr { return entryData.GDTBasePtr } // GetSegSel the segment selector initializer -func (entryData *EntrySACMDataCommon) GetSegSel() SegSel { return entryData.SegSel } +func (entryData *EntryStartupACMDataCommon) GetSegSel() SegSel { return entryData.SegSel } // GetEntryPoint returns the authenticated code entry point offset (bytes) -func (entryData *EntrySACMDataCommon) GetEntryPoint() EntryPoint { return entryData.EntryPoint } +func (entryData *EntryStartupACMDataCommon) GetEntryPoint() EntryPoint { return entryData.EntryPoint } // GetReserved2 returns the Reserved2 field value -func (entryData *EntrySACMDataCommon) GetReserved2() [64]byte { return entryData.Reserved2 } +func (entryData *EntryStartupACMDataCommon) GetReserved2() [64]byte { return entryData.Reserved2 } // GetKeySize returns the KeySize field value (the size in multiples of four bytes) -func (entryData *EntrySACMDataCommon) GetKeySize() SizeM4 { return entryData.KeySize } +func (entryData *EntryStartupACMDataCommon) GetKeySize() SizeM4 { return entryData.KeySize } // GetScratchSize returns the ScratchSize field value (the size in multiples of four bytes) -func (entryData *EntrySACMDataCommon) GetScratchSize() SizeM4 { return entryData.ScratchSize } +func (entryData *EntryStartupACMDataCommon) GetScratchSize() SizeM4 { return entryData.ScratchSize } // GetRSAPubKey returns the RSA public key -func (entryData *EntrySACMDataCommon) GetRSAPubKey() rsa.PublicKey { return rsa.PublicKey{} } +func (entryData *EntryStartupACMDataCommon) GetRSAPubKey() rsa.PublicKey { return rsa.PublicKey{} } // GetRSAPubExp returns the RSA exponent -func (entryData *EntrySACMDataCommon) GetRSAPubExp() uint32 { return 0 } +func (entryData *EntryStartupACMDataCommon) GetRSAPubExp() uint32 { return 0 } // GetRSASig returns the RSA signature. -func (entryData *EntrySACMDataCommon) GetRSASig() []byte { return nil } +func (entryData *EntryStartupACMDataCommon) GetRSASig() []byte { return nil } // RSASigBinaryOffset returns the RSA signature offset -func (entryData *EntrySACMDataCommon) RSASigBinaryOffset() uint64 { return 0 } +func (entryData *EntryStartupACMDataCommon) RSASigBinaryOffset() uint64 { return 0 } // GetScratch returns the Scratch field value -func (entryData *EntrySACMDataCommon) GetScratch() []byte { return nil } +func (entryData *EntryStartupACMDataCommon) GetScratch() []byte { return nil } // HeaderVersionBinaryOffset returns the offset of the field 'HeaderVersion' // relatively to the beginning of the structure in the binary // format (see 'encoding/binary'). -func (entryData EntrySACMDataCommon) HeaderVersionBinaryOffset() uint { +func (entryData EntryStartupACMDataCommon) HeaderVersionBinaryOffset() uint { return 8 } // DateBinaryOffset returns the offset of the field 'Date' // relatively to the beginning of the structure in the binary // format (see 'encoding/binary'). -func (entryData EntrySACMDataCommon) DateBinaryOffset() uint { +func (entryData EntryStartupACMDataCommon) DateBinaryOffset() uint { return 20 } // SizeBinaryOffset returns the offset of the field 'Size' // relatively to the beginning of the structure in the binary // format (see 'encoding/binary'). -func (entryData EntrySACMDataCommon) SizeBinaryOffset() uint { +func (entryData EntryStartupACMDataCommon) SizeBinaryOffset() uint { return 24 } // TXTSVNBinaryOffset returns the offset of the field 'TXTSVN' // relatively to the beginning of the structure in the binary // format (see 'encoding/binary'). -func (entryData *EntrySACMDataCommon) TXTSVNBinaryOffset() uint64 { +func (entryData *EntryStartupACMDataCommon) TXTSVNBinaryOffset() uint64 { return 28 } // KeySizeBinaryOffset returns the offset of the field 'KeySize' // relatively to the beginning of the structure in the binary // format (see 'encoding/binary'). -func (entryData EntrySACMDataCommon) KeySizeBinaryOffset() uint { +func (entryData EntryStartupACMDataCommon) KeySizeBinaryOffset() uint { return 120 } -// EntrySACMData0 is the structure for ACM of version 0.0. -type EntrySACMData0 struct { - EntrySACMDataCommon +// EntryStartupACMData0 is the structure for ACM of version 0.0. +type EntryStartupACMData0 struct { + EntryStartupACMDataCommon RSAPubKey [256]byte RSAPubExp [4]byte @@ -353,40 +357,40 @@ type EntrySACMData0 struct { Scratch [572]byte } -var entrySACMData0Size = uint(binary.Size(EntrySACMData0{})) +var entryStartupACMData0Size = uint(binary.Size(EntryStartupACMData0{})) // Read parses the ACM v0 headers -func (entryData *EntrySACMData0) Read(b []byte) (int, error) { +func (entryData *EntryStartupACMData0) Read(b []byte) (int, error) { n, err := entryData.ReadFrom(bytesextra.NewReadWriteSeeker(b)) return int(n), err } // ReadFrom parses the ACM v0 headers -func (entryData *EntrySACMData0) ReadFrom(r io.Reader) (int64, error) { +func (entryData *EntryStartupACMData0) ReadFrom(r io.Reader) (int64, error) { err := binary.Read(r, binary.LittleEndian, entryData) if err != nil { return -1, err } - return int64(entrySACMData0Size), nil + return int64(entryStartupACMData0Size), nil } -// Write compiles the SACM v0 headers into a binary representation -func (entryData *EntrySACMData0) Write(b []byte) (int, error) { +// Write compiles the ACM v0 headers into a binary representation +func (entryData *EntryStartupACMData0) Write(b []byte) (int, error) { n, err := entryData.WriteTo(bytesextra.NewReadWriteSeeker(b)) return int(n), err } -// WriteTo compiles the SACM v0 headers into a binary representation -func (entryData *EntrySACMData0) WriteTo(w io.Writer) (int64, error) { +// WriteTo compiles the ACM v0 headers into a binary representation +func (entryData *EntryStartupACMData0) WriteTo(w io.Writer) (int64, error) { err := binary.Write(w, binary.LittleEndian, entryData) if err != nil { return -1, err } - return int64(entrySACMData0Size), nil + return int64(entryStartupACMData0Size), nil } // GetRSAPubKey returns the RSA public key -func (entryData *EntrySACMData0) GetRSAPubKey() rsa.PublicKey { +func (entryData *EntryStartupACMData0) GetRSAPubKey() rsa.PublicKey { pubKey := rsa.PublicKey{ N: big.NewInt(0), E: int(entryData.GetRSAPubExp()), @@ -396,66 +400,66 @@ func (entryData *EntrySACMData0) GetRSAPubKey() rsa.PublicKey { } // GetRSAPubExp returns the RSA exponent -func (entryData *EntrySACMData0) GetRSAPubExp() uint32 { +func (entryData *EntryStartupACMData0) GetRSAPubExp() uint32 { return binary.LittleEndian.Uint32(entryData.RSAPubExp[:]) } // GetRSASig returns the RSA signature. -func (entryData *EntrySACMData0) GetRSASig() []byte { return entryData.RSASig[:] } +func (entryData *EntryStartupACMData0) GetRSASig() []byte { return entryData.RSASig[:] } // RSASigBinaryOffset returns the RSA signature offset -func (entryData *EntrySACMData0) RSASigBinaryOffset() uint64 { - return uint64(binary.Size(entryData.EntrySACMDataCommon)) + +func (entryData *EntryStartupACMData0) RSASigBinaryOffset() uint64 { + return uint64(binary.Size(entryData.EntryStartupACMDataCommon)) + uint64(binary.Size(entryData.RSAPubKey)) + uint64(binary.Size(entryData.RSAPubExp)) } // GetScratch returns the Scratch field value -func (entryData *EntrySACMData0) GetScratch() []byte { return entryData.Scratch[:] } +func (entryData *EntryStartupACMData0) GetScratch() []byte { return entryData.Scratch[:] } -// EntrySACMData3 is the structure for ACM of version 3.0 -type EntrySACMData3 struct { - EntrySACMDataCommon +// EntryStartupACMData3 is the structure for ACM of version 3.0 +type EntryStartupACMData3 struct { + EntryStartupACMDataCommon RSAPubKey [384]byte RSASig [384]byte Scratch [832]byte } -var entrySACMData3Size = uint(binary.Size(EntrySACMData3{})) +var entryStartupACMData3Size = uint(binary.Size(EntryStartupACMData3{})) // Read parses the ACM v3 headers -func (entryData *EntrySACMData3) Read(b []byte) (int, error) { +func (entryData *EntryStartupACMData3) Read(b []byte) (int, error) { n, err := entryData.ReadFrom(bytesextra.NewReadWriteSeeker(b)) return int(n), err } // ReadFrom parses the ACM v3 headers -func (entryData *EntrySACMData3) ReadFrom(r io.Reader) (int64, error) { +func (entryData *EntryStartupACMData3) ReadFrom(r io.Reader) (int64, error) { err := binary.Read(r, binary.LittleEndian, entryData) if err != nil { return -1, err } - return int64(entrySACMData3Size), nil + return int64(entryStartupACMData3Size), nil } -// Write compiles the SACM v3 headers into a binary representation -func (entryData *EntrySACMData3) Write(b []byte) (int, error) { +// Write compiles the StartupACM v3 headers into a binary representation +func (entryData *EntryStartupACMData3) Write(b []byte) (int, error) { n, err := entryData.WriteTo(bytesextra.NewReadWriteSeeker(b)) return int(n), err } -// WriteTo compiles the SACM v3 headers into a binary representation -func (entryData *EntrySACMData3) WriteTo(w io.Writer) (int64, error) { +// WriteTo compiles the StartupACM v3 headers into a binary representation +func (entryData *EntryStartupACMData3) WriteTo(w io.Writer) (int64, error) { err := binary.Write(w, binary.LittleEndian, entryData) if err != nil { return -1, err } - return int64(entrySACMData3Size), nil + return int64(entryStartupACMData3Size), nil } // GetRSAPubKey returns the RSA public key -func (entryData *EntrySACMData3) GetRSAPubKey() rsa.PublicKey { +func (entryData *EntryStartupACMData3) GetRSAPubKey() rsa.PublicKey { pubKey := rsa.PublicKey{ N: big.NewInt(0), E: 0x10001, // see Table 9. "RSAPubExp" of https://www.intel.com/content/www/us/en/software-developers/txt-software-development-guide.html @@ -465,49 +469,49 @@ func (entryData *EntrySACMData3) GetRSAPubKey() rsa.PublicKey { } // GetRSASig returns the RSA signature. -func (entryData *EntrySACMData3) GetRSASig() []byte { return entryData.RSASig[:] } +func (entryData *EntryStartupACMData3) GetRSASig() []byte { return entryData.RSASig[:] } // RSASigBinaryOffset returns the RSA signature offset -func (entryData *EntrySACMData3) RSASigBinaryOffset() uint64 { - return uint64(binary.Size(entryData.EntrySACMDataCommon)) + +func (entryData *EntryStartupACMData3) RSASigBinaryOffset() uint64 { + return uint64(binary.Size(entryData.EntryStartupACMDataCommon)) + uint64(binary.Size(entryData.RSAPubKey)) } // GetScratch returns the Scratch field value -func (entryData *EntrySACMData3) GetScratch() []byte { return entryData.Scratch[:] } +func (entryData *EntryStartupACMData3) GetScratch() []byte { return entryData.Scratch[:] } -// EntrySACMData combines the structure for ACM and the user area. -type EntrySACMData struct { - EntrySACMDataInterface +// EntryStartupACMData combines the structure for ACM and the user area. +type EntryStartupACMData struct { + EntryStartupACMDataInterface UserArea []byte } // Read parses the ACM -func (entryData *EntrySACMData) Read(b []byte) (int, error) { +func (entryData *EntryStartupACMData) Read(b []byte) (int, error) { n, err := entryData.ReadFrom(bytesextra.NewReadWriteSeeker(b)) return int(n), err } // ReadFrom parses the ACM -func (entryData *EntrySACMData) ReadFrom(r io.Reader) (int64, error) { - parsedEntryData, err := ParseSACMData(r) +func (entryData *EntryStartupACMData) ReadFrom(r io.Reader) (int64, error) { + parsedEntryData, err := ParseStartupACMData(r) if err != nil { return -1, err } *entryData = *parsedEntryData - return int64(binary.Size(entryData.EntrySACMDataInterface) + len(entryData.UserArea)), nil + return int64(binary.Size(entryData.EntryStartupACMDataInterface) + len(entryData.UserArea)), nil } -// Write compiles the SACM into a binary representation -func (entryData *EntrySACMData) Write(b []byte) (int, error) { +// Write compiles the StartupACM into a binary representation +func (entryData *EntryStartupACMData) Write(b []byte) (int, error) { n, err := entryData.WriteTo(bytesextra.NewReadWriteSeeker(b)) return int(n), err } -// WriteTo compiles the SACM into a binary representation -func (entryData *EntrySACMData) WriteTo(w io.Writer) (int64, error) { - totalN, err := entryData.EntrySACMDataInterface.WriteTo(w) +// WriteTo compiles the StartupACM into a binary representation +func (entryData *EntryStartupACMData) WriteTo(w io.Writer) (int64, error) { + totalN, err := entryData.EntryStartupACMDataInterface.WriteTo(w) if err != nil { return -1, err } @@ -525,24 +529,24 @@ func (entryData *EntrySACMData) WriteTo(w io.Writer) (int64, error) { } // GetCommon returns the common part of the structures for different ACM versions. -func (entryData *EntrySACMData) GetCommon() *EntrySACMDataCommon { +func (entryData *EntryStartupACMData) GetCommon() *EntryStartupACMDataCommon { if entryData == nil { return nil } - switch data := entryData.EntrySACMDataInterface.(type) { - case *EntrySACMDataCommon: + switch data := entryData.EntryStartupACMDataInterface.(type) { + case *EntryStartupACMDataCommon: return data - case *EntrySACMData0: - return &data.EntrySACMDataCommon - case *EntrySACMData3: - return &data.EntrySACMDataCommon + case *EntryStartupACMData0: + return &data.EntryStartupACMDataCommon + case *EntryStartupACMData3: + return &data.EntryStartupACMDataCommon } return nil } -// EntrySACMParseSizeFrom parses SACM structure size -func EntrySACMParseSizeFrom(r io.ReadSeeker, offset uint64) (uint32, error) { - sizeFieldLocalOffset := EntrySACMDataCommon{}.SizeBinaryOffset() +// EntryStartupACMParseSizeFrom parses ACM structure size +func EntryStartupACMParseSizeFrom(r io.ReadSeeker, offset uint64) (uint32, error) { + sizeFieldLocalOffset := EntryStartupACMDataCommon{}.SizeBinaryOffset() sizeFieldOffset := int64(offset) + int64(sizeFieldLocalOffset) _, err := r.Seek(sizeFieldOffset, io.SeekStart) if err != nil { @@ -556,18 +560,18 @@ func EntrySACMParseSizeFrom(r io.ReadSeeker, offset uint64) (uint32, error) { return result << 2, nil } -// EntrySACMParseSize parses SACM structure size -func EntrySACMParseSize(b []byte) (uint32, error) { - sizeFieldOffset := EntrySACMDataCommon{}.SizeBinaryOffset() +// EntryStartupACMParseSize parses ACM structure size +func EntryStartupACMParseSize(b []byte) (uint32, error) { + sizeFieldOffset := EntryStartupACMDataCommon{}.SizeBinaryOffset() if int(sizeFieldOffset) >= len(b)-4 { return 0, &check.ErrEndLessThanStart{StartIdx: int(sizeFieldOffset), EndIdx: len(b) - 4} } return binary.LittleEndian.Uint32(b[sizeFieldOffset:]) << 2, nil } -// ParseData parses SACM entry and returns EntrySACMData. -func (entry *EntrySACM) ParseData() (*EntrySACMData, error) { - entryData := EntrySACMData{} +// ParseData parses StartupACM entry and returns EntryStartupACMData. +func (entry *EntryStartupACM) ParseData() (*EntryStartupACMData, error) { + entryData := EntryStartupACMData{} _, err := entryData.Read(entry.DataSegmentBytes) if err != nil { return nil, err @@ -575,25 +579,25 @@ func (entry *EntrySACM) ParseData() (*EntrySACMData, error) { return &entryData, nil } -// ParseSACMData parses SACM entry and returns EntrySACMData. -func ParseSACMData(r io.Reader) (*EntrySACMData, error) { +// ParseStartupACMData parses StartupACM entry and returns EntryStartupACMData. +func ParseStartupACMData(r io.Reader) (*EntryStartupACMData, error) { // Read common headers - common := EntrySACMDataCommon{} + common := EntryStartupACMDataCommon{} if _, err := common.ReadFrom(r); err != nil { return nil, fmt.Errorf("unable to parse startup AC module entry: %w", err) } - result := &EntrySACMData{EntrySACMDataInterface: &common, UserArea: nil} + result := &EntryStartupACMData{EntryStartupACMDataInterface: &common, UserArea: nil} var requiredKeySize uint64 switch common.HeaderVersion { case ACHeaderVersion0: - result.EntrySACMDataInterface = &EntrySACMData0{EntrySACMDataCommon: common} - requiredKeySize = uint64(len(EntrySACMData0{}.RSAPubKey)) + result.EntryStartupACMDataInterface = &EntryStartupACMData0{EntryStartupACMDataCommon: common} + requiredKeySize = uint64(len(EntryStartupACMData0{}.RSAPubKey)) case ACHeaderVersion3: - result.EntrySACMDataInterface = &EntrySACMData3{EntrySACMDataCommon: common} - requiredKeySize = uint64(len(EntrySACMData3{}.RSAPubKey)) + result.EntryStartupACMDataInterface = &EntryStartupACMData3{EntryStartupACMDataCommon: common} + requiredKeySize = uint64(len(EntryStartupACMData3{}.RSAPubKey)) default: return result, &ErrUnknownACMHeaderVersion{ACHeaderVersion: common.HeaderVersion} } @@ -609,7 +613,7 @@ func ParseSACMData(r io.Reader) (*EntrySACMData, error) { // already read common headers). // Creating a substruct without the first field (which is already read) - t := reflect.TypeOf(result.EntrySACMDataInterface).Elem() + t := reflect.TypeOf(result.EntryStartupACMDataInterface).Elem() var fieldsToBeFilled []reflect.StructField for fieldNum := 1; fieldNum < t.NumField(); fieldNum++ { fieldsToBeFilled = append(fieldsToBeFilled, t.Field(fieldNum)) @@ -621,7 +625,7 @@ func ParseSACMData(r io.Reader) (*EntrySACMData, error) { } // Copying values from the substruct to the headers struct subStructToBeFilled = subStructToBeFilled.Elem() - v := reflect.ValueOf(result.EntrySACMDataInterface).Elem() + v := reflect.ValueOf(result.EntryStartupACMDataInterface).Elem() for fieldNum := 1; fieldNum < v.NumField(); fieldNum++ { v.Field(fieldNum).Set(subStructToBeFilled.Field(fieldNum - 1)) } @@ -629,11 +633,11 @@ func ParseSACMData(r io.Reader) (*EntrySACMData, error) { // Read UserArea // `UserArea` has variable length and therefore was not included into - // `EntrySACMData0` and `EntrySACMData3`, but it is in the tail, + // `EntryStartupACMData0` and `EntryStartupACMData3`, but it is in the tail, // so we just calculate the startIndex as the end of - // EntrySACMData0/EntrySACMData3. - userAreaStartIdx := uint64(binary.Size(result.EntrySACMDataInterface)) - userAreaEndIdx := result.EntrySACMDataInterface.GetSize().Size() + // EntryStartupACMData0/EntryStartupACMData3. + userAreaStartIdx := uint64(binary.Size(result.EntryStartupACMDataInterface)) + userAreaEndIdx := result.EntryStartupACMDataInterface.GetSize().Size() if userAreaEndIdx > userAreaStartIdx { var err error result.UserArea, err = readBytesFromReader(r, userAreaEndIdx-userAreaStartIdx) @@ -645,17 +649,17 @@ func ParseSACMData(r io.Reader) (*EntrySACMData, error) { return result, nil } -type entrySACMJSON struct { +type entryStartupACMJSON struct { Headers *EntryHeaders - DataParsed *EntrySACMData `json:",omitempty"` - DataNotParsed []byte `json:"DataNotParsedBase64,omitempty"` + DataParsed *EntryStartupACMData `json:",omitempty"` + DataNotParsed []byte `json:"DataNotParsedBase64,omitempty"` HeadersErrors []error DataParseError error } // MarshalJSON implements json.Marshaler -func (entry *EntrySACM) MarshalJSON() ([]byte, error) { - result := entrySACMJSON{} +func (entry *EntryStartupACM) MarshalJSON() ([]byte, error) { + result := entryStartupACMJSON{} result.DataParsed, result.DataParseError = entry.ParseData() result.Headers = &entry.Headers result.HeadersErrors = make([]error, len(entry.HeadersErrors)) @@ -665,8 +669,8 @@ func (entry *EntrySACM) MarshalJSON() ([]byte, error) { } // UnmarshalJSON implements json.Unmarshaller -func (entry *EntrySACM) UnmarshalJSON(b []byte) error { - result := entrySACMJSON{} +func (entry *EntryStartupACM) UnmarshalJSON(b []byte) error { + result := entryStartupACMJSON{} err := json.Unmarshal(b, &result) if err != nil { return err diff --git a/pkg/intel/metadata/fit/entry_type.go b/pkg/intel/metadata/fit/entry_type.go index 29c62f84..ae54d181 100644 --- a/pkg/intel/metadata/fit/entry_type.go +++ b/pkg/intel/metadata/fit/entry_type.go @@ -70,7 +70,7 @@ func RegisterEntryType(entryTypeID EntryType, entryGoType Entry) { func init() { RegisterEntryType(EntryTypeFITHeaderEntry, &EntryFITHeaderEntry{}) RegisterEntryType(EntryTypeMicrocodeUpdateEntry, &EntryMicrocodeUpdateEntry{}) - RegisterEntryType(EntryTypeStartupACModuleEntry, &EntrySACM{}) + RegisterEntryType(EntryTypeStartupACModuleEntry, &EntryStartupACM{}) RegisterEntryType(EntryTypeDiagnosticACModuleEntry, &EntryDiagnosticACM{}) RegisterEntryType(EntryTypeBIOSStartupModuleEntry, &EntryBIOSStartupModuleEntry{}) RegisterEntryType(EntryTypeTPMPolicyRecord, &EntryTPMPolicyRecord{}) From f784df2708f2d53359e41de92f20b702f9c663ab Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Tue, 16 May 2023 00:56:18 +0200 Subject: [PATCH 06/14] intelmeta: pick up TXT policy, print main info on FIT entries Signed-off-by: Daniel Maslowski --- cmds/intelmeta/main.go | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/cmds/intelmeta/main.go b/cmds/intelmeta/main.go index 4056b550..67932fe5 100644 --- a/cmds/intelmeta/main.go +++ b/cmds/intelmeta/main.go @@ -54,10 +54,19 @@ func getLeakedKeys() ([10][]byte, error) { type Manifest interface{} +type FEntry struct { + Type string + Address fit.Address64 + Offset uint64 + Size uint32 + Version fit.EntryVersion +} + type Meta struct { Keym Manifest Polm Manifest Fit []fit.Entry + Entries []FEntry LeakedKey string } @@ -77,8 +86,13 @@ func main() { log.Fatalf("cannot parse input file: %v", err) } + var meta Meta + // TODO: the whole FIT is too verbose + // meta.Fit = entries + var bme fit.Entry var kme fit.Entry + var txte fit.Entry for idx, entry := range entries { // if entry.GetEntryBase().Headers.Type() == fit.EntryTypeStartupACModuleEntry { if entry.GetEntryBase().Headers.Type() == fit.EntryTypeKeyManifestRecord { @@ -89,11 +103,19 @@ func main() { bme = entry fmt.Fprintf(os.Stderr, "boot policy manifest @ %v\n", idx) } + if entry.GetEntryBase().Headers.Type() == fit.EntryTypeTXTPolicyRecord { + txte = entry + fmt.Fprintf(os.Stderr, "TXT policy manifest @ %v\n", idx) + } + meta.Entries = append(meta.Entries, FEntry{ + Type: entry.GetEntryBase().Headers.Type().String(), + Address: entry.GetEntryBase().Headers.Address, + Offset: entry.GetEntryBase().Headers.Address.Offset(uint64(len(data))), + Size: entry.GetEntryBase().Headers.Size.Uint32(), + Version: entry.GetEntryBase().Headers.Version, + }) } - var meta Meta - meta.Fit = entries - if bme == nil { fmt.Fprintf(os.Stderr, "no boot manifest entry\n") } else { @@ -184,4 +206,5 @@ func main() { if meta.LeakedKey != "" { fmt.Fprintf(os.Stderr, "LEAKED BG KEY USED: %x\n", meta.LeakedKey) } + fmt.Fprintf(os.Stderr, "TXT policy manifest @ %v\n", txte) } From 7be1d57e27f982ad01239f04759bfc5b0c54b4da Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Tue, 16 May 2023 01:56:07 +0200 Subject: [PATCH 07/14] intelmeta: special handling for TXT entry Signed-off-by: Daniel Maslowski --- cmds/intelmeta/main.go | 44 +++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/cmds/intelmeta/main.go b/cmds/intelmeta/main.go index 67932fe5..ec95e74d 100644 --- a/cmds/intelmeta/main.go +++ b/cmds/intelmeta/main.go @@ -54,9 +54,23 @@ func getLeakedKeys() ([10][]byte, error) { type Manifest interface{} +/* +FIXME: Do address and offset really always exist? I don't think so... +Example FIT: + +01c39980: 5f46 4954 5f20 2020 0700 0000 0001 0000 _FIT_ ........ +01c39990: 0004 bdff 0000 0000 0000 0000 0001 0100 ................ +01c399a0: 0028 c0ff 0000 0000 0000 0000 0001 0100 .(.............. +01c399b0: 0000 f8ff 0000 0000 0000 0000 0001 0200 ................ +01c399c0: 7000 7100 0104 7d00 0000 0000 0000 0a00 p.q...}......... +01c399d0: 0046 feff 0000 0000 5503 0000 0001 0b00 .F......U....... +01c399e0: 0041 feff 0000 0000 9504 0000 0001 0c00 .A.............. + +*/ + type FEntry struct { Type string - Address fit.Address64 + Address uint64 Offset uint64 Size uint32 Version fit.EntryVersion @@ -65,8 +79,7 @@ type FEntry struct { type Meta struct { Keym Manifest Polm Manifest - Fit []fit.Entry - Entries []FEntry + Fit []FEntry LeakedKey string } @@ -87,30 +100,35 @@ func main() { } var meta Meta - // TODO: the whole FIT is too verbose - // meta.Fit = entries - var bme fit.Entry var kme fit.Entry var txte fit.Entry for idx, entry := range entries { + t := entry.GetEntryBase().Headers.Type() // if entry.GetEntryBase().Headers.Type() == fit.EntryTypeStartupACModuleEntry { - if entry.GetEntryBase().Headers.Type() == fit.EntryTypeKeyManifestRecord { + if t == fit.EntryTypeKeyManifestRecord { kme = entry fmt.Fprintf(os.Stderr, "key manifest @ %v\n", idx) } - if entry.GetEntryBase().Headers.Type() == fit.EntryTypeBootPolicyManifest { + if t == fit.EntryTypeBootPolicyManifest { bme = entry fmt.Fprintf(os.Stderr, "boot policy manifest @ %v\n", idx) } - if entry.GetEntryBase().Headers.Type() == fit.EntryTypeTXTPolicyRecord { + if t == fit.EntryTypeTXTPolicyRecord { txte = entry fmt.Fprintf(os.Stderr, "TXT policy manifest @ %v\n", idx) } - meta.Entries = append(meta.Entries, FEntry{ - Type: entry.GetEntryBase().Headers.Type().String(), - Address: entry.GetEntryBase().Headers.Address, - Offset: entry.GetEntryBase().Headers.Address.Offset(uint64(len(data))), + var a uint64 + var o uint64 + if t != fit.EntryTypeFITHeaderEntry && t != fit.EntryTypeTXTPolicyRecord { + addr := entry.GetEntryBase().Headers.Address + a = addr.Pointer() + o = addr.Offset(uint64(len(data))) + } + meta.Fit = append(meta.Fit, FEntry{ + Type: t.String(), + Address: a, + Offset: o, Size: entry.GetEntryBase().Headers.Size.Uint32(), Version: entry.GetEntryBase().Headers.Version, }) From ec7a37a2110ba0bfa49afe687f93a754dfc3951d Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Tue, 16 May 2023 18:31:52 +0200 Subject: [PATCH 08/14] intelmeta: pretty-print TXT policy manifest Signed-off-by: Daniel Maslowski --- cmds/intelmeta/main.go | 50 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/cmds/intelmeta/main.go b/cmds/intelmeta/main.go index ec95e74d..0cf6c109 100644 --- a/cmds/intelmeta/main.go +++ b/cmds/intelmeta/main.go @@ -6,16 +6,19 @@ package main import ( "bytes" + "encoding/binary" "encoding/hex" "encoding/json" "flag" "fmt" "os" + "strings" "github.com/linuxboot/fiano/pkg/intel/metadata/bg/bgbootpolicy" "github.com/linuxboot/fiano/pkg/intel/metadata/bg/bgkey" "github.com/linuxboot/fiano/pkg/intel/metadata/cbnt/cbntbootpolicy" "github.com/linuxboot/fiano/pkg/intel/metadata/cbnt/cbntkey" + "github.com/linuxboot/fiano/pkg/intel/metadata/common/pretty" "github.com/linuxboot/fiano/pkg/intel/metadata/fit" "github.com/linuxboot/fiano/pkg/log" ) @@ -68,6 +71,35 @@ Example FIT: */ +// https://edc.intel.com/content/www/us/en/design/products-and-solutions/software-and-services/firmware-and-bios/firmware-interface-table/1.4/intel-txt-policy-data-record-type-0xa-rules/ +type IndexIOAddress struct { + IndexRegisterAddress uint16 + DataRegisterAddress uint16 + AccessWidthInBytes uint8 // 1 -> 1-byte access, 2 -> 2-byte access + BitPosition uint8 // e.g. 15 -> Bit15 + Index uint16 +} + +// PrettyString returns the content of the structure in an easy-to-read format. +func (s *IndexIOAddress) PrettyString(depth uint, withHeader bool, opts ...pretty.Option) string { + var lines []string + if withHeader { + lines = append(lines, pretty.Header(depth, "Index IO Address", s)) + } + if s == nil { + return strings.Join(lines, "\n") + } + lines = append(lines, pretty.SubValue(depth+1, "Index Register Address", "", &s.IndexRegisterAddress, opts...)...) + lines = append(lines, pretty.SubValue(depth+1, "Data Register Address", "", &s.DataRegisterAddress, opts...)...) + lines = append(lines, pretty.SubValue(depth+1, "Access Width", "", &s.AccessWidthInBytes, opts...)...) + lines = append(lines, pretty.SubValue(depth+1, "Bit Position", "", &s.BitPosition, opts...)...) + lines = append(lines, pretty.SubValue(depth+1, "Index", "", &s.Index, opts...)...) + if depth < 2 { + lines = append(lines, "") + } + return strings.Join(lines, "\n") +} + type FEntry struct { Type string Address uint64 @@ -221,8 +253,24 @@ func main() { fmt.Println(string(j)) } + if txte != nil { + var x IndexIOAddress + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, txte.GetEntryBase().Headers.Address.Pointer()) + r := bytes.NewReader(b) + binary.Read(r, binary.LittleEndian, &x) + if *flagJSON { + j, err := json.MarshalIndent(x, "", " ") + if err != nil { + log.Fatalf("cannot marshal to JSON: %v", err) + } + fmt.Fprintf(os.Stderr, "TXT Policy\n%v\n", string(j)) + } else { + fmt.Fprintf(os.Stderr, "TXT Policy\n%+v\n", x.PrettyString(0, true)) + } + } + if meta.LeakedKey != "" { fmt.Fprintf(os.Stderr, "LEAKED BG KEY USED: %x\n", meta.LeakedKey) } - fmt.Fprintf(os.Stderr, "TXT policy manifest @ %v\n", txte) } From f5f60d657fd64f1334154dc033ae6a1527e85fa4 Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Tue, 16 May 2023 18:33:52 +0200 Subject: [PATCH 09/14] intelmeta: pretty-print TXT policy manifest - fixup The IndexIOAddress variant only applies for version 0. Signed-off-by: Daniel Maslowski --- cmds/intelmeta/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmds/intelmeta/main.go b/cmds/intelmeta/main.go index 0cf6c109..f960e239 100644 --- a/cmds/intelmeta/main.go +++ b/cmds/intelmeta/main.go @@ -253,7 +253,7 @@ func main() { fmt.Println(string(j)) } - if txte != nil { + if txte != nil && txte.GetEntryBase().Headers.Version.Major() == 0 { var x IndexIOAddress b := make([]byte, 8) binary.LittleEndian.PutUint64(b, txte.GetEntryBase().Headers.Address.Pointer()) From fea7a79aa24f7f39166c93a586829f926158e976 Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Thu, 1 Jun 2023 22:59:05 +0200 Subject: [PATCH 10/14] WIP Signed-off-by: Daniel Maslowski --- cmds/intelmeta/main.go | 13 +++++++++++-- pkg/intel/metadata/cbnt/key.go | 3 +++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/cmds/intelmeta/main.go b/cmds/intelmeta/main.go index f960e239..a505571c 100644 --- a/cmds/intelmeta/main.go +++ b/cmds/intelmeta/main.go @@ -225,7 +225,13 @@ func main() { _, ok := meta.Polm.(cbntbootpolicy.Manifest) if ok == true { pol := meta.Polm.(cbntbootpolicy.Manifest) - k := pol.PMSE.Key.Data[4:] + key := pol.PMSE.Key + alg := pol.PMSE.Signature.HashAlg + err = key.PrintBPMPubKey(alg) + fmt.Fprintf(os.Stderr, "KEY CBNT policy key err: %v alg: %v\n", err, alg) + err = key.PrintKMPubKey(alg) + fmt.Fprintf(os.Stderr, "KEY CBNT manifest key err: %v alg: %v\n", err, alg) + k := key.Data[4:] for _, lk := range leakedKeys { if bytes.Equal(k, lk) { meta.LeakedKey = hex.EncodeToString(lk[:8]) @@ -235,7 +241,9 @@ func main() { if ok == false { p, ok := meta.Polm.(bgbootpolicy.Manifest) if ok == true { - k := p.PMSE.Key.Data[4:] + // the first 4 bytes are some sort of flags + key := p.PMSE.Key + k := key.Data[4:] for _, lk := range leakedKeys { if bytes.Equal(k, lk) { meta.LeakedKey = hex.EncodeToString(lk[:8]) @@ -270,6 +278,7 @@ func main() { } } + fmt.Fprintf(os.Stderr, "key size: %v\n", len(leakedKeys[0])*8) if meta.LeakedKey != "" { fmt.Fprintf(os.Stderr, "LEAKED BG KEY USED: %x\n", meta.LeakedKey) } diff --git a/pkg/intel/metadata/cbnt/key.go b/pkg/intel/metadata/cbnt/key.go index 4b700592..8539637a 100644 --- a/pkg/intel/metadata/cbnt/key.go +++ b/pkg/intel/metadata/cbnt/key.go @@ -171,6 +171,7 @@ func (k *Key) PrintBPMPubKey(bpmAlg Algorithm) error { if _, err := hash.Write(buf.Bytes()); err != nil { return fmt.Errorf("unable to hash: %w", err) } + fmt.Printf(" Boot Policy Manifest Pubkey: 0x%x\n", buf) fmt.Printf(" Boot Policy Manifest Pubkey Hash: 0x%x\n", hash.Sum(nil)) } else if k.KeyAlg == AlgSM2 || k.KeyAlg == AlgECC { if err := binary.Write(buf, binary.LittleEndian, k.Data); err != nil { @@ -179,6 +180,7 @@ func (k *Key) PrintBPMPubKey(bpmAlg Algorithm) error { if _, err := hash.Write(buf.Bytes()); err != nil { return fmt.Errorf("unable to hash: %w", err) } + fmt.Printf(" Boot Policy Manifest Pubkey: 0x%x\n", buf) fmt.Printf(" Boot Policy Manifest Pubkey Hash: 0x%x\n", hash.Sum(nil)) } else { fmt.Printf(" Boot Policy Manifest Pubkey Hash: Unknown Algorithm\n") @@ -211,6 +213,7 @@ func (k *Key) PrintKMPubKey(kmAlg Algorithm) error { if _, err := hash.Write(buf.Bytes()); err != nil { return fmt.Errorf("unable to hash: %w", err) } + fmt.Printf(" Key Manifest Pubkey: 0x%x\n", buf) fmt.Printf(" Key Manifest Pubkey Hash: 0x%x\n", hash.Sum(nil)) // On SKL and KBL the exponent is not included in the KM hash buf.Truncate(len(k.Data[4:])) From 3d398e8e0f88cf45fb7cdfb0778db9774b1af346 Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Sun, 22 Sep 2024 18:26:43 +0200 Subject: [PATCH 11/14] intelmeta fixup Signed-off-by: Daniel Maslowski --- cmds/intelmeta/main.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cmds/intelmeta/main.go b/cmds/intelmeta/main.go index a505571c..1644f2fc 100644 --- a/cmds/intelmeta/main.go +++ b/cmds/intelmeta/main.go @@ -223,7 +223,7 @@ func main() { if meta.Polm != nil { // https://go.dev/tour/methods/15 _, ok := meta.Polm.(cbntbootpolicy.Manifest) - if ok == true { + if ok { pol := meta.Polm.(cbntbootpolicy.Manifest) key := pol.PMSE.Key alg := pol.PMSE.Signature.HashAlg @@ -237,10 +237,9 @@ func main() { meta.LeakedKey = hex.EncodeToString(lk[:8]) } } - } - if ok == false { + } else { p, ok := meta.Polm.(bgbootpolicy.Manifest) - if ok == true { + if ok { // the first 4 bytes are some sort of flags key := p.PMSE.Key k := key.Data[4:] From 044a9eebedb51c1686736530302555a0187f5ee7 Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Sun, 22 Sep 2024 18:24:47 +0200 Subject: [PATCH 12/14] bginfo fixup Signed-off-by: Daniel Maslowski --- cmds/bginfo/main.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmds/bginfo/main.go b/cmds/bginfo/main.go index c0475042..4d90c500 100644 --- a/cmds/bginfo/main.go +++ b/cmds/bginfo/main.go @@ -31,7 +31,7 @@ func main() { log.Fatalf("cannot read input file: %x", err) } - ACBPMagic := []byte("__ACBP__") + acbpMagic := []byte("__ACBP__") // __IBBS__ also seen in the next 16 bytes; not sure what that is offset := bytes.Index(data, ACBPMagic) if offset == -1 { @@ -39,8 +39,7 @@ func main() { } m := bgbootpolicy.Manifest{} - _, err = m.ReadFrom(bytes.NewReader(data[offset:])) - if err != nil { + if _, err = m.ReadFrom(bytes.NewReader(data[offset:])); err != nil { log.Fatalf("%v", err) } From 546b5619cdfdb4cb165d2d18da61502a06494e7e Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Sun, 22 Sep 2024 18:31:33 +0200 Subject: [PATCH 13/14] km fixup Signed-off-by: Daniel Maslowski --- cmds/km/main.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cmds/km/main.go b/cmds/km/main.go index 111bb889..0763f2c8 100644 --- a/cmds/km/main.go +++ b/cmds/km/main.go @@ -31,10 +31,9 @@ func main() { log.Fatalf("cannot read input file: %v", err) } - KEYMMagic := []byte("__KEYM__") - offset := bytes.Index(data, KEYMMagic) - if offset == -1 { - log.Fatalf("no %v magic (%x) found", string(KEYMMagic), KEYMMagic) + keymMagic := []byte("__KEYM__") + if !bytes.Contains(data, keymMagic) { + log.Fatalf("no %v magic (%x) found", string(keymMagic), keymMagic) } m := cbntkey.Manifest{} From e5012df22538c0d9dacf87a2bd01cf57cba21075 Mon Sep 17 00:00:00 2001 From: Daniel Maslowski Date: Sun, 22 Sep 2024 18:34:46 +0200 Subject: [PATCH 14/14] bginfo fixup Signed-off-by: Daniel Maslowski --- cmds/bginfo/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmds/bginfo/main.go b/cmds/bginfo/main.go index 4d90c500..31a9800c 100644 --- a/cmds/bginfo/main.go +++ b/cmds/bginfo/main.go @@ -33,9 +33,9 @@ func main() { acbpMagic := []byte("__ACBP__") // __IBBS__ also seen in the next 16 bytes; not sure what that is - offset := bytes.Index(data, ACBPMagic) + offset := bytes.Index(data, acbpMagic) if offset == -1 { - log.Fatalf("no %v (%x) magic found", string(ACBPMagic), ACBPMagic) + log.Fatalf("no %v (%x) magic found", string(acbpMagic), acbpMagic) } m := bgbootpolicy.Manifest{}