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 }