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