mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-25 01:20:18 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			513 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			513 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package ct
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"container/list"
 | |
| 	"crypto"
 | |
| 	"encoding/binary"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| )
 | |
| 
 | |
| // Variable size structure prefix-header byte lengths
 | |
| const (
 | |
| 	CertificateLengthBytes      = 3
 | |
| 	PreCertificateLengthBytes   = 3
 | |
| 	ExtensionsLengthBytes       = 2
 | |
| 	CertificateChainLengthBytes = 3
 | |
| 	SignatureLengthBytes        = 2
 | |
| )
 | |
| 
 | |
| // Max lengths
 | |
| const (
 | |
| 	MaxCertificateLength = (1 << 24) - 1
 | |
| 	MaxExtensionsLength  = (1 << 16) - 1
 | |
| )
 | |
| 
 | |
| func writeUint(w io.Writer, value uint64, numBytes int) error {
 | |
| 	buf := make([]uint8, numBytes)
 | |
| 	for i := 0; i < numBytes; i++ {
 | |
| 		buf[numBytes-i-1] = uint8(value & 0xff)
 | |
| 		value >>= 8
 | |
| 	}
 | |
| 	if value != 0 {
 | |
| 		return errors.New("numBytes was insufficiently large to represent value")
 | |
| 	}
 | |
| 	if _, err := w.Write(buf); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func writeVarBytes(w io.Writer, value []byte, numLenBytes int) error {
 | |
| 	if err := writeUint(w, uint64(len(value)), numLenBytes); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	if _, err := w.Write(value); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func readUint(r io.Reader, numBytes int) (uint64, error) {
 | |
| 	var l uint64
 | |
| 	for i := 0; i < numBytes; i++ {
 | |
| 		l <<= 8
 | |
| 		var t uint8
 | |
| 		if err := binary.Read(r, binary.BigEndian, &t); err != nil {
 | |
| 			return 0, err
 | |
| 		}
 | |
| 		l |= uint64(t)
 | |
| 	}
 | |
| 	return l, nil
 | |
| }
 | |
| 
 | |
| // Reads a variable length array of bytes from |r|. |numLenBytes| specifies the
 | |
| // number of (BigEndian) prefix-bytes which contain the length of the actual
 | |
| // array data bytes that follow.
 | |
| // Allocates an array to hold the contents and returns a slice view into it if
 | |
| // the read was successful, or an error otherwise.
 | |
| func readVarBytes(r io.Reader, numLenBytes int) ([]byte, error) {
 | |
| 	switch {
 | |
| 	case numLenBytes > 8:
 | |
| 		return nil, fmt.Errorf("numLenBytes too large (%d)", numLenBytes)
 | |
| 	case numLenBytes == 0:
 | |
| 		return nil, errors.New("numLenBytes should be > 0")
 | |
| 	}
 | |
| 	l, err := readUint(r, numLenBytes)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	data := make([]byte, l)
 | |
| 	n, err := r.Read(data)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if n != int(l) {
 | |
| 		return nil, fmt.Errorf("short read: expected %d but got %d", l, n)
 | |
| 	}
 | |
| 	return data, nil
 | |
| }
 | |
| 
 | |
| // Reads a list of ASN1Cert types from |r|
 | |
| func readASN1CertList(r io.Reader, totalLenBytes int, elementLenBytes int) ([]ASN1Cert, error) {
 | |
| 	listBytes, err := readVarBytes(r, totalLenBytes)
 | |
| 	if err != nil {
 | |
| 		return []ASN1Cert{}, err
 | |
| 	}
 | |
| 	list := list.New()
 | |
| 	listReader := bytes.NewReader(listBytes)
 | |
| 	var entry []byte
 | |
| 	for err == nil {
 | |
| 		entry, err = readVarBytes(listReader, elementLenBytes)
 | |
| 		if err != nil {
 | |
| 			if err != io.EOF {
 | |
| 				return []ASN1Cert{}, err
 | |
| 			}
 | |
| 		} else {
 | |
| 			list.PushBack(entry)
 | |
| 		}
 | |
| 	}
 | |
| 	ret := make([]ASN1Cert, list.Len())
 | |
| 	i := 0
 | |
| 	for e := list.Front(); e != nil; e = e.Next() {
 | |
| 		ret[i] = e.Value.([]byte)
 | |
| 		i++
 | |
| 	}
 | |
| 	return ret, nil
 | |
| }
 | |
| 
 | |
| // ReadTimestampedEntryInto parses the byte-stream representation of a
 | |
| // TimestampedEntry from |r| and populates the struct |t| with the data.  See
 | |
| // RFC section 3.4 for details on the format.
 | |
| // Returns a non-nil error if there was a problem.
 | |
| func ReadTimestampedEntryInto(r io.Reader, t *TimestampedEntry) error {
 | |
| 	var err error
 | |
| 	if err = binary.Read(r, binary.BigEndian, &t.Timestamp); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	if err = binary.Read(r, binary.BigEndian, &t.EntryType); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	switch t.EntryType {
 | |
| 	case X509LogEntryType:
 | |
| 		if t.X509Entry, err = readVarBytes(r, CertificateLengthBytes); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	case PrecertLogEntryType:
 | |
| 		if err := binary.Read(r, binary.BigEndian, &t.PrecertEntry.IssuerKeyHash); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		if t.PrecertEntry.TBSCertificate, err = readVarBytes(r, PreCertificateLengthBytes); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	default:
 | |
| 		return fmt.Errorf("unknown EntryType: %d", t.EntryType)
 | |
| 	}
 | |
| 	t.Extensions, err = readVarBytes(r, ExtensionsLengthBytes)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // ReadMerkleTreeLeaf parses the byte-stream representation of a MerkleTreeLeaf
 | |
| // and returns a pointer to a new MerkleTreeLeaf structure containing the
 | |
| // parsed data.
 | |
| // See RFC section 3.4 for details on the format.
 | |
| // Returns a pointer to a new MerkleTreeLeaf or non-nil error if there was a
 | |
| // problem
 | |
| func ReadMerkleTreeLeaf(r io.Reader) (*MerkleTreeLeaf, error) {
 | |
| 	var m MerkleTreeLeaf
 | |
| 	if err := binary.Read(r, binary.BigEndian, &m.Version); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if m.Version != V1 {
 | |
| 		return nil, fmt.Errorf("unknown Version %d", m.Version)
 | |
| 	}
 | |
| 	if err := binary.Read(r, binary.BigEndian, &m.LeafType); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if m.LeafType != TimestampedEntryLeafType {
 | |
| 		return nil, fmt.Errorf("unknown LeafType %d", m.LeafType)
 | |
| 	}
 | |
| 	if err := ReadTimestampedEntryInto(r, &m.TimestampedEntry); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &m, nil
 | |
| }
 | |
| 
 | |
| // UnmarshalX509ChainArray unmarshalls the contents of the "chain:" entry in a
 | |
| // GetEntries response in the case where the entry refers to an X509 leaf.
 | |
| func UnmarshalX509ChainArray(b []byte) ([]ASN1Cert, error) {
 | |
| 	return readASN1CertList(bytes.NewReader(b), CertificateChainLengthBytes, CertificateLengthBytes)
 | |
| }
 | |
| 
 | |
| // UnmarshalPrecertChainArray unmarshalls the contents of the "chain:" entry in
 | |
| // a GetEntries response in the case where the entry refers to a Precertificate
 | |
| // leaf.
 | |
| func UnmarshalPrecertChainArray(b []byte) ([]ASN1Cert, error) {
 | |
| 	var chain []ASN1Cert
 | |
| 
 | |
| 	reader := bytes.NewReader(b)
 | |
| 	// read the pre-cert entry:
 | |
| 	precert, err := readVarBytes(reader, CertificateLengthBytes)
 | |
| 	if err != nil {
 | |
| 		return chain, err
 | |
| 	}
 | |
| 	chain = append(chain, precert)
 | |
| 	// and then read and return the chain up to the root:
 | |
| 	remainingChain, err := readASN1CertList(reader, CertificateChainLengthBytes, CertificateLengthBytes)
 | |
| 	if err != nil {
 | |
| 		return chain, err
 | |
| 	}
 | |
| 	chain = append(chain, remainingChain...)
 | |
| 	return chain, nil
 | |
| }
 | |
| 
 | |
| // UnmarshalDigitallySigned reconstructs a DigitallySigned structure from a Reader
 | |
| func UnmarshalDigitallySigned(r io.Reader) (*DigitallySigned, error) {
 | |
| 	var h byte
 | |
| 	if err := binary.Read(r, binary.BigEndian, &h); err != nil {
 | |
| 		return nil, fmt.Errorf("failed to read HashAlgorithm: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	var s byte
 | |
| 	if err := binary.Read(r, binary.BigEndian, &s); err != nil {
 | |
| 		return nil, fmt.Errorf("failed to read SignatureAlgorithm: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	sig, err := readVarBytes(r, SignatureLengthBytes)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("failed to read Signature bytes: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	return &DigitallySigned{
 | |
| 		HashAlgorithm:      HashAlgorithm(h),
 | |
| 		SignatureAlgorithm: SignatureAlgorithm(s),
 | |
| 		Signature:          sig,
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| func marshalDigitallySignedHere(ds DigitallySigned, here []byte) ([]byte, error) {
 | |
| 	sigLen := len(ds.Signature)
 | |
| 	dsOutLen := 2 + SignatureLengthBytes + sigLen
 | |
| 	if here == nil {
 | |
| 		here = make([]byte, dsOutLen)
 | |
| 	}
 | |
| 	if len(here) < dsOutLen {
 | |
| 		return nil, ErrNotEnoughBuffer
 | |
| 	}
 | |
| 	here = here[0:dsOutLen]
 | |
| 
 | |
| 	here[0] = byte(ds.HashAlgorithm)
 | |
| 	here[1] = byte(ds.SignatureAlgorithm)
 | |
| 	binary.BigEndian.PutUint16(here[2:4], uint16(sigLen))
 | |
| 	copy(here[4:], ds.Signature)
 | |
| 
 | |
| 	return here, nil
 | |
| }
 | |
| 
 | |
| // MarshalDigitallySigned marshalls a DigitallySigned structure into a byte array
 | |
| func MarshalDigitallySigned(ds DigitallySigned) ([]byte, error) {
 | |
| 	return marshalDigitallySignedHere(ds, nil)
 | |
| }
 | |
| 
 | |
| func checkCertificateFormat(cert ASN1Cert) error {
 | |
| 	if len(cert) == 0 {
 | |
| 		return errors.New("certificate is zero length")
 | |
| 	}
 | |
| 	if len(cert) > MaxCertificateLength {
 | |
| 		return errors.New("certificate too large")
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func checkExtensionsFormat(ext CTExtensions) error {
 | |
| 	if len(ext) > MaxExtensionsLength {
 | |
| 		return errors.New("extensions too large")
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func serializeV1CertSCTSignatureInput(timestamp uint64, cert ASN1Cert, ext CTExtensions) ([]byte, error) {
 | |
| 	if err := checkCertificateFormat(cert); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := checkExtensionsFormat(ext); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	var buf bytes.Buffer
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, V1); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, CertificateTimestampSignatureType); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, timestamp); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, X509LogEntryType); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := writeVarBytes(&buf, cert, CertificateLengthBytes); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := writeVarBytes(&buf, ext, ExtensionsLengthBytes); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return buf.Bytes(), nil
 | |
| }
 | |
| 
 | |
| func serializeV1PrecertSCTSignatureInput(timestamp uint64, issuerKeyHash [issuerKeyHashLength]byte, tbs []byte, ext CTExtensions) ([]byte, error) {
 | |
| 	if err := checkCertificateFormat(tbs); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := checkExtensionsFormat(ext); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	var buf bytes.Buffer
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, V1); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, CertificateTimestampSignatureType); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, timestamp); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, PrecertLogEntryType); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := buf.Write(issuerKeyHash[:]); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := writeVarBytes(&buf, tbs, CertificateLengthBytes); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := writeVarBytes(&buf, ext, ExtensionsLengthBytes); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return buf.Bytes(), nil
 | |
| }
 | |
| 
 | |
| func serializeV1SCTSignatureInput(sct SignedCertificateTimestamp, entry LogEntry) ([]byte, error) {
 | |
| 	if sct.SCTVersion != V1 {
 | |
| 		return nil, fmt.Errorf("unsupported SCT version, expected V1, but got %s", sct.SCTVersion)
 | |
| 	}
 | |
| 	if entry.Leaf.LeafType != TimestampedEntryLeafType {
 | |
| 		return nil, fmt.Errorf("Unsupported leaf type %s", entry.Leaf.LeafType)
 | |
| 	}
 | |
| 	switch entry.Leaf.TimestampedEntry.EntryType {
 | |
| 	case X509LogEntryType:
 | |
| 		return serializeV1CertSCTSignatureInput(sct.Timestamp, entry.Leaf.TimestampedEntry.X509Entry, entry.Leaf.TimestampedEntry.Extensions)
 | |
| 	case PrecertLogEntryType:
 | |
| 		return serializeV1PrecertSCTSignatureInput(sct.Timestamp, entry.Leaf.TimestampedEntry.PrecertEntry.IssuerKeyHash,
 | |
| 			entry.Leaf.TimestampedEntry.PrecertEntry.TBSCertificate,
 | |
| 			entry.Leaf.TimestampedEntry.Extensions)
 | |
| 	default:
 | |
| 		return nil, fmt.Errorf("unknown TimestampedEntryLeafType %s", entry.Leaf.TimestampedEntry.EntryType)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // SerializeSCTSignatureInput serializes the passed in sct and log entry into
 | |
| // the correct format for signing.
 | |
| func SerializeSCTSignatureInput(sct SignedCertificateTimestamp, entry LogEntry) ([]byte, error) {
 | |
| 	switch sct.SCTVersion {
 | |
| 	case V1:
 | |
| 		return serializeV1SCTSignatureInput(sct, entry)
 | |
| 	default:
 | |
| 		return nil, fmt.Errorf("unknown SCT version %d", sct.SCTVersion)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // SerializedLength will return the space (in bytes)
 | |
| func (sct SignedCertificateTimestamp) SerializedLength() (int, error) {
 | |
| 	switch sct.SCTVersion {
 | |
| 	case V1:
 | |
| 		extLen := len(sct.Extensions)
 | |
| 		sigLen := len(sct.Signature.Signature)
 | |
| 		return 1 + 32 + 8 + 2 + extLen + 2 + 2 + sigLen, nil
 | |
| 	default:
 | |
| 		return 0, ErrInvalidVersion
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func serializeV1SCTHere(sct SignedCertificateTimestamp, here []byte) ([]byte, error) {
 | |
| 	if sct.SCTVersion != V1 {
 | |
| 		return nil, ErrInvalidVersion
 | |
| 	}
 | |
| 	sctLen, err := sct.SerializedLength()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if here == nil {
 | |
| 		here = make([]byte, sctLen)
 | |
| 	}
 | |
| 	if len(here) < sctLen {
 | |
| 		return nil, ErrNotEnoughBuffer
 | |
| 	}
 | |
| 	if err := checkExtensionsFormat(sct.Extensions); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	here = here[0:sctLen]
 | |
| 
 | |
| 	// Write Version
 | |
| 	here[0] = byte(sct.SCTVersion)
 | |
| 
 | |
| 	// Write LogID
 | |
| 	copy(here[1:33], sct.LogID[:])
 | |
| 
 | |
| 	// Write Timestamp
 | |
| 	binary.BigEndian.PutUint64(here[33:41], sct.Timestamp)
 | |
| 
 | |
| 	// Write Extensions
 | |
| 	extLen := len(sct.Extensions)
 | |
| 	binary.BigEndian.PutUint16(here[41:43], uint16(extLen))
 | |
| 	n := 43 + extLen
 | |
| 	copy(here[43:n], sct.Extensions)
 | |
| 
 | |
| 	// Write Signature
 | |
| 	_, err = marshalDigitallySignedHere(sct.Signature, here[n:])
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return here, nil
 | |
| }
 | |
| 
 | |
| // SerializeSCTHere serializes the passed in sct into the format specified
 | |
| // by RFC6962 section 3.2.
 | |
| // If a bytes slice here is provided then it will attempt to serialize into the
 | |
| // provided byte slice, ErrNotEnoughBuffer will be returned if the buffer is
 | |
| // too small.
 | |
| // If a nil byte slice is provided, a buffer for will be allocated for you
 | |
| // The returned slice will be sliced to the correct length.
 | |
| func SerializeSCTHere(sct SignedCertificateTimestamp, here []byte) ([]byte, error) {
 | |
| 	switch sct.SCTVersion {
 | |
| 	case V1:
 | |
| 		return serializeV1SCTHere(sct, here)
 | |
| 	default:
 | |
| 		return nil, fmt.Errorf("unknown SCT version %d", sct.SCTVersion)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // SerializeSCT serializes the passed in sct into the format specified
 | |
| // by RFC6962 section 3.2
 | |
| // Equivalent to SerializeSCTHere(sct, nil)
 | |
| func SerializeSCT(sct SignedCertificateTimestamp) ([]byte, error) {
 | |
| 	return SerializeSCTHere(sct, nil)
 | |
| }
 | |
| 
 | |
| func deserializeSCTV1(r io.Reader, sct *SignedCertificateTimestamp) error {
 | |
| 	if err := binary.Read(r, binary.BigEndian, &sct.LogID); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	if err := binary.Read(r, binary.BigEndian, &sct.Timestamp); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	ext, err := readVarBytes(r, ExtensionsLengthBytes)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	sct.Extensions = ext
 | |
| 	ds, err := UnmarshalDigitallySigned(r)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	sct.Signature = *ds
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func DeserializeSCT(r io.Reader) (*SignedCertificateTimestamp, error) {
 | |
| 	var sct SignedCertificateTimestamp
 | |
| 	if err := binary.Read(r, binary.BigEndian, &sct.SCTVersion); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	switch sct.SCTVersion {
 | |
| 	case V1:
 | |
| 		return &sct, deserializeSCTV1(r, &sct)
 | |
| 	default:
 | |
| 		return nil, fmt.Errorf("unknown SCT version %d", sct.SCTVersion)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func serializeV1STHSignatureInput(sth SignedTreeHead) ([]byte, error) {
 | |
| 	if sth.Version != V1 {
 | |
| 		return nil, fmt.Errorf("invalid STH version %d", sth.Version)
 | |
| 	}
 | |
| 	if sth.TreeSize < 0 {
 | |
| 		return nil, fmt.Errorf("invalid tree size %d", sth.TreeSize)
 | |
| 	}
 | |
| 	if len(sth.SHA256RootHash) != crypto.SHA256.Size() {
 | |
| 		return nil, fmt.Errorf("invalid TreeHash length, got %d expected %d", len(sth.SHA256RootHash), crypto.SHA256.Size())
 | |
| 	}
 | |
| 
 | |
| 	var buf bytes.Buffer
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, V1); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, TreeHashSignatureType); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, sth.Timestamp); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, sth.TreeSize); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := binary.Write(&buf, binary.BigEndian, sth.SHA256RootHash); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return buf.Bytes(), nil
 | |
| }
 | |
| 
 | |
| // SerializeSTHSignatureInput serializes the passed in sth into the correct
 | |
| // format for signing.
 | |
| func SerializeSTHSignatureInput(sth SignedTreeHead) ([]byte, error) {
 | |
| 	switch sth.Version {
 | |
| 	case V1:
 | |
| 		return serializeV1STHSignatureInput(sth)
 | |
| 	default:
 | |
| 		return nil, fmt.Errorf("unsupported STH version %d", sth.Version)
 | |
| 	}
 | |
| }
 |