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