123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- /**
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0.
- */
- #include <aws/cal/private/symmetric_cipher_priv.h>
- #include <aws/cal/symmetric_cipher.h>
- #include <aws/common/device_random.h>
- #ifndef BYO_CRYPTO
- extern struct aws_symmetric_cipher *aws_aes_cbc_256_new_impl(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *key,
- const struct aws_byte_cursor *iv);
- extern struct aws_symmetric_cipher *aws_aes_ctr_256_new_impl(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *key,
- const struct aws_byte_cursor *iv);
- extern struct aws_symmetric_cipher *aws_aes_gcm_256_new_impl(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *key,
- const struct aws_byte_cursor *iv,
- const struct aws_byte_cursor *aad,
- const struct aws_byte_cursor *decryption_tag);
- extern struct aws_symmetric_cipher *aws_aes_keywrap_256_new_impl(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *key);
- #else /* BYO_CRYPTO */
- struct aws_symmetric_cipher *aws_aes_cbc_256_new_impl(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *key,
- const struct aws_byte_cursor *iv) {
- (void)allocator;
- (void)key;
- (void)iv;
- abort();
- }
- struct aws_symmetric_cipher *aws_aes_ctr_256_new_impl(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *key,
- const struct aws_byte_cursor *iv) {
- (void)allocator;
- (void)key;
- (void)iv;
- abort();
- }
- struct aws_symmetric_cipher *aws_aes_gcm_256_new_impl(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *key,
- const struct aws_byte_cursor *iv,
- const struct aws_byte_cursor *aad,
- const struct aws_byte_cursor *decryption_tag) {
- (void)allocator;
- (void)key;
- (void)iv;
- (void)aad;
- (void)decryption_tag;
- abort();
- }
- struct aws_symmetric_cipher *aws_aes_keywrap_256_new_impl(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *key) {
- (void)allocator;
- (void)key;
- abort();
- }
- #endif /* BYO_CRYPTO */
- static aws_aes_cbc_256_new_fn *s_aes_cbc_new_fn = aws_aes_cbc_256_new_impl;
- static aws_aes_ctr_256_new_fn *s_aes_ctr_new_fn = aws_aes_ctr_256_new_impl;
- static aws_aes_gcm_256_new_fn *s_aes_gcm_new_fn = aws_aes_gcm_256_new_impl;
- static aws_aes_keywrap_256_new_fn *s_aes_keywrap_new_fn = aws_aes_keywrap_256_new_impl;
- static int s_check_input_size_limits(const struct aws_symmetric_cipher *cipher, const struct aws_byte_cursor *input) {
- /* libcrypto uses int, not size_t, so this is the limit.
- * For simplicity, enforce the same rules on all platforms. */
- return input->len <= INT_MAX - cipher->block_size ? AWS_OP_SUCCESS
- : aws_raise_error(AWS_ERROR_CAL_BUFFER_TOO_LARGE_FOR_ALGORITHM);
- }
- static int s_validate_key_materials(
- const struct aws_byte_cursor *key,
- size_t expected_key_size,
- const struct aws_byte_cursor *iv,
- size_t expected_iv_size) {
- if (key && key->len != expected_key_size) {
- return aws_raise_error(AWS_ERROR_CAL_INVALID_KEY_LENGTH_FOR_ALGORITHM);
- }
- if (iv && iv->len != expected_iv_size) {
- return aws_raise_error(AWS_ERROR_CAL_INVALID_CIPHER_MATERIAL_SIZE_FOR_ALGORITHM);
- }
- return AWS_OP_SUCCESS;
- }
- struct aws_symmetric_cipher *aws_aes_cbc_256_new(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *key,
- const struct aws_byte_cursor *iv) {
- if (s_validate_key_materials(key, AWS_AES_256_KEY_BYTE_LEN, iv, AWS_AES_256_CIPHER_BLOCK_SIZE) != AWS_OP_SUCCESS) {
- return NULL;
- }
- return s_aes_cbc_new_fn(allocator, key, iv);
- }
- struct aws_symmetric_cipher *aws_aes_ctr_256_new(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *key,
- const struct aws_byte_cursor *iv) {
- if (s_validate_key_materials(key, AWS_AES_256_KEY_BYTE_LEN, iv, AWS_AES_256_CIPHER_BLOCK_SIZE) != AWS_OP_SUCCESS) {
- return NULL;
- }
- return s_aes_ctr_new_fn(allocator, key, iv);
- }
- struct aws_symmetric_cipher *aws_aes_gcm_256_new(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *key,
- const struct aws_byte_cursor *iv,
- const struct aws_byte_cursor *aad,
- const struct aws_byte_cursor *decryption_tag) {
- if (s_validate_key_materials(key, AWS_AES_256_KEY_BYTE_LEN, iv, AWS_AES_256_CIPHER_BLOCK_SIZE - sizeof(uint32_t)) !=
- AWS_OP_SUCCESS) {
- return NULL;
- }
- return s_aes_gcm_new_fn(allocator, key, iv, aad, decryption_tag);
- }
- struct aws_symmetric_cipher *aws_aes_keywrap_256_new(
- struct aws_allocator *allocator,
- const struct aws_byte_cursor *key) {
- if (s_validate_key_materials(key, AWS_AES_256_KEY_BYTE_LEN, NULL, 0) != AWS_OP_SUCCESS) {
- return NULL;
- }
- return s_aes_keywrap_new_fn(allocator, key);
- }
- void aws_symmetric_cipher_destroy(struct aws_symmetric_cipher *cipher) {
- if (cipher) {
- cipher->vtable->destroy(cipher);
- }
- }
- int aws_symmetric_cipher_encrypt(
- struct aws_symmetric_cipher *cipher,
- struct aws_byte_cursor to_encrypt,
- struct aws_byte_buf *out) {
- if (AWS_UNLIKELY(s_check_input_size_limits(cipher, &to_encrypt) != AWS_OP_SUCCESS)) {
- return AWS_OP_ERR;
- }
- if (cipher->good) {
- return cipher->vtable->encrypt(cipher, to_encrypt, out);
- }
- return aws_raise_error(AWS_ERROR_INVALID_STATE);
- }
- int aws_symmetric_cipher_decrypt(
- struct aws_symmetric_cipher *cipher,
- struct aws_byte_cursor to_decrypt,
- struct aws_byte_buf *out) {
- if (AWS_UNLIKELY(s_check_input_size_limits(cipher, &to_decrypt) != AWS_OP_SUCCESS)) {
- return AWS_OP_ERR;
- }
- if (cipher->good) {
- return cipher->vtable->decrypt(cipher, to_decrypt, out);
- }
- return aws_raise_error(AWS_ERROR_INVALID_STATE);
- }
- int aws_symmetric_cipher_finalize_encryption(struct aws_symmetric_cipher *cipher, struct aws_byte_buf *out) {
- if (cipher->good) {
- int ret_val = cipher->vtable->finalize_encryption(cipher, out);
- cipher->good = false;
- return ret_val;
- }
- return aws_raise_error(AWS_ERROR_INVALID_STATE);
- }
- int aws_symmetric_cipher_finalize_decryption(struct aws_symmetric_cipher *cipher, struct aws_byte_buf *out) {
- if (cipher->good) {
- int ret_val = cipher->vtable->finalize_decryption(cipher, out);
- cipher->good = false;
- return ret_val;
- }
- return aws_raise_error(AWS_ERROR_INVALID_STATE);
- }
- int aws_symmetric_cipher_reset(struct aws_symmetric_cipher *cipher) {
- int ret_val = cipher->vtable->reset(cipher);
- if (ret_val == AWS_OP_SUCCESS) {
- cipher->good = true;
- }
- return ret_val;
- }
- struct aws_byte_cursor aws_symmetric_cipher_get_tag(const struct aws_symmetric_cipher *cipher) {
- return aws_byte_cursor_from_buf(&cipher->tag);
- }
- struct aws_byte_cursor aws_symmetric_cipher_get_initialization_vector(const struct aws_symmetric_cipher *cipher) {
- return aws_byte_cursor_from_buf(&cipher->iv);
- }
- struct aws_byte_cursor aws_symmetric_cipher_get_key(const struct aws_symmetric_cipher *cipher) {
- return aws_byte_cursor_from_buf(&cipher->key);
- }
- bool aws_symmetric_cipher_is_good(const struct aws_symmetric_cipher *cipher) {
- return cipher->good;
- }
- void aws_symmetric_cipher_generate_initialization_vector(
- size_t len_bytes,
- bool is_counter_mode,
- struct aws_byte_buf *out) {
- size_t counter_len = is_counter_mode ? sizeof(uint32_t) : 0;
- AWS_ASSERT(len_bytes > counter_len);
- size_t rand_len = len_bytes - counter_len;
- AWS_FATAL_ASSERT(aws_device_random_buffer_append(out, rand_len) == AWS_OP_SUCCESS);
- if (is_counter_mode) {
- /* put counter at the end, initialized to 1 */
- aws_byte_buf_write_be32(out, 1);
- }
- }
- void aws_symmetric_cipher_generate_key(size_t key_len_bytes, struct aws_byte_buf *out) {
- AWS_FATAL_ASSERT(aws_device_random_buffer_append(out, key_len_bytes) == AWS_OP_SUCCESS);
- }
- int aws_symmetric_cipher_try_ensure_sufficient_buffer_space(struct aws_byte_buf *buf, size_t size) {
- if (buf->capacity - buf->len < size) {
- return aws_byte_buf_reserve_relative(buf, size);
- }
- return AWS_OP_SUCCESS;
- }
|