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