/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.hardware.keymaster@3.0;

/**
 * Keymaster device definition.  For thorough documentation see the implementer's reference, at
 * https://source.android.com/security/keystore/implementer-ref.html
 */
@SensitiveData
interface IKeymasterDevice {

    /**
     * Returns information about the underlying keymaster hardware.
     *
     * @return isSecure is true if keys are stored and never leave secure hardware (Trusted
     *             Execution Environment or similar). CDD requires that all devices initially
     *             launched with Marshmallow or later must have secure hardware.
     *
     * @return supportsEllipticCurve is true if the hardware supports Elliptic Curve cryptography
     *             with the NIST curves (P-224, P-256, P-384, and P-521). CDD requires that all
     *             devices initially launched with Nougat or later must support Elliptic Curve
     *             cryptography.
     *
     * @return supportsSymmetricCryptography is true if the hardware supports symmetric
     *             cryptography, including AES and HMAC. CDD requires that all devices initially
     *             launched with Nougat or later must support hardware enforcement of Keymaster
     *             authorizations.
     *
     * @return supportsAttestation is true if the hardware supports generation of Keymaster public
     *             key attestation certificates, signed with a key injected in a secure
     *             environment. CDD requires that all devices initially launched with Android O or
     *             later must support hardware attestation.
     *
     * @return supportsAllDigests is true if the hardware supports all keymaster digest functions,
     *             namely ND-5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512. CDD requires that all
     *             devices launched initially with Android O or later must support all digests.
     *
     * @return keymasterName is the name of the keymaster implementation.
     *
     * @return keymasterAuthorName is the name of the author of the keymaster implementation
     *             (generally this should be the name of an organization, not an individual.)
     */
    getHardwareFeatures()
        generates(bool isSecure, bool supportsEllipticCurve, bool supportsSymmetricCryptography,
                  bool supportsAttestation, bool supportsAllDigests, string keymasterName,
                  string keymasterAuthorName);

    /**
     * Adds entropy to the RNG used by keymaster. Entropy added through this method is guaranteed
     * not to be the only source of entropy used, and the mixing function is required to be secure,
     * in the sense that if the RNG is seeded (from any source) with any data the attacker cannot
     * predict (or control), then the RNG output is indistinguishable from random. Thus, if the
     * entropy from any source is good, the output must be good.
     *
     * @param data Bytes to be mixed into the RNG.
     *
     * @return error See the ErrorCode enum in types.hal.
     */
    addRngEntropy(vec<uint8_t> data) generates(ErrorCode error);

    /**
     * Generates a key, or key pair, returning a key blob and/or a description of the key.
     *
     * @param keyParams Key generation parameters are defined as keymaster tag/value pairs, provided
     *             in params. See Tag in types.hal for the full list.
     *
     * @return error See the ErrorCode enum in types.hal.
     *
     * @return keyBlob Opaque, encrypted descriptor of the generated key, which generally contains a
     *             copy of the key material, wrapped in a key unavailable outside secure hardware.
     *
     * @return keyCharacteristics Description of the generated key.  See KeyCharacteristis in
     *             types.hal.
     */
    generateKey(vec<KeyParameter> keyParams)
        generates(ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);

    /**
     * Imports a key, or key pair, returning a key blob and/or a description of the key.
     *
     * @param keyParams Key generation parameters are defined as keymaster tag/value pairs, provided
     *             in params.  See Tag for the full list.
     *
     * @param keyFormat The format of the key material to import. See KeyFormat in types.hal.
     *
     * @pram keyData The key material to import, in the format specifed in keyFormat.
     *
     * @return error See the ErrorCode enum.
     *
     * @return keyBlob Opaque, encrypted descriptor of the generated key, which will generally
     *             contain a copy of the key material, wrapped in a key unavailable outside secure
     *             hardware.
     *
     * @return keyCharacteristics Decription of the generated key.  See KeyCharacteristis.
     *
     * @return error See the ErrorCode enum.
     */
    importKey(vec<KeyParameter> params, KeyFormat keyFormat, vec<uint8_t> keyData)
        generates(ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);

    /**
     * Returns the characteristics of the specified key, if the keyBlob is valid (implementations
     * must fully validate the integrity of the key).
     *
     * @param keyBlob The opaque descriptor returned by generateKey() or importKey();
     *
     * @param clientId An opaque byte string identifying the client. This value must match the
     *             Tag::APPLICATION_ID data provided during key generation/import.  Without the
     *             correct value it must be cryptographically impossible for the secure hardware to
     *             obtain the key material.
     *
     * @param appData An opaque byte string provided by the application. This value must match the
     *             Tag::APPLICATION_DATA data provided during key generation/import.  Without the
     *             correct value it must be cryptographically impossible for the secure hardware to
     *             obtain the key material.
     *
     * @return error See the ErrorCode enum in types.hal.
     *
     * @return keyCharacteristics Decription of the generated key.  See KeyCharacteristis in
     *             types.hal.
     */
    getKeyCharacteristics(vec<uint8_t> keyBlob, vec<uint8_t> clientId, vec<uint8_t> appData)
        generates(ErrorCode error, KeyCharacteristics keyCharacteristics);

