chromium/services/device/public/mojom/smart_card.mojom

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// The purpose of these mojo interfaces is to expose the platform's PC/SC
// implementation (according to "Interoperability Specification for ICCs and
// Personal Computer Systems; Part 5 ICC Resource Manager Definition") as close
// as possible, exposing the same concepts and functionality.
//
// See https://pcscworkgroup.com/specifications/download/
// And its authoritative implementation, winscard.h:
// https://learn.microsoft.com/en-us/windows/win32/api/winscard/

module device.mojom;

import "mojo/public/mojom/base/time.mojom";

// The result of a SmartCard request.
// Either a success or an error.
union SmartCardResult {
  SmartCardSuccess success;
  SmartCardError error;
};

// Indicates that a SmartCard request succeeded.
enum SmartCardSuccess {
  kOk
};

// Possible error results for a SmartCard* request.
enum SmartCardError {
  // PC/SC error codes we can expect to hit (thus a non-exhaustive list):
  kRemovedCard,
  kResetCard,
  kUnpoweredCard,
  kUnresponsiveCard,
  kUnsupportedCard,
  kReaderUnavailable,
  kSharingViolation,
  kNotTransacted,
  kNoSmartcard,
  kProtoMismatch,
  kSystemCancelled,
  kNotReady,
  kCancelled,
  kInsufficientBuffer,
  kInvalidHandle,
  kInvalidParameter,
  kInvalidValue,
  kNoMemory,
  kTimeout,
  kUnknownReader,
  kUnsupportedFeature,
  kNoReadersAvailable,
  kServiceStopped,
  kNoService,
  kCommError,
  kInternalError,
  kUnknownError,
  kServerTooBusy,
  kUnexpected,
  kShutdown,

  // UNKNOWN means an SCARD_* (PC/SC) error code that is not mapped in this enum
  // (and thus should probably be added above):
  kUnknown,

  // This request is covered by a permission check and the user has denied it.
  kPermissionDenied
};

// Share mode of a connection.
enum SmartCardShareMode {
  // SCARD_SHARE_SHARED
  kShared,
  // SCARD_SHARE_EXCLUSIVE
  kExclusive,
  // SCARD_SHARE_DIRECT
  kDirect
};

// Communication protocol for a connection to a smart card.
enum SmartCardProtocol {
  // SCARD_PROTOCOL_UNDEFINED
  kUndefined,
  // SCARD_PROTOCOL_T0
  // T=0 protocol
  kT0,
  // SCARD_PROTOCOL_T1
  // T=1 protocol
  kT1,
  // SCARD_PROTOCOL_RAW
  kRaw
};

// Action to take after disconnecting.
enum SmartCardDisposition {
  // SCARD_LEAVE_CARD - Do nothing.
  kLeave,
  // SCARD_RESET_CARD - Reset the card (warm reset).
  kReset,
  // SCARD_UNPOWER_CARD - Power down the card (cold reset).
  kUnpower,
  // SCARD_EJECT_CARD - Eject the card.
  kEject
};

// State of a SmartCardConnection.
// Note that there's quite some overlap with SmartCardReaderStateFlags.
// But that's what PC/SC does.
enum SmartCardConnectionState {
  // SCARD_ABSENT
  kAbsent,
  // SCARD_PRESENT
  kPresent,
  // SCARD_SWALLOWED
  kSwallowed,
  // SCARD_POWERED
  kPowered,
  // SCARD_NEGOTIABLE
  kNegotiable,
  // SCARD_SPECIFIC
  kSpecific
};

// Flags for describing the state of a smart card reader.
// Maps to the corresponding SCARD_STATE_* flags in winscard.h
struct SmartCardReaderStateFlags {
  bool unaware;
  bool ignore;
  bool changed;
  bool unknown;
  bool unavailable;
  bool empty;
  bool present;
  bool exclusive;
  bool inuse;
  bool mute;
  bool unpowered;
};

// Describes the last known state of a smart card reader.
// SmartCardContext uses that information to decide whether the reader state
// has changed (ie, whether it's different from what the API user knows).
struct SmartCardReaderStateIn {
  string reader;
  SmartCardReaderStateFlags current_state;
  // Number of card insertion and removal events that happened in this reader,
  // as known by the application.
  uint16 current_count;
};

// Describes the actual state of a smart card reader.
struct SmartCardReaderStateOut {
  string reader;
  SmartCardReaderStateFlags event_state;
  // Number of card insertion and removal events that happened in this reader.
  // Will always be zero if not supported by the platform.
  uint16 event_count;
  array<uint8> answer_to_reset;
};

