xref: /freebsd/crypto/openssl/test/evp_skey_test.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1 /*
2  * Copyright 2024-2025 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,
42         0x53, 0x4B, 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), 0))
76         goto end;
77 
78     /* Export raw key */
79     if (!TEST_int_gt(EVP_SKEY_get0_raw_key(key, &export, &export_len), 0)
80         || !TEST_mem_eq(export, export_len, import_key, sizeof(import_key)))
81         goto end;
82 
83     ret = 1;
84 
85 end:
86     OSSL_PARAM_free(export_params);
87     EVP_SKEY_free(key);
88     EVP_CIPHER_free(fake_cipher);
89     EVP_CIPHER_CTX_free(ctx);
90     fake_cipher_finish(fake_prov);
91 
92     return ret;
93 }
94 
95 #define IV_SIZE 16
96 #define DATA_SIZE 32
test_aes_raw_skey(void)97 static int test_aes_raw_skey(void)
98 {
99     const unsigned char data[DATA_SIZE] = {
100         0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
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     };
105     unsigned char aes_key[KEY_SIZE], aes_iv[IV_SIZE];
106     unsigned char encrypted_skey[DATA_SIZE + IV_SIZE];
107     unsigned char encrypted_raw[DATA_SIZE + IV_SIZE];
108     int enc_len, fin_len;
109     const unsigned char *export_key = NULL;
110     size_t export_length;
111     EVP_CIPHER *aes_cbc = NULL;
112     EVP_CIPHER_CTX *ctx = NULL;
113     EVP_SKEY *skey = NULL;
114     OSSL_PARAM_BLD *tmpl = NULL;
115     OSSL_PARAM *params = NULL;
116     int ret = 0;
117 
118     deflprov = OSSL_PROVIDER_load(libctx, "default");
119     if (!TEST_ptr(deflprov))
120         return 0;
121 
122     memset(encrypted_skey, 0, sizeof(encrypted_skey));
123     memset(encrypted_raw,  0, sizeof(encrypted_raw));
124     memset(aes_key, 1, KEY_SIZE);
125     memset(aes_iv, 2, IV_SIZE);
126 
127     /* Do a direct fetch to see it works */
128     aes_cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", "provider=default");
129     if (!TEST_ptr(aes_cbc))
130         goto end;
131 
132     /* Create EVP_SKEY */
133     skey = EVP_SKEY_import_raw_key(libctx, "AES-128", aes_key, KEY_SIZE, NULL);
134     if (!TEST_ptr(skey))
135         goto end;
136 
137     if (!TEST_int_gt(EVP_SKEY_get0_raw_key(skey, &export_key, &export_length), 0)
138         || !TEST_mem_eq(aes_key, KEY_SIZE, export_key, export_length))
139         goto end;
140 
141     enc_len = sizeof(encrypted_skey);
142     fin_len = 0;
143     if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
144         || !TEST_int_gt(EVP_CipherInit_SKEY(ctx, aes_cbc, skey, aes_iv, IV_SIZE, 1, NULL), 0)
145         || !TEST_int_gt(EVP_CipherUpdate(ctx, encrypted_skey, &enc_len, data, DATA_SIZE), 0)
146         || !TEST_int_gt(EVP_CipherFinal(ctx, encrypted_skey + enc_len, &fin_len), 0))
147         goto end;
148 
149     EVP_CIPHER_CTX_free(ctx);
150     ctx = EVP_CIPHER_CTX_new();
151 
152     enc_len = sizeof(encrypted_raw);
153     fin_len = 0;
154     if (!TEST_int_gt(EVP_CipherInit_ex2(ctx, aes_cbc, aes_key, aes_iv, 1, NULL), 0)
155         || !TEST_int_gt(EVP_CipherUpdate(ctx, encrypted_raw, &enc_len, data, DATA_SIZE), 0)
156         || !TEST_int_gt(EVP_CipherFinal(ctx, encrypted_raw + enc_len, &fin_len), 0)
157         || !TEST_mem_eq(encrypted_skey, DATA_SIZE + IV_SIZE, encrypted_raw, DATA_SIZE + IV_SIZE))
158         goto end;
159 
160     ret = 1;
161 end:
162     OSSL_PARAM_free(params);
163     OSSL_PARAM_BLD_free(tmpl);
164     EVP_SKEY_free(skey);
165     EVP_CIPHER_free(aes_cbc);
166     EVP_CIPHER_CTX_free(ctx);
167     OSSL_PROVIDER_unload(deflprov);
168     return ret;
169 }
170 
171 #ifndef OPENSSL_NO_DES
172 /* DES is used to test a "skey-unware" cipher provider */
173 # define DES_KEY_SIZE 24
174 # define DES_IV_SIZE 8
test_des_raw_skey(void)175 static int test_des_raw_skey(void)
176 {
177     const unsigned char data[DATA_SIZE] = {
178         0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2,
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     };
183     unsigned char des_key[DES_KEY_SIZE], des_iv[DES_IV_SIZE];
184     unsigned char encrypted_skey[DATA_SIZE + DES_IV_SIZE];
185     unsigned char encrypted_raw[DATA_SIZE + DES_IV_SIZE];
186     int enc_len, fin_len;
187     const unsigned char *export_key = NULL;
188     size_t export_length;
189     EVP_CIPHER *des_cbc = NULL;
190     EVP_CIPHER_CTX *ctx = NULL;
191     EVP_SKEY *skey = NULL;
192     int ret = 0;
193 
194     deflprov = OSSL_PROVIDER_load(libctx, "default");
195     if (!TEST_ptr(deflprov))
196         return 0;
197 
198     memset(encrypted_skey, 0, sizeof(encrypted_skey));
199     memset(encrypted_raw,  0, sizeof(encrypted_raw));
200     memset(des_key, 1, DES_KEY_SIZE);
201     memset(des_iv, 2, DES_IV_SIZE);
202 
203     /* Do a direct fetch to see it works */
204     des_cbc = EVP_CIPHER_fetch(libctx, "DES-EDE3-CBC", "provider=default");
205     if (!TEST_ptr(des_cbc))
206         goto end;
207 
208     /* Create EVP_SKEY */
209     skey = EVP_SKEY_import_raw_key(libctx, "DES", des_key, sizeof(des_key),
210                                    NULL);
211     if (!TEST_ptr(skey))
212         goto end;
213 
214     if (!TEST_int_gt(EVP_SKEY_get0_raw_key(skey, &export_key, &export_length), 0)
215         || !TEST_mem_eq(des_key, DES_KEY_SIZE, export_key, export_length))
216         goto end;
217 
218     enc_len = sizeof(encrypted_skey);
219     fin_len = 0;
220     if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
221         || !TEST_int_gt(EVP_CipherInit_SKEY(ctx, des_cbc, skey, des_iv, DES_IV_SIZE, 1, NULL), 0)
222         || !TEST_int_gt(EVP_CipherUpdate(ctx, encrypted_skey, &enc_len, data, DATA_SIZE), 0)
223         || !TEST_int_gt(EVP_CipherFinal(ctx, encrypted_skey + enc_len, &fin_len), 0))
224         goto end;
225 
226     EVP_CIPHER_CTX_free(ctx);
227     ctx = EVP_CIPHER_CTX_new();
228 
229     enc_len = sizeof(encrypted_raw);
230     fin_len = 0;
231     if (!TEST_int_gt(EVP_CipherInit_ex2(ctx, des_cbc, des_key, des_iv, 1, NULL), 0)
232         || !TEST_int_gt(EVP_CipherUpdate(ctx, encrypted_raw, &enc_len, data, DATA_SIZE), 0)
233         || !TEST_int_gt(EVP_CipherFinal(ctx, encrypted_raw + enc_len, &fin_len), 0)
234         || !TEST_mem_eq(encrypted_skey, DATA_SIZE + DES_IV_SIZE, encrypted_raw,
235                         DATA_SIZE + DES_IV_SIZE))
236         goto end;
237 
238     ret = 1;
239 end:
240     EVP_SKEY_free(skey);
241     EVP_CIPHER_free(des_cbc);
242     EVP_CIPHER_CTX_free(ctx);
243     OSSL_PROVIDER_unload(deflprov);
244     return ret;
245 }
246 #endif
247 
setup_tests(void)248 int setup_tests(void)
249 {
250     libctx = OSSL_LIB_CTX_new();
251     if (libctx == NULL)
252         return 0;
253 
254     ADD_TEST(test_skey_cipher);
255 
256     ADD_TEST(test_aes_raw_skey);
257 #ifndef OPENSSL_NO_DES
258     ADD_TEST(test_des_raw_skey);
259 #endif
260 
261     return 1;
262 }
263 
cleanup_tests(void)264 void cleanup_tests(void)
265 {
266     OSSL_LIB_CTX_free(libctx);
267 }
268