#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cryptech.h" #include "test-rsa.h" #include "test-modexp-for-pavel.h" int quiet = 0; int repeat = 0; int tc_width(off_t offset, uint32_t length) { length = htonl(length); // ! uint8_t width[4]; memcpy(width, &length, 4); return tc_write(offset, width, sizeof(width)); } /* * Utility to madly swap 32-bit words within an operand so that the * first word becomes the last word and so forth. */ static void two_card_monty(void *output, const void * const input, const size_t byte_count) { const size_t word_count = byte_count / 4; const uint32_t * const i32 = input; uint32_t * const o32 = output; int i; assert(byte_count % 4 == 0); for (i = 0; i < word_count; i++) o32[i] = i32[word_count - i - 1]; } /* * Clone operand into a reversed buffer. Necessary lack of curly * braces makes this unsuitable for use in library code, but it * simplifies test setup here. */ #define clone_reversed(_clone, _orig) \ uint8_t _clone[sizeof(_orig)]; \ two_card_monty(_clone, _orig, sizeof(_orig)) /* TC0: Read name and version from ModExpS6 core. */ int TC0(void) { uint8_t name0[4] = { 'm', 'o', 'd', 'e'}; uint8_t name1[4] = { 'x', 'p', 's', '6'}; uint8_t version[4] = { '0', '.', '1', '0'}; if (!quiet) printf("TC0: Reading name and version words from ModExpS6 core.\n"); return tc_expected(MODEXPS6_ADDR_NAME0, name0, sizeof(name0)) || tc_expected(MODEXPS6_ADDR_NAME1, name1, sizeof(name1)) || tc_expected(MODEXPS6_ADDR_VERSION, version, sizeof(version)); } /* TC1: Fast single 1024-bit message. */ int TC1(void) { int ret; if (!quiet) printf("TC1: Sign 1024-bit message (fast & unsafe public mode).\n"); /* Change order of 32-bit words for all the operands (first word becomes last word, and so on...) */ clone_reversed(modulus, n_1024); clone_reversed(message, m_1024); clone_reversed(exponent, d_1024); clone_reversed(result, s_1024); /* Set fast mode */ /*uint8_t mode_slow_secure[] = {0, 0, 0, 0};*/ uint8_t mode_fast_unsafe[] = {0, 0, 0, 1}; tc_write(MODEXPS6_ADDR_MODE, mode_fast_unsafe, sizeof(mode_fast_unsafe)); /* Set new modulus size */ tc_width(MODEXPS6_ADDR_MODULUS_WIDTH, sizeof(modulus) * 8); // number of bits /* Write new modulus */ tc_write(MODEXPS6_ADDR_MODULUS, modulus, sizeof(modulus)); /* Pre-calculate speed-up coefficient */ tc_init(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_ready(MODEXPS6_ADDR_STATUS); /* Write new message */ tc_write(MODEXPS6_ADDR_MESSAGE, message, sizeof(message)); /* Set new exponent length */ tc_width(MODEXPS6_ADDR_EXPONENT_WIDTH, sizeof(exponent) * 8); // number of bits /* Write new exponent */ tc_write(MODEXPS6_ADDR_EXPONENT, exponent, sizeof(exponent)); /* Start calculation */ tc_next(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_valid(MODEXPS6_ADDR_STATUS); /* Compare actual result with expected value */ ret = tc_expected(MODEXPS6_ADDR_RESULT, result, sizeof(result)); return ret; } /* TC2: Slow single 1024-bit message. */ int TC2(void) { int ret; if (!quiet) printf("TC2: Sign 1024-bit message (slow & secure private mode).\n"); /* Change order of 32-bit words for all the operands (first word becomes last word, and so on...) */ clone_reversed(modulus, n_1024); clone_reversed(message, m_1024); clone_reversed(exponent, d_1024); clone_reversed(result, s_1024); /* Set slow mode */ uint8_t mode_slow_secure[] = {0, 0, 0, 0}; /*uint8_t mode_fast_unsafe[] = {0, 0, 0, 1};*/ tc_write(MODEXPS6_ADDR_MODE, mode_slow_secure, sizeof(mode_slow_secure)); /* Set new modulus size */ tc_width(MODEXPS6_ADDR_MODULUS_WIDTH, sizeof(modulus) * 8); // number of bits /* Write new modulus */ tc_write(MODEXPS6_ADDR_MODULUS, modulus, sizeof(modulus)); /* Pre-calculate speed-up coefficient */ tc_init(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_ready(MODEXPS6_ADDR_STATUS); /* Write new message */ tc_write(MODEXPS6_ADDR_MESSAGE, message, sizeof(message)); /* Set new exponent length */ tc_width(MODEXPS6_ADDR_EXPONENT_WIDTH, sizeof(exponent) * 8); // number of bits /* Write new exponent */ tc_write(MODEXPS6_ADDR_EXPONENT, exponent, sizeof(exponent)); /* Start calculation */ tc_next(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_valid(MODEXPS6_ADDR_STATUS); /* Compare actual result with expected value */ ret = tc_expected(MODEXPS6_ADDR_RESULT, result, sizeof(result)); return ret; } /* TC3: Fast single 2048-bit message. */ int TC3(void) { int ret; if (!quiet) printf("TC3: Sign 2048-bit message (fast & unsafe public mode).\n"); /* Change order of 32-bit words for all the operands (first word becomes last word, and so on...) */ clone_reversed(modulus, n_2048); clone_reversed(message, m_2048); clone_reversed(exponent, d_2048); clone_reversed(result, s_2048); /* Set fast mode */ /*uint8_t mode_slow_secure[] = {0, 0, 0, 0};*/ uint8_t mode_fast_unsafe[] = {0, 0, 0, 1}; tc_write(MODEXPS6_ADDR_MODE, mode_fast_unsafe, sizeof(mode_fast_unsafe)); /* Set new modulus size */ tc_width(MODEXPS6_ADDR_MODULUS_WIDTH, sizeof(modulus) * 8); // number of bits /* Write new modulus */ tc_write(MODEXPS6_ADDR_MODULUS, modulus, sizeof(modulus)); /* Pre-calculate speed-up coefficient */ tc_init(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_ready(MODEXPS6_ADDR_STATUS); /* Write new message */ tc_write(MODEXPS6_ADDR_MESSAGE, message, sizeof(message)); /* Set new exponent length */ tc_width(MODEXPS6_ADDR_EXPONENT_WIDTH, sizeof(exponent) * 8); // number of bits /* Write new exponent */ tc_write(MODEXPS6_ADDR_EXPONENT, exponent, sizeof(exponent)); /* Start calculation */ tc_next(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_valid(MODEXPS6_ADDR_STATUS); /* Compare actual result with expected value */ ret = tc_expected(MODEXPS6_ADDR_RESULT, result, sizeof(result)); return ret; } /* TC4: Slow single 2048-bit message. */ int TC4(void) { int ret; if (!quiet) printf("TC4: Sign 2048-bit message (slow & secure private mode).\n"); /* Change order of 32-bit words for all the operands (first word becomes last word, and so on...) */ clone_reversed(modulus, n_2048); clone_reversed(message, m_2048); clone_reversed(exponent, d_2048); clone_reversed(result, s_2048); /* Set slow mode */ uint8_t mode_slow_secure[] = {0, 0, 0, 0}; /*uint8_t mode_fast_unsafe[] = {0, 0, 0, 1};*/ tc_write(MODEXPS6_ADDR_MODE, mode_slow_secure, sizeof(mode_slow_secure)); /* Set new modulus size */ tc_width(MODEXPS6_ADDR_MODULUS_WIDTH, sizeof(modulus) * 8); // number of bits /* Write new modulus */ tc_write(MODEXPS6_ADDR_MODULUS, modulus, sizeof(modulus)); /* Pre-calculate speed-up coefficient */ tc_init(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_ready(MODEXPS6_ADDR_STATUS); /* Write new message */ tc_write(MODEXPS6_ADDR_MESSAGE, message, sizeof(message)); /* Set new exponent length */ tc_width(MODEXPS6_ADDR_EXPONENT_WIDTH, sizeof(exponent) * 8); // number of bits /* Write new exponent */ tc_write(MODEXPS6_ADDR_EXPONENT, exponent, sizeof(exponent)); /* Start calculation */ tc_next(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_valid(MODEXPS6_ADDR_STATUS); /* Compare actual result with expected value */ ret = tc_expected(MODEXPS6_ADDR_RESULT, result, sizeof(result)); return ret; } /* TC5: Fast single 4096-bit message. */ int TC5(void) { int ret; if (!quiet) printf("TC5: Sign 4096-bit message (fast & unsafe public mode).\n"); /* Change order of 32-bit words for all the operands (first word becomes last word, and so on...) */ clone_reversed(modulus, n_4096); clone_reversed(message, m_4096); clone_reversed(exponent, d_4096); clone_reversed(result, s_4096); /* Set fast mode */ /*uint8_t mode_slow_secure[] = {0, 0, 0, 0};*/ uint8_t mode_fast_unsafe[] = {0, 0, 0, 1}; tc_write(MODEXPS6_ADDR_MODE, mode_fast_unsafe, sizeof(mode_fast_unsafe)); /* Set new modulus size */ tc_width(MODEXPS6_ADDR_MODULUS_WIDTH, sizeof(modulus) * 8); // number of bits /* Write new modulus */ tc_write(MODEXPS6_ADDR_MODULUS, modulus, sizeof(modulus)); /* Pre-calculate speed-up coefficient */ tc_init(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_ready(MODEXPS6_ADDR_STATUS); /* Write new message */ tc_write(MODEXPS6_ADDR_MESSAGE, message, sizeof(message)); /* Set new exponent length */ tc_width(MODEXPS6_ADDR_EXPONENT_WIDTH, sizeof(exponent) * 8); // number of bits /* Write new exponent */ tc_write(MODEXPS6_ADDR_EXPONENT, exponent, sizeof(exponent)); /* Start calculation */ tc_next(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_valid(MODEXPS6_ADDR_STATUS); /* Compare actual result with expected value */ ret = tc_expected(MODEXPS6_ADDR_RESULT, result, sizeof(result)); return ret; } /* TC6: Slow single 4096-bit message. */ int TC6(void) { int ret; if (!quiet) printf("TC6: Sign 4096-bit message (slow & secure private mode).\n"); /* Change order of 32-bit words for all the operands (first word becomes last word, and so on...) */ clone_reversed(modulus, n_4096); clone_reversed(message, m_4096); clone_reversed(exponent, d_4096); clone_reversed(result, s_4096); /* Set slow mode */ uint8_t mode_slow_secure[] = {0, 0, 0, 0}; /*uint8_t mode_fast_unsafe[] = {0, 0, 0, 1};*/ tc_write(MODEXPS6_ADDR_MODE, mode_slow_secure, sizeof(mode_slow_secure)); /* Set new modulus size */ tc_width(MODEXPS6_ADDR_MODULUS_WIDTH, sizeof(modulus) * 8); // number of bits /* Write new modulus */ tc_write(MODEXPS6_ADDR_MODULUS, modulus, sizeof(modulus)); /* Pre-calculate speed-up coefficient */ tc_init(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_ready(MODEXPS6_ADDR_STATUS); /* Write new message */ tc_write(MODEXPS6_ADDR_MESSAGE, message, sizeof(message)); /* Set new exponent length */ tc_width(MODEXPS6_ADDR_EXPONENT_WIDTH, sizeof(exponent) * 8); // number of bits /* Write new exponent */ tc_write(MODEXPS6_ADDR_EXPONENT, exponent, sizeof(exponent)); /* Start calculation */ tc_next(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_valid(MODEXPS6_ADDR_STATUS); /* Compare actual result with expected value */ ret = tc_expected(MODEXPS6_ADDR_RESULT, result, sizeof(result)); return ret; } /* TC7: Signing of multiple 1024-bit messages with same key. */ int TC7(void) { int ret; if (!quiet) printf("TC7: Sign several 1024-bit messages (without pre-calculation every time).\n"); /* Change order of 32-bit words for all the operands (first word becomes last word, and so on...) */ clone_reversed(modulus, n_1024); clone_reversed(exponent, d_1024); clone_reversed(message_0, m_1024_0); clone_reversed(message_1, m_1024_1); clone_reversed(message_2, m_1024_2); clone_reversed(message_3, m_1024_3); clone_reversed(result_0, s_1024_0); clone_reversed(result_1, s_1024_1); clone_reversed(result_2, s_1024_2); clone_reversed(result_3, s_1024_3); /* Set fast mode */ /*uint8_t mode_slow_secure[] = {0, 0, 0, 0};*/ uint8_t mode_fast_unsafe[] = {0, 0, 0, 1}; tc_write(MODEXPS6_ADDR_MODE, mode_fast_unsafe, sizeof(mode_fast_unsafe)); /* Set new modulus size */ tc_width(MODEXPS6_ADDR_MODULUS_WIDTH, sizeof(modulus) * 8); // number of bits /* Write new modulus */ tc_write(MODEXPS6_ADDR_MODULUS, modulus, sizeof(modulus)); /* Pre-calculate speed-up coefficient */ tc_init(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_ready(MODEXPS6_ADDR_STATUS); /* Set new exponent length */ tc_width(MODEXPS6_ADDR_EXPONENT_WIDTH, sizeof(exponent) * 8); // number of bits /* Write new exponent */ tc_write(MODEXPS6_ADDR_EXPONENT, exponent, sizeof(exponent)); { /* Write new message #0 */ tc_write(MODEXPS6_ADDR_MESSAGE, message_0, sizeof(message_0)); /* Start calculation */ tc_next(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_valid(MODEXPS6_ADDR_STATUS); /* Compare actual result with expected value */ ret = tc_expected(MODEXPS6_ADDR_RESULT, result_0, sizeof(result_0)); if (ret) return 1; } { /* Write new message #1 */ tc_write(MODEXPS6_ADDR_MESSAGE, message_1, sizeof(message_1)); /* Start calculation */ tc_next(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_valid(MODEXPS6_ADDR_STATUS); /* Compare actual result with expected value */ ret = tc_expected(MODEXPS6_ADDR_RESULT, result_1, sizeof(result_1)); if (ret) return 1; } { /* Write new message #2 */ tc_write(MODEXPS6_ADDR_MESSAGE, message_2, sizeof(message_2)); /* Start calculation */ tc_next(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_valid(MODEXPS6_ADDR_STATUS); /* Compare actual result with expected value */ ret = tc_expected(MODEXPS6_ADDR_RESULT, result_2, sizeof(result_2)); if (ret) return 1; } { /* Write new message #3 */ tc_write(MODEXPS6_ADDR_MESSAGE, message_3, sizeof(message_3)); /* Start calculation */ tc_next(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_valid(MODEXPS6_ADDR_STATUS); /* Compare actual result with expected value */ ret = tc_expected(MODEXPS6_ADDR_RESULT, result_3, sizeof(result_3)); if (ret) return 1; } return 0; } /* TC8: Fast 4096-bit message verification. */ int TC8(void) { int ret; if (!quiet) printf("TC8: Verify 4096-bit message (fast mode using public exponent).\n"); /* Change order of 32-bit words for all the operands (first word becomes last word, and so on...) */ clone_reversed(modulus, n_4096); clone_reversed(message, s_4096); clone_reversed(exponent, e_4096); clone_reversed(result, m_4096); /* Set fast mode */ /*uint8_t mode_slow_secure[] = {0, 0, 0, 0};*/ uint8_t mode_fast_unsafe[] = {0, 0, 0, 1}; tc_write(MODEXPS6_ADDR_MODE, mode_fast_unsafe, sizeof(mode_fast_unsafe)); /* Set new modulus size */ tc_width(MODEXPS6_ADDR_MODULUS_WIDTH, sizeof(modulus) * 8); // number of bits /* Write new modulus */ tc_write(MODEXPS6_ADDR_MODULUS, modulus, sizeof(modulus)); /* Pre-calculate speed-up coefficient */ tc_init(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_ready(MODEXPS6_ADDR_STATUS); /* Write new message */ tc_write(MODEXPS6_ADDR_MESSAGE, message, sizeof(message)); /* Set new exponent length */ #if 1 tc_width(MODEXPS6_ADDR_EXPONENT_WIDTH, 18); // number of bits #else tc_width(MODEXPS6_ADDR_EXPONENT_WIDTH, 24); // number of bits #endif /* Write new exponent */ tc_write(MODEXPS6_ADDR_EXPONENT, exponent, sizeof(exponent)); /* Start calculation */ tc_next(MODEXPS6_ADDR_CTRL); /* Wait while core is calculating */ tc_wait_valid(MODEXPS6_ADDR_STATUS); /* Compare actual result with expected value */ ret = tc_expected(MODEXPS6_ADDR_RESULT, result, sizeof(result)); return ret; } /* signal handler for ctrl-c to end repeat testing */ unsigned long iter = 0; struct timeval tv_start, tv_end; void sighandler(int unused) { double tv_diff; gettimeofday(&tv_end, NULL); tv_diff = (double)(tv_end.tv_sec - tv_start.tv_sec) + (double)(tv_end.tv_usec - tv_start.tv_usec)/1000000; printf("\n%lu iterations in %.3f seconds (%.3f iterations/sec)\n", iter, tv_diff, (double)iter/tv_diff); exit(EXIT_SUCCESS); } int main(int argc, char *argv[]) { typedef int (*tcfp)(void); tcfp all_tests[] = { TC0, TC1, TC2, TC3, TC4, TC5, TC6, TC7, TC8 }; char *usage = "Usage: %s [-h] [-d] [-q] [-r] tc...\n"; int i, j, opt; while ((opt = getopt(argc, argv, "h?dqr")) != -1) { switch (opt) { case 'h': case '?': printf(usage, argv[0]); return EXIT_SUCCESS; case 'd': tc_set_debug(1); break; case 'q': quiet = 1; break; case 'r': repeat = 1; break; default: fprintf(stderr, usage, argv[0]); return EXIT_FAILURE; } } /* repeat one test until interrupted */ if (repeat) { tcfp tc; if (optind != argc - 1) { fprintf(stderr, "only one test case can be repeated\n"); return EXIT_FAILURE; } j = atoi(argv[optind]); if (j < 0 || j >= sizeof(all_tests)/sizeof(all_tests[0])) { fprintf(stderr, "invalid test number %s\n", argv[optind]); return EXIT_FAILURE; } tc = (all_tests[j]); srand(time(NULL)); signal(SIGINT, sighandler); gettimeofday(&tv_start, NULL); while (1) { ++iter; if ((iter & 0xffff) == 0) { printf("."); fflush(stdout); } if (tc() != 0) sighandler(0); } return EXIT_SUCCESS; /*NOTREACHED*/ } /* no args == run all tests */ if (optind >= argc) { for (j = 0; j < sizeof(all_tests)/sizeof(all_tests[0]); ++j) if (all_tests[j]() != 0) return EXIT_FAILURE; return EXIT_SUCCESS; } /* run one or more tests (by number) or groups of tests (by name) */ for (i = optind; i < argc; ++i) { if (strcmp(argv[i], "all") == 0) { for (j = 0; j < sizeof(all_tests)/sizeof(all_tests[0]); ++j) if (all_tests[j]() != 0) return EXIT_FAILURE; } else if (isdigit(argv[i][0]) && (((j = atoi(argv[i])) >= 0) && (j < sizeof(all_tests)/sizeof(all_tests[0])))) { if (all_tests[j]() != 0) return EXIT_FAILURE; } else { fprintf(stderr, "unknown test case %s\n", argv[i]); return EXIT_FAILURE; } } return EXIT_SUCCESS; }