    /**
     * Exports a public key, returning the key in the specified format.
     *
     * @parm keyFormat The format used for export. See KeyFormat in types.hal.
     *
     * @param keyBlob The opaque descriptor returned by generateKey() or importKey().  The
     *             referenced key must be asymmetric.
     *
     * @param clientId An opaque byte string identifying the client. This value must match the
     *             Tag::APPLICATION_ID data provided during key generation/import.  Without the
     *             correct value it must be cryptographically impossible for the secure hardware to
     *             obtain the key material.
     *
     * @param appData An opaque byte string provided by the application. This value must match the
     *             Tag::APPLICATION_DATA data provided during key generation/import.  Without the
     *             correct value it must be cryptographically impossible for the secure hardware to
     *             obtain the key material.
     *
     * @return error See the ErrorCode enum in types.hal.
     *
     * @return keyMaterial The public key material in PKCS#8 format.
     */
    exportKey(KeyFormat keyFormat, vec<uint8_t> keyBlob, vec<uint8_t> clientId,
              vec<uint8_t> appData) generates(ErrorCode error, vec<uint8_t> keyMaterial);

    /**
     * Generates a signed X.509 certificate chain attesting to the presence of keyToAttest in
     * keymaster. The certificate will contain an extension with OID 1.3.6.1.4.1.11129.2.1.17 and
     * value defined in:
     *
     *     https://developer.android.com/training/articles/security-key-attestation.html.
     *
     * @param keyToAttest The opaque descriptor returned by generateKey() or importKey().  The
     *             referenced key must be asymmetric.
     *
     * @param attestParams Parameters for the attestation, notably Tag::ATTESTATION_CHALLENGE.
     *
     * @return error See the ErrorCode enum in types.hal.
     */
    attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams)
        generates(ErrorCode error, vec<vec<uint8_t>> certChain);

    /**
     * Upgrades an old key. Keys can become "old" in two ways: Keymaster can be upgraded to a new
     * version, or the system can be updated to invalidate the OS version and/or patch level. In
     * either case, attempts to use an old key with getKeyCharacteristics(), exportKey(),
     * attestKey() or begin() will result in keymaster returning
     * ErrorCode::KEY_REQUIRES_UPGRADE. This method must then be called to upgrade the key.
     *
     * @param keyBlobToUpgrade The opaque descriptor returned by generateKey() or importKey();
     *
     * @param upgradeParams A parameter list containing any parameters needed to complete the
     *             upgrade, including Tag::APPLICATION_ID and Tag::APPLICATION_DATA.
     *
     * @return error See the ErrorCode enum.
     */
    upgradeKey(vec<uint8_t> keyBlobToUpgrade, vec<KeyParameter> upgradeParams)
        generates(ErrorCode error, vec<uint8_t> upgradedKeyBlob);

    /**
     * Deletes the key, or key pair, associated with the key blob. After calling this function it
     * will be impossible to use the key for any other operations. May be applied to keys from
     * foreign roots of trust (keys not usable under the current root of trust).
     *
     * This is a NOP for keys that don't have rollback protection.
     *
     * @param keyBlobToUpgrade The opaque descriptor returned by generateKey() or importKey();
     *
     * @return error See the ErrorCode enum.
     */
    deleteKey(vec<uint8_t> keyBlob) generates(ErrorCode error);

    /**
     * Deletes all keys in the hardware keystore. Used when keystore is reset completely. After
     * calling this function it will be impossible to use any previously generated or imported key
     * blobs for any operations.
     *
     * This is a NOP if keys don't have rollback protection.
     *
     * @return error See the ErrorCode enum.
     */
    deleteAllKeys() generates(ErrorCode error);

    /**
     * Destroys knowledge of the device's ids. This prevents all device id attestation in the
     * future. The destruction must be permanent so that not even a factory reset will restore the
     * device ids.
     *
     * Device id attestation may be provided only if this method is fully implemented, allowing the
     * user to permanently disable device id attestation. If this cannot be guaranteed, the device
     * must never attest any device ids.
     *
     * This is a NOP if device id attestation is not supported.
     *
     * @return error See the ErrorCode enum.
     */
    destroyAttestationIds() generates(ErrorCode error);

    /**
     * Begins a cryptographic operation using the specified key. If all is well, begin() will return
     * ErrorCode::OK and create an operation handle which must be passed to subsequent calls to
     * update(), finish() or abort().
     *
     * It is critical that each call to begin() be paired with a subsequent call to finish() or
     * abort(), to allow the keymaster implementation to clean up any internal operation state.
     * Failure to do this may leak internal state space or other internal resources and may
     * eventually cause begin() to return ErrorCode::TOO_MANY_OPERATIONS when it runs out of space
     * for operations. Any result other than ErrorCode::OK from begin(), update() or finish()
     * implicitly aborts the operation, in which case abort() need not be called (and will return
     * ErrorCode::INVALID_OPERATION_HANDLE if called).
     *
     * @param purpose The purpose of the operation, one of KeyPurpose::ENCRYPT, KeyPurpose::DECRYPT,
     *             KeyPurpose::SIGN or KeyPurpose::VERIFY. Note that for AEAD modes, encryption and
     *             decryption imply signing and verification, respectively, but must be specified as
     *             KeyPurpose::ENCRYPT and KeyPurpose::DECRYPT.
     *
     * @param keyBlob The opaque key descriptor returned by generateKey() or importKey().  The key
     *             must have a purpose compatible with purpose and all of its usage requirements
     *             must be satisfied, or begin() will return an appropriate error code.
     *
     * @param inParams Additional parameters for the operation. This is typically used to provide
     *             authentication data, with Tag::AUTH_TOKEN. If Tag::APPLICATION_ID or
     *             Tag::APPLICATION_DATA were provided during generation, they must be provided
     *             here, or the operation will fail with ErrorCode::INVALID_KEY_BLOB. For operations
     *             that require a nonce or IV, on keys that were generated with Tag::CALLER_NONCE,
     *             inParams may contain a tag Tag::NONCE.
     *
     * @return error See the ErrorCode enum in types.hal.
     *
     * @return outParams Output parameters. Used to return additional data from the operation
     *             initialization, notably to return the IV or nonce from operations that generate
     *             an IV or nonce.
     *
     * @return operationHandle The newly-created operation handle which must be passed to update(),
     *             finish() or abort().
     */
    begin(KeyPurpose purpose, vec<uint8_t> key, vec<KeyParameter> inParams)
        generates(ErrorCode error, vec<KeyParameter> outParams, OperationHandle operationHandle);

    /**
     * Provides data to, and possibly receives output from, an ongoing cryptographic operation begun
     * with begin().
     *
     * If operationHandle is invalid, update() will return ErrorCode::INVALID_OPERATION_HANDLE.
     *
     * update() may not consume all of the data provided in the data buffer. update() will return
     * the amount consumed in inputConsumed. The caller may provide the unconsumed data in a
     * subsequent call.
     *
     * @param operationHandle The operation handle returned by begin().
     *
     * @param inParams Additional parameters for the operation. For AEAD modes, this is used to
     *             specify Tag::ADDITIONAL_DATA. Note that additional data may be provided in
     *             multiple calls to update(), but only until input data has been provided.
     *
     * @param input Data to be processed, per the parameters established in the call to begin().
     *             Note that update() may or may not consume all of the data provided. See
     *             inputConsumed.
     *
     * @return error See the ErrorCode enum in types.hal.
     *
     * @return inputConsumed Amount of data that was consumed by update(). If this is less than the
     *             amount provided, the caller may provide the remainder in a subsequent call to
     *             update() or finish().
     *
     * @return outParams Output parameters, used to return additional data from the operation The
     *             caller takes ownership of the output parameters array and must free it with
     *             keymaster_free_param_set().
     *
     * @return output The output data, if any.
     */
    update(OperationHandle operationHandle, vec<KeyParameter> inParams, vec<uint8_t> input)
        generates(ErrorCode error, uint32_t inputConsumed, vec<KeyParameter> outParams,
                  vec<uint8_t> output);

    /**
     * Finalizes a cryptographic operation begun with begin() and invalidates operationHandle.
     *
     * @param operationHandle The operation handle returned by begin(). This handle will be
     *             invalid when finish() returns.
     *
     * @param inParams Additional parameters for the operation. For AEAD modes, this is used to
     *             specify Tag::ADDITIONAL_DATA, but only if no input data was provided to update().
     *
     * @param input Data to be processed, per the parameters established in the call to
     *             begin(). finish() must consume all provided data or return
     *             ErrorCode::INVALID_INPUT_LENGTH.
     *
     * @param signature The signature to be verified if the purpose specified in the begin() call
     *             was KeyPurpose::VERIFY.
     *
     * @return error See the ErrorCode enum in types.hal.
     *
     * @return outParams Any output parameters generated by finish().
     *
     * @return output The output data, if any.
     */
    finish(OperationHandle operationHandle, vec<KeyParameter> inParams, vec<uint8_t> input,
           vec<uint8_t> signature)
        generates(ErrorCode error, vec<KeyParameter> outParams, vec<uint8_t> output);

    /**
     * Aborts a cryptographic operation begun with begin(), freeing all internal resources and
     * invalidating operationHandle.
     *
     * @param operationHandle The operation handle returned by begin(). This handle will be
     *             invalid when abort() returns.
     *
     * @return error See the ErrorCode enum in types.hal.
     */
    abort(OperationHandle operationHandle) generates(ErrorCode error);
};
