github.com/venafi-iw/cosign@v1.3.4/test/piv_test.go (about)

     1  // Copyright 2021 The Sigstore Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  //go:build resetyubikey && e2e && !pivkeydisabled
    16  // +build resetyubikey,e2e,!pivkeydisabled
    17  
    18  // DANGER
    19  // This test requires a yubikey to be present. It WILL reset the yubikey to exercise functionality.
    20  // DO NOT RUN THIS TEST IF YOU DO NOT WANT TO RESET YOUR YUBIKEY
    21  // This requires the "resetyubikey" tag to be passed to go test.
    22  
    23  package test
    24  
    25  import (
    26  	"context"
    27  	"crypto/x509"
    28  	"testing"
    29  
    30  	// Import the functions directly for testing.
    31  	. "github.com/sigstore/cosign/cmd/cosign/cli/pivcli"
    32  )
    33  
    34  func TestSetManagementKeyCmd(t *testing.T) {
    35  	ctx := context.Background()
    36  
    37  	Confirm = func(_ string) bool { return true }
    38  	must(ResetKeyCmd(ctx), t)
    39  
    40  	// The key should be the default management key so this should fail
    41  	mustErr(SetManagementKeyCmd(ctx, "foobar", "newkey", false), t)
    42  	must(SetManagementKeyCmd(ctx, "", "newkey", false), t)
    43  
    44  	// Now it should fail with the wrong key
    45  	mustErr(SetManagementKeyCmd(ctx, "", "otherkey", false), t)
    46  	// But pass if we use the right key
    47  	must(SetManagementKeyCmd(ctx, "newkey", "otherkey", false), t)
    48  
    49  	// Reset and try a random key too!
    50  	must(ResetKeyCmd(ctx), t)
    51  	must(SetManagementKeyCmd(ctx, "", "", true), t)
    52  	mustErr(SetManagementKeyCmd(ctx, "", "", true), t)
    53  }
    54  
    55  func TestSetPUKCmd(t *testing.T) {
    56  	ctx := context.Background()
    57  
    58  	Confirm = func(_ string) bool { return true }
    59  	must(ResetKeyCmd(ctx), t)
    60  
    61  	// The PUK should be the default key so this should fail
    62  	mustErr(SetPukCmd(ctx, "11111111", "12121212"), t)
    63  	must(SetPukCmd(ctx, "", "12121212"), t)
    64  
    65  	// Now it should fail with the wrong key
    66  	mustErr(SetPukCmd(ctx, "", "43214321"), t)
    67  	// But pass if we use the right key
    68  	must(SetPukCmd(ctx, "12121212", "43214321"), t)
    69  }
    70  
    71  func TestSetPinCmd(t *testing.T) {
    72  	ctx := context.Background()
    73  
    74  	Confirm = func(_ string) bool { return true }
    75  	must(ResetKeyCmd(ctx), t)
    76  
    77  	// The PIN should be the default PIN so this should fail
    78  	mustErr(SetPinCmd(ctx, "111111", "222222"), t)
    79  	must(SetPinCmd(ctx, "", "222222"), t)
    80  
    81  	// Now it should fail with the wrong key
    82  	mustErr(SetPinCmd(ctx, "333333", "444444"), t)
    83  	// But pass if we use the right key
    84  	must(SetPinCmd(ctx, "222222", "111111"), t)
    85  }
    86  
    87  func TestUnblockCmd(t *testing.T) {
    88  	ctx := context.Background()
    89  
    90  	Confirm = func(_ string) bool { return true }
    91  	must(ResetKeyCmd(ctx), t)
    92  
    93  	// Set a PUK
    94  	must(SetPukCmd(ctx, "", "43214321"), t)
    95  	// Set the pin to something, then lock the device by trying the wrong one too many times.
    96  	must(SetPinCmd(ctx, "", "111111"), t)
    97  
    98  	for i := 0; i < 5; i++ {
    99  		mustErr(SetPinCmd(ctx, "222222", "333333"), t)
   100  	}
   101  
   102  	// Now even with the right PIN it should be stuck
   103  	mustErr(SetPinCmd(ctx, "111111", "222222"), t)
   104  
   105  	// But we can unblock it
   106  	must(UnblockCmd(ctx, "43214321", "222222"), t)
   107  	must(SetPinCmd(ctx, "222222", "333333"), t)
   108  }
   109  
   110  func TestGenerateKeyCmd(t *testing.T) {
   111  	ctx := context.Background()
   112  
   113  	Confirm = func(_ string) bool { return true }
   114  	must(ResetKeyCmd(ctx), t)
   115  
   116  	// This should work with the default key
   117  	must(GenerateKeyCmd(ctx, "", false, "", "", ""), t)
   118  
   119  	// Set the key to something other than the default
   120  	must(SetManagementKeyCmd(ctx, "", "mynewkey", false), t)
   121  	// Now this should fail
   122  	mustErr(GenerateKeyCmd(ctx, "", false, "", "", ""), t)
   123  	// Unless we use the right key
   124  	must(GenerateKeyCmd(ctx, "mynewkey", false, "", "", ""), t)
   125  
   126  	// Now if we use a random key it should set a new one
   127  	must(GenerateKeyCmd(ctx, "mynewkey", true, "", "", ""), t)
   128  	// The old one shouldn't work.
   129  	mustErr(GenerateKeyCmd(ctx, "mynewkey", false, "", "", ""), t)
   130  }
   131  
   132  func TestAttestationCmd(t *testing.T) {
   133  	ctx := context.Background()
   134  
   135  	Confirm = func(_ string) bool { return true }
   136  	must(ResetKeyCmd(ctx), t)
   137  	must(GenerateKeyCmd(ctx, "", false, "", "", ""), t)
   138  
   139  	attestations, err := AttestationCmd(ctx, "")
   140  	if err != nil {
   141  		t.Fatal(err)
   142  	}
   143  
   144  	root := x509.NewCertPool()
   145  	if !root.AppendCertsFromPEM([]byte(yubicoCert)) {
   146  		t.Fatal("error adding roots")
   147  	}
   148  
   149  	// Check the device against the manufacturer
   150  	if _, err := attestations.DeviceCert.Verify(x509.VerifyOptions{
   151  		Roots: root,
   152  	}); err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	intermediate := x509.NewCertPool()
   157  	intermediate.AddCert(attestations.DeviceCert)
   158  	// Now check the key, with the device as a chain
   159  	if _, err := attestations.KeyCert.Verify(x509.VerifyOptions{
   160  		Roots:         root,
   161  		Intermediates: intermediate,
   162  	}); err != nil {
   163  		// This is known to fail on YubiKey firmware 4.3
   164  		// See https://labanskoller.se/blog/2019/12/30/pki-is-hard-how-yubico-trusted-openssl-and-got-it-wrong/
   165  		//
   166  		if attestations.KeyAttestation.Version.Major == 4 &&
   167  			attestations.KeyAttestation.Version.Minor == 3 {
   168  			t.Skipf("key attestation cert chain verification is known to be broken on firmware 4.3")
   169  		} else {
   170  			t.Fatal(err)
   171  		}
   172  
   173  	}
   174  
   175  }
   176  
   177  const yubicoCert = `-----BEGIN CERTIFICATE-----
   178  MIIDFzCCAf+gAwIBAgIDBAZHMA0GCSqGSIb3DQEBCwUAMCsxKTAnBgNVBAMMIFl1
   179  YmljbyBQSVYgUm9vdCBDQSBTZXJpYWwgMjYzNzUxMCAXDTE2MDMxNDAwMDAwMFoY
   180  DzIwNTIwNDE3MDAwMDAwWjArMSkwJwYDVQQDDCBZdWJpY28gUElWIFJvb3QgQ0Eg
   181  U2VyaWFsIDI2Mzc1MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMN2
   182  cMTNR6YCdcTFRxuPy31PabRn5m6pJ+nSE0HRWpoaM8fc8wHC+Tmb98jmNvhWNE2E
   183  ilU85uYKfEFP9d6Q2GmytqBnxZsAa3KqZiCCx2LwQ4iYEOb1llgotVr/whEpdVOq
   184  joU0P5e1j1y7OfwOvky/+AXIN/9Xp0VFlYRk2tQ9GcdYKDmqU+db9iKwpAzid4oH
   185  BVLIhmD3pvkWaRA2H3DA9t7H/HNq5v3OiO1jyLZeKqZoMbPObrxqDg+9fOdShzgf
   186  wCqgT3XVmTeiwvBSTctyi9mHQfYd2DwkaqxRnLbNVyK9zl+DzjSGp9IhVPiVtGet
   187  X02dxhQnGS7K6BO0Qe8CAwEAAaNCMEAwHQYDVR0OBBYEFMpfyvLEojGc6SJf8ez0
   188  1d8Cv4O/MA8GA1UdEwQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
   189  DQEBCwUAA4IBAQBc7Ih8Bc1fkC+FyN1fhjWioBCMr3vjneh7MLbA6kSoyWF70N3s
   190  XhbXvT4eRh0hvxqvMZNjPU/VlRn6gLVtoEikDLrYFXN6Hh6Wmyy1GTnspnOvMvz2
   191  lLKuym9KYdYLDgnj3BeAvzIhVzzYSeU77/Cupofj093OuAswW0jYvXsGTyix6B3d
   192  bW5yWvyS9zNXaqGaUmP3U9/b6DlHdDogMLu3VLpBB9bm5bjaKWWJYgWltCVgUbFq
   193  Fqyi4+JE014cSgR57Jcu3dZiehB6UtAPgad9L5cNvua/IWRmm+ANy3O2LH++Pyl8
   194  SREzU8onbBsjMg9QDiSf5oJLKvd/Ren+zGY7
   195  -----END CERTIFICATE-----`