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.
108 lines
2.3 KiB
Go
108 lines
2.3 KiB
Go
package pcsc
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
const HardwareKind = "pcsc"
|
|
|
|
var (
|
|
ErrUnsupported = errors.New("pcsc: platform is not supported")
|
|
ErrUnavailable = errors.New("pcsc: service is unavailable")
|
|
ErrReaderNotFound = errors.New("pcsc: reader not found")
|
|
ErrNoCard = errors.New("pcsc: no card is inserted")
|
|
ErrPINRequired = errors.New("pcsc: SIM PIN is required")
|
|
ErrPINTriesLow = errors.New("pcsc: refusing PIN verification because too few attempts remain")
|
|
ErrPINRejected = errors.New("pcsc: SIM PIN was rejected")
|
|
ErrUSIMUnavailable = errors.New("pcsc: no usable USIM application was found")
|
|
ErrCardChanged = errors.New("pcsc: card identity changed during authentication")
|
|
ErrAKARejected = errors.New("pcsc: USIM rejected the network authentication token")
|
|
)
|
|
|
|
type Reader struct {
|
|
Name string
|
|
USBPath string
|
|
VendorID string
|
|
ProductID string
|
|
Manufacturer string
|
|
Product string
|
|
CardPresent bool
|
|
ATR string
|
|
}
|
|
|
|
type Selector struct {
|
|
USBPath string
|
|
ReaderName string
|
|
}
|
|
|
|
func (selector Selector) validate() error {
|
|
if strings.TrimSpace(selector.USBPath) == "" && strings.TrimSpace(selector.ReaderName) == "" {
|
|
return errors.New("pcsc: reader selector is empty")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type Identity struct {
|
|
ICCID string
|
|
IMSI string
|
|
MNCLength int
|
|
USIMAID []byte
|
|
SMSC string
|
|
SPN string
|
|
PINRequired bool
|
|
PINTries int
|
|
}
|
|
|
|
type Snapshot struct {
|
|
Reader Reader
|
|
Identity Identity
|
|
}
|
|
|
|
type AKAChallenge struct {
|
|
RAND [16]byte
|
|
AUTN [16]byte
|
|
}
|
|
|
|
type AKAResult struct {
|
|
RES []byte
|
|
CK []byte
|
|
IK []byte
|
|
AUTS []byte
|
|
SynchronizationFailure bool
|
|
}
|
|
|
|
type PINError struct {
|
|
Kind error
|
|
Tries int
|
|
}
|
|
|
|
func (err *PINError) Error() string {
|
|
if err == nil {
|
|
return "pcsc: SIM PIN error"
|
|
}
|
|
if err.Tries >= 0 {
|
|
return fmt.Sprintf("%v (%d attempts remain)", err.Kind, err.Tries)
|
|
}
|
|
return err.Kind.Error()
|
|
}
|
|
|
|
func (err *PINError) Unwrap() error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
return err.Kind
|
|
}
|
|
|
|
type Card interface {
|
|
Transmit(context.Context, []byte) ([]byte, uint16, error)
|
|
Close() error
|
|
}
|
|
|
|
type Backend interface {
|
|
Readers(context.Context) ([]Reader, error)
|
|
Open(context.Context, Selector) (Card, error)
|
|
}
|