|
| 1 | +// Copyright 2023 the LinuxBoot Authors. All rights reserved |
| 2 | +// Use of this source code is governed by a BSD-style |
| 3 | +// license that can be found in the LICENSE file. |
| 4 | + |
| 5 | +package main |
| 6 | + |
| 7 | +import ( |
| 8 | + "bytes" |
| 9 | + "encoding/hex" |
| 10 | + "encoding/json" |
| 11 | + "flag" |
| 12 | + "fmt" |
| 13 | + "os" |
| 14 | + |
| 15 | + "github.com/linuxboot/fiano/pkg/intel/metadata/bg/bgbootpolicy" |
| 16 | + "github.com/linuxboot/fiano/pkg/intel/metadata/bg/bgkey" |
| 17 | + "github.com/linuxboot/fiano/pkg/intel/metadata/cbnt/cbntbootpolicy" |
| 18 | + "github.com/linuxboot/fiano/pkg/intel/metadata/cbnt/cbntkey" |
| 19 | + "github.com/linuxboot/fiano/pkg/intel/metadata/fit" |
| 20 | + "github.com/linuxboot/fiano/pkg/log" |
| 21 | +) |
| 22 | + |
| 23 | +var ( |
| 24 | + flagJSON = flag.Bool("j", false, "Output as JSON") |
| 25 | +) |
| 26 | + |
| 27 | +func getLeakedKeys() [10][]byte { |
| 28 | + var keys = [10]string{ |
| 29 | + // https://github.com/binarly-io/SupplyChainAttacks/blob/main/MSI/MsiImpactedDevices.md |
| 30 | + "77304b5179d0924e55060188495c80135da6be5a357234809e04a50c9629be6832f2d71be5e720a71bc9103b62413f91f98bf35723a358c5a24530fd46f6c89e6b3c22b77cd364b252bb0190cbc5ef6dd91811bfeff9a7308a6b5d60a4297dcfab6302d5d9db78103d4467d097bacce456b54c983f175c44bfd150b5121a589fa642308fd522471b6216afa0a9dbf8f158b0f7a787c0c6a58e70f2ebbff73708a880ae929bdc6097d6bc6463ab524c4ee6e9aa208ac845211b0e04fe8f2dca3799641af550e4740498ed7c3b4e9ceaf8e9256a30623cba4799ba8198cb3d53e28492c49ce3512856dfd4577992c6c7867eee353bbb38424ac83dcfc7dfba902bb41b180ded8026ac9591f3575cc4e2a6e228c4f12e978996984cb48bfd982067c00baa789447f56d63f52f4bc210025b239b92141592eb0734088647c14ff3df646bd0e629ccb0ec57bec4372700d1041cdd44ecf4e4067cc363e76af1d52fbffc8a6164b25d4c7611b57169c76717a940f387959916aa259a1064596bbc76a7", |
| 31 | + "af3a5bee87e8cfa1bc040c7dab318d74278c453f7fc750e1f9de642bb1e467dd36f84f548acb4270a58bdbcb54584c55a60466ea54d34053de06526ff32f1aafd1d8c4c92dae8d2bb097e7d36de9f0b41431de36e543386dbc6c8f674195bd8f5b6d0b39546c728e76075127d27adb1dc1d9e4ead47aae51812ba7655136d5be5b670f083505c5eec58ff77892e519220ab579bfdd7031d2a7f9534279424901cffe30ee1e585ba3e1f5faa8e5ad99f39fa87f27c39b854abcf3e0b7f6330439ce82074beb1d0b90ad13bf29463695cea80d5e1deb12ac58c946deac0de5393258dd545bd9fbf5fb55a052a7c2fcc181af9595fff110248e2eb1814cddf5fb6f8765019c6eb21bfa2b5e3826ec801cd7828a831cdcbdc8b3479b4109e86421af509b9c15bea0dd52af5ea5320258f326bf8116cf1a665f96a30eec72e9c75a1972f3b28b83a0060b8fd819fc898a967580c3ce027b6c3fa94ec7dfe125973a9a275762bbc799ff2d8184974de74cce78cb530f6009432e951dbf37d5ac966abb", |
| 32 | + "b54d2b7c8a5be3023b7de2a7e75b2b8e927359c893c4977027f957f6ac7c580f78fec3eae65b7a34915bb2029404fba8c562ffe193fc2a469e995ff947f23029ccd8bea9843fe28901ebc1ac99f0a2be6284257248b213e4d83f755ac29faa1bf22d1eee0ff04f7645b87c66aecb6253c094a0bcf4b305d8567b6d5a80daf2b720ea966a198b6830095fac5ec386537b0dee6d222225abebdadd15a991080429566ae3b132c6678ad0697d0045d389cef8e965ebc2a165ce37311cb2bbf57512ac7aedfee9266b20b0d767992a0d6cae757793e058a24ead0d0335aa2b0118b8db60cfceb2c737706e62c6b4ac98a676c52150762659a2ca60125d774ac40413120477501fb18155619cc14fddef8e322f3a9fffdbeefaa4989043890d1f1bc67a9bc7657a5cc409435daf84fd39776e62ee583778f12062ab613aeaf6e62b32b415759cbc93c223fb45b8c87c9f0bf1bd9e749858350c4c7c26cf6c7e6d9ca1fd6d56d66450feb38ce3a25aa44c1bdc978641e02affb76cba8684a326845bdd", |
| 33 | + "fdc427b39f77949c8c657a09484ee2fda4378cbece0d3651202e4fa62d0cf7916b9ae0592d1d8687f312406fc7e37504a80740eddf788a20a4d2ad3fad9105956ac27ed48e60acef4cc70092348676649e44b371772ca1a5225dd966ca955a5a8dd713c1ed31876f3846b1efce5734d7833ee3db9acb4c123cf3a79be142aa97603ba853d4cbe44c14bb10db27233a7db7fe5e57d3ea34cd9a6413d0d33dbf569238d314f9f3c7e93372cd6554ce15126ff4aa3819b4b28a645fa8fc4186110ddc1bc4dcc6bf11ecec639976424459bc6f817ae4364002062a59e3509b928f2b659b193b6f453f68ea82863ea2b2de1f4c19324d217e4830a6dd2cebd6192aaf646e3066e3991346428ef834fa06897446d9b507a6035cb8067e7ab3d621c012566d687748e60dcd0782772dcb805fc55c4b83d9c12b0e43c03583f894b51453f5fcaa16ba54abf90e8bb6e49b4999727228f4c437aef223e34964e30ab360357282d8187b4cf8a36a946ab35540df41f2f45ea8a00e64603da4fa2b56ba4bdd", |
| 34 | + // https://github.com/binarly-io/SupplyChainAttacks/blob/main/Lenovo:LCFC/IntelKeysImpactedDevices.md |
| 35 | + "53450ff591470c7dc3d7430b3f99780d3d6c87b54b32224d6a1ca88394c4c0831393d9d6bd5f9c2c2edf86959caaa36917c05ef42b9e0fc16c966e0fdf968014fe51a7886313ea804815d5ed249e7dfe177c518c023b280fcf62d713e04895fc3be67c5fdee26fd3f502a60c8be9ccadefe632d53807ee7e67875905239bc88b84c02faa4e095c778e5087794ec6c36f39f950c8935ca62c4c2e3f2ac3025a9c6d0d4e3e5b3cf85dc78dafc7eaadcd2f1337ff4f8cf3fae48bc7b631e464a923dd1f602f17a22289c2f4ec5657289d801831eec84cf8a79087e47a7afbf3f085ae42b054d4a3fd2c4f87827946ea4fa24581b7cd7633496e5db89385a947e2c07b24eb7fd9bda266f6abe60789e1deee1a27c9cc33cb86e0a62ad8e5fcf2a0cc52368bc73b2dc209cf2a6ad380e597dec884051af8883042675d95617a8b9902446948e896c1a1375b64fbce46f0b3927f77d1b1b6b3d6e0069df307afc7e6d60e113996038c348bbf0ea8dab5025a61a140349957e8a00589a6e7b9cb5043e3", |
| 36 | + "13158420e2d1fb847e49a7994df957efdfcc975b8238aa2191e98c24620db163b9d34ba8f1e96b408ec8173291324c25ade38a3f2c77081e4f19550112fb5c9055e2e57642ecc0411fe7ec965f1eab8f9c24d62690a84e3a51e514931c86049b6574438d997c79503136e9979192c66ba8aa4f7db77a760fba352174b6048bf5a0820c0b3087e32f75d72ef27ddc70e8b2807d39f1c49140ec125e7a445cc722c7809e563f990935ce33f8e4b25c4433fdd73d31ec2136fd1206f19678cbcea8b64c58c2b7a8ddea5daee54a289b5f6c8ab8f8698d977a241cbf74c5b102ea0e650bd0d5405f6bdc9bcfec40d1dd6af2c7294eb880a16bcf8e3b1c284069e0e4", |
| 37 | + "ff849b32ff8a956b5949868d619101651a35ae51182a8f550592a82ff14e96403f35c2fad403c8f91310f0e4adcf747c62a0805d40d8802e474024dffd02288991086ad818afb83a967dbee073a94b20fa095751e6be3d4378c99429f5af93b1b303a5886bc7d728f451eff0f23a0af9812eb6c55b9b1275faebd16acedb9f52b08a5ce7802e0971126fa6910ace7a70b13284e9a12e3f4f953de93ec0b1941a2b7e6f47c714e2d5cb481a4230c8b8032815183aa32e5b1997145063176dda642485c271649d6fe2900760b527c86f516de73f5c777a29aa54173a2f3b51d0713c4f4c8ceeb8b0bc3869d5aba0743796d8f65001371eea7bb1a1472d67ce5dbf", |
| 38 | + "ddd5d1efba0b586e933c3dfbf7aa84deaba6716c57747c517b8243884f0fa5dc57ebb2ede50c1f3dfe5b07c9c32c8f463fcb73856674b7996df5673666be1a4e989084f3a519b03f1a4ad2975166ff4c75097f300b328fd61e879a38fbf341c1b34f896b1a82dfc51bb2857d64a8e052621ef57ed6a9e6d3939fe968826ddc69e2a12e293a569fd5043ce33bb0926979fa24071bb174858d941f50390fdbc414fd4669434c76419978dd019b0c5496377641cccf13675ac573db0e525c47d4c875ed8a7374f325609f7c571a95e9ea0d144fadcfd6a57c013b9daeddd06e156831fca833e8b3fd941b280d595589427f9a3e331e9f47b15027be6c960f82feca", |
| 39 | + "d903fc44ebad1579bfb1a54522f2afa86ebdb862f54b59fe6b97a69af0745989e2352700747e8b10dfef1584d0d9a777e8aff37ede4a2a1a185f50ed01b74da4bdb465a57488108a22f6b0c6e6a1ba645ed85e8ffc9137effa886656401d9a604391dc0b6d8b01284a5b4db71ffc0f798e92b4030b02b83b16bad3a7f47072d84ee7c00c5257b10574c724d26bc6b75aba356e810fca0c46cf8fbbf48dfc5b3d8559b0357b30c2104e933c6ecc66cc2dd14f5a5ece734c2578f1734ce2253325189c639b21581fc56faa4036582578a4a86dc5ca5f9511d2036e00fa74619d2b1816410a3ccf84e8bbb4a776d3d9862b4268f31e31314ead28ecf66653e5269fc6fa396d1704bf5bd33e55240eb11f2090608d97c5b3b7eddc9f469f2f625d10e980e84ccc0d64e01ab211d6034424aa411407280de3a8a6e7271723658846ed9bde9ac237e22f4f143d322ae20e2c41367ad69bf1a4ea8d26a9a885f0566900658847ca3b7d17f67be9cb5a49398b41f0f65bd01130c892c89851afc64a76d8", |
| 40 | + } |
| 41 | + |
| 42 | + var bkeys [10][]byte |
| 43 | + var err error |
| 44 | + |
| 45 | + for i, k := range keys { |
| 46 | + bkeys[i], err = hex.DecodeString(k) |
| 47 | + if err != nil { |
| 48 | + fmt.Fprintf(os.Stderr, "cannot decode key\n") |
| 49 | + } |
| 50 | + } |
| 51 | + |
| 52 | + return bkeys |
| 53 | +} |
| 54 | + |
| 55 | +type Manifest interface{} |
| 56 | + |
| 57 | +type Meta struct { |
| 58 | + Keym Manifest |
| 59 | + Polm Manifest |
| 60 | +} |
| 61 | + |
| 62 | +func main() { |
| 63 | + flag.Parse() |
| 64 | + if flag.Arg(0) == "" { |
| 65 | + log.Fatalf("missing file name") |
| 66 | + } |
| 67 | + filePath := flag.Arg(0) |
| 68 | + data, err := os.ReadFile(filePath) |
| 69 | + if err != nil { |
| 70 | + log.Fatalf("cannot read input file: %v", err) |
| 71 | + } |
| 72 | + |
| 73 | + entries, err := fit.GetEntries(data) |
| 74 | + if err != nil { |
| 75 | + log.Fatalf("cannot parse input file: %v", err) |
| 76 | + } |
| 77 | + |
| 78 | + var bme fit.Entry |
| 79 | + var kme fit.Entry |
| 80 | + for idx, entry := range entries { |
| 81 | + // if entry.GetEntryBase().Headers.Type() == fit.EntryTypeStartupACModuleEntry { |
| 82 | + if entry.GetEntryBase().Headers.Type() == fit.EntryTypeKeyManifestRecord { |
| 83 | + kme = entry |
| 84 | + fmt.Fprintf(os.Stderr, "key manifest @ %v\n", idx) |
| 85 | + } |
| 86 | + if entry.GetEntryBase().Headers.Type() == fit.EntryTypeBootPolicyManifest { |
| 87 | + bme = entry |
| 88 | + fmt.Fprintf(os.Stderr, "boot policy manifest @ %v\n", idx) |
| 89 | + } |
| 90 | + } |
| 91 | + |
| 92 | + var meta Meta |
| 93 | + |
| 94 | + if bme == nil { |
| 95 | + fmt.Fprintf(os.Stderr, "no boot manifest entry\n") |
| 96 | + } else { |
| 97 | + bpm := bgbootpolicy.Manifest{} |
| 98 | + _, err = bpm.ReadFrom(bytes.NewReader(bme.GetEntryBase().DataSegmentBytes)) |
| 99 | + if err == nil { |
| 100 | + if !*flagJSON { |
| 101 | + fmt.Print(bpm.PrettyString(0, true)) |
| 102 | + } |
| 103 | + meta.Polm = bpm |
| 104 | + } else { |
| 105 | + // log.Fatalf("%v", err) |
| 106 | + bpm := cbntbootpolicy.Manifest{} |
| 107 | + _, err = bpm.ReadFrom(bytes.NewReader(bme.GetEntryBase().DataSegmentBytes)) |
| 108 | + if err == nil { |
| 109 | + if !*flagJSON { |
| 110 | + fmt.Print(bpm.PrettyString(0, true)) |
| 111 | + } |
| 112 | + meta.Polm = bpm |
| 113 | + } else { |
| 114 | + // log.Fatalf("%v", err) |
| 115 | + } |
| 116 | + } |
| 117 | + } |
| 118 | + |
| 119 | + if kme == nil { |
| 120 | + fmt.Fprintf(os.Stderr, "no key manifest entry\n") |
| 121 | + } else { |
| 122 | + km := bgkey.Manifest{} |
| 123 | + _, err = km.ReadFrom(bytes.NewReader(kme.GetEntryBase().DataSegmentBytes)) |
| 124 | + if err == nil { |
| 125 | + if !*flagJSON { |
| 126 | + fmt.Print(km.PrettyString(0, true)) |
| 127 | + } |
| 128 | + meta.Keym = km |
| 129 | + } else { |
| 130 | + // log.Fatalf("%v", err) |
| 131 | + km := cbntkey.Manifest{} |
| 132 | + _, err = km.ReadFrom(bytes.NewReader(kme.GetEntryBase().DataSegmentBytes)) |
| 133 | + if err == nil { |
| 134 | + if !*flagJSON { |
| 135 | + fmt.Print(km.PrettyString(0, true)) |
| 136 | + } |
| 137 | + meta.Keym = km |
| 138 | + } else { |
| 139 | + // log.Fatalf("%v", err) |
| 140 | + } |
| 141 | + } |
| 142 | + } |
| 143 | + |
| 144 | + if *flagJSON { |
| 145 | + j, err := json.MarshalIndent(meta, "", " ") |
| 146 | + if err != nil { |
| 147 | + log.Fatalf("cannot marshal JSON: %v", err) |
| 148 | + } |
| 149 | + if err != nil { |
| 150 | + log.Fatalf("cannot marshal JSON: %v", err) |
| 151 | + } |
| 152 | + fmt.Println(string(j)) |
| 153 | + } |
| 154 | + |
| 155 | + leakedKeys := getLeakedKeys() |
| 156 | + if meta.Polm != nil { |
| 157 | + p := meta.Polm.(cbntbootpolicy.Manifest) |
| 158 | + k := p.PMSE.Key.Data[4:] |
| 159 | + // fmt.Fprintf(os.Stderr, "%v\n", k) |
| 160 | + for _, lk := range leakedKeys { |
| 161 | + if bytes.Equal(k, lk) { |
| 162 | + fmt.Fprintf(os.Stderr, "LEAKED BG KEY USED: %x\n", lk[:8]) |
| 163 | + } |
| 164 | + } |
| 165 | + } |
| 166 | +} |
0 commit comments