github.com/linuxboot/fiano@v1.2.0/pkg/intel/metadata/cbnt/cbntkey/manifest.go (about)

     1  // Copyright 2017-2021 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  //go:generate manifestcodegen
     6  
     7  package cbntkey
     8  
     9  import (
    10  	"bytes"
    11  	"crypto"
    12  	"fmt"
    13  
    14  	"github.com/linuxboot/fiano/pkg/intel/metadata/cbnt"
    15  )
    16  
    17  // PrettyString: CBnT Key Manifest
    18  type Manifest struct {
    19  	cbnt.StructInfo `id:"__KEYM__" version:"0x21" var0:"0" var1:"0"`
    20  
    21  	// KeyManifestSignatureOffset is Key Manifest KeySignature offset.
    22  	//
    23  	// The original name is "KeySignatureOffset" (in #575623).
    24  	KeyManifestSignatureOffset uint16 `rehashValue:"KeyAndSignatureOffset()" json:"kmSigOffset,omitempty"`
    25  
    26  	// Reserved2 is an alignment.
    27  	Reserved2 [3]byte `json:"kmReserved2,omitempty"`
    28  
    29  	// Revision is the revision of the Key Manifest defined by the Platform
    30  	// Manufacturer.
    31  	Revision uint8 `json:"kmRevision"`
    32  
    33  	// KMSVN is the Key Manifest Security Version Number.
    34  	KMSVN cbnt.SVN `json:"kmSVN"`
    35  
    36  	// KMID is the Key Manifest Identifier.
    37  	KMID uint8 `json:"kmID"`
    38  
    39  	// PubKeyHashAlg is the hash algorithm of OEM public key digest programmed
    40  	// into the FPF.
    41  	PubKeyHashAlg cbnt.Algorithm `json:"kmPubKeyHashAlg"`
    42  
    43  	// Hash is the slice of KMHASH_STRUCT (KHS) structures (see table 5-3
    44  	// of the document #575623). Describes BPM pubkey digest (among other).
    45  	Hash []Hash `json:"kmHash"`
    46  
    47  	// KeyAndSignature is the Key Manifest signature.
    48  	KeyAndSignature cbnt.KeySignature `json:"kmKeySignature"`
    49  }
    50  
    51  func (m *Manifest) SetSignature(
    52  	algo cbnt.Algorithm,
    53  	hashAlgo cbnt.Algorithm,
    54  	privKey crypto.Signer,
    55  	signedData []byte,
    56  ) error {
    57  	err := m.KeyAndSignature.SetSignature(algo, hashAlgo, privKey, signedData)
    58  	if err != nil {
    59  		return fmt.Errorf("unable to set the signature: %w", err)
    60  	}
    61  	m.PubKeyHashAlg = m.KeyAndSignature.Signature.HashAlg
    62  
    63  	return nil
    64  }
    65  
    66  func (m *Manifest) ValidateBPMKey(bpmKS cbnt.KeySignature) error {
    67  	hashCount := 0
    68  	for _, hashEntry := range m.Hash {
    69  		if !hashEntry.Usage.IsSet(UsageBPMSigningPKD) {
    70  			continue
    71  		}
    72  
    73  		h, err := hashEntry.Digest.HashAlg.Hash()
    74  		if err != nil {
    75  			return fmt.Errorf("invalid hash algo %v: %w", hashEntry.Digest.HashAlg, err)
    76  		}
    77  
    78  		if len(hashEntry.Digest.HashBuffer) != h.Size() {
    79  			return fmt.Errorf("invalid hash lenght: actual:%d expected:%d", len(hashEntry.Digest.HashBuffer), h.Size())
    80  		}
    81  
    82  		switch bpmKS.Key.KeyAlg {
    83  		case cbnt.AlgRSA:
    84  			if _, err := h.Write(bpmKS.Key.Data[4:]); err != nil {
    85  				return fmt.Errorf("unable to hash: %w", err)
    86  			}
    87  		default:
    88  			return fmt.Errorf("unsupported key algorithm: %v", bpmKS.Key.KeyAlg)
    89  		}
    90  		digest := h.Sum(nil)
    91  
    92  		if !bytes.Equal(hashEntry.Digest.HashBuffer, digest) {
    93  			return fmt.Errorf("BPM key hash does not match the one in KM: actual:%X != in-KM:%X (hash algo: %v)", digest, hashEntry.Digest.HashBuffer, hashEntry.Digest.HashAlg)
    94  		}
    95  		hashCount++
    96  	}
    97  
    98  	if hashCount == 0 {
    99  		return fmt.Errorf("no hash of BPM's key was found in KM")
   100  	}
   101  
   102  	return nil
   103  }