...

Source file src/github.com/Microsoft/hcsshim/internal/cosesign1/misc.go

Documentation: github.com/Microsoft/hcsshim/internal/cosesign1

     1  package cosesign1
     2  
     3  //	Little handy utilities that make logging and a command line tool easier.
     4  
     5  import (
     6  	"crypto/x509"
     7  	"encoding/base64"
     8  	"errors"
     9  	"fmt"
    10  	"io"
    11  	"os"
    12  
    13  	"github.com/veraison/go-cose"
    14  )
    15  
    16  // Type to replace the rand.Reader with a source of fixed salt.
    17  // Can be provided to the cose.Sign1 method instead of rand.Reader such that
    18  // the signature is deterministic for testing and debugging purposes.
    19  type fixedReader struct {
    20  	valueToReturn byte
    21  }
    22  
    23  func (fr *fixedReader) Read(p []byte) (int, error) {
    24  	if len(p) > 0 {
    25  		p[0] = fr.valueToReturn
    26  		return 1, nil
    27  	}
    28  	return 0, nil
    29  }
    30  
    31  func NewFixedReader(value byte) io.Reader {
    32  	return &fixedReader{valueToReturn: value}
    33  }
    34  
    35  func WriteBlob(path string, data []byte) error {
    36  	return os.WriteFile(path, data, 0644)
    37  }
    38  
    39  func WriteString(path string, str string) error {
    40  	var data = []byte(str)
    41  	return WriteBlob(path, data)
    42  }
    43  
    44  func x509ToBase64(cert *x509.Certificate) string {
    45  	base64Cert := base64.StdEncoding.EncodeToString(cert.Raw)
    46  
    47  	return base64Cert
    48  }
    49  
    50  func keyToBase64(key any) string {
    51  	derKey, err := x509.MarshalPKIXPublicKey(key)
    52  	if err != nil {
    53  		return ""
    54  	}
    55  	base64Key := base64.StdEncoding.EncodeToString(derKey)
    56  
    57  	return base64Key
    58  }
    59  
    60  // convertx509ToPEM creates a PEM from input cert in the form:
    61  //
    62  //	-----BEGIN CERTIFICATE-----
    63  //	single line base64 standard encoded raw DER certificate
    64  //	-----END CERTIFICATE-----
    65  //
    66  // Note that there are no extra line breaks added and that a string compare will
    67  // need to accommodate that.
    68  func convertx509ToPEM(cert *x509.Certificate) string {
    69  	base64Cert := x509ToBase64(cert)
    70  	return base64CertToPEM(base64Cert)
    71  }
    72  
    73  func base64CertToPEM(base64Cert string) string {
    74  	begin := "-----BEGIN CERTIFICATE-----\n"
    75  	end := "\n-----END CERTIFICATE-----"
    76  
    77  	pemData := begin + base64Cert + end
    78  
    79  	return pemData
    80  }
    81  
    82  // StringToAlgorithm returns cose.Algorithm code corresponding to algorithm name.
    83  func StringToAlgorithm(algoType string) (algo cose.Algorithm, err error) {
    84  	switch algoType {
    85  	case "PS256":
    86  		algo = cose.AlgorithmPS256
    87  	case "PS384":
    88  		algo = cose.AlgorithmPS384
    89  	case "PS512":
    90  		algo = cose.AlgorithmPS512
    91  	case "ES256":
    92  		algo = cose.AlgorithmES256
    93  	case "ES384":
    94  		algo = cose.AlgorithmES384
    95  	case "ES512":
    96  		algo = cose.AlgorithmES512
    97  	case "EdDSA":
    98  		algo = cose.AlgorithmEd25519
    99  	default:
   100  		return 0, fmt.Errorf("unknown cose.Algorithm type %q", algoType)
   101  	}
   102  	return algo, err
   103  }
   104  
   105  // ParsePemChain reads cose document and converts certificate chain to pem slice
   106  func ParsePemChain(filename string) ([]string, error) {
   107  	raw, err := os.ReadFile(filename)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	var msg cose.Sign1Message
   113  	if err = msg.UnmarshalCBOR(raw); err != nil {
   114  		return nil, err
   115  	}
   116  
   117  	protected := msg.Headers.Protected
   118  
   119  	// The spec says this is ordered - leaf, intermediates, root. X5Bag is
   120  	// unordered and would need sorting
   121  	chainDer, ok := protected[cose.HeaderLabelX5Chain]
   122  	if !ok {
   123  		return nil, errors.New("x5Chain missing")
   124  	}
   125  
   126  	chainIA, ok := chainDer.([]interface{})
   127  	if !ok {
   128  		return nil, errors.New("invalid chainDer format")
   129  	}
   130  
   131  	var pems []string
   132  	for _, c := range chainIA {
   133  		cb, ok := c.([]byte)
   134  		if !ok {
   135  			return nil, errors.New("invalid chain element")
   136  		}
   137  		cert, err := x509.ParseCertificate(cb)
   138  		if err != nil {
   139  			return nil, err
   140  		}
   141  		pems = append(pems, convertx509ToPEM(cert))
   142  	}
   143  	return pems, nil
   144  }
   145  

View as plain text