chromium/ash/components/arc/mojom/keymint.mojom

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

// Next MinVersion: 3

// This file defines the mojo interface between Android and Chrome OS for the
// keymint implementation used in ARC.
module arc.mojom.keymint;

// Host is implemented in Chrome and called by arc-keymint-service (in ARC).
// Listens until server and instance come online and forwards a server handle to
// the instance.
interface KeyMintHost {
  // arc-keymint-service will call this to get an instance to KeyMintServer.
  GetServer@0() => (pending_remote<KeyMintServer>? server_remote);
};

// Instance is implemented in arc-keymint-service (in ARC) and called by Chrome
// (ConnectionHolderImpl).
interface KeyMintInstance {
  // As the first step to establish ARC-to-CrOS connection, between
  // arc-keymint-service and arc-keymintd, Chrome calls this to give a
  // KeyMintHost pending_remote to arc-keymint-service.
  Init@0(pending_remote<KeyMintHost> host_remote) => ();
};

// Server is implemented in arc-keymintd in ChromeOS, and called by
// arc-keymint-service (in ARC). This interface is the mojo equivalent of the
// IKeyMintDevice AIDL interface. Current version is based on v2 of KeyMint ALDL
// definitions.
// The documentation here is very brief and lacks important details. Please
// refer to Android's KeyMint AIDL files for a more detailed description on how
// the methods and structs below should function.
// https://cs.android.com/android/_/android/platform/hardware/interfaces/+/466f3c55a90631f5dd9a6fa949278a2a0a435b71:security/keymint/aidl/android/hardware/security/keymint/;bpv=1
// Next Method ID: 26
interface KeyMintServer {
  // Sets the Android version information used.
  SetSystemVersion@0(uint32 android_version, uint32 android_patchlevel);

  // Adds entropy to the Random Number Generator (RNG) used by Keymint.
  AddRngEntropy@1(array<uint8> data) => (int32 error);

  // Generates a new cryptographic key, specifying associated parameters, which
  // must be cryptographically bound to the key.
  GenerateKey@2(GenerateKeyRequest request)
      => (KeyCreationResultOrError response);

  // Imports key material into an IKeyMintDevice.
  ImportKey@3(ImportKeyRequest request)
      => (KeyCreationResultOrError response);

  // Securely imports a key, or key pair, returning a key blob and a description
  // of the imported key.
  ImportWrappedKey@4(ImportWrappedKeyRequest request)
      => (KeyCreationResultOrError response);

  // Upgrades an old key blob.
  UpgradeKey@5(UpgradeKeyRequest request) => (ByteArrayOrError response);

  // Deletes the key, or key pair, associated with the key blob.
  DeleteKey@6(array<uint8> key_blob) => (int32 error);

  // Deletes all keys in the hardware keystore. Used when keystore is reset
  // completely.
  DeleteAllKeys@7() => (int32 error);

  // Destroys knowledge of the device's ids.  This prevents all device id
  // attestation in the future.
  DestroyAttestationIds@8() => (int32 error);

  // Begins a cryptographic operation using the specified key. If all is well,
  // begin() must create an KeyMintOperation handle which will be used to
  // perform the cryptographic operation.
  Begin@9(BeginRequest request) => (BeginResultOrError response);

  // Called by client to notify the IKeyMintDevice that the device is now
  // locked, and keys with the UNLOCKED_DEVICE_REQUIRED tag should no longer be
  // usable.
  //
  // |password_only| specifies whether the device must be unlocked with a
  // password, rather than a biometric, before UNLOCKED_DEVICE_REQUIRED keys can
  // be used.
  //
  // |timestamp_token| is used by StrongBox implementations of IKeyMintDevice.
  DeviceLocked@10(bool password_only, TimeStampToken? timestamp_token)
      => (int32 error);

  // Called by client to notify the IKeyMintDevice that the device has left the
  // early boot state, and that keys with the EARLY_BOOT_ONLY tag may no longer
  // be used.
  EarlyBootEnded@11() => (int32 error);

