// Copyright 2020 The Monogon Project Authors.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Taken and pruned from go-attestation under Apache 2.0
package eventlog

import (
	"bytes"
	"errors"
	"fmt"

	"github.com/google/certificate-transparency-go/x509"

	"source.monogon.dev/osbase/tpm/eventlog/internal"
)

// SecurebootState describes the secure boot status of a machine, as determined
// by processing its event log.
type SecurebootState struct {
	Enabled bool

	// PlatformKeys enumerates keys which can sign a key exchange key.
	PlatformKeys []x509.Certificate
	// PlatformKeys enumerates key hashes which can sign a key exchange key.
	PlatformKeyHashes [][]byte

	// ExchangeKeys enumerates keys which can sign a database of permitted or
	// forbidden keys.
	ExchangeKeys []x509.Certificate
	// ExchangeKeyHashes enumerates key hashes which can sign a database or
	// permitted or forbidden keys.
	ExchangeKeyHashes [][]byte

	// PermittedKeys enumerates keys which may sign binaries to run.
	PermittedKeys []x509.Certificate
	// PermittedHashes enumerates hashes which permit binaries to run.
	PermittedHashes [][]byte

	// ForbiddenKeys enumerates keys which must not permit a binary to run.
	ForbiddenKeys []x509.Certificate
	// ForbiddenKeys enumerates hashes which must not permit a binary to run.
	ForbiddenHashes [][]byte

	// PreSeparatorAuthority describes the use of a secure-boot key to authorize
	// the execution of a binary before the separator.
	PreSeparatorAuthority []x509.Certificate
	// PostSeparatorAuthority describes the use of a secure-boot key to authorize
	// the execution of a binary after the separator.
	PostSeparatorAuthority []x509.Certificate
}

