Files
oemcrypto/oemcrypto/opk/oemcrypto_ta/wtpi/wtpi_crypto_asymmetric_interface.h
Fred Gylys-Colwell 684711a20f Second OPK Partner Beta v16 Release
See https://developers.google.com/widevine/drm/client/opk
for documentation and an integration guide.

See CHANGELOG.md for details about recent changes.
2022-02-25 12:02:41 -08:00

288 lines
11 KiB
C

/* Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
source code may only be used and distributed under the Widevine License
Agreement. */
#ifndef OEMCRYPTO_TA_WTPI_CRYPTO_ASYMMETRIC_INTERFACE_H_
#define OEMCRYPTO_TA_WTPI_CRYPTO_ASYMMETRIC_INTERFACE_H_
#include "OEMCryptoCENC.h"
#include "oemcrypto_key_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @defgroup asymmetric-crypto Asymmetric Cryptography
*
* This component handles loading decrypted asymmetric keys, using the keys to
* perform cryptographic operations, and wrapping the keys before saving to
* persistent storage.
*
* @{
*/
/**
* Forward declaration of a pointer to an implementation-specific struct holding
* all asymmetric key information.
*/
typedef struct tee_asymmetric_key_handle* WTPI_AsymmetricKey_Handle;
/**
* Creates a key handle from |input_length| bytes of |input| and the
* |key_type|, and places the result in |key_handle|.
*
* If the key type is DRM_RSA_PRIVATE_KEY, then |input| must be a DER-encoded
* PKCS8 RSA private key.
*
* If the key type is DRM_ECC_PRIVATE_KEY, then |input| must be a DER-encoded
* PKCS8 ECPrivateKey.
*
* Returns
* OEMCrypto_ERROR_INVALID_CONTEXT if any of the parameters are NULL or
* |input_length| is 0.
* OEMCrypto_ERROR_INVALID_RSA_KEY if |serialized_bytes| does not point
* to a valid private key of the specified |key_type| (ECC keys also return
* this error code TODO(b/201581141): Update with generic code).
* OEMCrypto_ERROR_UNKNOWN_FAILURE if there are any other failures/
* OEMCrypto_SUCCESS otherwise.
*
* Caller retains ownership of all parameters.
*
* @param[in] input: DER-encoded PKCS8 private key byte array
* @param[in] input_length: length of the input data
* @param[in] key_type: type of asymmetric key
* @param[out] key_handle: output key handle
*/
OEMCryptoResult WTPI_CreateAsymmetricKeyHandle(
const uint8_t* input, size_t input_length, AsymmetricKeyType key_type,
WTPI_AsymmetricKey_Handle* key_handle);
/**
* Creates a key handle from |input_length| bytes of |input| and the
* |key_type|, and places the result in |key_handle|.
*
* |*allowed_schemes| should be filled with the padding schemes that can be used
* with the key.
*
* Returns
* OEMCrypto_ERROR_INVALID_CONTEXT if any of the parameters are NULL or
* |input_length| is 0.
* OEMCrypto_ERROR_INVALID_RSA_KEY if |key_type| is DRM_PRIVATE_RSA_KEY
* and |serialized_bytes| is an invalid PKCS8 RSA private key; or if |key_type|
* DRM_ECC_PRIVATE_KEY and |serialized_bytes| is not a valid ECPrivateKey.
* OEMCrypto_ERROR_UNKNOWN_FAILURE if there are any other failures.
* OEMCrypto_SUCCESS otherwise.
*
* Caller retains ownership of all parameters.
*
* @param[in] input:
* @param[in] input_length:
* @param[in] key_type:
* @param[out] key_handle:
* @param[out] allowed_schemes:
*/
OEMCryptoResult WTPI_UnwrapIntoAsymmetricKeyHandle(
const uint8_t* input, size_t input_length, AsymmetricKeyType key_type,
WTPI_AsymmetricKey_Handle* key_handle, uint32_t* allowed_schemes);
/**
* Frees |key_handle| that was constructed from a previous call to
* WTPI_CreateAsymmetricKeyHandle.
*
* Returns
* OEMCrypto_ERROR_INVALID_CONTEXT if |key_handle| is NULL.
* OEMCrypto_ERROR_UNKNOWN_FAILURE if there are any other failures.
* OEMCrypto_SUCCESS otherwise.
*
* Caller retains ownership of all pointers.
*
* @param[in] key_handle: previously allocated key handle
*/
OEMCryptoResult WTPI_FreeAsymmetricKeyHandle(
WTPI_AsymmetricKey_Handle key_handle);
/**
* Calculates the buffer size needed to wrap the given private key. This is
* given the number of bytes in the encrypted private key.
*
* @param[in] enc_private_key_length: length of encrypted private key to be
* wrapped
* @param[in] key_type: type of asymmetric key
* @param[out] buffer_size: output result with required wrapping size
*/
OEMCryptoResult WTPI_GetWrappedAsymmetricKeySize(size_t enc_private_key_length,
AsymmetricKeyType key_type,
size_t* buffer_size);
// TODO(b/185149406): Consider using WTPI_AsymmetricKey_Handle instead to avoid
// passing clear keys around.
/**
* Wraps the key data into a buffer that can be saved to the file system. The
* wrapping must be device unique.
*
* Caller retains ownership of |clear_key| and |output| and they must
* not be NULL. Caller ensures that size is at least as big as the wrapped key
* size specified in WTPI_GetWrappedAsymmetricKeySize.
*
* This is given the clear, PKCS8-padded key and the key may be prefixed with
* "SIGN" and a 4-byte code for the padding schemes.
*
* @retval OEMCrypto_SUCCESS success
* @retval OEMCrypto_ERROR_INVALID_CONTEXT any of the pointers are NULL,
* |clear_key_length| is 0
* @retval OEMCrypto_ERROR_SHORT_BUFFER output_length is too small
* @retval OEMCrypto_ERROR_UNKNOWN_FAILURE otherwise
*
* @param[out] output: destination buffer that will contain the wrapped key data
* @param[in] output_length: length of destination buffer
* @param[in] key_type: type of asymmetric key
* @param[in] clear_key: DER-encoded PKCS8 RSA private key data with 8 bytes of
* prefix data or PKCS8 ECPrivateKey (no prefix data).
* @param[in] clear_key_length: length of input data
*/
OEMCryptoResult WTPI_WrapAsymmetricKey(uint8_t* output, size_t output_length,
AsymmetricKeyType key_type,
const uint8_t* clear_key,
size_t clear_key_length);
/**
* Sign |message_length| bytes of |message| with the given RSA key handle using
* the given |padding scheme| and place the result in |signature|.
* |key| is a handle to the RSA key used for signing.
*
* Returns
* OEMCrypto_ERROR_SHORT_BUFFER if |signature_length| is too small or if
* |signature| is NULL, in which case it sets |signature_length| to the
* appropriate length.
* OEMCrypto_ERROR_INVALID_CONTEXT if |message_length| is 0 or if any of the
* pointers except |signature| are NULL,
* OEMCrypto_ERROR_INVALID_RSA_KEY if the padding_scheme provided is not
* supported,
* OEMCrypto_ERROR_UNKNOWN_FAILURE if there are any other failures,
* OEMCrypto_SUCCESS otherwise.
*
* Caller retains ownership of all pointers.
*
* @param[in] key: handle with RSA key required to sign
* @param[in] message: input data to be signed
* @param[in] message_length: length of data to be signed
* @param[out] signature: destination buffer for output signature
* @param[in,out] signature_length: size of destination buffer
* @param[in] padding_scheme: RSA padding scheme used for signing
*/
OEMCryptoResult WTPI_RSASign(WTPI_AsymmetricKey_Handle key,
const uint8_t* message, size_t message_length,
uint8_t* signature, size_t* signature_length,
RSA_Padding_Scheme padding_scheme);
/**
* Decrypts |input_length| bytes of |input| and places it in |out|. The padding
* scheme shall only be PKCS1 OAEP. |key| is a handle to the RSA key used for
* decryption.
*
* Returns
* OEMCrypto_ERROR_INVALID_CONTEXT if any of the pointers are NULL or
* |input_length| is 0,
* OEMCrypto_ERROR_SHORT_BUFFER if |out_length| is too small, in which case it
* sets |out_length| to the appropriate length,
* OEMCrypto_ERROR_UNKNOWN_FAILURE if there are any other failures,
* OEMCrypto_SUCCESS otherwise.
*
* Caller retains ownership of all pointers.
*
* @param[in] key: handle with RSA key required to decrypt
* @param[in] input: input data to be decrypted
* @param[in] input_length: length of data to be decrypted
* @param[out] out: destination buffer for decrypted data
* @param[in,out] out_length: size of destination buffer
*/
OEMCryptoResult WTPI_RSADecrypt(WTPI_AsymmetricKey_Handle key,
const uint8_t* input, size_t input_length,
uint8_t* out, size_t* out_length);
/**
* Sign |message_length| bytes of |message| with the given ECC key handle using
* the ECDSA with a curve specific hashing algorithm and place the result in
* |signature|. |key| is a handle to the ECC key used for signing.
*
* Returns
* OEMCrypto_ERROR_SHORT_BUFFER if |signature_length| is too small or if
* |signature| is NULL, in which case it sets |signature_length| to the
* appropriate length.
* OEMCrypto_ERROR_INVALID_CONTEXT if |message_length| is 0 or if any of
* the pointers except |signature| are NULL.
* OEMCrypto_ERROR_UNKNOWN_FAILURE if there are any other failures.
* OEMCrypto_SUCCESS otherwise.
*
* Caller retains ownership of all pointers.
*
* @param[in] key: handle with ECC key, required for signing.
* @param[in] message: input data to be signed
* @param[in] message_length: length of input data in bytes
* @param[out] signature: destination buffer for signature
* @param[in,out] signature_length: size of |signature| buffer, may be
* modified based on used/required space of output.
*/
OEMCryptoResult WTPI_ECCSign(WTPI_AsymmetricKey_Handle key,
const uint8_t* message, size_t message_length,
uint8_t* signature, size_t* signature_length);
/**
* Derives the ECC-based session key using Widevine ECDH. The derived
* key is placed into |session_key|. This key is a AES-256 to be used
* as the key in the CMAC function used in the MAC and ENC key session
* processes.
*
* Returns
* OEMCrypto_ERROR_SHORT_BUFFER if |session_key_length| is too small or
* if |session_key| is NULL, in which case it sets |session_key_length|
* to the appropriate length.
* OEMCrypto_ERROR_INVALID_CONTEXT if |key_source_length| is 0 or if
* any of the pointers except |session_key| are NULL,
* OEMCrypto_ERROR_UNKNOWN_FAILURE if there are any other failures.
* OEMCrypto_SUCCESS otherwise.
*
* Caller retains ownership of all pointers.
*
* @param[in] key: handle with ECC key, required for derivation.
* @param[in] key_source: an ephemeral ECC public key used in ECDH.
* @param[in] key_source_length: length of |key_source|
* @param[out] session_key: destination buffer for derivated session key
* @param[in,out] session_key_length: size of |session_key| buffer, may
* be modified based on used/required space of output.
*/
OEMCryptoResult WTPI_ECCDeriveSessionKey(WTPI_AsymmetricKey_Handle key,
const uint8_t* key_source,
size_t key_source_length,
uint8_t* session_key,
size_t* session_key_length);
/**
* Gets the maximum RSA or ECC signature size from |key| and places the result
* in |signature_length|.
* Note, it is possible that the signature generate by this key be a few bytes
* shorter depending on the actual signature value.
*
* Returns
* OEMCrypto_ERROR_INVALID_CONTEXT if any of the pointers are NULL
* OEMCrypto_ERROR_UNKNOWN_FAILURE if there are any other failures
* OEMCrypto_SUCCESS otherwise
*
* Caller retains ownership of all pointers.
*
* @param[in] key: input key handle
* @param[out] signature_length: max size of the signature generated
* by |key|.
*/
OEMCryptoResult WTPI_GetSignatureSize(WTPI_AsymmetricKey_Handle key,
size_t* signature_length);
/// @}
#ifdef __cplusplus
}
#endif
#endif /* OEMCRYPTO_TA_WTPI_CRYPTO_ASYMMETRIC_INTERFACE_H_ */