github.com/linuxboot/fiano@v1.2.0/pkg/intel/metadata/cbnt/signature.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 cbnt
     8  
     9  import (
    10  	"crypto"
    11  	"crypto/rand"
    12  	"fmt"
    13  	"math/big"
    14  )
    15  
    16  var (
    17  	// RandReader exports the rand.Reader
    18  	RandReader = rand.Reader
    19  )
    20  
    21  // Signature exports the Signature structure
    22  type Signature struct {
    23  	SigScheme Algorithm `json:"sigScheme"`
    24  	Version   uint8     `require:"0x10" json:"sigVersion,omitempty"`
    25  	KeySize   BitSize   `json:"sigKeysize,omitempty"`
    26  	HashAlg   Algorithm `json:"sigHashAlg"`
    27  	Data      []byte    `countValue:"KeySize.InBytes()" prettyValue:"dataPrettyValue()" json:"sigData"`
    28  }
    29  
    30  func (m Signature) dataPrettyValue() interface{} {
    31  	r, _ := m.SignatureData()
    32  	return r
    33  }
    34  
    35  // SignatureData parses field Data and returns the signature as one of these types:
    36  // * SignatureRSAPSS
    37  // * SignatureRSAASA
    38  // * SignatureECDSA
    39  // * SignatureSM2
    40  func (m Signature) SignatureData() (SignatureDataInterface, error) {
    41  	switch m.SigScheme {
    42  	case AlgRSAPSS:
    43  		return SignatureRSAPSS(m.Data), nil
    44  	case AlgRSASSA:
    45  		return SignatureRSAASA(m.Data), nil
    46  	case AlgECDSA:
    47  		if len(m.Data) != 64 && len(m.Data) != 96 {
    48  			return nil, fmt.Errorf("invalid length of the signature data: %d (expected 64 or 96)", len(m.Data))
    49  		}
    50  		return SignatureECDSA{
    51  			R: new(big.Int).SetBytes(reverseBytes(m.Data[:len(m.Data)/2])),
    52  			S: new(big.Int).SetBytes(reverseBytes(m.Data[len(m.Data)/2:])),
    53  		}, nil
    54  	case AlgSM2:
    55  		if len(m.Data) != 64 && len(m.Data) != 96 {
    56  			return nil, fmt.Errorf("invalid length of the signature data: %d (expected 64 or 96)", len(m.Data))
    57  		}
    58  		return SignatureSM2{
    59  			R: new(big.Int).SetBytes(reverseBytes(m.Data[:len(m.Data)/2])),
    60  			S: new(big.Int).SetBytes(reverseBytes(m.Data[len(m.Data)/2:])),
    61  		}, nil
    62  	}
    63  
    64  	return nil, fmt.Errorf("unexpected signature scheme: %s", m.SigScheme)
    65  }
    66  
    67  // SetSignatureByData sets all the fields of the structure Signature by
    68  // accepting one of these types as the input argument `sig`:
    69  // * SignatureRSAPSS
    70  // * SignatureRSAASA
    71  // * SignatureECDSA
    72  // * SignatureSM2
    73  func (m *Signature) SetSignatureByData(sig SignatureDataInterface, hashAlgo Algorithm) error {
    74  	err := m.SetSignatureData(sig)
    75  	if err != nil {
    76  		return err
    77  	}
    78  
    79  	switch sig := sig.(type) {
    80  	case SignatureRSAPSS:
    81  		m.SigScheme = AlgRSAPSS
    82  		if hashAlgo.IsNull() {
    83  			m.HashAlg = AlgSHA384
    84  		} else {
    85  			m.HashAlg = hashAlgo
    86  		}
    87  		m.KeySize.SetInBytes(uint16(len(m.Data)))
    88  	case SignatureRSAASA:
    89  		m.SigScheme = AlgRSASSA
    90  		if hashAlgo.IsNull() {
    91  			m.HashAlg = AlgSHA256
    92  		} else {
    93  			m.HashAlg = hashAlgo
    94  		}
    95  		m.KeySize.SetInBytes(uint16(len(m.Data)))
    96  	case SignatureECDSA:
    97  		m.SigScheme = AlgECDSA
    98  		if hashAlgo.IsNull() {
    99  			m.HashAlg = AlgSHA512
   100  		} else {
   101  			m.HashAlg = hashAlgo
   102  		}
   103  		m.KeySize.SetInBits(uint16(sig.R.BitLen()))
   104  	case SignatureSM2:
   105  		m.SigScheme = AlgSM2
   106  		if hashAlgo.IsNull() {
   107  			m.HashAlg = AlgSM3
   108  		} else {
   109  			m.HashAlg = hashAlgo
   110  		}
   111  		m.KeySize.SetInBits(uint16(sig.R.BitLen()))
   112  	default:
   113  		return fmt.Errorf("unexpected signature type: %T", sig)
   114  	}
   115  	return nil
   116  }
   117  
   118  // SetSignatureData sets the value of the field Data by accepting one of these
   119  // types as the input argument `sig`:
   120  // * SignatureRSAPSS
   121  // * SignatureRSAASA
   122  // * SignatureECDSA
   123  // * SignatureSM2
   124  func (m *Signature) SetSignatureData(sig SignatureDataInterface) error {
   125  	switch sig := sig.(type) {
   126  	case SignatureRSAPSS:
   127  		m.Data = sig
   128  	case SignatureRSAASA:
   129  		m.Data = sig
   130  	case SignatureECDSA, SignatureSM2:
   131  		var r, s *big.Int
   132  		switch sig := sig.(type) {
   133  		case SignatureECDSA:
   134  			r, s = sig.R, sig.S
   135  		case SignatureSM2:
   136  			r, s = sig.R, sig.S
   137  		default:
   138  			return fmt.Errorf("internal error")
   139  		}
   140  		if r.BitLen() != s.BitLen() {
   141  			return fmt.Errorf("the length of component R (%d) is not equal to the length of component S (%d)", r.BitLen(), s.BitLen())
   142  		}
   143  		if r.BitLen() != 256 && r.BitLen() != 384 {
   144  			return fmt.Errorf("component R (or S) size should be 256 or 384 bites (not %d)", r.BitLen())
   145  		}
   146  		m.Data = make([]byte, r.BitLen()/8+s.BitLen()/8)
   147  		copy(m.Data[:], reverseBytes(r.Bytes()))
   148  		copy(m.Data[r.BitLen()/8:], reverseBytes(s.Bytes()))
   149  	default:
   150  		return fmt.Errorf("unexpected signature type: %T", sig)
   151  	}
   152  	return nil
   153  }
   154  
   155  // SetSignature calculates the signature accordingly to arguments signAlgo,
   156  // privKey and signedData; and sets all the fields of the structure Signature.
   157  //
   158  // if signAlgo is zero then it is detected automatically, based on the type
   159  // of the provided private key.
   160  func (m *Signature) SetSignature(signAlgo Algorithm, hashAlgo Algorithm, privKey crypto.Signer, signedData []byte) error {
   161  	m.Version = 0x10
   162  	m.HashAlg = hashAlgo
   163  	signData, err := NewSignatureData(signAlgo, privKey, signedData)
   164  	if err != nil {
   165  		return fmt.Errorf("unable to construct the signature data: %w", err)
   166  	}
   167  	err = m.SetSignatureByData(signData, m.HashAlg)
   168  	if err != nil {
   169  		return fmt.Errorf("unable to set the signature: %w", err)
   170  	}
   171  
   172  	return nil
   173  }
   174  
   175  // FillSignature sets the signature accordingly to arguments signAlgo,
   176  // pubKey and signedData; and sets all the fields of the structure Signature.
   177  //
   178  // if signAlgo is zero then it is detected automatically, based on the type
   179  // of the provided private key.
   180  func (m *Signature) FillSignature(signAlgo Algorithm, pubKey crypto.PublicKey, signedData []byte, hashAlgo Algorithm) error {
   181  	m.Version = 0x10
   182  	signData, err := NewSignatureByData(signAlgo, pubKey, signedData)
   183  	if err != nil {
   184  		return fmt.Errorf("unable to construct the signature data: %w", err)
   185  	}
   186  
   187  	err = m.SetSignatureByData(signData, hashAlgo)
   188  	if err != nil {
   189  		return fmt.Errorf("unable to set the signature: %w", err)
   190  	}
   191  
   192  	return nil
   193  }