1313#include < openssl/kdf.h>
1414#include " e_scossl.h"
1515
16+ #if OPENSSL_VERSION_MAJOR == 3
17+ #include < openssl/provider.h>
18+ #endif
19+
1620BIO *bio_err = NULL ;
1721
1822// By default exit Sslplay application if an error is encountered
@@ -1126,7 +1130,7 @@ void TestRsaEvpAll()
11261130
11271131}
11281132
1129- bool TestDigest (const char * digestname)
1133+ bool TestDigest (const char * digestname, const char *expected )
11301134{
11311135 bool result = false ;
11321136 EVP_MD_CTX *mdctx;
@@ -1161,24 +1165,208 @@ bool TestDigest(const char* digestname)
11611165 for (i = 0 ; i < md_len; i++)
11621166 printf (" %02x" , md_value[i]);
11631167 printf (" \n " );
1168+
1169+ if (memcmp (md_value, expected, md_len) != 0 )
1170+ {
1171+ handleError (" Result does not match expected value" );
1172+ goto end;
1173+ }
1174+
11641175 result = true ;
11651176end:
11661177 printf (" %s" , SeparatorLine);
11671178 return result;
11681179}
11691180
1170- void TestDigests ()
1181+ #if OPENSSL_VERSION_MAJOR == 3
1182+ bool TestDigestImportExport (const char *digestname, const char *expected, size_t export_state_size)
11711183{
1184+ bool result = false ;
1185+ EVP_MD *md = NULL ;
1186+ EVP_MD_CTX *mdctx;
11721187 char mess1[] = " Test Message1234567" ;
11731188 char mess2[] = " Hello World" ;
1174- unsigned int md_len=32 , i;
1189+ unsigned char md_value[EVP_MAX_MD_SIZE];
1190+ unsigned int md_len, i;
1191+
1192+ const OSSL_PROVIDER *provider;
1193+ const char *providername;
1194+ const OSSL_PARAM *capableParams = NULL ;
1195+ BYTE exported_state[export_state_size];
1196+ int recompute_checksum = 0 ;
1197+ OSSL_PARAM params[3 ] = {
1198+ OSSL_PARAM_construct_octet_string (" state" , exported_state, export_state_size),
1199+ OSSL_PARAM_construct_int (" recompute_checksum" , &recompute_checksum),
1200+ OSSL_PARAM_construct_end ()
1201+ };
1202+
1203+ printf (" \n TestDigestImportExport: %s\n\n " , digestname);
1204+
1205+ md = EVP_MD_fetch (nullptr , digestname, " provider=symcryptprovider" );
1206+ if (md == NULL )
1207+ {
1208+ printf (" No Digest found for %s\n " , digestname);
1209+ goto end;
1210+ }
1211+
1212+ printf (" Command EVP_MD_CTX_new\n " );
1213+ mdctx = EVP_MD_CTX_new ();
1214+ printf (" Command EVP_DigestInit_ex\n " );
1215+ EVP_DigestInit_ex2 (mdctx, md, NULL );
1216+
1217+ // Check capabilities
1218+ capableParams = EVP_MD_CTX_gettable_params (mdctx);
1219+ if (OSSL_PARAM_locate_const (capableParams, " state" ) == NULL )
1220+ {
1221+ handleError (" state parameter not gettable" );
1222+ goto end;
1223+ }
11751224
1176- TestDigest (" MD5" );
1177- TestDigest (" SHA1" );
1178- TestDigest (" SHA224" );
1179- TestDigest (" SHA256" );
1180- TestDigest (" SHA384" );
1181- TestDigest (" SHA512" );
1225+ capableParams = EVP_MD_CTX_settable_params (mdctx);
1226+ if (OSSL_PARAM_locate_const (capableParams, " state" ) == NULL ||
1227+ OSSL_PARAM_locate_const (capableParams, " recompute_checksum" ) == NULL )
1228+ {
1229+ handleError (" state parameter not settable" );
1230+ goto end;
1231+ }
1232+
1233+ printf (" Command EVP_DigestUpdate\n " );
1234+ EVP_DigestUpdate (mdctx, mess1, strlen (mess1));
1235+
1236+ // Export state
1237+ printf (" Command EVP_MD_CTX_get_params\n " );
1238+ EVP_MD_CTX_get_params (mdctx, params);
1239+ printf (" Command EVP_MD_CTX_free\n " );
1240+ EVP_MD_CTX_free (mdctx);
1241+
1242+ // New context with imported state supplied
1243+ printf (" Command EVP_MD_CTX_new\n " );
1244+ mdctx = EVP_MD_CTX_new ();
1245+ printf (" Command EVP_DigestInit_ex\n " );
1246+ EVP_DigestInit_ex2 (mdctx, md, params);
1247+
1248+ printf (" Command EVP_DigestUpdate\n " );
1249+ EVP_DigestUpdate (mdctx, mess2, strlen (mess2));
1250+ printf (" Command EVP_DigestFinal_ex\n " );
1251+ EVP_DigestFinal_ex (mdctx, md_value, &md_len);
1252+ printf (" Command EVP_MD_CTX_free\n " );
1253+ EVP_MD_CTX_free (mdctx);
1254+
1255+ printf (" Digest (Original checksum) (%s) : \t " , digestname);
1256+ for (i = 0 ; i < md_len; i++)
1257+ printf (" %02x" , md_value[i]);
1258+ printf (" \n " );
1259+
1260+ if (memcmp (md_value, expected, md_len) != 0 )
1261+ {
1262+ handleError (" Result does not match expected value" );
1263+ goto end;
1264+ }
1265+
1266+ // Clear last 8 bytes of state (Marvin32 checksum of SymCrypt export)
1267+ OPENSSL_cleanse (exported_state + export_state_size - 8 , 8 );
1268+ recompute_checksum = 1 ;
1269+
1270+ printf (" Command EVP_MD_CTX_new\n " );
1271+ mdctx = EVP_MD_CTX_new ();
1272+ printf (" Command EVP_DigestInit_ex\n " );
1273+ EVP_DigestInit_ex2 (mdctx, md, params);
1274+
1275+ printf (" Command EVP_DigestUpdate\n " );
1276+ EVP_DigestUpdate (mdctx, mess2, strlen (mess2));
1277+ printf (" Command EVP_DigestFinal_ex\n " );
1278+ EVP_DigestFinal_ex (mdctx, md_value, &md_len);
1279+ printf (" Command EVP_MD_CTX_free\n " );
1280+ EVP_MD_CTX_free (mdctx);
1281+
1282+ printf (" Digest (Recomputed checksum) (%s) : \t " , digestname);
1283+ for (i = 0 ; i < md_len; i++)
1284+ printf (" %02x" , md_value[i]);
1285+ printf (" \n " );
1286+
1287+ if (memcmp (md_value, expected, md_len) != 0 )
1288+ {
1289+ handleError (" Result does not match expected value" );
1290+ goto end;
1291+ }
1292+
1293+ result = true ;
1294+
1295+ end:
1296+ EVP_MD_free (md);
1297+
1298+ printf (" %s" , SeparatorLine);
1299+ return result;
1300+ }
1301+ #endif
1302+
1303+ typedef struct {
1304+ const char *digestname;
1305+ const char *expected;
1306+ size_t export_state_size;
1307+ } SCOSSL_DIGEST_TEST_CASE;
1308+
1309+ // TestDigests tests hash state export and import if supported.
1310+ // This functionality is added by the SymCrypt provider and is
1311+ // only available when the engine is not loaded. If the engine
1312+ // is loaded, OpenSSL will use it for digests and the import/export
1313+ // functionality will not be available.
1314+ void TestDigests (bool useEngine)
1315+ {
1316+ char mess1[] = " Test Message1234567" ;
1317+ char mess2[] = " Hello World" ;
1318+ char expected_md_value[EVP_MAX_MD_SIZE];
1319+ unsigned int md_len=32 , i, j;
1320+ const char *digestname, *expected;
1321+
1322+ const SCOSSL_DIGEST_TEST_CASE digest_test_cases[] =
1323+ {
1324+ {" MD5" , " 4d1074949b1b41311eff270f84804433" ,
1325+ SYMCRYPT_MD5_STATE_EXPORT_SIZE},
1326+ {" SHA1" , " fc5f088a0395c8ad887ff531333b0405a7dbb098" ,
1327+ SYMCRYPT_SHA1_STATE_EXPORT_SIZE},
1328+ {" SHA224" , " 6fe30848035b96665e1f02eae7b2bcafa600e466d80bc1b93b6094cc" ,
1329+ SYMCRYPT_SHA224_STATE_EXPORT_SIZE},
1330+ {" SHA256" , " 6810f8a56670662c0e7a10ca415f270eae0aeb1f7b153d02668ae5e7143fcc40" ,
1331+ SYMCRYPT_SHA256_STATE_EXPORT_SIZE},
1332+ {" SHA384" , " 1f051f47c1b29006383bbc07f0f14b4cb81bac3c78604e2164e89acddf701264f9b5664686412b17624f67baf3af28a7" ,
1333+ SYMCRYPT_SHA384_STATE_EXPORT_SIZE},
1334+ {" SHA512" , " 070820b341fd2a45d28b390e67e3f3e4ce30c5b345540e1f587ccfbe94e22c3079f6c28e906b95871a21d1871a198c581ee9a71b7bcaec5f542d026f5dc87183" ,
1335+ SYMCRYPT_SHA512_STATE_EXPORT_SIZE},
1336+ #if OPENSSL_VERSION_MAJOR == 3
1337+ {" SHA512-224" , " ff3da53a61923d460f85f98de06c6312092d0be3712ee611c4fe0a19" ,
1338+ SYMCRYPT_SHA512_224_STATE_EXPORT_SIZE},
1339+ {" SHA512-256" , " 036dbd97db1e37aabe6ded8ef9ead203e9adb02ad5596ac5af072dd7374993a0" ,
1340+ SYMCRYPT_SHA512_256_STATE_EXPORT_SIZE},
1341+ {" SHA3-224" , " 489a032b8923a05eca5b40f2ed9838f218c65bd082acc48fa2067213" ,
1342+ SYMCRYPT_SHA3_224_STATE_EXPORT_SIZE},
1343+ {" SHA3-256" , " 375e793a6d4e4947658e78cb697789434b8279feb2ec9595d03e44473ac478f6" ,
1344+ SYMCRYPT_SHA3_256_STATE_EXPORT_SIZE},
1345+ {" SHA3-384" , " 1d47002a9e96d5b6bdd70d476fd2038e50ac3eb0d4202b4eb988f02185fbb9c85cb7ed62804ddaff894e84d62e5832f2" ,
1346+ SYMCRYPT_SHA3_384_STATE_EXPORT_SIZE},
1347+ {" SHA3-512" , " bf63544ae59243a5419a3ff5f598352eb1409d41dc746c9e9d5f258cddaff4e7f7b9d9ae13e90eb07f27e4e157b3fcf796f6554732a2e78a621f7313aba827f3" ,
1348+ SYMCRYPT_SHA3_512_STATE_EXPORT_SIZE},
1349+ #endif
1350+ };
1351+
1352+ for (i = 0 ; i < sizeof (digest_test_cases)/sizeof (digest_test_cases[0 ]); i++)
1353+ {
1354+ // Convert expected hex string to binary
1355+ for (int j = 0 ; digest_test_cases[i].expected [j] != ' \0 ' && digest_test_cases[i].expected [j + 1 ] != ' \0 ' ; j += 2 )
1356+ {
1357+ expected_md_value[j / 2 ] = OPENSSL_hexchar2int (digest_test_cases[i].expected [j]) << 4 |
1358+ OPENSSL_hexchar2int (digest_test_cases[i].expected [j + 1 ]);
1359+ }
1360+
1361+ TestDigest (digest_test_cases[i].digestname , expected_md_value);
1362+
1363+ #if OPENSSL_VERSION_MAJOR == 3
1364+ if (!useEngine && digest_test_cases[i].export_state_size > 0 )
1365+ {
1366+ TestDigestImportExport (digest_test_cases[i].digestname , expected_md_value, digest_test_cases[i].export_state_size );
1367+ }
1368+ #endif
1369+ }
11821370
11831371 unsigned char md1[SHA256_DIGEST_LENGTH]; // 32 bytes
11841372 SHA256_CTX context;
@@ -1377,15 +1565,15 @@ void TestAesXts()
13771565{
13781566 unsigned char plaintext[8192 ];
13791567 int plaintext_len = 64 ;
1380- unsigned char iv[8 ];
1568+ unsigned char iv[16 ];
13811569 unsigned char key[64 ];
13821570
13831571 while (!RAND_bytes (key, 64 ));
1384- while (!RAND_bytes (iv, 8 ));
1572+ while (!RAND_bytes (iv, 16 ));
13851573 while (!RAND_bytes (plaintext, plaintext_len));
13861574
1387- TestAesCipher (" EVP_aes_128_xts" , EVP_aes_128_xts (), key, 32 , iv, 8 , plaintext, plaintext_len);
1388- TestAesCipher (" EVP_aes_256_xts" , EVP_aes_256_xts (), key, 64 , iv, 8 , plaintext, plaintext_len);
1575+ TestAesCipher (" EVP_aes_128_xts" , EVP_aes_128_xts (), key, 32 , iv, 16 , plaintext, plaintext_len);
1576+ TestAesCipher (" EVP_aes_256_xts" , EVP_aes_256_xts (), key, 64 , iv, 16 , plaintext, plaintext_len);
13891577
13901578 printf (" %s" , SeparatorLine);
13911579 return ;
@@ -2300,19 +2488,85 @@ void TestSshKdf(void)
23002488
23012489int main (int argc, char ** argv)
23022490{
2491+ #if OPENSSL_VERSION_MAJOR == 3
2492+ OSSL_PROVIDER *symcrypt_provider = NULL ;
2493+ #endif
23032494 int scossl_log_level = SCOSSL_LOG_LEVEL_NO_CHANGE;
23042495 int scossl_ossl_ERR_level = SCOSSL_LOG_LEVEL_NO_CHANGE;
2305- if (argc >= 2 ) {
2306- scossl_log_level = atoi (argv[1 ]);
2307- }
2308- if (argc >= 3 ) {
2309- scossl_ossl_ERR_level = atoi (argv[2 ]);
2496+ bool useEngine = true ;
2497+
2498+ for (int i = 1 ; i < argc; i++)
2499+ {
2500+ if (strcmp (argv[i], " --log-level" ) == 0 )
2501+ {
2502+ if (argc < ++i)
2503+ {
2504+ printf (" Missing log level" );
2505+ return 0 ;
2506+ }
2507+
2508+ scossl_log_level = atoi (argv[i]);
2509+ }
2510+ else if (strcmp (argv[i], " --err-level" ) == 0 )
2511+ {
2512+ if (argc < ++i)
2513+ {
2514+ printf (" Missing log level" );
2515+ return 0 ;
2516+ }
2517+
2518+ scossl_ossl_ERR_level = atoi (argv[i]);
2519+ }
2520+ #if OPENSSL_VERSION_MAJOR == 3
2521+ else if (strcmp (argv[i], " --provider-path" ) == 0 )
2522+ {
2523+ if (argc < ++i)
2524+ {
2525+ printf (" Missing provider path" );
2526+ return 0 ;
2527+ }
2528+
2529+ if (!OSSL_PROVIDER_set_default_search_path (NULL , argv[i]))
2530+ {
2531+ {
2532+ handleOpenSSLError (" Failed to set provider path" );
2533+ return 0 ;
2534+ }
2535+ }
2536+
2537+ if ((symcrypt_provider = OSSL_PROVIDER_load (NULL , " symcryptprovider" )) == NULL )
2538+ {
2539+ handleOpenSSLError (" Failed to load symcrypt provider" );
2540+ return 0 ;
2541+ }
2542+ }
2543+ else if (strcmp (argv[i], " --no-engine" ) == 0 )
2544+ {
2545+ useEngine = false ;
2546+ }
2547+ #endif
2548+ else if (strcmp (argv[i], " --help" ) == 0 )
2549+ {
2550+ printf (" Usage: SslPlay <options>\n " );
2551+ printf (" Options:\n " );
2552+ printf (" --log-level <log level> Specify the SCOSSL logging level\n " );
2553+ printf (" --err-level <err level> Specify the SCOSSL error logging level\n " );
2554+ #if OPENSSL_VERSION_MAJOR == 3
2555+ printf (" --provider-path <provider path> Specify a directory to locate the symcrypt provider\n " );
2556+ printf (" --no-engine Disable the SymCrypt engine for testing\n " );
2557+ #endif
2558+ return 0 ;
2559+ }
23102560 }
2561+
23112562 SCOSSL_set_trace_level (scossl_log_level, scossl_ossl_ERR_level);
2312- SCOSSL_ENGINE_Initialize ();
2563+ if (useEngine)
2564+ {
2565+ SCOSSL_ENGINE_Initialize ();
2566+ }
23132567 bio_err = BIO_new_fp (stdout, BIO_NOCLOSE);
23142568
2315- TestDigests ();
2569+ TestDigests (useEngine );
23162570 TestCiphers ();
23172571 TestHKDF ();
23182572 TestTls1Prf ();
@@ -2325,6 +2579,10 @@ int main(int argc, char** argv)
23252579 TestSshKdf ();
23262580#endif
23272581
2582+ #if OPENSSL_VERSION_MAJOR == 3
2583+ OSSL_PROVIDER_unload (symcrypt_provider);
2584+ #endif
2585+
23282586 BIO_free (bio_err);
23292587 return 0 ;
23302588}
0 commit comments