See https://developers.google.com/widevine/drm/client/opk for documentation and an integration guide. See CHANGELOG.md for details about recent changes.
288 lines
11 KiB
C
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_ */
|