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, 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 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 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 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 264 void cleanup_tests(void) 265 { 266 OSSL_LIB_CTX_free(libctx); 267 } 268