Home | History | Annotate | Line # | Download | only in cipher
      1      1.1  christos /*
      2      1.1  christos  * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
      3      1.1  christos  *
      4      1.1  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5      1.1  christos  * this file except in compliance with the License.  You can obtain a copy
      6      1.1  christos  * in the file LICENSE in the source distribution or at
      7      1.1  christos  * https://www.openssl.org/source/license.html
      8      1.1  christos  */
      9      1.1  christos 
     10      1.1  christos /*
     11      1.1  christos  * Simple aes wrap encryption demonstration program.
     12      1.1  christos  */
     13      1.1  christos 
     14      1.1  christos #include <stdio.h>
     15      1.1  christos #include <openssl/err.h>
     16      1.1  christos #include <openssl/bio.h>
     17      1.1  christos #include <openssl/evp.h>
     18      1.1  christos #include <openssl/crypto.h>
     19      1.1  christos #include <openssl/core_names.h>
     20      1.1  christos 
     21      1.1  christos /* aes key */
     22      1.1  christos static const unsigned char wrap_key[] = {
     23      1.1  christos     0xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92, 0x1c, 0x04, 0x65, 0x66,
     24      1.1  christos     0x5f, 0x8a, 0xe6, 0xd1, 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69,
     25      1.1  christos     0xa3, 0x52, 0x02, 0x93, 0xa5, 0x72, 0x07, 0x8f
     26      1.1  christos };
     27      1.1  christos 
     28      1.1  christos /* Unique initialisation vector */
     29      1.1  christos static const unsigned char wrap_iv[] = {
     30  1.1.1.2  christos     0x99,
     31  1.1.1.2  christos     0xaa,
     32  1.1.1.2  christos     0x3e,
     33  1.1.1.2  christos     0x68,
     34  1.1.1.2  christos     0xed,
     35  1.1.1.2  christos     0x81,
     36  1.1.1.2  christos     0x73,
     37  1.1.1.2  christos     0xa0,
     38  1.1.1.2  christos     0xee,
     39  1.1.1.2  christos     0xd0,
     40  1.1.1.2  christos     0x66,
     41  1.1.1.2  christos     0x84,
     42  1.1.1.2  christos     0x99,
     43  1.1.1.2  christos     0xaa,
     44  1.1.1.2  christos     0x3e,
     45  1.1.1.2  christos     0x68,
     46      1.1  christos };
     47      1.1  christos 
     48      1.1  christos /* Example plaintext to encrypt */
     49      1.1  christos static const unsigned char wrap_pt[] = {
     50  1.1.1.2  christos     0xad,
     51  1.1.1.2  christos     0x4f,
     52  1.1.1.2  christos     0xc9,
     53  1.1.1.2  christos     0xfc,
     54  1.1.1.2  christos     0x77,
     55  1.1.1.2  christos     0x69,
     56  1.1.1.2  christos     0xc9,
     57  1.1.1.2  christos     0xea,
     58  1.1.1.2  christos     0xfc,
     59  1.1.1.2  christos     0xdf,
     60  1.1.1.2  christos     0x00,
     61  1.1.1.2  christos     0xac,
     62  1.1.1.2  christos     0x34,
     63  1.1.1.2  christos     0xec,
     64  1.1.1.2  christos     0x40,
     65  1.1.1.2  christos     0xbc,
     66  1.1.1.2  christos     0x28,
     67  1.1.1.2  christos     0x3f,
     68  1.1.1.2  christos     0xa4,
     69  1.1.1.2  christos     0x5e,
     70  1.1.1.2  christos     0xd8,
     71  1.1.1.2  christos     0x99,
     72  1.1.1.2  christos     0xe4,
     73  1.1.1.2  christos     0x5d,
     74  1.1.1.2  christos     0x5e,
     75  1.1.1.2  christos     0x7a,
     76  1.1.1.2  christos     0xc4,
     77  1.1.1.2  christos     0xe6,
     78  1.1.1.2  christos     0xca,
     79  1.1.1.2  christos     0x7b,
     80  1.1.1.2  christos     0xa5,
     81  1.1.1.2  christos     0xb7,
     82      1.1  christos };
     83      1.1  christos 
     84      1.1  christos /* Expected ciphertext value */
     85      1.1  christos static const unsigned char wrap_ct[] = {
     86  1.1.1.2  christos     0x97,
     87  1.1.1.2  christos     0x99,
     88  1.1.1.2  christos     0x55,
     89  1.1.1.2  christos     0xca,
     90  1.1.1.2  christos     0xf6,
     91  1.1.1.2  christos     0x3e,
     92  1.1.1.2  christos     0x95,
     93  1.1.1.2  christos     0x54,
     94  1.1.1.2  christos     0x39,
     95  1.1.1.2  christos     0xd6,
     96  1.1.1.2  christos     0xaf,
     97  1.1.1.2  christos     0x63,
     98  1.1.1.2  christos     0xff,
     99  1.1.1.2  christos     0x2c,
    100  1.1.1.2  christos     0xe3,
    101  1.1.1.2  christos     0x96,
    102  1.1.1.2  christos     0xf7,
    103  1.1.1.2  christos     0x0d,
    104  1.1.1.2  christos     0x2c,
    105  1.1.1.2  christos     0x9c,
    106  1.1.1.2  christos     0xc7,
    107  1.1.1.2  christos     0x43,
    108  1.1.1.2  christos     0xc0,
    109  1.1.1.2  christos     0xb6,
    110  1.1.1.2  christos     0x31,
    111  1.1.1.2  christos     0x43,
    112  1.1.1.2  christos     0xb9,
    113  1.1.1.2  christos     0x20,
    114  1.1.1.2  christos     0xac,
    115  1.1.1.2  christos     0x6b,
    116  1.1.1.2  christos     0xd3,
    117  1.1.1.2  christos     0x67,
    118  1.1.1.2  christos     0xad,
    119  1.1.1.2  christos     0x01,
    120  1.1.1.2  christos     0xaf,
    121  1.1.1.2  christos     0xa7,
    122  1.1.1.2  christos     0x32,
    123  1.1.1.2  christos     0x74,
    124  1.1.1.2  christos     0x26,
    125  1.1.1.2  christos     0x92,
    126      1.1  christos };
    127      1.1  christos 
    128      1.1  christos /*
    129      1.1  christos  * A library context and property query can be used to select & filter
    130      1.1  christos  * algorithm implementations. If they are NULL then the default library
    131      1.1  christos  * context and properties are used.
    132      1.1  christos  */
    133      1.1  christos static OSSL_LIB_CTX *libctx = NULL;
    134      1.1  christos static const char *propq = NULL;
    135      1.1  christos 
    136      1.1  christos static int aes_wrap_encrypt(void)
    137      1.1  christos {
    138      1.1  christos     int ret = 0;
    139      1.1  christos     EVP_CIPHER_CTX *ctx;
    140      1.1  christos     EVP_CIPHER *cipher = NULL;
    141      1.1  christos     int outlen, tmplen;
    142      1.1  christos     unsigned char outbuf[1024];
    143      1.1  christos 
    144      1.1  christos     printf("aes wrap Encrypt:\n");
    145      1.1  christos     printf("Plaintext:\n");
    146      1.1  christos     BIO_dump_fp(stdout, wrap_pt, sizeof(wrap_pt));
    147      1.1  christos 
    148      1.1  christos     /* Create a context for the encrypt operation */
    149      1.1  christos     if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
    150      1.1  christos         goto err;
    151      1.1  christos 
    152      1.1  christos     EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
    153      1.1  christos 
    154      1.1  christos     /* Fetch the cipher implementation */
    155      1.1  christos     if ((cipher = EVP_CIPHER_fetch(libctx, "AES-256-WRAP", propq)) == NULL)
    156      1.1  christos         goto err;
    157      1.1  christos 
    158      1.1  christos     /*
    159      1.1  christos      * Initialise an encrypt operation with the cipher/mode, key and IV.
    160      1.1  christos      * We are not setting any custom params so let params be just NULL.
    161      1.1  christos      */
    162      1.1  christos     if (!EVP_EncryptInit_ex2(ctx, cipher, wrap_key, wrap_iv, /* params */ NULL))
    163      1.1  christos         goto err;
    164      1.1  christos 
    165      1.1  christos     /* Encrypt plaintext */
    166      1.1  christos     if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, wrap_pt, sizeof(wrap_pt)))
    167      1.1  christos         goto err;
    168      1.1  christos 
    169      1.1  christos     /* Finalise: there can be some additional output from padding */
    170      1.1  christos     if (!EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen))
    171      1.1  christos         goto err;
    172      1.1  christos     outlen += tmplen;
    173      1.1  christos 
    174      1.1  christos     /* Output encrypted block */
    175      1.1  christos     printf("Ciphertext (outlen:%d):\n", outlen);
    176      1.1  christos     BIO_dump_fp(stdout, outbuf, outlen);
    177      1.1  christos 
    178      1.1  christos     if (sizeof(wrap_ct) == outlen && !CRYPTO_memcmp(outbuf, wrap_ct, outlen))
    179      1.1  christos         printf("Final ciphertext matches expected ciphertext\n");
    180      1.1  christos     else
    181      1.1  christos         printf("Final ciphertext differs from expected ciphertext\n");
    182      1.1  christos 
    183      1.1  christos     ret = 1;
    184      1.1  christos err:
    185      1.1  christos     if (!ret)
    186      1.1  christos         ERR_print_errors_fp(stderr);
    187      1.1  christos 
    188      1.1  christos     EVP_CIPHER_free(cipher);
    189      1.1  christos     EVP_CIPHER_CTX_free(ctx);
    190      1.1  christos 
    191      1.1  christos     return ret;
    192      1.1  christos }
    193      1.1  christos 
    194      1.1  christos static int aes_wrap_decrypt(void)
    195      1.1  christos {
    196      1.1  christos     int ret = 0;
    197      1.1  christos     EVP_CIPHER_CTX *ctx;
    198      1.1  christos     EVP_CIPHER *cipher = NULL;
    199      1.1  christos     int outlen, tmplen;
    200      1.1  christos     unsigned char outbuf[1024];
    201      1.1  christos 
    202      1.1  christos     printf("aes wrap Decrypt:\n");
    203      1.1  christos     printf("Ciphertext:\n");
    204      1.1  christos     BIO_dump_fp(stdout, wrap_ct, sizeof(wrap_ct));
    205      1.1  christos 
    206      1.1  christos     if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
    207      1.1  christos         goto err;
    208      1.1  christos 
    209      1.1  christos     EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
    210      1.1  christos 
    211      1.1  christos     /* Fetch the cipher implementation */
    212      1.1  christos     if ((cipher = EVP_CIPHER_fetch(libctx, "aes-256-wrap", propq)) == NULL)
    213      1.1  christos         goto err;
    214      1.1  christos 
    215      1.1  christos     /*
    216      1.1  christos      * Initialise an encrypt operation with the cipher/mode, key and IV.
    217      1.1  christos      * We are not setting any custom params so let params be just NULL.
    218      1.1  christos      */
    219      1.1  christos     if (!EVP_DecryptInit_ex2(ctx, cipher, wrap_key, wrap_iv, /* params */ NULL))
    220      1.1  christos         goto err;
    221      1.1  christos 
    222      1.1  christos     /* Decrypt plaintext */
    223      1.1  christos     if (!EVP_DecryptUpdate(ctx, outbuf, &outlen, wrap_ct, sizeof(wrap_ct)))
    224      1.1  christos         goto err;
    225      1.1  christos 
    226      1.1  christos     /* Finalise: there can be some additional output from padding */
    227      1.1  christos     if (!EVP_DecryptFinal_ex(ctx, outbuf + outlen, &tmplen))
    228      1.1  christos         goto err;
    229      1.1  christos     outlen += tmplen;
    230      1.1  christos 
    231      1.1  christos     /* Output decrypted block */
    232      1.1  christos     printf("Plaintext (outlen:%d):\n", outlen);
    233      1.1  christos     BIO_dump_fp(stdout, outbuf, outlen);
    234      1.1  christos 
    235      1.1  christos     if (sizeof(wrap_pt) == outlen && !CRYPTO_memcmp(outbuf, wrap_pt, outlen))
    236      1.1  christos         printf("Final plaintext matches original plaintext\n");
    237      1.1  christos     else
    238      1.1  christos         printf("Final plaintext differs from original plaintext\n");
    239      1.1  christos 
    240      1.1  christos     ret = 1;
    241      1.1  christos err:
    242      1.1  christos     if (!ret)
    243      1.1  christos         ERR_print_errors_fp(stderr);
    244      1.1  christos 
    245      1.1  christos     EVP_CIPHER_free(cipher);
    246      1.1  christos     EVP_CIPHER_CTX_free(ctx);
    247      1.1  christos 
    248      1.1  christos     return ret;
    249      1.1  christos }
    250      1.1  christos 
    251      1.1  christos int main(int argc, char **argv)
    252      1.1  christos {
    253      1.1  christos     if (!aes_wrap_encrypt())
    254  1.1.1.2  christos         return EXIT_FAILURE;
    255      1.1  christos 
    256      1.1  christos     if (!aes_wrap_decrypt())
    257      1.1  christos         return EXIT_FAILURE;
    258      1.1  christos 
    259      1.1  christos     return EXIT_SUCCESS;
    260      1.1  christos }
    261