xref: /freebsd/crypto/openssl/test/evp_skey_test.c (revision 1523ccfd9c8c254f7928143d31c305384b05fd11)
1 /*
2  * Copyright 2024-2026 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 #include <openssl/provider.h>
11 #include <openssl/params.h>
12 #include <openssl/param_build.h>
13 #include <openssl/core_names.h>
14 #include <openssl/evp.h>
15 #include "testutil.h"
16 #include "fake_cipherprov.h"
17 
18 static OSSL_LIB_CTX *libctx = NULL;
19 static OSSL_PROVIDER *deflprov = NULL;
20 
21 #define KEY_SIZE 16
22 
23 static OSSL_CALLBACK ossl_pkey_todata_cb;
24 
ossl_pkey_todata_cb(const OSSL_PARAM params[],void * arg)25 static int ossl_pkey_todata_cb(const OSSL_PARAM params[], void *arg)
26 {
27     OSSL_PARAM **ret = arg;
28 
29     *ret = OSSL_PARAM_dup(params);
30     return 1;
31 }
32 
test_skey_cipher(void)33 static int test_skey_cipher(void)
34 {
35     int ret = 0;
36     OSSL_PROVIDER *fake_prov = NULL;
37     EVP_SKEY *key = NULL;
38     EVP_CIPHER *fake_cipher = NULL;
39     EVP_CIPHER_CTX *ctx = NULL;
40     const unsigned char import_key[KEY_SIZE] = {
41         0x53, 0x4B, 0x45, 0x59, 0x53, 0x4B, 0x45, 0x59, 0x53, 0x4B,
42         0x45, 0x59, 0x53, 0x4B, 0x45, 0x59
43     };
44     OSSL_PARAM params[3];
45     OSSL_PARAM *export_params = NULL;
46     const unsigned char *export;
47     size_t export_len;
48 
49     if (!TEST_ptr(fake_prov = fake_cipher_start(libctx)))
50         return 0;
51 
52     /* Do a direct fetch to see it works */
53     fake_cipher = EVP_CIPHER_fetch(libctx, "fake_cipher", FAKE_CIPHER_FETCH_PROPS);
54     if (!TEST_ptr(fake_cipher))
55         goto end;
56 
57     /* Create EVP_SKEY */
58     params[0] = OSSL_PARAM_construct_utf8_string(FAKE_CIPHER_PARAM_KEY_NAME,
59         "fake key name", 0);
60     params[1] = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES,
61         (void *)import_key, KEY_SIZE);
62     params[2] = OSSL_PARAM_construct_end();
63     key = EVP_SKEY_import(libctx, "fake_cipher", FAKE_CIPHER_FETCH_PROPS,
64         OSSL_SKEYMGMT_SELECT_ALL, params);
65     if (!TEST_ptr(key))
66         goto end;
67 
68     /* Init cipher */
69     if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
70         || !TEST_int_gt(EVP_CipherInit_SKEY(ctx, fake_cipher, key, NULL, 0, 1, NULL), 0))
71         goto end;
72 
73     /* Export params */
74     if (!TEST_int_gt(EVP_SKEY_export(key, OSSL_SKEYMGMT_SELECT_SECRET_KEY,
75                          ossl_pkey_todata_cb, &export_params),
76             0))
77         goto end;
78 
79     /* Export raw key */
80     if (!TEST_int_gt(EVP_SKEY_get0_raw_key(key, &export, &export_len), 0)
81         || !TEST_mem_eq(export, export_len, import_key, sizeof(import_key)))
82         goto end;
83 
84     ret = 1;
85 
86 end:
87     OSSL_PARAM_free(export_params);
88     EVP_SKEY_free(key);
89     EVP_CIPHER_free(fake_cipher);
90     EVP_CIPHER_CTX_free(ctx);
91     fake_cipher_finish(fake_prov);
92 
93     return ret;
94 }
95 
96 #define IV_SIZE 16
97 #define DATA_SIZE 32
test_aes_raw_skey(void)98 static int test_aes_raw_skey(void)
99 {
100     const unsigned char data[DATA_SIZE] = {
101         0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
102         0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
103         0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
104         0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2
105     };
106     unsigned char aes_key[KEY_SIZE], aes_iv[IV_SIZE];
107     unsigned char encrypted_skey[DATA_SIZE + IV_SIZE];
108     unsigned char encrypted_raw[DATA_SIZE + IV_SIZE];
109     int enc_len, fin_len;
110     const unsigned char *export_key = NULL;
111     size_t export_length;
112     EVP_CIPHER *aes_cbc = NULL;
113     EVP_CIPHER_CTX *ctx = NULL;
114     EVP_SKEY *skey = NULL;
115     OSSL_PARAM_BLD *tmpl = NULL;
116     OSSL_PARAM *params = NULL;
117     int ret = 0;
118 
119     deflprov = OSSL_PROVIDER_load(libctx, "default");
120     if (!TEST_ptr(deflprov))
121         return 0;
122 
123     memset(encrypted_skey, 0, sizeof(encrypted_skey));
124     memset(encrypted_raw, 0, sizeof(encrypted_raw));
125     memset(aes_key, 1, KEY_SIZE);
126     memset(aes_iv, 2, IV_SIZE);
127 
128     /* Do a direct fetch to see it works */
129     aes_cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", "provider=default");
130     if (!TEST_ptr(aes_cbc))
131         goto end;
132 
133     /* Create EVP_SKEY */
134     skey = EVP_SKEY_import_raw_key(libctx, "AES-128", aes_key, KEY_SIZE, NULL);
135     if (!TEST_ptr(skey))
136         goto end;
137 
138     if (!TEST_int_gt(EVP_SKEY_get0_raw_key(skey, &export_key, &export_length), 0)
139         || !TEST_mem_eq(aes_key, KEY_SIZE, export_key, export_length))
140         goto end;
141 
142     enc_len = sizeof(encrypted_skey);
143     fin_len = 0;
144     if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
145         || !TEST_int_gt(EVP_CipherInit_SKEY(ctx, aes_cbc, skey, aes_iv, IV_SIZE, 1, NULL), 0)
146         || !TEST_int_gt(EVP_CipherUpdate(ctx, encrypted_skey, &enc_len, data, DATA_SIZE), 0)
147         || !TEST_int_gt(EVP_CipherFinal(ctx, encrypted_skey + enc_len, &fin_len), 0))
148         goto end;
149 
150     EVP_CIPHER_CTX_free(ctx);
151     ctx = EVP_CIPHER_CTX_new();
152 
153     enc_len = sizeof(encrypted_raw);
154     fin_len = 0;
155     if (!TEST_int_gt(EVP_CipherInit_ex2(ctx, aes_cbc, aes_key, aes_iv, 1, NULL), 0)
156         || !TEST_int_gt(EVP_CipherUpdate(ctx, encrypted_raw, &enc_len, data, DATA_SIZE), 0)
157         || !TEST_int_gt(EVP_CipherFinal(ctx, encrypted_raw + enc_len, &fin_len), 0)
158         || !TEST_mem_eq(encrypted_skey, DATA_SIZE + IV_SIZE, encrypted_raw, DATA_SIZE + IV_SIZE))
159         goto end;
160 
161     ret = 1;
162 end:
163     OSSL_PARAM_free(params);
164     OSSL_PARAM_BLD_free(tmpl);
165     EVP_SKEY_free(skey);
166     EVP_CIPHER_free(aes_cbc);
167     EVP_CIPHER_CTX_free(ctx);
168     OSSL_PROVIDER_unload(deflprov);
169     return ret;
170 }
171 
172 #ifndef OPENSSL_NO_DES
173 /* DES is used to test a "skey-unware" cipher provider */
174 #define DES_KEY_SIZE 24
175 #define DES_IV_SIZE 8
test_des_raw_skey(void)176 static int test_des_raw_skey(void)
177 {
178     const unsigned char data[DATA_SIZE] = {
179         0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
180         0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
181         0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
182         0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2
183     };
184     unsigned char des_key[DES_KEY_SIZE], des_iv[DES_IV_SIZE];
185     unsigned char encrypted_skey[DATA_SIZE + DES_IV_SIZE];
186     unsigned char encrypted_raw[DATA_SIZE + DES_IV_SIZE];
187     int enc_len, fin_len;
188     const unsigned char *export_key = NULL;
189     size_t export_length;
190     EVP_CIPHER *des_cbc = NULL;
191     EVP_CIPHER_CTX *ctx = NULL;
192     EVP_SKEY *skey = NULL;
193     int ret = 0;
194 
195     deflprov = OSSL_PROVIDER_load(libctx, "default");
196     if (!TEST_ptr(deflprov))
197         return 0;
198 
199     memset(encrypted_skey, 0, sizeof(encrypted_skey));
200     memset(encrypted_raw, 0, sizeof(encrypted_raw));
201     memset(des_key, 1, DES_KEY_SIZE);
202     memset(des_iv, 2, DES_IV_SIZE);
203 
204     /* Do a direct fetch to see it works */
205     des_cbc = EVP_CIPHER_fetch(libctx, "DES-EDE3-CBC", "provider=default");
206     if (!TEST_ptr(des_cbc))
207         goto end;
208 
209     /* Create EVP_SKEY */
210     skey = EVP_SKEY_import_raw_key(libctx, "DES", des_key, sizeof(des_key),
211         NULL);
212     if (!TEST_ptr(skey))
213         goto end;
214 
215     if (!TEST_int_gt(EVP_SKEY_get0_raw_key(skey, &export_key, &export_length), 0)
216         || !TEST_mem_eq(des_key, DES_KEY_SIZE, export_key, export_length))
217         goto end;
218 
219     enc_len = sizeof(encrypted_skey);
220     fin_len = 0;
221     if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
222         || !TEST_int_gt(EVP_CipherInit_SKEY(ctx, des_cbc, skey, des_iv, DES_IV_SIZE, 1, NULL), 0)
223         || !TEST_int_gt(EVP_CipherUpdate(ctx, encrypted_skey, &enc_len, data, DATA_SIZE), 0)
224         || !TEST_int_gt(EVP_CipherFinal(ctx, encrypted_skey + enc_len, &fin_len), 0))
225         goto end;
226 
227     EVP_CIPHER_CTX_free(ctx);
228     ctx = EVP_CIPHER_CTX_new();
229 
230     enc_len = sizeof(encrypted_raw);
231     fin_len = 0;
232     if (!TEST_int_gt(EVP_CipherInit_ex2(ctx, des_cbc, des_key, des_iv, 1, NULL), 0)
233         || !TEST_int_gt(EVP_CipherUpdate(ctx, encrypted_raw, &enc_len, data, DATA_SIZE), 0)
234         || !TEST_int_gt(EVP_CipherFinal(ctx, encrypted_raw + enc_len, &fin_len), 0)
235         || !TEST_mem_eq(encrypted_skey, DATA_SIZE + DES_IV_SIZE, encrypted_raw,
236             DATA_SIZE + DES_IV_SIZE))
237         goto end;
238 
239     ret = 1;
240 end:
241     EVP_SKEY_free(skey);
242     EVP_CIPHER_free(des_cbc);
243     EVP_CIPHER_CTX_free(ctx);
244     OSSL_PROVIDER_unload(deflprov);
245     return ret;
246 }
247 #endif
248 
setup_tests(void)249 int setup_tests(void)
250 {
251     libctx = OSSL_LIB_CTX_new();
252     if (libctx == NULL)
253         return 0;
254 
255     ADD_TEST(test_skey_cipher);
256 
257     ADD_TEST(test_aes_raw_skey);
258 #ifndef OPENSSL_NO_DES
259     ADD_TEST(test_des_raw_skey);
260 #endif
261 
262     return 1;
263 }
264 
cleanup_tests(void)265 void cleanup_tests(void)
266 {
267     OSSL_LIB_CTX_free(libctx);
268 }
269