  // Called by the client to get a wrapped per-boot ephemeral key from a wrapped
  // storage key. Clients will then use the returned per-boot ephemeral key in
  // place of the wrapped storage key. Whenever the hardware is presented with a
  // per-boot ephemeral key for an operation, it must use the storage key
  // associated with that ephemeral key to perform the requested operation.
  //
  // |storage_key_blob| is the wrapped storage key, for which the client wants a
  // per-boot ephemeral key.
  //
  // |ephemeral_key_blob| is the per-boot ephemeral keyblob that should
  // henceforth be used in place of the input |storage_key_blob|.
  ConvertStorageKeyToEphemeral@12(array<uint8> storage_key_blob)
      => (ByteArrayOrError response);

  // Returns KeyMint-enforced parameters associated with the provided key.
  //
  // |key_characteristics| is the characteristics of the generated key.
  GetKeyCharacteristics@13(GetKeyCharacteristicsRequest request)
      => (KeyCharacteristicsArrayOrError response);

  // Returns a 16-byte random challenge nonce, used to prove freshness when
  // exchanging root of trust data. This method may only be implemented by
  // StrongBox KeyMint. TEE KeyMint implementations must return error.
  GetRootOfTrustChallenge@14() => (ByteArrayOrError response);

  // Returns the TEE KeyMint Root of Trust data. This method is required for TEE
  // KeyMint.  StrongBox KeyMint implementations MUST return error.
  GetRootOfTrust@15(array<uint8, 16> challenge)
      => (ByteArrayOrError response);

  // Delivers the TEE KeyMint Root of Trust data to StrongBox KeyMint.
  // The implementation must verify the MAC on the RootOfTrust data.  If it is
  // valid, and if this is the first time since reboot that StrongBox KeyMint
  // has received this data, it must store the RoT data for use in key
  // attestation requests.
  SendRootOfTrust@16(array<uint8> root_of_trust) => (int32 error);

  // KeyMint Operation methods.

  // Provides additional authentication data (AAD) to a cryptographic operation
  // begun with begin(), provided in the input argument.  This method only
  // applies to AEAD modes.  This method may be called multiple times, supplying
  // the AAD in chunks, but may not be called after update() is called.
  UpdateAad@17(UpdateRequest request) => (int32 error);

  // Provides data to, and possibly receives output from, an ongoing
  // cryptographic operation begun with begin().
  Update@18(UpdateRequest request) => (ByteArrayOrError response);

  // Finalizes a cryptographic operation begun with begin() and invalidates the
  // operation.
  Finish@19(FinishRequest request) => (ByteArrayOrError response);

  // Aborts this cryptographic operation.
  // |op_handle| is the handle of the operation to abort.
  Abort@20(uint64 op_handle) => (int32 error);

  // Gets the secret parameters which are used in the process of agreeing on a
  // shared key. Called by Android during startup.
  GetSharedSecretParameters@21() => (SharedSecretParametersOrError response);

  // Final step in the process of agreeing on a shared key. Called by Android
  // during startup.
  ComputeSharedSecret@22(array<SharedSecretParameters> secret_params)
      => (ByteArrayOrError response);

  // Generates an authenticated timestamp for ISecureClock.
  GenerateTimeStamp@23(uint64 challenge) => (TimeStampTokenOrError response);

  // Generates a new ECDSA P-256 key pair that can be attested by the remote
  // server.
  // |test_mode| indicates whether the returned public key should be marked
  // as such for testing in order to differentiate them from private keys.
  // If |test_mode| is accidentally set with production keys, an error is
  // returned. Similarly, an error is returned if test keys are being used
  // with |test_mode| set to false.
  [MinVersion=1]
  GenerateEcdsaP256KeyPair@24(bool test_mode)
      => (GenerateEcdsaP256KeyPairResultOrError response);

  // Creates a certificate request to be sent to Android Provisioning Server.
  // This is the V1 method for GenerateCertificateRequest. V2 method applies
  // from Android 14.
  [MinVersion=2]
  GenerateCertificateRequest@25(CertificateRequest request)
      => (GenerateCertificateRequestResultOrError response);
};

