Home | History | Annotate | Line # | Download | only in test
      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