err_status_t cipher_array_delete(cipher_t *cipher_array[], int num_cipher) { int i; for (i=0; i < num_cipher; i++) { cipher_dealloc(cipher_array[i]); } free(cipher_array); return err_status_ok; }
int main (int argc, char *argv[]) { uint8_t buffer[2532]; unsigned int buf_len = 2500; int i, j; extern cipher_type_t aes_icm; #ifdef OPENSSL extern cipher_type_t aes_gcm_128_openssl; extern cipher_type_t aes_gcm_256_openssl; #endif cipher_t *c; uint8_t key[46] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; v128_t nonce; int num_trials = 500; int num_fail; printf("statistical tests driver\n"); v128_set_to_zero(&nonce); for (i=0; i < 2500; i++) buffer[i] = 0; /* run tests */ printf("running stat_tests on all-null buffer, expecting failure\n"); printf("monobit %d\n", stat_test_monobit(buffer)); printf("poker %d\n", stat_test_poker(buffer)); printf("runs %d\n", stat_test_runs(buffer)); for (i=0; i < 2500; i++) buffer[i] = rand(); printf("running stat_tests on rand(), expecting success\n"); printf("monobit %d\n", stat_test_monobit(buffer)); printf("poker %d\n", stat_test_poker(buffer)); printf("runs %d\n", stat_test_runs(buffer)); printf("running stat_tests on AES-128-ICM, expecting success\n"); /* set buffer to cipher output */ for (i=0; i < 2500; i++) buffer[i] = 0; err_check(cipher_type_alloc(&aes_icm, &c, 30, 0)); err_check(cipher_init(c, key)); err_check(cipher_set_iv(c, &nonce, direction_encrypt)); err_check(cipher_encrypt(c, buffer, &buf_len)); /* run tests on cipher outout */ printf("monobit %d\n", stat_test_monobit(buffer)); printf("poker %d\n", stat_test_poker(buffer)); printf("runs %d\n", stat_test_runs(buffer)); printf("runs test (please be patient): "); fflush(stdout); num_fail = 0; v128_set_to_zero(&nonce); for(j=0; j < num_trials; j++) { for (i=0; i < 2500; i++) buffer[i] = 0; nonce.v32[3] = i; err_check(cipher_set_iv(c, &nonce, direction_encrypt)); err_check(cipher_encrypt(c, buffer, &buf_len)); if (stat_test_runs(buffer)) { num_fail++; } } printf("%d failures in %d tests\n", num_fail, num_trials); printf("(nota bene: a small fraction of stat_test failures does not \n" "indicate that the random source is invalid)\n"); err_check(cipher_dealloc(c)); printf("running stat_tests on AES-256-ICM, expecting success\n"); /* set buffer to cipher output */ for (i=0; i < 2500; i++) buffer[i] = 0; err_check(cipher_type_alloc(&aes_icm, &c, 46, 0)); err_check(cipher_init(c, key)); err_check(cipher_set_iv(c, &nonce, direction_encrypt)); err_check(cipher_encrypt(c, buffer, &buf_len)); /* run tests on cipher outout */ printf("monobit %d\n", stat_test_monobit(buffer)); printf("poker %d\n", stat_test_poker(buffer)); printf("runs %d\n", stat_test_runs(buffer)); printf("runs test (please be patient): "); fflush(stdout); num_fail = 0; v128_set_to_zero(&nonce); for(j=0; j < num_trials; j++) { for (i=0; i < 2500; i++) buffer[i] = 0; nonce.v32[3] = i; err_check(cipher_set_iv(c, &nonce, direction_encrypt)); err_check(cipher_encrypt(c, buffer, &buf_len)); if (stat_test_runs(buffer)) { num_fail++; } } #ifdef OPENSSL { printf("running stat_tests on AES-128-GCM, expecting success\n"); /* set buffer to cipher output */ for (i=0; i < 2500; i++) { buffer[i] = 0; } err_check(cipher_type_alloc(&aes_gcm_128_openssl, &c, AES_128_GCM_KEYSIZE_WSALT, 8)); err_check(cipher_init(c, key)); err_check(cipher_set_iv(c, &nonce, direction_encrypt)); err_check(cipher_encrypt(c, buffer, &buf_len)); /* run tests on cipher outout */ printf("monobit %d\n", stat_test_monobit(buffer)); printf("poker %d\n", stat_test_poker(buffer)); printf("runs %d\n", stat_test_runs(buffer)); fflush(stdout); num_fail = 0; v128_set_to_zero(&nonce); for(j=0; j < num_trials; j++) { for (i=0; i < 2500; i++) { buffer[i] = 0; } nonce.v32[3] = i; err_check(cipher_set_iv(c, &nonce, direction_encrypt)); err_check(cipher_encrypt(c, buffer, &buf_len)); buf_len = 2500; if (stat_test_runs(buffer)) { num_fail++; } } printf("running stat_tests on AES-256-GCM, expecting success\n"); /* set buffer to cipher output */ for (i=0; i < 2500; i++) { buffer[i] = 0; } err_check(cipher_type_alloc(&aes_gcm_256_openssl, &c, AES_256_GCM_KEYSIZE_WSALT, 16)); err_check(cipher_init(c, key)); err_check(cipher_set_iv(c, &nonce, direction_encrypt)); err_check(cipher_encrypt(c, buffer, &buf_len)); /* run tests on cipher outout */ printf("monobit %d\n", stat_test_monobit(buffer)); printf("poker %d\n", stat_test_poker(buffer)); printf("runs %d\n", stat_test_runs(buffer)); fflush(stdout); num_fail = 0; v128_set_to_zero(&nonce); for(j=0; j < num_trials; j++) { for (i=0; i < 2500; i++) { buffer[i] = 0; } nonce.v32[3] = i; err_check(cipher_set_iv(c, &nonce, direction_encrypt)); err_check(cipher_encrypt(c, buffer, &buf_len)); buf_len = 2500; if (stat_test_runs(buffer)) { num_fail++; } } } #endif printf("%d failures in %d tests\n", num_fail, num_trials); printf("(nota bene: a small fraction of stat_test failures does not \n" "indicate that the random source is invalid)\n"); err_check(cipher_dealloc(c)); return 0; }
int main (int argc, char *argv[]) { cipher_t *c = NULL; err_status_t status; unsigned char test_key[32] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, }; int q; unsigned do_timing_test = 0; unsigned do_validation = 0; unsigned do_array_timing_test = 0; /* process input arguments */ while (1) { q = getopt(argc, argv, "tva"); if (q == -1) { break; } switch (q) { case 't': do_timing_test = 1; break; case 'v': do_validation = 1; break; case 'a': do_array_timing_test = 1; break; default: usage(argv[0]); } } printf("cipher test driver\n" "David A. McGrew\n" "Cisco Systems, Inc.\n"); if (!do_validation && !do_timing_test && !do_array_timing_test) { usage(argv[0]); } /* arry timing (cache thrash) test */ if (do_array_timing_test) { int max_num_cipher = 1 << 16; /* number of ciphers in cipher_array */ int num_cipher; for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) { cipher_driver_test_array_throughput(&null_cipher, 0, num_cipher); } for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) { cipher_driver_test_array_throughput(&aes_icm_openssl, 30, num_cipher); } for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) { cipher_driver_test_array_throughput(&aes_icm_192_openssl, 38, num_cipher); } for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) { cipher_driver_test_array_throughput(&aes_icm_256_openssl, 46, num_cipher); } for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) { cipher_driver_test_array_throughput(&aes_gcm_128_8_openssl, 16, num_cipher); } } if (do_validation) { cipher_driver_self_test(&null_cipher); cipher_driver_self_test(&aes_icm_openssl); cipher_driver_self_test(&aes_icm_192_openssl); cipher_driver_self_test(&aes_icm_256_openssl); cipher_driver_self_test(&aes_gcm_128_8_openssl); } /* do timing and/or buffer_test on null_cipher */ status = cipher_type_alloc(&null_cipher, &c, 0); check_status(status); status = cipher_init(c, NULL); check_status(status); if (do_timing_test) { cipher_driver_test_throughput(c); } if (do_validation) { status = cipher_driver_test_buffering(c); check_status(status); } status = cipher_dealloc(c); check_status(status); /* run the throughput test on the aes_icm_openssl cipher */ status = cipher_type_alloc(&aes_icm_openssl, &c, 30); if (status) { fprintf(stderr, "error: can't allocate cipher\n"); exit(status); } status = cipher_init(c, test_key); check_status(status); if (do_timing_test) { cipher_driver_test_throughput(c); } if (do_validation) { status = cipher_driver_test_buffering(c); check_status(status); } status = cipher_dealloc(c); check_status(status); /* run the throughput test on the aes_icm_192_openssl cipher */ status = cipher_type_alloc(&aes_icm_192_openssl, &c, 38); if (status) { fprintf(stderr, "error: can't allocate cipher\n"); exit(status); } status = cipher_init(c, test_key); check_status(status); if (do_timing_test) { cipher_driver_test_throughput(c); } if (do_validation) { status = cipher_driver_test_buffering(c); check_status(status); } status = cipher_dealloc(c); check_status(status); /* run the throughput test on the aes_icm_256_openssl cipher */ status = cipher_type_alloc(&aes_icm_256_openssl, &c, 46); if (status) { fprintf(stderr, "error: can't allocate cipher\n"); exit(status); } status = cipher_init(c, test_key); check_status(status); if (do_timing_test) { cipher_driver_test_throughput(c); } if (do_validation) { status = cipher_driver_test_buffering(c); check_status(status); } status = cipher_dealloc(c); check_status(status); /* run the throughput test on the aes_gcm_128_8_openssl cipher */ status = cipher_type_alloc(&aes_gcm_128_8_openssl, &c, 16); if (status) { fprintf(stderr, "error: can't allocate cipher\n"); exit(status); } status = cipher_init(c, test_key); check_status(status); if (do_timing_test) { cipher_driver_test_throughput(c); } if (do_validation) { status = cipher_driver_test_buffering(c); check_status(status); } status = cipher_dealloc(c); check_status(status); return 0; }
int main(int argc, char *argv[]) { cipher_t *c = NULL; err_status_t status; unsigned char test_key[48] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, }; int q; unsigned do_timing_test = 0; unsigned do_validation = 0; unsigned do_array_timing_test = 0; /* process input arguments */ while (1) { q = getopt(argc, argv, "tva"); if (q == -1) break; switch (q) { case 't': do_timing_test = 1; break; case 'v': do_validation = 1; break; case 'a': do_array_timing_test = 1; break; default: usage(argv[0]); } } printf("cipher test driver\n" "David A. McGrew\n" "Cisco Systems, Inc.\n"); if (!do_validation && !do_timing_test && !do_array_timing_test) usage(argv[0]); /* arry timing (cache thrash) test */ if (do_array_timing_test) { int max_num_cipher = 1 << 16; /* number of ciphers in cipher_array */ int num_cipher; for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) cipher_driver_test_array_throughput(&null_cipher, 0, num_cipher); for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) cipher_driver_test_array_throughput(&aes_icm, 30, num_cipher); #ifndef OPENSSL for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) cipher_driver_test_array_throughput(&aes_icm, 46, num_cipher); for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) cipher_driver_test_array_throughput(&aes_cbc, 16, num_cipher); for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) cipher_driver_test_array_throughput(&aes_cbc, 32, num_cipher); #else #ifndef BORINGSSL for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) cipher_driver_test_array_throughput(&aes_icm_192, 38, num_cipher); #endif for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) cipher_driver_test_array_throughput(&aes_icm_256, 46, num_cipher); for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) { cipher_driver_test_array_throughput(&aes_gcm_128_openssl, AES_128_GCM_KEYSIZE_WSALT, num_cipher); } for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) { cipher_driver_test_array_throughput(&aes_gcm_256_openssl, AES_256_GCM_KEYSIZE_WSALT, num_cipher); } #endif } if (do_validation) { cipher_driver_self_test(&null_cipher); cipher_driver_self_test(&aes_icm); #ifndef OPENSSL cipher_driver_self_test(&aes_cbc); #else #ifndef BORINGSSL cipher_driver_self_test(&aes_icm_192); #endif cipher_driver_self_test(&aes_icm_256); cipher_driver_self_test(&aes_gcm_128_openssl); cipher_driver_self_test(&aes_gcm_256_openssl); #endif } /* do timing and/or buffer_test on null_cipher */ status = cipher_type_alloc(&null_cipher, &c, 0, 0); check_status(status); status = cipher_init(c, NULL); check_status(status); if (do_timing_test) cipher_driver_test_throughput(c); if (do_validation) { status = cipher_driver_test_buffering(c); check_status(status); } status = cipher_dealloc(c); check_status(status); /* run the throughput test on the aes_icm cipher (128-bit key) */ status = cipher_type_alloc(&aes_icm, &c, 30, 0); if (status) { fprintf(stderr, "error: can't allocate cipher\n"); exit(status); } status = cipher_init(c, test_key); check_status(status); if (do_timing_test) cipher_driver_test_throughput(c); if (do_validation) { status = cipher_driver_test_buffering(c); check_status(status); } status = cipher_dealloc(c); check_status(status); /* repeat the tests with 256-bit keys */ #ifndef OPENSSL status = cipher_type_alloc(&aes_icm, &c, 46, 0); #else status = cipher_type_alloc(&aes_icm_256, &c, 46, 0); #endif if (status) { fprintf(stderr, "error: can't allocate cipher\n"); exit(status); } status = cipher_init(c, test_key); check_status(status); if (do_timing_test) cipher_driver_test_throughput(c); if (do_validation) { status = cipher_driver_test_buffering(c); check_status(status); } status = cipher_dealloc(c); check_status(status); #ifdef OPENSSL /* run the throughput test on the aes_gcm_128_openssl cipher */ status = cipher_type_alloc(&aes_gcm_128_openssl, &c, AES_128_GCM_KEYSIZE_WSALT, 8); if (status) { fprintf(stderr, "error: can't allocate GCM 128 cipher\n"); exit(status); } status = cipher_init(c, test_key); check_status(status); if (do_timing_test) { cipher_driver_test_throughput(c); } if (do_validation) { status = cipher_driver_test_buffering(c); check_status(status); } status = cipher_dealloc(c); check_status(status); /* run the throughput test on the aes_gcm_256_openssl cipher */ status = cipher_type_alloc(&aes_gcm_256_openssl, &c, AES_256_GCM_KEYSIZE_WSALT, 16); if (status) { fprintf(stderr, "error: can't allocate GCM 256 cipher\n"); exit(status); } status = cipher_init(c, test_key); check_status(status); if (do_timing_test) { cipher_driver_test_throughput(c); } if (do_validation) { status = cipher_driver_test_buffering(c); check_status(status); } status = cipher_dealloc(c); check_status(status); #endif return 0; }
err_status_t cipher_type_test(const cipher_type_t *ct, const cipher_test_case_t *test_data) { const cipher_test_case_t *test_case = test_data; cipher_t *c; err_status_t status; uint8_t buffer[SELF_TEST_BUF_OCTETS]; uint8_t buffer2[SELF_TEST_BUF_OCTETS]; unsigned int len; int i, j, case_num = 0; debug_print(mod_cipher, "running self-test for cipher %s", ct->description); /* * check to make sure that we have at least one test case, and * return an error if we don't - we need to be paranoid here */ if (test_case == NULL) return err_status_cant_check; /* * loop over all test cases, perform known-answer tests of both the * encryption and decryption functions */ while (test_case != NULL) { /* allocate cipher */ status = cipher_type_alloc(ct, &c, test_case->key_length_octets); if (status) return status; /* * test the encrypt function */ debug_print(mod_cipher, "testing encryption", NULL); /* initialize cipher */ status = cipher_init(c, test_case->key, direction_encrypt); if (status) { cipher_dealloc(c); return status; } /* copy plaintext into test buffer */ if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) { cipher_dealloc(c); return err_status_bad_param; } for (i=0; i < test_case->plaintext_length_octets; i++) buffer[i] = test_case->plaintext[i]; debug_print(mod_cipher, "plaintext: %s", octet_string_hex_string(buffer, test_case->plaintext_length_octets)); /* set the initialization vector */ status = cipher_set_iv(c, test_case->idx); if (status) { cipher_dealloc(c); return status; } /* encrypt */ len = test_case->plaintext_length_octets; status = cipher_encrypt(c, buffer, &len); if (status) { cipher_dealloc(c); return status; } debug_print(mod_cipher, "ciphertext: %s", octet_string_hex_string(buffer, test_case->ciphertext_length_octets)); /* compare the resulting ciphertext with that in the test case */ if (len != (unsigned int)test_case->ciphertext_length_octets) return err_status_algo_fail; status = err_status_ok; for (i=0; i < test_case->ciphertext_length_octets; i++) if (buffer[i] != test_case->ciphertext[i]) { status = err_status_algo_fail; debug_print(mod_cipher, "test case %d failed", case_num); debug_print(mod_cipher, "(failure at byte %d)", i); break; } if (status) { debug_print(mod_cipher, "c computed: %s", octet_string_hex_string(buffer, 2*test_case->plaintext_length_octets)); debug_print(mod_cipher, "c expected: %s", octet_string_hex_string(test_case->ciphertext, 2*test_case->plaintext_length_octets)); cipher_dealloc(c); return err_status_algo_fail; } /* * test the decrypt function */ debug_print(mod_cipher, "testing decryption", NULL); /* re-initialize cipher for decryption */ status = cipher_init(c, test_case->key, direction_decrypt); if (status) { cipher_dealloc(c); return status; } /* copy ciphertext into test buffer */ if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) { cipher_dealloc(c); return err_status_bad_param; } for (i=0; i < test_case->ciphertext_length_octets; i++) buffer[i] = test_case->ciphertext[i]; debug_print(mod_cipher, "ciphertext: %s", octet_string_hex_string(buffer, test_case->plaintext_length_octets)); /* set the initialization vector */ status = cipher_set_iv(c, test_case->idx); if (status) { cipher_dealloc(c); return status; } /* decrypt */ len = test_case->ciphertext_length_octets; status = cipher_decrypt(c, buffer, &len); if (status) { cipher_dealloc(c); return status; } debug_print(mod_cipher, "plaintext: %s", octet_string_hex_string(buffer, test_case->plaintext_length_octets)); /* compare the resulting plaintext with that in the test case */ if (len != (unsigned int)test_case->plaintext_length_octets) return err_status_algo_fail; status = err_status_ok; for (i=0; i < test_case->plaintext_length_octets; i++) if (buffer[i] != test_case->plaintext[i]) { status = err_status_algo_fail; debug_print(mod_cipher, "test case %d failed", case_num); debug_print(mod_cipher, "(failure at byte %d)", i); } if (status) { debug_print(mod_cipher, "p computed: %s", octet_string_hex_string(buffer, 2*test_case->plaintext_length_octets)); debug_print(mod_cipher, "p expected: %s", octet_string_hex_string(test_case->plaintext, 2*test_case->plaintext_length_octets)); cipher_dealloc(c); return err_status_algo_fail; } /* deallocate the cipher */ status = cipher_dealloc(c); if (status) return status; /* * the cipher passed the test case, so move on to the next test * case in the list; if NULL, we'l proceed to the next test */ test_case = test_case->next_test_case; ++case_num; } /* now run some random invertibility tests */ /* allocate cipher, using paramaters from the first test case */ test_case = test_data; status = cipher_type_alloc(ct, &c, test_case->key_length_octets); if (status) return status; rand_source_init(); for (j=0; j < NUM_RAND_TESTS; j++) { unsigned length; int plaintext_len; uint8_t key[MAX_KEY_LEN]; uint8_t iv[MAX_KEY_LEN]; /* choose a length at random (leaving room for IV and padding) */ length = rand() % (SELF_TEST_BUF_OCTETS - 64); debug_print(mod_cipher, "random plaintext length %d\n", length); status = rand_source_get_octet_string(buffer, length); if (status) return status; debug_print(mod_cipher, "plaintext: %s", octet_string_hex_string(buffer, length)); /* copy plaintext into second buffer */ for (i=0; (unsigned int)i < length; i++) buffer2[i] = buffer[i]; /* choose a key at random */ if (test_case->key_length_octets > MAX_KEY_LEN) return err_status_cant_check; status = rand_source_get_octet_string(key, test_case->key_length_octets); if (status) return status; /* chose a random initialization vector */ status = rand_source_get_octet_string(iv, MAX_KEY_LEN); if (status) return status; /* initialize cipher */ status = cipher_init(c, key, direction_encrypt); if (status) { cipher_dealloc(c); return status; } /* set initialization vector */ status = cipher_set_iv(c, test_case->idx); if (status) { cipher_dealloc(c); return status; } /* encrypt buffer with cipher */ plaintext_len = length; status = cipher_encrypt(c, buffer, &length); if (status) { cipher_dealloc(c); return status; } debug_print(mod_cipher, "ciphertext: %s", octet_string_hex_string(buffer, length)); /* * re-initialize cipher for decryption, re-set the iv, then * decrypt the ciphertext */ status = cipher_init(c, key, direction_decrypt); if (status) { cipher_dealloc(c); return status; } status = cipher_set_iv(c, test_case->idx); if (status) { cipher_dealloc(c); return status; } status = cipher_decrypt(c, buffer, &length); if (status) { cipher_dealloc(c); return status; } debug_print(mod_cipher, "plaintext[2]: %s", octet_string_hex_string(buffer, length)); /* compare the resulting plaintext with the original one */ if (length != (unsigned int)plaintext_len) return err_status_algo_fail; status = err_status_ok; for (i=0; i < plaintext_len; i++) if (buffer[i] != buffer2[i]) { status = err_status_algo_fail; debug_print(mod_cipher, "random test case %d failed", case_num); debug_print(mod_cipher, "(failure at byte %d)", i); } if (status) { cipher_dealloc(c); return err_status_algo_fail; } } status = cipher_dealloc(c); if (status) return status; return err_status_ok; }