struct AttestationKey {
  array<uint8> key_blob;
  array<KeyParameter> attest_key_params;
  array<uint8> issuer_subject_name;
};

[Extensible]
enum KeyFormat {
  [Default] UNKNOWN = -1,
  X509 = 0,  // for public key export
  PKCS8 = 1,  // for asymmetric key pair import
  RAW = 3,  // for symmetric key import and export
};

// Identifies the key authorization parameters to be used with KeyMint.
struct KeyParameter {
  // |tag| specifies which kind of data is stored in |value|.
  Tag tag = INVALID;
  KeyParameterValue value;
};

union KeyParameterValue {
  // Represent an invalid value type.
  uint32 invalid;

  Algorithm algorithm;
  BlockMode block_mode;
  PaddingMode padding_mode;
  Digest digest;
  EcCurve ec_curve;
  KeyOrigin origin;
  KeyPurpose key_purpose;
  HardwareAuthenticatorType hardware_authenticator_type;
  SecurityLevel security_level;

  // Always true, if present.
  bool bool_value;
  uint32 integer;
  uint64 long_integer;
  // In milliseconds from epoch.
  uint64 date_time;
  array<uint8> blob;
};

// Enables agreement on a shared key.
struct SharedSecretParameters {
  // |seed| and |nonce| are used in the generation of Shared Secret Parameters.
  array<uint8> seed;
  array<uint8> nonce;
};

// This structure is returned when a new key is created with generateKey(),
// importKey() or importWrappedKey().
struct KeyCreationResult {
  // A descriptor of the generated/imported key.
  array<uint8> key_blob;
  // A description of the generated key in the form of authorization lists
  // associated with security levels.
  array<KeyCharacteristics> key_characteristics;
  // If the generated/imported key is an asymmetric key, `certificateChain` will
  // contain a chain of one or more certificates.
  array<Certificate> certificate_chain;
};

struct Certificate {
  array<uint8> encoded_certificate;
};

struct KeyCharacteristics {
  SecurityLevel security_level = SOFTWARE;
  array<KeyParameter> authorizations;
};

// Parameters for generating a new key.
struct GenerateKeyRequest {
  // Key generation parameters.
  array<KeyParameter> key_params;
  // |attestation_key|, if provided, specifies the key that must be used to sign
  // the attestation certificate.
  AttestationKey? attestation_key;
};

// Parameters for importing a key.
struct ImportKeyRequest {
  // Key generation parameters.
  array<KeyParameter> key_params;
  // Format of the key material to import.
  KeyFormat key_format;
  // The key material to import.
  array<uint8> key_data;
  // |attestation_key| if provided, specifies the key that must be used to sign
  // the attestation certificate.
  AttestationKey? attestation_key;
};

struct ImportWrappedKeyRequest {
  // The wrapped key material to import, as ASN.1 DER-encoded data.
  array<uint8> wrapped_key_data;
  // The opaque key descriptor returned by generateKey() or importKey().
  array<uint8> wrapping_key_blob;
  // The 32-byte value XOR'd with the transport key in the SecureWrappedKey
  // structure.
  array<uint8> masking_key;
  // It must contain any parameters needed to perform the unwrapping operation.
  array<KeyParameter> unwrapping_params;
  // Specifies the password secure ID (SID) of the user that owns the key being
  // installed.
  uint64 password_sid;
  // Specifies the biometric secure ID (SID) of the user that owns the key being
  // installed.
  uint64 biometric_sid;
};

struct UpgradeKeyRequest {
  // The opaque descriptor returned by generateKey() or importKey().
  array<uint8> key_blob_to_upgrade;
  // A parameter list containing any parameters needed to complete the upgrade.
  array<KeyParameter> upgrade_params;
};

struct BeginRequest {
  // The purpose of the operation.
  KeyPurpose key_purpose;
  // The opaque key descriptor returned by generateKey() or importKey().
  array<uint8> key_blob;
  // Additional parameters for the operation.
  array<KeyParameter> params;
  // Authentication token.
  HardwareAuthToken? auth_token;
};