// Preferred protocols.
struct SmartCardProtocols {
  // SCARD_PROTOCOL_T0
  bool t0;
  // SCARD_PROTOCOL_T1
  bool t1;
  // SCARD_PROTOCOL_RAW
  bool raw;
};

// Status of a SmartCardConnection.
struct SmartCardStatus {
  string reader_name;
  SmartCardConnectionState state;
  SmartCardProtocol protocol;
  array<uint8> answer_to_reset;
};

// The result of a SmartCardContext.GetStatusChange request.
union SmartCardStatusChangeResult {
  array<SmartCardReaderStateOut> reader_states;
  SmartCardError error;
};

// The result of a SmartCardContext.ListReaders request.
union SmartCardListReadersResult {
  array<string> readers;
  SmartCardError error;
};

// The result of a SmartCardContextFactory.CreateContext request.
union SmartCardCreateContextResult {
  pending_remote<SmartCardContext> context;
  SmartCardError error;
};

// The result of a SmartCardContext.Connect request in
// case of success.
struct SmartCardConnectSuccess {
  pending_remote<SmartCardConnection> connection;
  SmartCardProtocol active_protocol;
};

// The result of a SmartCardContext.Connect request.
union SmartCardConnectResult {
  SmartCardConnectSuccess success;
  SmartCardError error;
};

// Result of a PC/SC request that sends back data on success.
// Otherwise, an error.
union SmartCardDataResult {
  array<uint8> data;
  SmartCardError error;
};

// The result of a SmartCardConnection.Status request.
union SmartCardStatusResult {
  SmartCardStatus status;
  SmartCardError error;
};

// The result of a SmartCardConnection.BeginTransaction request.
union SmartCardTransactionResult {
  pending_associated_remote<SmartCardTransaction> transaction;
  SmartCardError error;
};

// An interface to a transaction.
// All commands sent through the related SmartCardConnection will be part of
// this transaction.
interface SmartCardTransaction {
  // Ends a logical transaction, allowing other applications to resume
  // interactions with that card.
  // Upon termination, the action indicated by `disposition` is performed.
  EndTransaction(SmartCardDisposition disposition) => (SmartCardResult result);
};

// An interface to a valid connection (SCARDHANDLE) within a context
// in a PC/SC (winscard.h) provider.
interface SmartCardConnection {
  // Terminates the connection and leaves the card in the given `disposition`.
  Disconnect(SmartCardDisposition disposition)
      => (SmartCardResult result);

  // Sends an APDU to the smart card and receives a response back from it.
  Transmit(SmartCardProtocol protocol, array<uint8> data)
      => (SmartCardDataResult result);

  // Sends a command directly to the Interface Device (IFD) Handler (reader
  // driver) to be processed by the reader.
  Control(uint32 control_code, array<uint8> data)
      => (SmartCardDataResult result);

  // Gets an attribute from the Interface Device Handler (reader driver).
  GetAttrib(uint32 id) => (SmartCardDataResult result);

  // Sets an attribute of the Interface Device Handler.
  SetAttrib(uint32 id, array<uint8> data) => (SmartCardResult result);

  // Returns the status of the connected reader.
  Status() => (SmartCardStatusResult result);

  // Initiates a logical transaction against the card in the reader associated
  // with this connection. If successful, this blocks other applications from
  // accessing the card, allowing the calling application to perform a sequence
  // of operations against the card with assurance that any intermediate state
  // information will remain valid.
  //
  // On Windows, if a transaction is held on the card for more than five seconds
  // with no operations happening on that card, then the card is reset.
  BeginTransaction() => (SmartCardTransactionResult result);
};

// An interface to a valid context in a PC/SC (winscard.h) provider.
//
// Dropping a remote of this interface equates to calling SCardReleaseContext()
// on the corresponding PC/SC provider.
interface SmartCardContext {
  // Returns a list of currently available readers on the system.
  ListReaders() => (SmartCardListReadersResult result);

  // Waits until the current availability of the cards in a specific set of
  // readers changes.
  GetStatusChange(mojo_base.mojom.TimeDelta timeout,
                  array<SmartCardReaderStateIn> reader_states)
    => (SmartCardStatusChangeResult result);

  // Terminates an outstanding GetStatusChange() call with
  // SmartCardError::kCancelled.
  Cancel() => (SmartCardResult result);

  // Establishes a connection to the specified reader.
  Connect(string reader, SmartCardShareMode share_mode,
          SmartCardProtocols preferred_protocols) =>
    (SmartCardConnectResult result);
};

// An interface to establish contexts with a PC/SC (winscard.h) provider.
interface SmartCardContextFactory {
  // Creates an Application Context to the PC/SC Resource Manager.
  CreateContext() => (SmartCardCreateContextResult result);
};