Improvement on the digest testcase: 2 new testcases with generated variable input data. do_DigestVar() for single digest with variable data size and do_DigestUpdateVar() for multipart digest with var data size. There comes a new command line parameter with this change: -datasize <size> with size may be a number optional followed by k or m for kilobyte or megabyte. If this parameter is not given, default is BIG_REQUEST which is currently 4k.
Signed-off-by: Harald Freudenberger <[email protected]> --- testcases/crypto/digest_func.c | 281 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 280 insertions(+), 1 deletion(-) diff --git a/testcases/crypto/digest_func.c b/testcases/crypto/digest_func.c index cfa4427..d5ba9d9 100644 --- a/testcases/crypto/digest_func.c +++ b/testcases/crypto/digest_func.c @@ -11,6 +11,11 @@ #include "common.c" #define MAX_HASH_LEN 512 +#define MIN_DATA_SIZE 32 + +// holds value of the -datasize argument if given +static unsigned data_size = 0; + /** Tests messge digest with published test vectors. **/ CK_RV do_Digest(struct digest_test_suite_info *tsuite) @@ -110,6 +115,101 @@ testcase_cleanup: return rc; } +/** same as do_Digest() but with variable generated input data **/ +CK_RV do_DigestVar(struct digest_test_suite_info *tsuite, size_t datasize) +{ + int i, j; + CK_BYTE *data; + CK_ULONG data_len; + CK_BYTE actual[MAX_HASH_SIZE]; + CK_ULONG actual_len; + CK_MECHANISM mech; + + CK_SESSION_HANDLE session; + CK_SLOT_ID slot_id = SLOT_ID; + CK_ULONG flags; + CK_RV rc; + + // begin test suite + testsuite_begin("%s Digest with %u bytes", tsuite->name, (unsigned)datasize); + testcase_rw_session(); + + // allocate buffers + if (datasize < MIN_DATA_SIZE) datasize = MIN_DATA_SIZE; + data = (CK_BYTE*) malloc(datasize); + if (!data) { + fprintf(stderr, "Memory Allocation Error, aborting test run !!!\n"); + exit(1); + } + + // skip test if mech is not supported with this slot + if (! mech_supported(slot_id, tsuite->mech.mechanism)){ + testsuite_skip(tsuite->tvcount, + "mechanism %s is not supported with slot %ld", + tsuite->name, slot_id); + goto testcase_cleanup; + } + + // iterate over test vectors + for(i = 0; i < tsuite->tvcount; i++){ + + /** begin test **/ + testcase_begin("Starting %s Digest with test vector %d.", + tsuite->name, i); + + rc = CKR_OK; // set rc + + // clear buffers + memset(actual, 0, sizeof(actual)); + + // set up data buffer + data_len = datasize; + for (j=0; j < data_len; j++) + data[i] = (CK_BYTE) j; + + // get mech + mech = tsuite->mech; + + // initialize single digest + rc = funcs->C_DigestInit(session, &mech); + if (rc != CKR_OK) { + testcase_error("C_DigestInit rc=%s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + actual_len = sizeof(actual); // set digest buffer size + + // do single digest + rc = funcs->C_Digest(session, data, data_len, actual, &actual_len); + if (rc != CKR_OK) { + testcase_error("C_Digest rc=%s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + // compare digest results with expected results + testcase_new_assertion(); + + // if hash was sucessful generated that's all we expect here + if (actual_len != tsuite->tv[i].hash_len) { + testcase_fail("hashed data length does not match test vector's" + " hashed data length.\nexpected length=%ld, found " + "length=%ld.", + tsuite->tv[i].hash_len, actual_len); + } else { + testcase_pass("%s Digest with test vector %d and %u bytes of data passed.", + tsuite->name, i, (unsigned)datasize); + } + } + +testcase_cleanup: + rc = funcs->C_CloseAllSessions(slot_id); + if (rc != CKR_OK) { + testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); + } + free(data); + return rc; +} + /** Tests multipart message digest with published test vectors. **/ CK_RV do_DigestUpdate(struct digest_test_suite_info *tsuite) { @@ -220,6 +320,115 @@ testcase_cleanup: return rc; } +/** same as do_DigestUpdate() but with variable generated input data **/ +CK_RV do_DigestUpdateVar(struct digest_test_suite_info *tsuite, size_t datasize) +{ + int i, j; + CK_BYTE *data; + CK_ULONG data_len, data_done; + CK_BYTE actual[MAX_HASH_SIZE]; + CK_ULONG actual_len; + CK_MECHANISM mech; + + CK_SESSION_HANDLE session; + CK_SLOT_ID slot_id = SLOT_ID; + CK_ULONG flags; + CK_RV rc; + + // begin test + testsuite_begin("Starting %s Multipart Digest with %u bytes", + tsuite->name, (unsigned)datasize); + testcase_rw_session(); + + // allocate buffers + if (datasize < MIN_DATA_SIZE) datasize = MIN_DATA_SIZE; + data = (CK_BYTE*) malloc(datasize); + if (!data) { + fprintf(stderr, "Memory Allocation Error, aborting test run !!!\n"); + exit(1); + } + + // skip test if mech is not supported with this slot + if (! mech_supported(slot_id, tsuite->mech.mechanism)){ + testsuite_skip(tsuite->tvcount, + "mechanism %s is not supported with slot %ld", + tsuite->name, slot_id); + goto testcase_cleanup; + } + + // iterate over test vectors + for(i = 0; i < tsuite->tvcount; i++){ + + // begin test + testcase_begin("Starting %s Multipart Digest with test vector %d.", + tsuite->name, i); + + rc = CKR_OK; // set rc + + // clear buffers + memset(actual, 0, sizeof(actual)); + + // set up data buffer + data_done = 0; + data_len = datasize; + for (j=0; j < data_len; j++) + data[i] = (CK_BYTE) j; + + // get mechanism + mech = tsuite->mech; + + // initialize multipart digest + rc = funcs->C_DigestInit(session, &mech); + if (rc != CKR_OK) { + testcase_error("C_DigestInit rc=%s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + actual_len = sizeof(actual); + + // do multipart digest + while (data_done < data_len) { + CK_ULONG len = data_len - data_done; + if (len >= DIGEST_UPDATE_JUNK_SIZE) + len = DIGEST_UPDATE_JUNK_SIZE; + rc = funcs->C_DigestUpdate(session, data + data_done, len); + if (rc != CKR_OK) { + testcase_error("C_DigestUpdate rc=%s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + data_done += len; + } + + // finalize multipart digest + rc = funcs->C_DigestFinal(session, actual, &actual_len); + if (rc != CKR_OK) { + testcase_error("C_DigestFinal rc=%s", p11_get_ckr(rc)); + goto testcase_cleanup; + } + + // compare digest results with expected results + testcase_new_assertion(); + + // if hash was sucessful generated that's all we expect here + if (actual_len != tsuite->tv[i].hash_len) { + testcase_fail("hashed multipart data length does not " + "match test vector's hashed data length.\n"); + } else { + testcase_pass("%s Multipart Digest with test vector " + "%d and %u bytes of data passed.", + tsuite->name, i, (unsigned)datasize); + } + } + +testcase_cleanup: + rc = funcs->C_CloseAllSessions(slot_id); + if (rc != CKR_OK) { + testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); + } + free(data); + return rc; +} + /** Tests signature verification with published test vectors. **/ CK_RV do_SignVerify_HMAC(struct HMAC_TEST_SUITE_INFO *tsuite){ @@ -572,9 +781,14 @@ testcase_cleanup: } CK_RV digest_funcs() { - CK_RV rc; + CK_RV rc = CKR_OK; int i; + // set default data size for variable data tests + // if no value is given on the command line + if (data_size == 0) + data_size = BIG_REQUEST; + /** Digest tests **/ for (i = 0; i < NUM_DIGEST_TEST_SUITES; i++){ rc = do_Digest(&digest_test_suites[i]); @@ -583,6 +797,14 @@ CK_RV digest_funcs() { } } + /** Digest tests with variable data size **/ + for (i = 0; i < NUM_DIGEST_TEST_SUITES; i++){ + rc = do_DigestVar(&digest_test_suites[i], data_size); + if (rc && !no_stop) { + return rc; + } + } + /** Multipart Digest tests **/ for (i = 0; i < NUM_DIGEST_TEST_SUITES; i++){ rc = do_DigestUpdate(&digest_test_suites[i]); @@ -590,6 +812,15 @@ CK_RV digest_funcs() { return rc; } } + + /** Multipart Digest tests with variable data data size **/ + for (i = 0; i < NUM_DIGEST_TEST_SUITES; i++){ + rc = do_DigestUpdateVar(&digest_test_suites[i], data_size); + if (rc && !no_stop) { + return rc; + } + } + /** HMAC tests **/ for(i = 0; i < NUM_OF_HMAC_TEST_SUITES; i++){ rc = do_SignVerify_HMAC(&hmac_test_suites[i]); @@ -614,6 +845,51 @@ CK_RV digest_funcs() { return rc; } +/* + * Process arguments which are only local to this testcase + * and not recognized by do_ParseArgs from common.c. + * This function manipulates argv and argc (which is valid + * according to Posix) to hide the processed arguments and + * thus should be called before do_ParseArgs() is invoked. + */ +static int do_ParseLocalArgs(int *argc, char **argv) +{ + char c; + int i, j; + + for (i=1; i < *argc; i++) { + if (strcmp(argv[i], "-datasize") == 0) { + if (i+1 >= *argc) { + fprintf (stderr, "Wrong/missing argument for '-datasize'\n"); + return -1; + } + j = strlen(argv[i+1]); + if (j < 1) { + fprintf (stderr, "Wrong/missing numerical value for 'datasize'\n"); + return -1; + } + c = argv[i+1][j-1]; + j = atoi(argv[i+1]); + if (j < 1) { + fprintf (stderr, "Wrong/missing numerical value for 'datasize'\n"); + return -1; + } + data_size = j; + if (c == 'k' || c == 'K') + data_size *= 1024; + if (c == 'm' || c == 'M') + data_size *= 1024*1024; + // remove argv[i] and argv[i+1] (thats "-datasize <size>") from argv + for (j=i; j+2 < *argc; j++) + argv[j] = argv[j+2]; + *argc -= 2; + i--; + } + + } + return 0; +} + int main(int argc, char **argv) { CK_C_INITIALIZE_ARGS cinit_args; @@ -625,6 +901,9 @@ int main(int argc, char **argv) no_init = FALSE; no_stop = FALSE; + rc = do_ParseLocalArgs(&argc, argv); + if ( rc < 0) + return rc; rc = do_ParseArgs(argc, argv); if ( rc != 1) -- 1.7.9.5 ------------------------------------------------------------------------------ Infragistics Professional Build stunning WinForms apps today! Reboot your WinForms applications with our WinForms controls. Build a bridge from your legacy apps to the future. http://pubads.g.doubleclick.net/gampad/clk?id=153845071&iu=/4140/ostg.clktrk _______________________________________________ Opencryptoki-tech mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/opencryptoki-tech