struct BeginResult {
  // This is the challenge used to verify authorization of an operation.
  uint64 challenge;
  // begin() uses this field to return additional data from the operation
  // initialization, notably to return the IV or nonce from operations that
  // generate an IV or nonce.
  array<KeyParameter> params;
  // Operation handle which is used to perform updateAad(), update(), finish()
  // or abort() operations.
  uint64 op_handle;
};

struct HardwareAuthToken {
  // It is a value that's used to enable authentication tokens to authorize
  // specific events.
  uint64 challenge;
  uint64 user_id;
  // It is a "secure" user ID.
  uint64 authenticator_id;
  // It describes the type of authentication that took place, e.g. password or
  // fingerprint.
  HardwareAuthenticatorType authenticator_type = NONE;
  // It indicates when the user authentication took place, in milliseconds since
  // some starting point (generally the most recent device boot) which all of
  // the applications within one secure environment must agree upon.
  Timestamp timestamp;
  array<uint8> mac;
};

struct Timestamp {
  // Time in milliseconds since some arbitrary point in time.
  uint64 milli_seconds;
};

struct TimeStampToken {
  // The challenge that was provided as argument to
  // ISecureClock.generateTimeStamp by the client.
  uint64 challenge;
  // The current time of the secure environment that generates the
  // TimeStampToken.
  Timestamp timestamp;
  // 32-byte HMAC-SHA256 of the above values.
  array<uint8> mac;
};

struct GetKeyCharacteristicsRequest {
  // The opaque descriptor returned by generateKey, importKey or
  // importWrappedKey.
  array<uint8> key_blob;
  // An opaque byte string identifying the client. This value must match the
  // Tag::APPLICATION_ID data provided during key generation/import.
  array<uint8> app_id;
  // An opaque byte string provided by the application.  This value must match
  // the Tag::APPLICATION_DATA data provided during key generation/import.
  array<uint8> app_data;
};

struct UpdateRequest {
  // Operation handle.
  uint64 op_handle;
  // Data to be processed.  update() must consume all input data.
  array<uint8> input;
  // Authentication token. It is optional.
  HardwareAuthToken? auth_token;
  // |timestamp_token| certifies the freshness of an auth token in case the
  // security domain of this KeyMint instance has a different clock than the
  // authenticator issuing the auth token.
  TimeStampToken? timestamp_token;
};

struct FinishRequest {
  // Operation handle.
  uint64 op_handle;
  // Data to be processed, per the parameters established in the call to
  // begin(). finish() must consume all provided data or return
  array<uint8>? input;
  // The signature to be verified if the purpose specified in the begin() call
  // was KeyPurpose.VERIFY.
  array<uint8>? signature;
  // Optional authentication token.
  HardwareAuthToken? auth_token;
  // |timestamp_token| certifies the freshness of an auth token in case the
  // security domain of this KeyMint instance has a different clock than the
  // authenticator issuing the auth token.
  TimeStampToken? timestamp_token;
  // |confirmation_token| is the confirmation token required by keys with
  // Tag.TRUSTED_CONFIRMATION_REQUIRED.
  array<uint8>? confirmation_token;
};

// Remote Provisioning Component Structs - from here.
// Blob Structs for Remote Provisioning Component are using array of bytes
// since the AIDL interface between Keystore and Android KeyMint HAL is defined
// in such a way.
struct KeyMintKeyBlob {
  array<uint8> key_material;
};

struct KeyMintBlob {
  array<uint8> data;
};

struct GenerateEcdsaP256KeyPairResult {
  KeyMintBlob maced_public_key;
  KeyMintKeyBlob handle_to_private_key;
};

union GenerateEcdsaP256KeyPairResultOrError {
  GenerateEcdsaP256KeyPairResult key_pair_result;
  int32 error;
};

