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