diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index a8d7bbf..1790b87 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -9,35 +9,41 @@ on: jobs: build: + strategy: + matrix: + go-version: [1.18.x, 1.19.x] name: Linux runs-on: ubuntu-latest steps: - - name: Set up Go 1.16 + - name: Set up Go uses: actions/setup-go@v2 with: - go-version: '^1.16.6' + go-version: ${{ matrix.go-version }} id: go - name: Check out code into the Go module directory uses: actions/checkout@v2 - - name: Install golint - run: go get -u golang.org/x/lint/golint + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@v0.3.3 - name: Install libpcsc run: sudo apt-get install -y libpcsclite-dev pcscd pcsc-tools - name: Test run: "make test" build-windows: + strategy: + matrix: + go-version: [1.18.x, 1.19.x] name: Windows runs-on: windows-latest steps: - - name: Set up Go 1.16 + - name: Set up Go uses: actions/setup-go@v2 with: - go-version: '^1.16.6' + go-version: ${{ matrix.go-version }} id: go - name: Check out code into the Go module directory uses: actions/checkout@v2 - - name: Install golint - run: go get -u golang.org/x/lint/golint + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@v0.3.3 - name: Test run: "make build" env: diff --git a/Makefile b/Makefile index 15275a8..698d316 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ test: lint .PHONY: lint lint: - golint -set_exit_status ./... + staticcheck ./... .PHONY: build build: lint diff --git a/piv/key.go b/piv/key.go index 1cec128..d3ec1a5 100644 --- a/piv/key.go +++ b/piv/key.go @@ -199,10 +199,6 @@ func (a *Attestation) addExt(e pkix.Extension) error { return nil } -func verifySignature(parent, c *x509.Certificate) error { - return parent.CheckSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature) -} - // Verify proves that a key was generated on a YubiKey. It ensures the slot and // YubiKey certificate chains up to the Yubico CA, parsing additional information // out of the slot certificate, such as the touch and PIN policies of a key. @@ -232,7 +228,7 @@ func (v *verifier) Verify(attestationCert, slotCert *x509.Certificate) (*Attesta // This isn't valid as per https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.9 // (fourth paragraph) and thus makes x509.go validation fail. // Work around this by setting this constraint here. - if attestationCert.BasicConstraintsValid == false { + if !attestationCert.BasicConstraintsValid { attestationCert.BasicConstraintsValid = true attestationCert.IsCA = true } @@ -747,14 +743,6 @@ type KeyAuth struct { PINPolicy PINPolicy } -func isAuthErr(err error) bool { - var e *apduErr - if !errors.As(err, &e) { - return false - } - return e.sw1 == 0x69 && e.sw2 == 0x82 // "security status not satisfied" -} - func (k KeyAuth) authTx(yk *YubiKey, pp PINPolicy) error { // PINPolicyNever shouldn't require a PIN. if pp == PINPolicyNever { diff --git a/piv/key_test.go b/piv/key_test.go index e4727f0..46b9b8a 100644 --- a/piv/key_test.go +++ b/piv/key_test.go @@ -767,7 +767,7 @@ func TestSetRSAPrivateKey(t *testing.T) { t.Fatalf("decrypting data: %v", err) } - if bytes.Compare(data, decrypted) != 0 { + if !bytes.Equal(data, decrypted) { t.Fatalf("decrypted data is different to the source data") } }) diff --git a/piv/pcsc_windows.go b/piv/pcsc_windows.go index 930ef38..845194f 100644 --- a/piv/pcsc_windows.go +++ b/piv/pcsc_windows.go @@ -127,9 +127,13 @@ func (c *scContext) Connect(reader string) (*scHandle, error) { handle syscall.Handle activeProtocol uint16 ) + readerPtr, err := syscall.UTF16PtrFromString(reader) + if err != nil { + return nil, fmt.Errorf("invalid reader string: %v", err) + } r0, _, _ := procSCardConnectW.Call( uintptr(c.ctx), - uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(reader))), + uintptr(unsafe.Pointer(readerPtr)), scardShareExclusive, scardProtocolT1, uintptr(unsafe.Pointer(&handle)), diff --git a/piv/piv.go b/piv/piv.go index 001d5c3..4e7171a 100644 --- a/piv/piv.go +++ b/piv/piv.go @@ -402,12 +402,12 @@ func ykAuthenticate(tx *scTx, key [24]byte, rand io.Reader) error { response := make([]byte, 8) block.Encrypt(response, challenge) - data := append([]byte{ + data := []byte{ 0x7c, // Dynamic Authentication Template tag 20, // 2+8+2+8 0x80, // 'Witness' 0x08, // Tag length - }) + } data = append(data, cardResponse...) data = append(data, 0x81, // 'Challenge' @@ -632,47 +632,6 @@ func ykSerial(tx *scTx, v *version) (uint32, error) { return binary.BigEndian.Uint32(resp), nil } -// ykChangeManagementKey sets the Management Key to the new key provided. The -// user must have authenticated with the existing key first. -func ykChangeManagementKey(tx *scTx, key [24]byte) error { - cmd := apdu{ - instruction: insSetMGMKey, - param1: 0xff, - param2: 0xff, // TODO: support touch policy - data: append([]byte{ - alg3DES, keyCardManagement, 24, - }, key[:]...), - } - if _, err := tx.Transmit(cmd); err != nil { - return fmt.Errorf("command failed: %w", err) - } - return nil -} - -func unmarshalDERField(b []byte, tag uint64) (obj []byte, err error) { - var prefix []byte - for tag > 0 { - prefix = append(prefix, byte(tag)) - tag = tag >> 8 - } - for i, j := 0, len(prefix)-1; i < j; i, j = i+1, j-1 { - prefix[i], prefix[j] = prefix[j], prefix[i] - } - - hasPrefix := bytes.HasPrefix(b, prefix) - for len(b) > 0 { - var v asn1.RawValue - b, err = asn1.Unmarshal(b, &v) - if err != nil { - return nil, err - } - if hasPrefix { - return v.Bytes, nil - } - } - return nil, fmt.Errorf("no der value with tag 0x%x", prefix) -} - // Metadata returns protected data stored on the card. This can be used to // retrieve PIN protected management keys. func (yk *YubiKey) Metadata(pin string) (*Metadata, error) { @@ -780,9 +739,7 @@ func (m *Metadata) unmarshal(b []byte) error { return fmt.Errorf("invalid management key length: %d", len(v.Bytes)) } var key [24]byte - for i := 0; i < len(v.Bytes); i++ { - key[i] = v.Bytes[i] - } + copy(key[:], v.Bytes) m.ManagementKey = &key } return nil