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