mirror of
https://github.com/MengMengCode/VoCat.git
synced 2026-08-13 03:13:43 +08:00
- Implemented a new `unsupportedBackend` in `backend_stub.go` to handle unsupported platforms. - Created a `Service` struct in `service.go` to manage interactions with smart cards, including session management and identity reading. - Added methods for reading identity, checking readiness, and authenticating with USIM applications. - Introduced a `scriptedCard` for testing purposes in `service_test.go` to simulate card responses. - Defined necessary types and error handling in `types.go` for better clarity and usability. - Developed a `PCSCAdapter` in `vowifi/pcsc_adapter.go` to integrate PC/SC service with Wi-Fi calling functionalities. - Added a new SVG icon for USB SIM readers in `public/sim-reader.svg`. - Implemented tests to ensure correct functionality and error handling in various scenarios.
85 lines
2.3 KiB
Go
85 lines
2.3 KiB
Go
package pcsc
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
type scriptedReply struct {
|
|
data []byte
|
|
sw uint16
|
|
}
|
|
|
|
type scriptedCard struct {
|
|
replies []scriptedReply
|
|
calls [][]byte
|
|
}
|
|
|
|
func (card *scriptedCard) Transmit(_ context.Context, command []byte) ([]byte, uint16, error) {
|
|
card.calls = append(card.calls, append([]byte(nil), command...))
|
|
if len(card.replies) == 0 {
|
|
return nil, 0, errors.New("unexpected APDU")
|
|
}
|
|
reply := card.replies[0]
|
|
card.replies = card.replies[1:]
|
|
return append([]byte(nil), reply.data...), reply.sw, nil
|
|
}
|
|
|
|
func (*scriptedCard) Close() error { return nil }
|
|
|
|
func TestDecodeIdentifiers(t *testing.T) {
|
|
if got := decodeSwappedBCD([]byte{0x98, 0x10, 0x32, 0x54, 0xF6}, false); got != "890123456" {
|
|
t.Fatalf("ICCID BCD = %q", got)
|
|
}
|
|
imsi, err := decodeIMSI([]byte{0x08, 0x19, 0x32, 0x54, 0x76, 0x98, 0x10, 0x32, 0x54})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if imsi != "123456789012345" {
|
|
t.Fatalf("IMSI = %q", imsi)
|
|
}
|
|
}
|
|
|
|
func TestVerifyPINRefusesLowAttemptCount(t *testing.T) {
|
|
card := &scriptedCard{replies: []scriptedReply{{sw: 0x63C2}}}
|
|
err := verifyPIN(context.Background(), card, "1234")
|
|
if !errors.Is(err, ErrPINTriesLow) {
|
|
t.Fatalf("error = %v", err)
|
|
}
|
|
if len(card.calls) != 1 {
|
|
t.Fatalf("APDU calls = %d, PIN must not be submitted", len(card.calls))
|
|
}
|
|
}
|
|
|
|
func TestParseAKAResponse(t *testing.T) {
|
|
data := []byte{0xDB, 0x08, 1, 2, 3, 4, 5, 6, 7, 8, 0x10}
|
|
data = append(data, bytes.Repeat([]byte{0xAA}, 16)...)
|
|
data = append(data, 0x10)
|
|
data = append(data, bytes.Repeat([]byte{0xBB}, 16)...)
|
|
result, err := parseAKAResponse(data)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(result.RES) != 8 || len(result.CK) != 16 || len(result.IK) != 16 || result.SynchronizationFailure {
|
|
t.Fatalf("unexpected AKA result: %#v", result)
|
|
}
|
|
|
|
syncResult, err := parseAKAResponse(append([]byte{0xDC, 0x0E}, bytes.Repeat([]byte{0xCC}, 14)...))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !syncResult.SynchronizationFailure || len(syncResult.AUTS) != 14 {
|
|
t.Fatalf("unexpected sync result: %#v", syncResult)
|
|
}
|
|
}
|
|
|
|
func TestDeviceIDUsesStableUSBPath(t *testing.T) {
|
|
a := DeviceID(Reader{Name: "reader 00 00", USBPath: "1-3"})
|
|
b := DeviceID(Reader{Name: "renamed reader", USBPath: "1-3"})
|
|
if a != b || a == "" {
|
|
t.Fatalf("device IDs = %q, %q", a, b)
|
|
}
|
|
}
|