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