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
aes_wrap_encrypt(void)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
aes_wrap_decrypt(void)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
main(int argc,char ** argv)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