blob: 22b4c5619521baf4db1e64d777829ca1c3314396 [file] [log] [blame]
/*
*
* Copyright (c) 2020 Project CHIP Authors
*
* 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.
*/
/**
* @file
* Header that exposes the platform agnostic CHIP crypto primitives
*/
#ifndef _CHIP_CRYPTO_PAL_H_
#define _CHIP_CRYPTO_PAL_H_
#include <core/CHIPError.h>
#include <stddef.h>
#if CHIP_CRYPTO_OPENSSL
#include <openssl/sha.h>
#elif CHIP_CRYPTO_MBEDTLS
#include <mbedtls/sha256.h>
#endif
namespace chip {
namespace Crypto {
const size_t kMax_ECDSA_Signature_Length = 72;
const size_t kMax_ECDH_Secret_Length = 32;
const size_t kSHA256_Hash_Length = 32;
/**
* @brief A function that implements AES-CCM encryption
* @param plaintext Plaintext to encrypt
* @param plaintext_length Length of plain_text
* @param aad Additional authentication data
* @param aad_length Length of additional authentication data
* @param key Encryption key
* @param key_length Length of encryption key (in bytes)
* @param iv Initial vector
* @param iv_length Length of initial vector
* @param ciphertext Buffer to write ciphertext into. Caller must ensure this is large enough to hold the ciphertext
* @param tag Buffer to write tag into. Caller must ensure this is large enough to hold the tag
* @param tag_length Expected length of tag
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
* */
CHIP_ERROR AES_CCM_encrypt(const unsigned char * plaintext, size_t plaintext_length, const unsigned char * aad, size_t aad_length,
const unsigned char * key, size_t key_length, const unsigned char * iv, size_t iv_length,
unsigned char * ciphertext, unsigned char * tag, size_t tag_length);
/**
* @brief A function that implements AES-CCM decryption
* @param ciphertext Ciphertext to decrypt
* @param ciphertext_length Length of ciphertext
* @param aad Additional authentical data.
* @param aad_length Length of additional authentication data
* @param tag Tag to use to decrypt
* @param tag_length Length of tag
* @param key Decryption key
* @param key_length Length of Decryption key (in bytes)
* @param iv Initial vector
* @param iv_length Length of initial vector
* @param plaintext Buffer to write plaintext into
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR AES_CCM_decrypt(const unsigned char * ciphertext, size_t ciphertext_length, const unsigned char * aad, size_t aad_length,
const unsigned char * tag, size_t tag_length, const unsigned char * key, size_t key_length,
const unsigned char * iv, size_t iv_length, unsigned char * plaintext);
/**
* @brief A function that implements SHA-256 hash
* @param data The data to hash
* @param data_length Length of the data
* @param out_buffer Pointer to buffer to write output into
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR Hash_SHA256(const unsigned char * data, const size_t data_length, unsigned char * out_buffer);
/**
* @brief A class that defines stream based implementation of SHA-256 hash
**/
class Hash_SHA256_stream
{
public:
Hash_SHA256_stream(void);
~Hash_SHA256_stream(void);
CHIP_ERROR Begin(void);
CHIP_ERROR AddData(const unsigned char * data, const size_t data_length);
CHIP_ERROR Finish(unsigned char * out_buffer);
void Clear(void);
private:
#if CHIP_CRYPTO_OPENSSL
SHA256_CTX context;
#elif CHIP_CRYPTO_MBEDTLS
mbedtls_sha256_context context;
#else
SHA256_CTX_PLATFORM context; // To be defined by the platform specific implementation of sha256.
#endif
};
/**
* @brief A function that implements SHA-256 based HKDF
* @param secret The secret to use as the key to the HKDF
* @param secret_length Length of the secret
* @param salt Optional salt to use as input to the HKDF
* @param salt_length Length of the salt
* @param info Optional info to use as input to the HKDF
* @param info_length Length of the info
* @param out_buffer Pointer to buffer to write output into.
* @param out_length Resulting length of out_buffer
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR HKDF_SHA256(const unsigned char * secret, const size_t secret_length, const unsigned char * salt,
const size_t salt_length, const unsigned char * info, const size_t info_length, unsigned char * out_buffer,
size_t out_length);
/**
* @brief A cryptographically secure random number generator based on NIST SP800-90A
* @param out_buffer Buffer to write random bytes into
* @param out_length Number of random bytes to generate
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR DRBG_get_bytes(unsigned char * out_buffer, const size_t out_length);
/**
* @brief A function to sign a msg using ECDSA
* @param msg Message that needs to be signed
* @param msg_length Length of message
* @param private_key Key to use to sign the message. Private keys are ASN.1 DER encoded as padded big-endian field elements as
*described in SEC 1: Elliptic Curve Cryptography [https://www.secg.org/sec1-v2.pdf]
* @param private_key_length Length of private key
* @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s), represented
*as ASN.1 DER integers, plus the ASN.1 sequence Header
* @param out_signature_length Length of out buffer
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR ECDSA_sign_msg(const unsigned char * msg, const size_t msg_length, const unsigned char * private_key,
const size_t private_key_length, unsigned char * out_signature, size_t & out_signature_length);
/**
* @brief A function to sign a msg using ECDSA
* @param msg Message that needs to be signed
* @param msg_length Length of message
* @param public_key Key to use to verify the message signature. Public keys are ASN.1 DER encoded as uncompressed points as
*described in SEC 1: Elliptic Curve Cryptography [https://www.secg.org/sec1-v2.pdf]
* @param private_key_length Length of public key
* @param signature Signature to use for verification. The signature consists of: 2 EC elements (r and s), represented as ASN.1 DER
*integers, plus the ASN.1 sequence Header
* @param signature_length Length of signature
* @return Returns a CHIP_NO_ERROR on successful verification, a CHIP_ERROR otherwise
**/
CHIP_ERROR ECDSA_validate_msg_signature(const unsigned char * msg, const size_t msg_length, const unsigned char * public_key,
const size_t public_key_length, const unsigned char * signature,
const size_t signature_length);
/** @brief A function to derive a shared secret using ECDH
* @param remote_public_key Public key of remote peer with which we are trying to establish secure channel. remote_public_key is
*ASN.1 DER encoded as padded big-endian field elements as described in SEC 1: Elliptic Curve Cryptography
*[https://www.secg.org/sec1-v2.pdf]
* @param remote_public_key_length Length of remote_public_key
* @param local_private_key Local private key. local_private_key is ASN.1 DER encoded as padded big-endian field elements as
*described in SEC 1: Elliptic Curve Cryptography [https://www.secg.org/sec1-v2.pdf]
* @param local_private_key_length Length of private_key_length
* @param out_secret Buffer to write out secret into. This is a byte array representing the x coordinate of the shared secret.
* @param out_secret_length Length of out_secret
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR ECDH_derive_secret(const unsigned char * remote_public_key, const size_t remote_public_key_length,
const unsigned char * local_private_key, const size_t local_private_key_length,
unsigned char * out_secret, size_t & out_secret_length);
/** @brief Entropy callback function
* @param data Callback-specific data pointer
* @param output Output data to fill
* @param len Length of output buffer
* @param olen The actual amount of data that was written to output buffer
* @return 0 if success
*/
typedef int (*entropy_source)(void * data, unsigned char * output, size_t len, size_t * olen);
/** @brief A function to add entropy sources to crypto library
* @param fn_source Function pointer to the entropy source
* @param p_source Data that should be provided when fn_source is called
* @param threshold Minimum required from source before entropy is released
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold);
/** @brief Function to derive key using password. SHA256 hashing algorithm is used for calculating hmac.
* @param password password used for key derivation
* @param plen length of buffer containing password
* @param salt salt to use as input to the KDF
* @param slen length of salt
* @param iteration_count number of iterations to run
* @param key_length length of output key
* @param output output buffer where the key will be written
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR pbkdf2_sha256(const unsigned char * password, size_t plen, const unsigned char * salt, size_t slen,
unsigned int iteration_count, uint32_t key_length, unsigned char * output);
/** @brief Clears the first `len` bytes of memory area `buf`.
* @param buf Pointer to a memory buffer holding secret data that should be cleared.
* @param len Specifies secret data size in bytes.
* @return void
**/
void ClearSecretData(uint8_t * buf, uint32_t len);
} // namespace Crypto
} // namespace chip
#endif