1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 3a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 4a8e1175bSopenharmony_ci * 5a8e1175bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); you may 6a8e1175bSopenharmony_ci * not use this file except in compliance with the License. 7a8e1175bSopenharmony_ci * You may obtain a copy of the License at 8a8e1175bSopenharmony_ci * 9a8e1175bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 10a8e1175bSopenharmony_ci * 11a8e1175bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 12a8e1175bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13a8e1175bSopenharmony_ci * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14a8e1175bSopenharmony_ci * See the License for the specific language governing permissions and 15a8e1175bSopenharmony_ci * limitations under the License. 16a8e1175bSopenharmony_ci */ 17a8e1175bSopenharmony_ci 18a8e1175bSopenharmony_ci#include "psa/crypto.h" 19a8e1175bSopenharmony_ci#include <string.h> 20a8e1175bSopenharmony_ci#include <stdio.h> 21a8e1175bSopenharmony_ci#include <stdlib.h> 22a8e1175bSopenharmony_ci 23a8e1175bSopenharmony_ci#define ASSERT(predicate) \ 24a8e1175bSopenharmony_ci do \ 25a8e1175bSopenharmony_ci { \ 26a8e1175bSopenharmony_ci if (!(predicate)) \ 27a8e1175bSopenharmony_ci { \ 28a8e1175bSopenharmony_ci printf("\tassertion failed at %s:%d - '%s'\r\n", \ 29a8e1175bSopenharmony_ci __FILE__, __LINE__, #predicate); \ 30a8e1175bSopenharmony_ci goto exit; \ 31a8e1175bSopenharmony_ci } \ 32a8e1175bSopenharmony_ci } while (0) 33a8e1175bSopenharmony_ci 34a8e1175bSopenharmony_ci#define ASSERT_STATUS(actual, expected) \ 35a8e1175bSopenharmony_ci do \ 36a8e1175bSopenharmony_ci { \ 37a8e1175bSopenharmony_ci if ((actual) != (expected)) \ 38a8e1175bSopenharmony_ci { \ 39a8e1175bSopenharmony_ci printf("\tassertion failed at %s:%d - " \ 40a8e1175bSopenharmony_ci "actual:%d expected:%d\r\n", __FILE__, __LINE__, \ 41a8e1175bSopenharmony_ci (psa_status_t) actual, (psa_status_t) expected); \ 42a8e1175bSopenharmony_ci goto exit; \ 43a8e1175bSopenharmony_ci } \ 44a8e1175bSopenharmony_ci } while (0) 45a8e1175bSopenharmony_ci 46a8e1175bSopenharmony_ci#if !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(MBEDTLS_AES_C) || \ 47a8e1175bSopenharmony_ci !defined(MBEDTLS_CIPHER_MODE_CBC) || !defined(MBEDTLS_CIPHER_MODE_CTR) || \ 48a8e1175bSopenharmony_ci !defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) || \ 49a8e1175bSopenharmony_ci defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) 50a8e1175bSopenharmony_ciint main(void) 51a8e1175bSopenharmony_ci{ 52a8e1175bSopenharmony_ci printf("MBEDTLS_PSA_CRYPTO_C and/or MBEDTLS_AES_C and/or " 53a8e1175bSopenharmony_ci "MBEDTLS_CIPHER_MODE_CBC and/or MBEDTLS_CIPHER_MODE_CTR " 54a8e1175bSopenharmony_ci "and/or MBEDTLS_CIPHER_MODE_WITH_PADDING " 55a8e1175bSopenharmony_ci "not defined and/or MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER" 56a8e1175bSopenharmony_ci " defined.\r\n"); 57a8e1175bSopenharmony_ci return 0; 58a8e1175bSopenharmony_ci} 59a8e1175bSopenharmony_ci#else 60a8e1175bSopenharmony_ci 61a8e1175bSopenharmony_cistatic psa_status_t cipher_operation(psa_cipher_operation_t *operation, 62a8e1175bSopenharmony_ci const uint8_t *input, 63a8e1175bSopenharmony_ci size_t input_size, 64a8e1175bSopenharmony_ci size_t part_size, 65a8e1175bSopenharmony_ci uint8_t *output, 66a8e1175bSopenharmony_ci size_t output_size, 67a8e1175bSopenharmony_ci size_t *output_len) 68a8e1175bSopenharmony_ci{ 69a8e1175bSopenharmony_ci psa_status_t status; 70a8e1175bSopenharmony_ci size_t bytes_to_write = 0, bytes_written = 0, len = 0; 71a8e1175bSopenharmony_ci 72a8e1175bSopenharmony_ci *output_len = 0; 73a8e1175bSopenharmony_ci while (bytes_written != input_size) { 74a8e1175bSopenharmony_ci bytes_to_write = (input_size - bytes_written > part_size ? 75a8e1175bSopenharmony_ci part_size : 76a8e1175bSopenharmony_ci input_size - bytes_written); 77a8e1175bSopenharmony_ci 78a8e1175bSopenharmony_ci status = psa_cipher_update(operation, input + bytes_written, 79a8e1175bSopenharmony_ci bytes_to_write, output + *output_len, 80a8e1175bSopenharmony_ci output_size - *output_len, &len); 81a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 82a8e1175bSopenharmony_ci 83a8e1175bSopenharmony_ci bytes_written += bytes_to_write; 84a8e1175bSopenharmony_ci *output_len += len; 85a8e1175bSopenharmony_ci } 86a8e1175bSopenharmony_ci 87a8e1175bSopenharmony_ci status = psa_cipher_finish(operation, output + *output_len, 88a8e1175bSopenharmony_ci output_size - *output_len, &len); 89a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 90a8e1175bSopenharmony_ci *output_len += len; 91a8e1175bSopenharmony_ci 92a8e1175bSopenharmony_ciexit: 93a8e1175bSopenharmony_ci return status; 94a8e1175bSopenharmony_ci} 95a8e1175bSopenharmony_ci 96a8e1175bSopenharmony_cistatic psa_status_t cipher_encrypt(psa_key_id_t key, 97a8e1175bSopenharmony_ci psa_algorithm_t alg, 98a8e1175bSopenharmony_ci uint8_t *iv, 99a8e1175bSopenharmony_ci size_t iv_size, 100a8e1175bSopenharmony_ci const uint8_t *input, 101a8e1175bSopenharmony_ci size_t input_size, 102a8e1175bSopenharmony_ci size_t part_size, 103a8e1175bSopenharmony_ci uint8_t *output, 104a8e1175bSopenharmony_ci size_t output_size, 105a8e1175bSopenharmony_ci size_t *output_len) 106a8e1175bSopenharmony_ci{ 107a8e1175bSopenharmony_ci psa_status_t status; 108a8e1175bSopenharmony_ci psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; 109a8e1175bSopenharmony_ci size_t iv_len = 0; 110a8e1175bSopenharmony_ci 111a8e1175bSopenharmony_ci memset(&operation, 0, sizeof(operation)); 112a8e1175bSopenharmony_ci status = psa_cipher_encrypt_setup(&operation, key, alg); 113a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 114a8e1175bSopenharmony_ci 115a8e1175bSopenharmony_ci status = psa_cipher_generate_iv(&operation, iv, iv_size, &iv_len); 116a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 117a8e1175bSopenharmony_ci 118a8e1175bSopenharmony_ci status = cipher_operation(&operation, input, input_size, part_size, 119a8e1175bSopenharmony_ci output, output_size, output_len); 120a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 121a8e1175bSopenharmony_ci 122a8e1175bSopenharmony_ciexit: 123a8e1175bSopenharmony_ci psa_cipher_abort(&operation); 124a8e1175bSopenharmony_ci return status; 125a8e1175bSopenharmony_ci} 126a8e1175bSopenharmony_ci 127a8e1175bSopenharmony_cistatic psa_status_t cipher_decrypt(psa_key_id_t key, 128a8e1175bSopenharmony_ci psa_algorithm_t alg, 129a8e1175bSopenharmony_ci const uint8_t *iv, 130a8e1175bSopenharmony_ci size_t iv_size, 131a8e1175bSopenharmony_ci const uint8_t *input, 132a8e1175bSopenharmony_ci size_t input_size, 133a8e1175bSopenharmony_ci size_t part_size, 134a8e1175bSopenharmony_ci uint8_t *output, 135a8e1175bSopenharmony_ci size_t output_size, 136a8e1175bSopenharmony_ci size_t *output_len) 137a8e1175bSopenharmony_ci{ 138a8e1175bSopenharmony_ci psa_status_t status; 139a8e1175bSopenharmony_ci psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; 140a8e1175bSopenharmony_ci 141a8e1175bSopenharmony_ci memset(&operation, 0, sizeof(operation)); 142a8e1175bSopenharmony_ci status = psa_cipher_decrypt_setup(&operation, key, alg); 143a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 144a8e1175bSopenharmony_ci 145a8e1175bSopenharmony_ci status = psa_cipher_set_iv(&operation, iv, iv_size); 146a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 147a8e1175bSopenharmony_ci 148a8e1175bSopenharmony_ci status = cipher_operation(&operation, input, input_size, part_size, 149a8e1175bSopenharmony_ci output, output_size, output_len); 150a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 151a8e1175bSopenharmony_ci 152a8e1175bSopenharmony_ciexit: 153a8e1175bSopenharmony_ci psa_cipher_abort(&operation); 154a8e1175bSopenharmony_ci return status; 155a8e1175bSopenharmony_ci} 156a8e1175bSopenharmony_ci 157a8e1175bSopenharmony_cistatic psa_status_t 158a8e1175bSopenharmony_cicipher_example_encrypt_decrypt_aes_cbc_nopad_1_block(void) 159a8e1175bSopenharmony_ci{ 160a8e1175bSopenharmony_ci enum { 161a8e1175bSopenharmony_ci block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES), 162a8e1175bSopenharmony_ci key_bits = 256, 163a8e1175bSopenharmony_ci part_size = block_size, 164a8e1175bSopenharmony_ci }; 165a8e1175bSopenharmony_ci const psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING; 166a8e1175bSopenharmony_ci 167a8e1175bSopenharmony_ci psa_status_t status; 168a8e1175bSopenharmony_ci psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 169a8e1175bSopenharmony_ci psa_key_id_t key = 0; 170a8e1175bSopenharmony_ci size_t output_len = 0; 171a8e1175bSopenharmony_ci uint8_t iv[block_size]; 172a8e1175bSopenharmony_ci uint8_t input[block_size]; 173a8e1175bSopenharmony_ci uint8_t encrypt[block_size]; 174a8e1175bSopenharmony_ci uint8_t decrypt[block_size]; 175a8e1175bSopenharmony_ci 176a8e1175bSopenharmony_ci status = psa_generate_random(input, sizeof(input)); 177a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 178a8e1175bSopenharmony_ci 179a8e1175bSopenharmony_ci psa_set_key_usage_flags(&attributes, 180a8e1175bSopenharmony_ci PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); 181a8e1175bSopenharmony_ci psa_set_key_algorithm(&attributes, alg); 182a8e1175bSopenharmony_ci psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); 183a8e1175bSopenharmony_ci psa_set_key_bits(&attributes, key_bits); 184a8e1175bSopenharmony_ci 185a8e1175bSopenharmony_ci status = psa_generate_key(&attributes, &key); 186a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 187a8e1175bSopenharmony_ci 188a8e1175bSopenharmony_ci status = cipher_encrypt(key, alg, iv, sizeof(iv), 189a8e1175bSopenharmony_ci input, sizeof(input), part_size, 190a8e1175bSopenharmony_ci encrypt, sizeof(encrypt), &output_len); 191a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 192a8e1175bSopenharmony_ci 193a8e1175bSopenharmony_ci status = cipher_decrypt(key, alg, iv, sizeof(iv), 194a8e1175bSopenharmony_ci encrypt, output_len, part_size, 195a8e1175bSopenharmony_ci decrypt, sizeof(decrypt), &output_len); 196a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 197a8e1175bSopenharmony_ci 198a8e1175bSopenharmony_ci status = memcmp(input, decrypt, sizeof(input)); 199a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 200a8e1175bSopenharmony_ci 201a8e1175bSopenharmony_ciexit: 202a8e1175bSopenharmony_ci psa_destroy_key(key); 203a8e1175bSopenharmony_ci return status; 204a8e1175bSopenharmony_ci} 205a8e1175bSopenharmony_ci 206a8e1175bSopenharmony_cistatic psa_status_t cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi(void) 207a8e1175bSopenharmony_ci{ 208a8e1175bSopenharmony_ci enum { 209a8e1175bSopenharmony_ci block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES), 210a8e1175bSopenharmony_ci key_bits = 256, 211a8e1175bSopenharmony_ci input_size = 100, 212a8e1175bSopenharmony_ci part_size = 10, 213a8e1175bSopenharmony_ci }; 214a8e1175bSopenharmony_ci 215a8e1175bSopenharmony_ci const psa_algorithm_t alg = PSA_ALG_CBC_PKCS7; 216a8e1175bSopenharmony_ci 217a8e1175bSopenharmony_ci psa_status_t status; 218a8e1175bSopenharmony_ci psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 219a8e1175bSopenharmony_ci psa_key_id_t key = 0; 220a8e1175bSopenharmony_ci size_t output_len = 0; 221a8e1175bSopenharmony_ci uint8_t iv[block_size], input[input_size], 222a8e1175bSopenharmony_ci encrypt[input_size + block_size], decrypt[input_size + block_size]; 223a8e1175bSopenharmony_ci 224a8e1175bSopenharmony_ci status = psa_generate_random(input, sizeof(input)); 225a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 226a8e1175bSopenharmony_ci 227a8e1175bSopenharmony_ci psa_set_key_usage_flags(&attributes, 228a8e1175bSopenharmony_ci PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); 229a8e1175bSopenharmony_ci psa_set_key_algorithm(&attributes, alg); 230a8e1175bSopenharmony_ci psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); 231a8e1175bSopenharmony_ci psa_set_key_bits(&attributes, key_bits); 232a8e1175bSopenharmony_ci 233a8e1175bSopenharmony_ci status = psa_generate_key(&attributes, &key); 234a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 235a8e1175bSopenharmony_ci 236a8e1175bSopenharmony_ci status = cipher_encrypt(key, alg, iv, sizeof(iv), 237a8e1175bSopenharmony_ci input, sizeof(input), part_size, 238a8e1175bSopenharmony_ci encrypt, sizeof(encrypt), &output_len); 239a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 240a8e1175bSopenharmony_ci 241a8e1175bSopenharmony_ci status = cipher_decrypt(key, alg, iv, sizeof(iv), 242a8e1175bSopenharmony_ci encrypt, output_len, part_size, 243a8e1175bSopenharmony_ci decrypt, sizeof(decrypt), &output_len); 244a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 245a8e1175bSopenharmony_ci 246a8e1175bSopenharmony_ci status = memcmp(input, decrypt, sizeof(input)); 247a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 248a8e1175bSopenharmony_ci 249a8e1175bSopenharmony_ciexit: 250a8e1175bSopenharmony_ci psa_destroy_key(key); 251a8e1175bSopenharmony_ci return status; 252a8e1175bSopenharmony_ci} 253a8e1175bSopenharmony_ci 254a8e1175bSopenharmony_cistatic psa_status_t cipher_example_encrypt_decrypt_aes_ctr_multi(void) 255a8e1175bSopenharmony_ci{ 256a8e1175bSopenharmony_ci enum { 257a8e1175bSopenharmony_ci block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES), 258a8e1175bSopenharmony_ci key_bits = 256, 259a8e1175bSopenharmony_ci input_size = 100, 260a8e1175bSopenharmony_ci part_size = 10, 261a8e1175bSopenharmony_ci }; 262a8e1175bSopenharmony_ci const psa_algorithm_t alg = PSA_ALG_CTR; 263a8e1175bSopenharmony_ci 264a8e1175bSopenharmony_ci psa_status_t status; 265a8e1175bSopenharmony_ci psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 266a8e1175bSopenharmony_ci psa_key_id_t key = 0; 267a8e1175bSopenharmony_ci size_t output_len = 0; 268a8e1175bSopenharmony_ci uint8_t iv[block_size], input[input_size], encrypt[input_size], 269a8e1175bSopenharmony_ci decrypt[input_size]; 270a8e1175bSopenharmony_ci 271a8e1175bSopenharmony_ci status = psa_generate_random(input, sizeof(input)); 272a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 273a8e1175bSopenharmony_ci 274a8e1175bSopenharmony_ci psa_set_key_usage_flags(&attributes, 275a8e1175bSopenharmony_ci PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); 276a8e1175bSopenharmony_ci psa_set_key_algorithm(&attributes, alg); 277a8e1175bSopenharmony_ci psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); 278a8e1175bSopenharmony_ci psa_set_key_bits(&attributes, key_bits); 279a8e1175bSopenharmony_ci 280a8e1175bSopenharmony_ci status = psa_generate_key(&attributes, &key); 281a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 282a8e1175bSopenharmony_ci 283a8e1175bSopenharmony_ci status = cipher_encrypt(key, alg, iv, sizeof(iv), 284a8e1175bSopenharmony_ci input, sizeof(input), part_size, 285a8e1175bSopenharmony_ci encrypt, sizeof(encrypt), &output_len); 286a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 287a8e1175bSopenharmony_ci 288a8e1175bSopenharmony_ci status = cipher_decrypt(key, alg, iv, sizeof(iv), 289a8e1175bSopenharmony_ci encrypt, output_len, part_size, 290a8e1175bSopenharmony_ci decrypt, sizeof(decrypt), &output_len); 291a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 292a8e1175bSopenharmony_ci 293a8e1175bSopenharmony_ci status = memcmp(input, decrypt, sizeof(input)); 294a8e1175bSopenharmony_ci ASSERT_STATUS(status, PSA_SUCCESS); 295a8e1175bSopenharmony_ci 296a8e1175bSopenharmony_ciexit: 297a8e1175bSopenharmony_ci psa_destroy_key(key); 298a8e1175bSopenharmony_ci return status; 299a8e1175bSopenharmony_ci} 300a8e1175bSopenharmony_ci 301a8e1175bSopenharmony_cistatic void cipher_examples(void) 302a8e1175bSopenharmony_ci{ 303a8e1175bSopenharmony_ci psa_status_t status; 304a8e1175bSopenharmony_ci 305a8e1175bSopenharmony_ci printf("cipher encrypt/decrypt AES CBC no padding:\r\n"); 306a8e1175bSopenharmony_ci status = cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block(); 307a8e1175bSopenharmony_ci if (status == PSA_SUCCESS) { 308a8e1175bSopenharmony_ci printf("\tsuccess!\r\n"); 309a8e1175bSopenharmony_ci } 310a8e1175bSopenharmony_ci 311a8e1175bSopenharmony_ci printf("cipher encrypt/decrypt AES CBC PKCS7 multipart:\r\n"); 312a8e1175bSopenharmony_ci status = cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi(); 313a8e1175bSopenharmony_ci if (status == PSA_SUCCESS) { 314a8e1175bSopenharmony_ci printf("\tsuccess!\r\n"); 315a8e1175bSopenharmony_ci } 316a8e1175bSopenharmony_ci 317a8e1175bSopenharmony_ci printf("cipher encrypt/decrypt AES CTR multipart:\r\n"); 318a8e1175bSopenharmony_ci status = cipher_example_encrypt_decrypt_aes_ctr_multi(); 319a8e1175bSopenharmony_ci if (status == PSA_SUCCESS) { 320a8e1175bSopenharmony_ci printf("\tsuccess!\r\n"); 321a8e1175bSopenharmony_ci } 322a8e1175bSopenharmony_ci} 323a8e1175bSopenharmony_ci 324a8e1175bSopenharmony_ciint main(void) 325a8e1175bSopenharmony_ci{ 326a8e1175bSopenharmony_ci ASSERT(psa_crypto_init() == PSA_SUCCESS); 327a8e1175bSopenharmony_ci cipher_examples(); 328a8e1175bSopenharmony_ciexit: 329a8e1175bSopenharmony_ci mbedtls_psa_crypto_free(); 330a8e1175bSopenharmony_ci return 0; 331a8e1175bSopenharmony_ci} 332a8e1175bSopenharmony_ci#endif /* MBEDTLS_PSA_CRYPTO_C && MBEDTLS_AES_C && MBEDTLS_CIPHER_MODE_CBC && 333a8e1175bSopenharmony_ci MBEDTLS_CIPHER_MODE_CTR && MBEDTLS_CIPHER_MODE_WITH_PADDING */ 334