quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

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 */