// ParseSecurebootState parses a series of events to determine the
// configuration of secure boot on a device. An error is returned if
// the state cannot be determined, or if the event log is structured
// in such a way that it may have been tampered post-execution of
// platform firmware.
func ParseSecurebootState(events []Event) (*SecurebootState, error) {
	// This algorithm verifies the following:
	// - All events in PCR 7 have event types which are expected in PCR 7.
	// - All events are parsable according to their event type.
	// - All events have digests values corresponding to their data/event type.
	// - No unverifiable events were present.
	// - All variables are specified before the separator and never duplicated.
	// - The SecureBoot variable has a value of 0 or 1.
	// - If SecureBoot was 1 (enabled), authority events were present indicating
	//   keys were used to perform verification.
	// - If SecureBoot was 1 (enabled), platform + exchange + database keys
	//   were specified.
	// - No UEFI debugger was attached.

	var (
		out           SecurebootState
		seenSeparator bool
		seenAuthority bool
		seenVars      = map[string]bool{}
	)

	for _, e := range events {
		if e.Index != 7 {
			continue
		}

		et, err := internal.UntrustedParseEventType(uint32(e.Type))
		if err != nil {
			return nil, fmt.Errorf("unrecognised event type: %v", err)
		}

		digestVerify := e.digestEquals(e.Data)
		switch et {
		case internal.Separator:
			if seenSeparator {
				return nil, fmt.Errorf("duplicate separator at event %d", e.sequence)
			}
			seenSeparator = true
			if !bytes.Equal(e.Data, []byte{0, 0, 0, 0}) {
				return nil, fmt.Errorf("invalid separator data at event %d: %v", e.sequence, e.Data)
			}
			if digestVerify != nil {
				return nil, fmt.Errorf("invalid separator digest at event %d: %v", e.sequence, digestVerify)
			}

		case internal.EFIAction:
			if string(e.Data) == "UEFI Debug Mode" {
				return nil, errors.New("a UEFI debugger was present during boot")
			}
			return nil, fmt.Errorf("event %d: unexpected EFI action event", e.sequence)

		case internal.EFIVariableDriverConfig:
			v, err := internal.ParseUEFIVariableData(bytes.NewReader(e.Data))
			if err != nil {
				return nil, fmt.Errorf("failed parsing EFI variable at event %d: %v", e.sequence, err)
			}
			if _, seenBefore := seenVars[v.VarName()]; seenBefore {
				return nil, fmt.Errorf("duplicate EFI variable %q at event %d", v.VarName(), e.sequence)
			}
			seenVars[v.VarName()] = true
			if seenSeparator {
				return nil, fmt.Errorf("event %d: variable %q specified after separator", e.sequence, v.VarName())
			}

			if digestVerify != nil {
				return nil, fmt.Errorf("invalid digest for variable %q on event %d: %v", v.VarName(), e.sequence, digestVerify)
			}

			switch v.VarName() {
			case "SecureBoot":
				if len(v.VariableData) != 1 {
					return nil, fmt.Errorf("event %d: SecureBoot data len is %d, expected 1", e.sequence, len(v.VariableData))
				}
				out.Enabled = v.VariableData[0] == 1
			case "PK":
				if out.PlatformKeys, out.PlatformKeyHashes, err = v.SignatureData(); err != nil {
					return nil, fmt.Errorf("event %d: failed parsing platform keys: %v", e.sequence, err)
				}
			case "KEK":
				if out.ExchangeKeys, out.ExchangeKeyHashes, err = v.SignatureData(); err != nil {
					return nil, fmt.Errorf("event %d: failed parsing key exchange keys: %v", e.sequence, err)
				}
			case "db":
				if out.PermittedKeys, out.PermittedHashes, err = v.SignatureData(); err != nil {
					return nil, fmt.Errorf("event %d: failed parsing signature database: %v", e.sequence, err)
				}
			case "dbx":
				if out.ForbiddenKeys, out.ForbiddenHashes, err = v.SignatureData(); err != nil {
					return nil, fmt.Errorf("event %d: failed parsing forbidden signature database: %v", e.sequence, err)
				}
			}

		case internal.EFIVariableAuthority:
			a, err := internal.ParseUEFIVariableAuthority(bytes.NewReader(e.Data))
			if err != nil {
				// Workaround for: https://github.com/google/go-attestation/issues/157
				if errors.Is(err, internal.ErrSigMissingGUID) {
					// Versions of shim which do not carry
					// https://github.com/rhboot/shim/commit/8a27a4809a6a2b40fb6a4049071bf96d6ad71b50
					// have an erroneous additional byte in the event, which breaks digest
					// verification. If verification failed, we try removing the last byte.
					if digestVerify != nil {
						digestVerify = e.digestEquals(e.Data[:len(e.Data)-1])
					}
				} else {
					return nil, fmt.Errorf("failed parsing EFI variable authority at event %d: %v", e.sequence, err)
				}
			}
			seenAuthority = true
			if digestVerify != nil {
				return nil, fmt.Errorf("invalid digest for authority on event %d: %v", e.sequence, digestVerify)
			}
			if !seenSeparator {
				out.PreSeparatorAuthority = append(out.PreSeparatorAuthority, a.Certs...)
			} else {
				out.PostSeparatorAuthority = append(out.PostSeparatorAuthority, a.Certs...)
			}

		default:
			return nil, fmt.Errorf("unexpected event type: %v", et)
		}
	}

	if !out.Enabled {
		return &out, nil
	}

	if !seenAuthority {
		return nil, errors.New("secure boot was enabled but no key was used")
	}
	if len(out.PlatformKeys) == 0 && len(out.PlatformKeyHashes) == 0 {
		return nil, errors.New("secure boot was enabled but no platform keys were known")
	}
	if len(out.ExchangeKeys) == 0 && len(out.ExchangeKeyHashes) == 0 {
		return nil, errors.New("secure boot was enabled but no key exchange keys were known")
	}
	if len(out.PermittedKeys) == 0 && len(out.PermittedHashes) == 0 {
		return nil, errors.New("secure boot was enabled but no keys or hashes were permitted")
	}
	return &out, nil
}