struct CertificateRequest {
  // |test_mode| indicates whether the generated certificate request is
  // for testing only.
  // If |test_mode| is accidentally set with production keys, an error is
  // returned. Similarly, an error is returned if test keys are being used
  // with |test_mode| set to false.
  bool test_mode;
  // Set of keys to certify. The IRemotelyProvisionedComponent will
  // validate the MACs on each key.
  array<KeyMintBlob> keys_to_sign;
  // Contains public key used to encypt the BCC.
  KeyMintBlob encryption_cert_chain;
  // Contains a byte string from the provisioning server.
  KeyMintBlob challenge;
};

struct GenerateCertificateRequestResult {
  KeyMintBlob device_info;
  KeyMintBlob protected_data;
  KeyMintBlob mac_of_keys_to_sign;
};

union GenerateCertificateRequestResultOrError {
  GenerateCertificateRequestResult certificate_request_result;
  int32 error;
};

// Remote Provisioning Component Structs - till here.
union KeyCharacteristicsArrayOrError {
  array<KeyCharacteristics> key_characteristics;
  int32 error;
};

union BeginResultOrError {
  BeginResult begin_result;
  int32 error;
};

// Used for Key Creation methods.
union KeyCreationResultOrError {
  KeyCreationResult key_creation_result;
  int32 error;
};

// Result used for Array outputs.
union ByteArrayOrError {
  array<uint8> output;
  int32 error;
};

// Result used for GetSharedSecretParameters.
union SharedSecretParametersOrError {
  SharedSecretParameters secret_parameters;
  int32 error;
};

union TimeStampTokenOrError {
  TimeStampToken timestamp_token;
  int32 error;
};

// String used as label in the shared key derivation.
const string shared_secret_key_agreement_label = "KeymasterSharedMac";

// String used as context in the computation of the sharingCheck.
const string shared_secret_key_check_label = "Keymaster HMAC Verification";

// String used as context in the HMAC computation signing the generated time
// stamp.
const string secure_clock_time_stamp_mac_label = "Auth Verification";

[Extensible]
enum Algorithm {
  [Default] UNKNOWN = -1,
  RSA = 1,
  EC = 3,
  AES = 32,
  TRIPLE_DES = 33,
  HMAC = 128,
};

[Extensible]
enum BlockMode {
  [Default] UNKNOWN = -1,
  ECB = 1,
  CBC = 2,
  CTR = 3,
  GCM = 32,
};

[Extensible]
enum PaddingMode {
  [Default] UNKNOWN = -1,
  NONE = 1,
  RSA_OAEP = 2,
  RSA_PSS = 3,
  RSA_PKCS1_1_5_ENCRYPT = 4,
  RSA_PKCS1_1_5_SIGN = 5,
  PKCS7 = 64,
};

[Extensible]
enum Digest {
  [Default] UNKNOWN = -1,
  NONE = 0,
  MD5 = 1,
  SHA1 = 2,
  SHA_2_224 = 3,
  SHA_2_256 = 4,
  SHA_2_384 = 5,
  SHA_2_512 = 6,
};

[Extensible]
enum EcCurve {
  [Default] UNKNOWN = -1,
  P_224 = 0,
  P_256 = 1,
  P_384 = 2,
  P_521 = 3,
  CURVE_25519 = 4,
};

[Extensible]
enum KeyOrigin {
  [Default] UNKNOWN = -1,
  GENERATED = 0,
  DERIVED = 1,
  IMPORTED = 2,
  RESERVED = 3,
  SECURELY_IMPORTED = 4,
};

[Extensible]
enum KeyPurpose {
  [Default] UNKNOWN = -1,
  ENCRYPT = 0,
  DECRYPT = 1,
  SIGN = 2,
  VERIFY = 3,
  WRAP_KEY = 5,
  AGREE_KEY = 6,
  ATTEST_KEY = 7,
};

[Extensible]
enum HardwareAuthenticatorType {
  // Normal entries must be power of 2, thus invalid value is not power of 2.
  [Default] UNKNOWN = 0xff00,
  NONE = 0,
  PASSWORD = 1,
  FINGERPRINT = 2,
  ANY = -1,
};

