...

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

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

     1  //go:build linux
     2  // +build linux
     3  
     4  package cosesign1
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"os"
    10  	"os/exec"
    11  	"testing"
    12  
    13  	"github.com/veraison/go-cose"
    14  )
    15  
    16  func readFileBytes(filename string) ([]byte, error) {
    17  	content, err := os.ReadFile(filename)
    18  	if err != nil {
    19  		println("Error reading '" + filename + "': " + string(err.Error()))
    20  		return nil, err
    21  	}
    22  	if len(content) == 0 {
    23  		println("Warning: empty file '" + filename + "'")
    24  	}
    25  	return content, nil
    26  }
    27  
    28  func readFileBytesOrExit(filename string) []byte {
    29  	val, err := readFileBytes(filename)
    30  	if err != nil {
    31  		println("failed to load from file '" + filename + "' with error " + string(err.Error()))
    32  		os.Exit(1)
    33  	}
    34  	return val
    35  }
    36  
    37  func readFileStringOrExit(filename string) string {
    38  	val := readFileBytesOrExit(filename)
    39  	return string(val)
    40  }
    41  
    42  var fragmentRego string
    43  var fragmentCose []byte
    44  var leafPrivatePem string
    45  var leafCertPEM string
    46  var leafPubkeyPEM string
    47  var certChainPEM string
    48  
    49  func TestMain(m *testing.M) {
    50  	fmt.Println("Generating files...")
    51  
    52  	err := exec.Command("make", "chain.pem", "infra.rego.cose").Run()
    53  	if err != nil {
    54  		fmt.Fprintf(os.Stderr, "Failed to build the required test files: %s", err)
    55  		os.Exit(1)
    56  	}
    57  
    58  	fragmentRego = readFileStringOrExit("infra.rego.base64")
    59  	fragmentCose = readFileBytesOrExit("infra.rego.cose")
    60  	leafPrivatePem = readFileStringOrExit("leaf.private.pem")
    61  	leafCertPEM = readFileStringOrExit("leaf.cert.pem")
    62  	leafPubkeyPEM = readFileStringOrExit("leaf.public.pem")
    63  	certChainPEM = readFileStringOrExit("chain.pem")
    64  
    65  	os.Exit(m.Run())
    66  }
    67  
    68  func comparePEMs(pk1pem string, pk2pem string) bool {
    69  	pk1der := pem2der([]byte(pk1pem))
    70  	pk2der := pem2der([]byte(pk2pem))
    71  	return bytes.Equal(pk1der, pk2der)
    72  }
    73  
    74  func base64PublicKeyToPEM(base64Key string) string {
    75  	begin := "-----BEGIN PUBLIC KEY-----\n"
    76  	end := "\n-----END PUBLIC KEY-----"
    77  
    78  	pemData := begin + base64Key + end
    79  	return pemData
    80  }
    81  
    82  // Decode a COSE_Sign1 document and check that we get the expected payload, issuer, keys, certs etc.
    83  func Test_UnpackAndValidateCannedFragment(t *testing.T) {
    84  	var unpacked *UnpackedCoseSign1
    85  	unpacked, err := UnpackAndValidateCOSE1CertChain(fragmentCose)
    86  
    87  	if err != nil {
    88  		t.Errorf("UnpackAndValidateCOSE1CertChain failed: %s", err.Error())
    89  	}
    90  
    91  	iss := unpacked.Issuer
    92  	feed := unpacked.Feed
    93  	pubkey := base64PublicKeyToPEM(unpacked.Pubkey)
    94  	pubcert := base64CertToPEM(unpacked.Pubcert)
    95  	payload := string(unpacked.Payload[:])
    96  	cty := unpacked.ContentType
    97  
    98  	if !comparePEMs(pubkey, leafPubkeyPEM) {
    99  		t.Fatal("pubkey did not match")
   100  	}
   101  	if !comparePEMs(pubcert, leafCertPEM) {
   102  		t.Fatal("pubcert did not match")
   103  	}
   104  	if cty != "application/unknown+json" {
   105  		t.Fatal("cty did not match")
   106  	}
   107  	if payload != fragmentRego {
   108  		t.Fatal("payload did not match")
   109  	}
   110  	if iss != "TestIssuer" {
   111  		t.Fatal("iss did not match")
   112  	}
   113  	if feed != "TestFeed" {
   114  		t.Fatal("feed did not match")
   115  	}
   116  }
   117  
   118  func Test_UnpackAndValidateCannedFragmentCorrupted(t *testing.T) {
   119  	fragCose := make([]byte, len(fragmentCose))
   120  	copy(fragCose, fragmentCose)
   121  
   122  	offset := len(fragCose) / 2
   123  	// corrupt the cose document (use the uncorrupted one as source in case we loop back to a good value)
   124  	fragCose[offset] = fragmentCose[offset] + 1
   125  
   126  	_, err := UnpackAndValidateCOSE1CertChain(fragCose)
   127  	// expect it to fail
   128  	if err == nil {
   129  		t.Fatal("corrupted document passed validation")
   130  	}
   131  }
   132  
   133  // Use CreateCoseSign1 to make a document that should match the one made by the makefile
   134  func Test_CreateCoseSign1Fragment(t *testing.T) {
   135  	var raw, err = CreateCoseSign1([]byte(fragmentRego), "TestIssuer", "TestFeed", "application/unknown+json", []byte(certChainPEM), []byte(leafPrivatePem), "zero", cose.AlgorithmES384)
   136  	if err != nil {
   137  		t.Fatalf("CreateCoseSign1 failed: %s", err)
   138  	}
   139  
   140  	if len(raw) != len(fragmentCose) {
   141  		t.Fatal("created fragment length does not match expected")
   142  	}
   143  
   144  	for i := range raw {
   145  		if raw[i] != fragmentCose[i] {
   146  			t.Errorf("created fragment byte offset %d does not match expected", i)
   147  		}
   148  	}
   149  }
   150  
   151  func Test_OldCose(t *testing.T) {
   152  	filename := "esrp.test.cose"
   153  	cose, err := readFileBytes(filename)
   154  	if err == nil {
   155  		_, err = UnpackAndValidateCOSE1CertChain(cose)
   156  	}
   157  	if err != nil {
   158  		t.Fatalf("validation of %s failed: %s", filename, err)
   159  	}
   160  }
   161  
   162  func Test_DidX509(t *testing.T) {
   163  	chainPEMBytes, err := os.ReadFile("chain.pem")
   164  	if err != nil {
   165  		t.Fatalf("failed to read PEM: %s", err)
   166  	}
   167  	chainPEM := string(chainPEMBytes)
   168  
   169  	if _, err := MakeDidX509("sha256", 1, chainPEM, "subject:CN:Test Leaf (DO NOT TRUST)", true); err != nil {
   170  		t.Fatalf("did:x509 creation failed: %s", err)
   171  	}
   172  }
   173  

View as plain text