| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,410 @@ | ||
| package attest | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "crypto" | ||
| "crypto/rsa" | ||
| "crypto/sha1" | ||
| "encoding/binary" | ||
| "fmt" | ||
| "io" | ||
| "sort" | ||
|
|
||
| // Ensure hashes are available. | ||
| _ "crypto/sha256" | ||
|
|
||
| "github.com/google/go-tpm/tpm2" | ||
| "github.com/google/go-tpm/tpmutil" | ||
| ) | ||
|
|
||
| // TPM algorithms. See the TPM 2.0 specification section 6.3. | ||
| // | ||
| // https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf#page=42 | ||
| const ( | ||
| algSHA1 uint16 = 0x0004 | ||
ericchiang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| algSHA256 uint16 = 0x000B | ||
| ) | ||
|
|
||
| // EventType indicates what kind of data an event is reporting. | ||
| type EventType uint32 | ||
|
|
||
| // Event is a single event from a TCG event log. This reports descrete items such | ||
| // as BIOs measurements or EFI states. | ||
| type Event struct { | ||
| // PCR index of the event. | ||
| Index int | ||
| // Type of the event. | ||
| Type EventType | ||
|
|
||
| // Data of the event. For certain kinds of events, this must match the event | ||
| // digest to be valid. | ||
| Data []byte | ||
| // Digest is the verified digest of the event data. While an event can have | ||
| // multiple for different hash values, this is the one that was matched to the | ||
| // PCR value. | ||
| Digest []byte | ||
|
|
||
| // TODO(ericchiang): Provide examples or links for which event types must | ||
| // match their data to their digest. | ||
| } | ||
|
|
||
| // EventLog contains the data required to parse and validate an event log. | ||
| type EventLog struct { | ||
| // AIKPublic is the activated public key that has been proven to be under the | ||
| // control of the TPM. | ||
| AIKPublic crypto.PublicKey | ||
| // AIKHash is the hash used to generate the quote. | ||
| AIKHash crypto.Hash | ||
|
|
||
| // Quote is a signature over the values of a PCR. | ||
| Quote *Quote | ||
| // PCRs are the hash values in a given number of registers. | ||
| PCRs []PCR | ||
| // Nonce is additional data used to validate the quote signature. It's used | ||
| // by the server to prevent clients from re-playing quotes. | ||
| Nonce []byte | ||
|
|
||
| // MeasurementLog contains the raw event log data, which is matched against | ||
| // the PCRs for validation. | ||
| MeasurementLog []byte | ||
| } | ||
|
|
||
| // Validate verifies the signature of the quote agains the public key, that the | ||
| // quote matches the PCRs, parses the measurement log, and replays the PCRs. | ||
| // | ||
| // Events for PCRs not in the quote are dropped. | ||
| func (e *EventLog) Validate() (events []Event, err error) { | ||
| var pcrs []PCR | ||
| switch e.Quote.Version { | ||
| case TPMVersion12: | ||
| pcrs, err = e.validate12Quote() | ||
| case TPMVersion20: | ||
| pcrs, err = e.validate20Quote() | ||
| default: | ||
| return nil, fmt.Errorf("quote used unknown tpm version 0x%x", e.Quote.Version) | ||
| } | ||
| if err != nil { | ||
| return nil, fmt.Errorf("invalid quote: %v", err) | ||
| } | ||
| rawEvents, err := parseEventLog(e.MeasurementLog) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("parsing measurement log: %v", err) | ||
| } | ||
| events, err = replayEvents(rawEvents, pcrs) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("pcrs failed to replay: %v", err) | ||
| } | ||
| return events, nil | ||
| } | ||
|
|
||
| type rawAttestationData struct { | ||
ericchiang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Version [4]byte // This MUST be 1.1.0.0 | ||
| Fixed [4]byte // This SHALL always be the string ‘QUOT’ | ||
| Digest [20]byte // PCR Composite Hash | ||
| Nonce [20]byte // Nonce Hash | ||
| } | ||
|
|
||
| var ( | ||
| fixedQuote = [4]byte{'Q', 'U', 'O', 'T'} | ||
| ) | ||
|
|
||
| type rawPCRComposite struct { | ||
| Size uint16 // always 3 | ||
| PCRMask [3]byte | ||
| Values tpmutil.U32Bytes | ||
| } | ||
|
|
||
| func (e *EventLog) validate12Quote() (pcrs []PCR, err error) { | ||
| pub, ok := e.AIKPublic.(*rsa.PublicKey) | ||
| if !ok { | ||
| return nil, fmt.Errorf("unsupported public key type: %T", e.AIKPublic) | ||
| } | ||
| quote := sha1.Sum(e.Quote.Quote) | ||
| if err := rsa.VerifyPKCS1v15(pub, crypto.SHA1, quote[:], e.Quote.Signature); err != nil { | ||
| return nil, fmt.Errorf("invalid quote signature: %v", err) | ||
| } | ||
|
|
||
| var att rawAttestationData | ||
| if _, err := tpmutil.Unpack(e.Quote.Quote, &att); err != nil { | ||
| return nil, fmt.Errorf("parsing quote: %v", err) | ||
| } | ||
| // TODO(ericchiang): validate Version field. | ||
| if att.Nonce != sha1.Sum(e.Nonce) { | ||
| return nil, fmt.Errorf("invalid nonce") | ||
| } | ||
| if att.Fixed != fixedQuote { | ||
| return nil, fmt.Errorf("quote wasn't a QUOT object: %x", att.Fixed) | ||
| } | ||
|
|
||
| // See 5.4.1 Creating a PCR composite hash | ||
| sort.Slice(e.PCRs, func(i, j int) bool { return e.PCRs[i].Index < e.PCRs[j].Index }) | ||
| var ( | ||
| pcrMask [3]byte // bitmap indicating which PCRs are active | ||
| values []byte // appended values of all PCRs | ||
| ) | ||
| for _, pcr := range e.PCRs { | ||
| if pcr.Index < 0 || pcr.Index >= 24 { | ||
| return nil, fmt.Errorf("invalid PCR index: %d", pcr.Index) | ||
| } | ||
| pcrMask[pcr.Index/8] |= 1 << uint(pcr.Index%8) | ||
| values = append(values, pcr.Digest...) | ||
| } | ||
| composite, err := tpmutil.Pack(rawPCRComposite{3, pcrMask, values}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("marshaling PCRss: %v", err) | ||
| } | ||
| if att.Digest != sha1.Sum(composite) { | ||
| return nil, fmt.Errorf("PCRs passed didn't match quote: %v", err) | ||
| } | ||
| return e.PCRs, nil | ||
| } | ||
|
|
||
| func (e *EventLog) validate20Quote() (pcrs []PCR, err error) { | ||
| sig, err := tpm2.DecodeSignature(bytes.NewBuffer(e.Quote.Signature)) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("parse quote signature: %v", err) | ||
| } | ||
|
|
||
| sigHash := e.AIKHash.New() | ||
| sigHash.Write(e.Quote.Quote) | ||
|
|
||
| switch pub := e.AIKPublic.(type) { | ||
| case *rsa.PublicKey: | ||
| if sig.RSA == nil { | ||
| return nil, fmt.Errorf("rsa public key provided for ec signature") | ||
| } | ||
| sigBytes := []byte(sig.RSA.Signature) | ||
| if err := rsa.VerifyPKCS1v15(pub, e.AIKHash, sigHash.Sum(nil), sigBytes); err != nil { | ||
| return nil, fmt.Errorf("invalid quote signature: %v", err) | ||
| } | ||
| default: | ||
| // TODO(ericchiang): support ecdsa | ||
| return nil, fmt.Errorf("unsupported public key type %T", pub) | ||
| } | ||
|
|
||
| att, err := tpm2.DecodeAttestationData(e.Quote.Quote) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("parsing quote signature: %v", err) | ||
| } | ||
| if att.Type != tpm2.TagAttestQuote { | ||
| return nil, fmt.Errorf("attestation isn't a quote, tag of type 0x%x", att.Type) | ||
| } | ||
| if !bytes.Equal([]byte(att.ExtraData), e.Nonce) { | ||
| return nil, fmt.Errorf("nonce didn't match: %v", err) | ||
| } | ||
|
|
||
| pcrByIndex := map[int][]byte{} | ||
| for _, pcr := range e.PCRs { | ||
| pcrByIndex[pcr.Index] = pcr.Digest | ||
| } | ||
|
|
||
| n := len(att.AttestedQuoteInfo.PCRDigest) | ||
| hash, ok := hashBySize[n] | ||
| if !ok { | ||
| return nil, fmt.Errorf("quote used unsupported hash algorithm length: %d", n) | ||
| } | ||
| var validatedPCRs []PCR | ||
| h := hash.New() | ||
| for _, index := range att.AttestedQuoteInfo.PCRSelection.PCRs { | ||
| digest, ok := pcrByIndex[index] | ||
| if !ok { | ||
| return nil, fmt.Errorf("quote was over PCR %d which wasn't provided", index) | ||
| } | ||
| if len(digest) != hash.Size() { | ||
| return nil, fmt.Errorf("mismatch pcr and quote hash, pcr hash length=%d, quote hash length=%d", len(digest), hash.Size()) | ||
| } | ||
| h.Write(digest) | ||
| validatedPCRs = append(validatedPCRs, PCR{Index: index, Digest: digest}) | ||
| } | ||
|
|
||
| if !bytes.Equal(h.Sum(nil), att.AttestedQuoteInfo.PCRDigest) { | ||
| return nil, fmt.Errorf("quote digest didn't match pcrs provided") | ||
| } | ||
| return validatedPCRs, nil | ||
| } | ||
|
|
||
| var hashBySize = map[int]crypto.Hash{ | ||
| crypto.SHA1.Size(): crypto.SHA1, | ||
| crypto.SHA256.Size(): crypto.SHA256, | ||
| } | ||
|
|
||
| func extend(pcr, replay []byte, e rawEvent) ([]byte, Event, error) { | ||
| h, ok := hashBySize[len(pcr)] | ||
| if !ok { | ||
| return nil, Event{}, fmt.Errorf("pcr %d was not a known hash size: %d", e.index, len(pcr)) | ||
| } | ||
| for _, digest := range e.digests { | ||
| if len(digest) != len(pcr) { | ||
| continue | ||
| } | ||
| hash := h.New() | ||
| if len(replay) != 0 { | ||
| hash.Write(replay) | ||
| } else { | ||
| b := make([]byte, h.Size()) | ||
| hash.Write(b) | ||
| } | ||
| hash.Write(digest) | ||
| return hash.Sum(nil), Event{e.index, e.typ, e.data, digest}, nil | ||
| } | ||
| return nil, Event{}, fmt.Errorf("no event digest matches pcr length: %d", len(pcr)) | ||
| } | ||
|
|
||
| func replayEvents(rawEvents []rawEvent, pcrs []PCR) ([]Event, error) { | ||
| events := []Event{} | ||
| replay := map[int][]byte{} | ||
| pcrByIndex := map[int][]byte{} | ||
| for _, pcr := range pcrs { | ||
| pcrByIndex[pcr.Index] = pcr.Digest | ||
| } | ||
|
|
||
| for i, e := range rawEvents { | ||
| pcrValue, ok := pcrByIndex[e.index] | ||
| if !ok { | ||
| // Ignore events for PCRs that weren't included in the quote. | ||
| continue | ||
| } | ||
| replayValue, event, err := extend(pcrValue, replay[e.index], e) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("replaying event %d: %v", i, err) | ||
| } | ||
| replay[e.index] = replayValue | ||
| events = append(events, event) | ||
| } | ||
|
|
||
| var invalidReplays []int | ||
| for i, value := range replay { | ||
| if !bytes.Equal(value, pcrByIndex[i]) { | ||
| invalidReplays = append(invalidReplays, i) | ||
| } | ||
| } | ||
| if len(invalidReplays) > 0 { | ||
| return nil, fmt.Errorf("the following registers failed to replay: %d", invalidReplays) | ||
| } | ||
| return events, nil | ||
| } | ||
|
|
||
| // EV_NO_ACTION is a special event type that indicates information to the parser | ||
| // instead of holding a measurement. For TPM 2.0, this event type is used to signal | ||
| // switching from SHA1 format to a variable length digest. | ||
| // | ||
| // https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClientSpecPlat_TPM_2p0_1p04_pub.pdf#page=110 | ||
| const eventTypeNoAction = 0x03 | ||
|
|
||
| func parseEventLog(b []byte) ([]rawEvent, error) { | ||
| r := bytes.NewBuffer(b) | ||
| parseFn := parseRawEvent | ||
| e, err := parseFn(r) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("parse first event: %v", err) | ||
| } | ||
| var events []rawEvent | ||
| if e.typ == eventTypeNoAction { | ||
| // Switch to parsing crypto agile events. Don't include this in the | ||
| // replayed events since it's intentionally switching from SHA1 to | ||
| // SHA256 and will fail to extend a SHA256 PCR value. | ||
| // | ||
| // NOTE(ericchiang): to be strict, we could parse the event data as a | ||
| // TCG_EfiSpecIDEventStruct and validate the algorithms. But for now, | ||
| // assume this indicates a switch from SHA1 format to SHA1/SHA256. | ||
| // | ||
| // https://trustedcomputinggroup.org/wp-content/uploads/EFI-Protocol-Specification-rev13-160330final.pdf#page=18 | ||
| parseFn = parseRawEvent2 | ||
| } else { | ||
| events = append(events, e) | ||
| } | ||
| for r.Len() != 0 { | ||
| e, err := parseFn(r) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| events = append(events, e) | ||
| } | ||
| return events, nil | ||
| } | ||
|
|
||
| type rawEvent struct { | ||
| index int | ||
| typ EventType | ||
| data []byte | ||
| digests [][]byte | ||
| } | ||
|
|
||
| // TPM 1.2 event log format. See "5.1 SHA1 Event Log Entry Format" | ||
| // https://trustedcomputinggroup.org/wp-content/uploads/EFI-Protocol-Specification-rev13-160330final.pdf#page=15 | ||
| type rawEventHeader struct { | ||
| PCRIndex uint32 | ||
| Type uint32 | ||
| Digest [20]byte | ||
| EventSize uint32 | ||
| } | ||
|
|
||
| func parseRawEvent(r io.Reader) (event rawEvent, err error) { | ||
| var h rawEventHeader | ||
| if err = binary.Read(r, binary.LittleEndian, &h); err != nil { | ||
| return event, err | ||
| } | ||
| data := make([]byte, int(h.EventSize)) | ||
| if _, err := io.ReadFull(r, data); err != nil { | ||
| return event, err | ||
| } | ||
| return rawEvent{ | ||
| typ: EventType(h.Type), | ||
| data: data, | ||
| index: int(h.PCRIndex), | ||
| digests: [][]byte{h.Digest[:]}, | ||
| }, nil | ||
| } | ||
|
|
||
| // TPM 2.0 event log format. See "5.2 Crypto Agile Log Entry Format" | ||
| // https://trustedcomputinggroup.org/wp-content/uploads/EFI-Protocol-Specification-rev13-160330final.pdf#page=15 | ||
| type rawEvent2Header struct { | ||
| PCRIndex uint32 | ||
| Type uint32 | ||
| } | ||
|
|
||
| func parseRawEvent2(r io.Reader) (event rawEvent, err error) { | ||
| var h rawEvent2Header | ||
| if err = binary.Read(r, binary.LittleEndian, &h); err != nil { | ||
| return event, err | ||
| } | ||
| event.typ = EventType(h.Type) | ||
| event.index = int(h.PCRIndex) | ||
|
|
||
| // parse the event digests | ||
| var numDigests uint32 | ||
| if err := binary.Read(r, binary.LittleEndian, &numDigests); err != nil { | ||
| return event, err | ||
| } | ||
| for i := 0; i < int(numDigests); i++ { | ||
| var algID uint16 | ||
| if err := binary.Read(r, binary.LittleEndian, &algID); err != nil { | ||
| return event, err | ||
| } | ||
| var digest []byte | ||
| switch algID { | ||
| case algSHA1: | ||
| digest = make([]byte, crypto.SHA1.Size()) | ||
| case algSHA256: | ||
| digest = make([]byte, crypto.SHA256.Size()) | ||
| default: | ||
| // ignore signatures that aren't SHA1 or SHA256 | ||
| continue | ||
| } | ||
| if _, err := io.ReadFull(r, digest); err != nil { | ||
| return event, err | ||
| } | ||
| event.digests = append(event.digests, digest) | ||
| } | ||
|
|
||
| // parse event data | ||
| var eventSize uint32 | ||
| if err = binary.Read(r, binary.LittleEndian, &eventSize); err != nil { | ||
| return event, err | ||
| } | ||
| event.data = make([]byte, int(eventSize)) | ||
| if _, err := io.ReadFull(r, event.data); err != nil { | ||
| return event, err | ||
| } | ||
| return event, err | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| package attest | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "io/ioutil" | ||
| "testing" | ||
|
|
||
| "github.com/google/go-tpm/tpm2" | ||
| ) | ||
|
|
||
| // Dump describes the layout of serialized information from the dump command. | ||
| type Dump struct { | ||
| Static struct { | ||
| TPMVersion TPMVersion | ||
| EKPem []byte | ||
| } | ||
|
|
||
| AIK AttestationParameters | ||
|
|
||
| Quote struct { | ||
| Nonce []byte | ||
| Alg HashAlg | ||
| Quote []byte | ||
| Signature []byte | ||
| } | ||
|
|
||
| Log struct { | ||
| PCRs []PCR | ||
| PCRAlg tpm2.Algorithm | ||
| Raw []byte // The measured boot log in binary form. | ||
| } | ||
| } | ||
|
|
||
| func TestParseEventLogWindows(t *testing.T) { | ||
| testParseEventLog(t, "testdata/windows_gcp_shielded_vm.json") | ||
| } | ||
|
|
||
| func TestParseEventLogLinux(t *testing.T) { | ||
| testParseEventLog(t, "testdata/linux_tpm12.json") | ||
| } | ||
|
|
||
| func testParseEventLog(t *testing.T, testdata string) { | ||
| data, err := ioutil.ReadFile(testdata) | ||
| if err != nil { | ||
| t.Fatalf("reading test data: %v", err) | ||
| } | ||
| var dump Dump | ||
| if err := json.Unmarshal(data, &dump); err != nil { | ||
| t.Fatalf("parsing test data: %v", err) | ||
| } | ||
| if _, err := parseEventLog(dump.Log.Raw); err != nil { | ||
| t.Fatalf("parsing event log: %v", err) | ||
| } | ||
| } | ||
|
|
||
| func TestEventLogLinux(t *testing.T) { | ||
| testEventLog(t, "testdata/linux_tpm12.json") | ||
| } | ||
|
|
||
| func TestEventLog(t *testing.T) { | ||
| testEventLog(t, "testdata/windows_gcp_shielded_vm.json") | ||
| } | ||
|
|
||
| func testEventLog(t *testing.T, testdata string) { | ||
| data, err := ioutil.ReadFile(testdata) | ||
| if err != nil { | ||
| t.Fatalf("reading test data: %v", err) | ||
| } | ||
| var dump Dump | ||
| if err := json.Unmarshal(data, &dump); err != nil { | ||
| t.Fatalf("parsing test data: %v", err) | ||
| } | ||
|
|
||
| aik, err := ParseAIKPublic(dump.Static.TPMVersion, dump.AIK.Public) | ||
| if err != nil { | ||
| t.Fatalf("parsing AIK: %v", err) | ||
| } | ||
|
|
||
| el := EventLog{ | ||
| AIKPublic: aik.Public, | ||
| AIKHash: aik.Hash, | ||
| Quote: &Quote{ | ||
| Version: dump.Static.TPMVersion, | ||
| Quote: dump.Quote.Quote, | ||
| Signature: dump.Quote.Signature, | ||
| }, | ||
| Nonce: dump.Quote.Nonce, | ||
| PCRs: dump.Log.PCRs, | ||
| MeasurementLog: dump.Log.Raw, | ||
| } | ||
| if _, err := el.Validate(); err != nil { | ||
| t.Fatalf("validating event log: %v", err) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {"Static":{"TPMVersion":1,"EKPem":"LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQWxpeWp3c1o3ZU5WMVkxRGVSMUtrL0JIdHFhcnRhREZQTXh5S05tWXdSbHZiTDJ1UXBObGIKT2MwaXpWVlZaelJORTY2T2pmcUZCT045K3d5ZUdsQXZGMW5LdWtxM3BLTlBFMVNwUm80eUUvbWZVdW14d1pPUgpzWnlNZXZPelNhbVQxaWdhMHZ0c1Q4TktvVGdRQTFjQUNLNXNYeGpDRDRjMmxYb1dtV3dlRWJMc3N6andualBVCkNNU1pWWnZlQ2RLM1NtL05WamhVdnRab1JodTc3NEZXOUl1NUhZaFVQWXFRNWVBaEVtMlFQT1NQOE10MmJIWTcKM3UzYlkwd0pvNVlxRzNaRkJQYjJLaUxlY3hacFZYY0k5VHNxbmlLcW5XLzJkdlhMRyt5WHVxVTBpVkhiSTZZTQozTjdTUmVGODhNMXBaQTZXSTI5emNtQThHN0NXL3NVWW1RSURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K"},"AIK":{"Public":"AAAAAQABAAIAAAAMAAAIAAAAAAIAAAAAAAABAJt+7mczx4uRZR3Y2MUSBBBipAK588vhMHYMI4tDGwXBF+4Ri7spbIrYoRykafNupO57w+sS0GwpAotbkm7LLWXjNkioFVxige6uKsh+gqlNOy98tou9y4kgQFHmJbchxmz9o9Mo2Oi/MLC9thq/iYt5b2nmiNILnQZS+YGg1lPIoBxOhkVEoTSzpAFV1CstJJRhqkKlPmeR9fm1lnJeUapN0BD0WZ0PSWYmS/iUno1OnDp/mrqIrX28HPIaU3hDNVnQvgRmtl+e35VpoqXpW58Ej5jnLaipJsG7PWVd33JTu5ezTk3OG3C4zjgrHq4eTszV7F1BPUwq4Zmb2e6FsxU=","UseTCSDActivationFormat":true,"CreateData":null,"CreateAttestation":null,"CreateSignature":null},"Quote":{"Nonce":"","Alg":4,"Quote":"AQEAAFFVT1TUe8hZBOBgoRyPd07c7+kmB3KYG9o5o+5ea0sNMlW/75VgGJCv2AcJ","Signature":"AYWsgkmbV1kr65B4tHA3dYN4LD2+FaZQz8mq80Bu+M+yqBxGdGsELKC0TSLfXRXTbmA8fQAH7X++tM2M9z5PaIWtqULfGfkn/ao8dhFE0T/gm2c47/BgG7oyxtdnSlzFaQwQQzdprkHq6bBZDMA7AhcUXKfnxIllh9DsHGgPSrrOT44mwAnmpf/3eNDQ++2b+Sy01csAXtkVCB4tRyOgf48KpS0uEQ647bYsjCJatMOAXx+YV3XB7c9Drj4hsORsOpXaaFOTpN5HOAmIQqsS0tJKM78i1Sbp1/E/WlqLjffTwoeP2OJlsT85Xkmss0vhy9xBLcHV1oe0X5PUziZfjg=="},"Log":{"PCRs":[{"Index":11,"Digest":"AAAAAAAAAAAAAAAAAAAAAAAAAAA=","DigestAlg":3},{"Index":0,"Digest":"g1hNOUmsEYL7BJe1mz33M2uGSPo=","DigestAlg":3},{"Index":2,"Digest":"sqg7Dr8vg3Qpmlsr38MeqVWtcjY=","DigestAlg":3},{"Index":15,"Digest":"AAAAAAAAAAAAAAAAAAAAAAAAAAA=","DigestAlg":3},{"Index":22,"Digest":"//////////////////////////8=","DigestAlg":3},{"Index":1,"Digest":"DaB6FWt2viN2iGOSkoJNPmDLm0w=","DigestAlg":3},{"Index":19,"Digest":"//////////////////////////8=","DigestAlg":3},{"Index":18,"Digest":"//////////////////////////8=","DigestAlg":3},{"Index":23,"Digest":"AAAAAAAAAAAAAAAAAAAAAAAAAAA=","DigestAlg":3},{"Index":8,"Digest":"AAAAAAAAAAAAAAAAAAAAAAAAAAA=","DigestAlg":3},{"Index":4,"Digest":"krsrnniakXVjtxmHfpilZCyBCp8=","DigestAlg":3},{"Index":5,"Digest":"wkFtAPfMHl/BdtCt4He+zj8ksXM=","DigestAlg":3},{"Index":6,"Digest":"sqg7Dr8vg3Qpmlsr38MeqVWtcjY=","DigestAlg":3},{"Index":21,"Digest":"//////////////////////////8=","DigestAlg":3},{"Index":7,"Digest":"mhb64z08eV0diLoORWo98L745Yc=","DigestAlg":3},{"Index":13,"Digest":"AAAAAAAAAAAAAAAAAAAAAAAAAAA=","DigestAlg":3},{"Index":14,"Digest":"AAAAAAAAAAAAAAAAAAAAAAAAAAA=","DigestAlg":3},{"Index":16,"Digest":"AAAAAAAAAAAAAAAAAAAAAAAAAAA=","DigestAlg":3},{"Index":17,"Digest":"//////////////////////////8=","DigestAlg":3},{"Index":12,"Digest":"AAAAAAAAAAAAAAAAAAAAAAAAAAA=","DigestAlg":3},{"Index":3,"Digest":"sqg7Dr8vg3Qpmlsr38MeqVWtcjY=","DigestAlg":3},{"Index":9,"Digest":"AAAAAAAAAAAAAAAAAAAAAAAAAAA=","DigestAlg":3},{"Index":20,"Digest":"//////////////////////////8=","DigestAlg":3},{"Index":10,"Digest":"RoMGhc7O9bCOMFX7dG5X04Hj4/k=","DigestAlg":3}],"PCRAlg":0,"Raw":"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"}} |