[Extensible]
enum SecurityLevel {
  [Default] UNKNOWN = -1,
  SOFTWARE = 0,
  TRUSTED_ENVIRONMENT = 1,
  STRONGBOX = 2,
  KEYSTORE = 100,
};

// Refer to Tag.aidl for detailed description of the values.
[Extensible]
enum Tag {
  [Default] INVALID = 0,
  PURPOSE = 536870913,
  ALGORITHM = 268435458,
  KEY_SIZE = 805306371,
  BLOCK_MODE = 536870916,
  DIGEST = 536870917,
  PADDING = 536870918,
  CALLER_NONCE = 1879048199,
  MIN_MAC_LENGTH = 805306376,
  EC_CURVE = 268435466,
  RSA_PUBLIC_EXPONENT = 1342177480,
  INCLUDE_UNIQUE_ID = 1879048394,
  RSA_OAEP_MGF_DIGEST = 536871115,
  BOOTLOADER_ONLY = 1879048494,
  ROLLBACK_RESISTANCE = 1879048495,
  HARDWARE_TYPE = 268435760,
  EARLY_BOOT_ONLY = 1879048497,
  ACTIVE_DATETIME = 1610613136,
  ORIGINATION_EXPIRE_DATETIME = 1610613137,
  USAGE_EXPIRE_DATETIME = 1610613138,
  MIN_SECONDS_BETWEEN_OPS = 805306771,
  MAX_USES_PER_BOOT = 805306772,
  USAGE_COUNT_LIMIT = 805306773,
  USER_ID = 805306869,
  USER_SECURE_ID = -1610612234,
  NO_AUTH_REQUIRED = 1879048695,
  USER_AUTH_TYPE = 268435960,
  AUTH_TIMEOUT = 805306873,
  ALLOW_WHILE_ON_BODY = 1879048698,
  TRUSTED_USER_PRESENCE_REQUIRED = 1879048699,
  TRUSTED_CONFIRMATION_REQUIRED = 1879048700,
  UNLOCKED_DEVICE_REQUIRED = 1879048701,
  APPLICATION_ID = -1879047591,
  APPLICATION_DATA = -1879047492,
  CREATION_DATETIME = 1610613437,
  ORIGIN = 268436158,
  ROOT_OF_TRUST = -1879047488,
  OS_VERSION = 805307073,
  OS_PATCHLEVEL = 805307074,
  UNIQUE_ID = -1879047485,
  ATTESTATION_CHALLENGE = -1879047484,
  ATTESTATION_APPLICATION_ID = -1879047483,
  ATTESTATION_ID_BRAND = -1879047482,
  ATTESTATION_ID_DEVICE = -1879047481,
  ATTESTATION_ID_PRODUCT = -1879047480,
  ATTESTATION_ID_SERIAL = -1879047479,
  ATTESTATION_ID_IMEI = -1879047478,
  ATTESTATION_ID_MEID = -1879047477,
  ATTESTATION_ID_MANUFACTURER = -1879047476,
  ATTESTATION_ID_MODEL = -1879047475,
  VENDOR_PATCHLEVEL = 805307086,
  BOOT_PATCHLEVEL = 805307087,
  DEVICE_UNIQUE_ATTESTATION = 1879048912,
  IDENTITY_CREDENTIAL_KEY = 1879048913,
  STORAGE_KEY = 1879048914,
  ASSOCIATED_DATA = -1879047192,
  NONCE = -1879047191,
  MAC_LENGTH = 805307371,
  RESET_SINCE_ID_ROTATION = 1879049196,
  CONFIRMATION_TOKEN = -1879047187,
  CERTIFICATE_SERIAL = -2147482642,
  CERTIFICATE_SUBJECT = -1879047185,
  CERTIFICATE_NOT_BEFORE = 1610613744,
  CERTIFICATE_NOT_AFTER = 1610613745,
  MAX_BOOT_LEVEL = 805307378,
};