github.com/linuxboot/fiano@v1.2.0/pkg/amd/psb/errors.go (about)

     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 psb
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  
    11  	amd_manifest "github.com/linuxboot/fiano/pkg/amd/manifest"
    12  )
    13  
    14  // SignatureCheckError is an error type which indicates that signature of an element cannot be validated against its signing key
    15  type SignatureCheckError struct {
    16  	signingKey    *Key
    17  	signedElement FirmwareItem
    18  	err           error
    19  }
    20  
    21  // Error returns the string representation of SignatureCheckError
    22  func (m *SignatureCheckError) Error() string {
    23  	if m.signedElement == nil {
    24  		return fmt.Sprintf("signature does not validate against signing key %s: %s", m.signingKey.data.KeyID.Hex(), m.err.Error())
    25  	}
    26  	return fmt.Sprintf("signature of element %s does not validate against signing key %s: %s", m.signedElement, m.signingKey.data.KeyID.Hex(), m.err.Error())
    27  }
    28  
    29  func (m *SignatureCheckError) Unwrap() error {
    30  	return m.err
    31  }
    32  
    33  // SigningKey returns the SigningKey associated to the error. Might return nil value
    34  func (m *SignatureCheckError) SigningKey() *Key {
    35  	return m.signingKey
    36  }
    37  
    38  // SignedElement returns an optional item whose signature check failed
    39  func (m *SignatureCheckError) SignedElement() FirmwareItem {
    40  	return m.signedElement
    41  }
    42  
    43  // UnknownSigningKeyError is an error type which indicates that the signing key is unknown
    44  type UnknownSigningKeyError struct {
    45  	signedElement FirmwareItem
    46  	keyID         KeyID
    47  }
    48  
    49  // SignedElement returns an optional item whose signature check failed
    50  func (s *UnknownSigningKeyError) SignedElement() FirmwareItem {
    51  	return s.signedElement
    52  }
    53  
    54  // Error returns the string representation of the UnknownSigningKeyError
    55  func (s *UnknownSigningKeyError) Error() string {
    56  	if s.signedElement == nil {
    57  		return fmt.Sprintf("key ID '%s' is unknown", s.keyID.Hex())
    58  	}
    59  	return fmt.Sprintf("failed to check signature of element '%s' key ID '%s' is unknown", s.signedElement, s.keyID.Hex())
    60  }
    61  
    62  // FirmwareItem is a special item that references a PSP firmware item and could be one of the following types:
    63  // DirectoryType or BIOSDirectoryEntryItem or PSPDirectoryEntryItem
    64  type FirmwareItem interface{}
    65  
    66  func newDirectoryItem(directory DirectoryType) FirmwareItem {
    67  	return directory
    68  }
    69  
    70  // BIOSDirectoryEntryItem determines a BIOS directory entry
    71  type BIOSDirectoryEntryItem struct {
    72  	Level    uint8
    73  	Entry    amd_manifest.BIOSDirectoryTableEntryType
    74  	Instance uint8
    75  }
    76  
    77  func (biosEntry BIOSDirectoryEntryItem) String() string {
    78  	return fmt.Sprintf("entry '0x%X' (%s) instance %d of bios directory level %d", biosEntry.Entry, BIOSEntryType(biosEntry.Entry), biosEntry.Instance, biosEntry.Level)
    79  }
    80  
    81  func newBIOSDirectoryEntryItem(level uint8, entry amd_manifest.BIOSDirectoryTableEntryType, instance uint8) FirmwareItem {
    82  	return BIOSDirectoryEntryItem{
    83  		Level:    level,
    84  		Entry:    entry,
    85  		Instance: instance,
    86  	}
    87  }
    88  
    89  // PSPDirectoryEntryItem determines a PSP directory entry
    90  type PSPDirectoryEntryItem struct {
    91  	Level uint8
    92  	Entry amd_manifest.PSPDirectoryTableEntryType
    93  }
    94  
    95  func (pspEntry PSPDirectoryEntryItem) String() string {
    96  	return fmt.Sprintf("entry '0x%X' (%s) of psp directory level %d", pspEntry.Entry, PSPEntryType(pspEntry.Entry), pspEntry.Level)
    97  }
    98  
    99  func newPSPDirectoryEntryItem(level uint8, entry amd_manifest.PSPDirectoryTableEntryType) PSPDirectoryEntryItem {
   100  	return PSPDirectoryEntryItem{
   101  		Level: level,
   102  		Entry: entry,
   103  	}
   104  }
   105  
   106  // ErrNotFound describes a situation when firmware item is not found
   107  type ErrNotFound struct {
   108  	item FirmwareItem
   109  }
   110  
   111  // GetItem returns a not found item
   112  func (err ErrNotFound) GetItem() FirmwareItem {
   113  	return err.item
   114  }
   115  
   116  // Error returns the string representation of the UnknownSigningKeyError
   117  func (err ErrNotFound) Error() string {
   118  	if err.item == nil {
   119  		return "not found"
   120  	}
   121  	return fmt.Sprintf("'%s' is not found", err.item)
   122  }
   123  
   124  func newErrNotFound(item FirmwareItem) ErrNotFound {
   125  	return ErrNotFound{
   126  		item: item,
   127  	}
   128  }
   129  
   130  // ErrInvalidFormat describes a situation when parsing of firmware failed because of invalid format
   131  type ErrInvalidFormat struct {
   132  	item FirmwareItem
   133  	err  error
   134  }
   135  
   136  // GetItem returns the affected item (could be nil)
   137  func (err ErrInvalidFormat) GetItem() FirmwareItem {
   138  	return err.item
   139  }
   140  
   141  func (err ErrInvalidFormat) Error() string {
   142  	return fmt.Sprintf("'%s' has invalid format format: '%s'", err.item, err.err.Error())
   143  }
   144  
   145  func (err ErrInvalidFormat) Unwrap() error {
   146  	return err.err
   147  }
   148  
   149  func newErrInvalidFormatWithItem(item FirmwareItem, err error) ErrInvalidFormat {
   150  	return ErrInvalidFormat{item: item, err: err}
   151  }
   152  
   153  func newErrInvalidFormat(err error) ErrInvalidFormat {
   154  	return ErrInvalidFormat{err: err}
   155  }
   156  
   157  func addFirmwareItemToError(err error, item FirmwareItem) error {
   158  	if err == nil {
   159  		return nil
   160  	}
   161  
   162  	var sigCheckErr *SignatureCheckError
   163  	if errors.As(err, &sigCheckErr) {
   164  		if sigCheckErr.signedElement == nil {
   165  			return &SignatureCheckError{signingKey: sigCheckErr.signingKey, signedElement: item, err: sigCheckErr.err}
   166  		}
   167  		return err
   168  	}
   169  
   170  	var unknownKey *UnknownSigningKeyError
   171  	if errors.As(err, &unknownKey) {
   172  		if unknownKey.signedElement == nil {
   173  			return &UnknownSigningKeyError{keyID: unknownKey.keyID, signedElement: item}
   174  		}
   175  		return err
   176  	}
   177  
   178  	var notFoundErr ErrNotFound
   179  	if errors.As(err, &notFoundErr) {
   180  		if notFoundErr.item == nil {
   181  			return ErrNotFound{item: item}
   182  		}
   183  		return err
   184  	}
   185  
   186  	var invalidFormatErr ErrInvalidFormat
   187  	if errors.As(err, &invalidFormatErr) {
   188  		if notFoundErr.item == nil {
   189  			return ErrNotFound{item: item}
   190  		}
   191  		return err
   192  	}
   193  	return err
   194  }