*: clean up actions and address all staticcheck findings
Eric Chiang authored 1 year, 8 months ago
Eric Chiang committed 1 year, 8 months ago
8 | 8 | |
9 | 9 | jobs: |
10 | 10 | build: |
11 | strategy: | |
12 | matrix: | |
13 | go-version: [1.18.x, 1.19.x] | |
11 | 14 | name: Linux |
12 | 15 | runs-on: ubuntu-latest |
13 | 16 | steps: |
14 | - name: Set up Go 1.16 | |
17 | - name: Set up Go | |
15 | 18 | uses: actions/setup-go@v2 |
16 | 19 | with: |
17 | go-version: '^1.16.6' | |
20 | go-version: ${{ matrix.go-version }} | |
18 | 21 | id: go |
19 | 22 | - name: Check out code into the Go module directory |
20 | 23 | uses: actions/checkout@v2 |
21 | - name: Install golint | |
22 | run: go get -u golang.org/x/lint/golint | |
24 | - name: Install staticcheck | |
25 | run: go install honnef.co/go/tools/cmd/staticcheck@v0.3.3 | |
23 | 26 | - name: Install libpcsc |
24 | 27 | run: sudo apt-get install -y libpcsclite-dev pcscd pcsc-tools |
25 | 28 | - name: Test |
26 | 29 | run: "make test" |
27 | 30 | build-windows: |
31 | strategy: | |
32 | matrix: | |
33 | go-version: [1.18.x, 1.19.x] | |
28 | 34 | name: Windows |
29 | 35 | runs-on: windows-latest |
30 | 36 | steps: |
31 | - name: Set up Go 1.16 | |
37 | - name: Set up Go | |
32 | 38 | uses: actions/setup-go@v2 |
33 | 39 | with: |
34 | go-version: '^1.16.6' | |
40 | go-version: ${{ matrix.go-version }} | |
35 | 41 | id: go |
36 | 42 | - name: Check out code into the Go module directory |
37 | 43 | uses: actions/checkout@v2 |
38 | - name: Install golint | |
39 | run: go get -u golang.org/x/lint/golint | |
44 | - name: Install staticcheck | |
45 | run: go install honnef.co/go/tools/cmd/staticcheck@v0.3.3 | |
40 | 46 | - name: Test |
41 | 47 | run: "make build" |
42 | 48 | env: |
3 | 3 | |
4 | 4 | .PHONY: lint |
5 | 5 | lint: |
6 | golint -set_exit_status ./... | |
6 | staticcheck ./... | |
7 | 7 | |
8 | 8 | .PHONY: build |
9 | 9 | build: lint |
198 | 198 | return nil |
199 | 199 | } |
200 | 200 | |
201 | func verifySignature(parent, c *x509.Certificate) error { | |
202 | return parent.CheckSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature) | |
203 | } | |
204 | ||
205 | 201 | // Verify proves that a key was generated on a YubiKey. It ensures the slot and |
206 | 202 | // YubiKey certificate chains up to the Yubico CA, parsing additional information |
207 | 203 | // out of the slot certificate, such as the touch and PIN policies of a key. |
231 | 227 | // This isn't valid as per https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.9 |
232 | 228 | // (fourth paragraph) and thus makes x509.go validation fail. |
233 | 229 | // Work around this by setting this constraint here. |
234 | if attestationCert.BasicConstraintsValid == false { | |
230 | if !attestationCert.BasicConstraintsValid { | |
235 | 231 | attestationCert.BasicConstraintsValid = true |
236 | 232 | attestationCert.IsCA = true |
237 | 233 | } |
746 | 742 | PINPolicy PINPolicy |
747 | 743 | } |
748 | 744 | |
749 | func isAuthErr(err error) bool { | |
750 | var e *apduErr | |
751 | if !errors.As(err, &e) { | |
752 | return false | |
753 | } | |
754 | return e.sw1 == 0x69 && e.sw2 == 0x82 // "security status not satisfied" | |
755 | } | |
756 | ||
757 | 745 | func (k KeyAuth) authTx(yk *YubiKey, pp PINPolicy) error { |
758 | 746 | // PINPolicyNever shouldn't require a PIN. |
759 | 747 | if pp == PINPolicyNever { |
766 | 766 | t.Fatalf("decrypting data: %v", err) |
767 | 767 | } |
768 | 768 | |
769 | if bytes.Compare(data, decrypted) != 0 { | |
769 | if !bytes.Equal(data, decrypted) { | |
770 | 770 | t.Fatalf("decrypted data is different to the source data") |
771 | 771 | } |
772 | 772 | }) |
126 | 126 | handle syscall.Handle |
127 | 127 | activeProtocol uint16 |
128 | 128 | ) |
129 | readerPtr, err := syscall.UTF16PtrFromString(reader) | |
130 | if err != nil { | |
131 | return nil, fmt.Errorf("invalid reader string: %v", err) | |
132 | } | |
129 | 133 | r0, _, _ := procSCardConnectW.Call( |
130 | 134 | uintptr(c.ctx), |
131 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(reader))), | |
135 | uintptr(unsafe.Pointer(readerPtr)), | |
132 | 136 | scardShareExclusive, |
133 | 137 | scardProtocolT1, |
134 | 138 | uintptr(unsafe.Pointer(&handle)), |
401 | 401 | response := make([]byte, 8) |
402 | 402 | block.Encrypt(response, challenge) |
403 | 403 | |
404 | data := append([]byte{ | |
404 | data := []byte{ | |
405 | 405 | 0x7c, // Dynamic Authentication Template tag |
406 | 406 | 20, // 2+8+2+8 |
407 | 407 | 0x80, // 'Witness' |
408 | 408 | 0x08, // Tag length |
409 | }) | |
409 | } | |
410 | 410 | data = append(data, cardResponse...) |
411 | 411 | data = append(data, |
412 | 412 | 0x81, // 'Challenge' |
631 | 631 | return binary.BigEndian.Uint32(resp), nil |
632 | 632 | } |
633 | 633 | |
634 | // ykChangeManagementKey sets the Management Key to the new key provided. The | |
635 | // user must have authenticated with the existing key first. | |
636 | func ykChangeManagementKey(tx *scTx, key [24]byte) error { | |
637 | cmd := apdu{ | |
638 | instruction: insSetMGMKey, | |
639 | param1: 0xff, | |
640 | param2: 0xff, // TODO: support touch policy | |
641 | data: append([]byte{ | |
642 | alg3DES, keyCardManagement, 24, | |
643 | }, key[:]...), | |
644 | } | |
645 | if _, err := tx.Transmit(cmd); err != nil { | |
646 | return fmt.Errorf("command failed: %w", err) | |
647 | } | |
648 | return nil | |
649 | } | |
650 | ||
651 | func unmarshalDERField(b []byte, tag uint64) (obj []byte, err error) { | |
652 | var prefix []byte | |
653 | for tag > 0 { | |
654 | prefix = append(prefix, byte(tag)) | |
655 | tag = tag >> 8 | |
656 | } | |
657 | for i, j := 0, len(prefix)-1; i < j; i, j = i+1, j-1 { | |
658 | prefix[i], prefix[j] = prefix[j], prefix[i] | |
659 | } | |
660 | ||
661 | hasPrefix := bytes.HasPrefix(b, prefix) | |
662 | for len(b) > 0 { | |
663 | var v asn1.RawValue | |
664 | b, err = asn1.Unmarshal(b, &v) | |
665 | if err != nil { | |
666 | return nil, err | |
667 | } | |
668 | if hasPrefix { | |
669 | return v.Bytes, nil | |
670 | } | |
671 | } | |
672 | return nil, fmt.Errorf("no der value with tag 0x%x", prefix) | |
673 | } | |
674 | ||
675 | 634 | // Metadata returns protected data stored on the card. This can be used to |
676 | 635 | // retrieve PIN protected management keys. |
677 | 636 | func (yk *YubiKey) Metadata(pin string) (*Metadata, error) { |
779 | 738 | return fmt.Errorf("invalid management key length: %d", len(v.Bytes)) |
780 | 739 | } |
781 | 740 | var key [24]byte |
782 | for i := 0; i < len(v.Bytes); i++ { | |
783 | key[i] = v.Bytes[i] | |
784 | } | |
741 | copy(key[:], v.Bytes) | |
785 | 742 | m.ManagementKey = &key |
786 | 743 | } |
787 | 744 | return nil |