static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2) { struct cipher_ctx *cipher_ctx = (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2; struct cipher_ctx *to_cipher_ctx; switch (type) { case EVP_CTRL_COPY: if (cipher_ctx == NULL) return 1; /* when copying the context, a new session needs to be initialized */ to_cipher_ctx = (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx); memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess)); return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx), (cipher_ctx->op == COP_ENCRYPT)); case EVP_CTRL_INIT: memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess)); return 1; default: break; } return -1; }
static void test_encrypt_op(const uint8_t* key, uint8_t key_len, const uint8_t* adata, size_t adata_len, const uint8_t* nonce, uint8_t nonce_len, const uint8_t* plain, size_t plain_len, const uint8_t* output_expected, size_t output_expected_len, uint8_t mac_length) { cipher_t cipher; int len, err, cmp; size_t len_encoding = nonce_and_len_encoding_size - nonce_len; TEST_ASSERT_MESSAGE(sizeof(data) >= output_expected_len, "Output buffer too small"); err = cipher_init(&cipher, CIPHER_AES_128, key, key_len); TEST_ASSERT_EQUAL_INT(1, err); len = cipher_encrypt_ccm(&cipher, adata, adata_len, mac_length, len_encoding, nonce, nonce_len, plain, plain_len, data); TEST_ASSERT_MESSAGE(len > 0, "Encryption failed"); TEST_ASSERT_EQUAL_INT(output_expected_len, len); cmp = compare(output_expected, data, len); TEST_ASSERT_MESSAGE(1 == cmp , "wrong ciphertext"); }
static int read_config_file (void *ptr) { if (ptr) hxd_log("SIGHUP: rereading config file"); hxd_read_config(hxdconf, &hxd_cfg); umask(hxd_cfg.permissions.umask); #if defined(CONFIG_HOTLINE_SERVER) read_banlist(); read_applevolume(); if (hxd_cfg.operation.hfs) hfs_set_config(hxd_cfg.files.fork, hxd_cfg.permissions.files, hxd_cfg.permissions.directories, hxd_cfg.files.comment, hxd_cfg.files.dir_comment); #ifdef CONFIG_CIPHER cipher_init(); #endif #ifdef CONFIG_NETWORK g_my_sid = hxd_cfg.network.server_id; #endif #endif #if defined(CONFIG_TRACKER_SERVER) tracker_read_banlist(); #endif #ifndef ONLY_TRACKER if (hxd_cfg.operation.trxreg) tracker_register_init(); #endif return 0; }
err_status_t cipher_array_alloc_init(cipher_t ***ca, int num_ciphers, cipher_type_t *ctype, int klen) { int i, j; err_status_t status; uint8_t *key; cipher_t **cipher_array; /* pad klen allocation, to handle aes_icm reading 16 bytes for the 14-byte salt */ int klen_pad = ((klen + 15) >> 4) << 4; /* allocate array of pointers to ciphers */ cipher_array = (cipher_t **) malloc(sizeof(cipher_t *) * num_ciphers); if (cipher_array == NULL) return err_status_alloc_fail; /* set ca to location of cipher_array */ *ca = cipher_array; /* allocate key */ key = crypto_alloc(klen_pad); if (key == NULL) { free(cipher_array); return err_status_alloc_fail; } /* allocate and initialize an array of ciphers */ for (i=0; i < num_ciphers; i++) { /* allocate cipher */ status = cipher_type_alloc(ctype, cipher_array, klen, 16); if (status) return status; /* generate random key and initialize cipher */ for (j=0; j < klen; j++) key[j] = (uint8_t) rand(); for (; j < klen_pad; j++) key[j] = 0; status = cipher_init(*cipher_array, key); if (status) return status; /* printf("%dth cipher is at %p\n", i, *cipher_array); */ /* printf("%dth cipher description: %s\n", i, */ /* (*cipher_array)->type->description); */ /* advance cipher array pointer */ cipher_array++; } crypto_free(key); return err_status_ok; }
err_status_t cipher_array_alloc_init (cipher_t ***ca, int num_ciphers, cipher_type_t *ctype, int klen) { int i, j; err_status_t status; uint8_t *key; cipher_t **cipher_array; /* allocate array of pointers to ciphers */ cipher_array = (cipher_t**)malloc(sizeof(cipher_t *) * num_ciphers); if (cipher_array == NULL) { return err_status_alloc_fail; } /* set ca to location of cipher_array */ *ca = cipher_array; /* allocate key */ key = crypto_alloc(klen); if (key == NULL) { free(cipher_array); return err_status_alloc_fail; } /* allocate and initialize an array of ciphers */ for (i = 0; i < num_ciphers; i++) { /* allocate cipher */ status = cipher_type_alloc(ctype, cipher_array, klen); if (status) { return status; } /* generate random key and initialize cipher */ for (j = 0; j < klen; j++) { key[j] = (uint8_t)rand(); } status = cipher_init(*cipher_array, key); if (status) { return status; } /* printf("%dth cipher is at %p\n", i, *cipher_array); */ /* printf("%dth cipher description: %s\n", i, */ /* (*cipher_array)->type->description); */ /* advance cipher array pointer */ cipher_array++; } return err_status_ok; }
void cipher_set_key_string(CipherContext *cc, const Cipher *cipher, const char *passphrase, int do_encrypt) { MD5_CTX md; u_char digest[16]; MD5_Init(&md); MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); MD5_Final(digest, &md); cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); memset(digest, 0, sizeof(digest)); memset(&md, 0, sizeof(md)); }
static int _test_ccm_len(func_ccm_t func, uint8_t len_encoding, const uint8_t *input, size_t input_len, size_t adata_len) { int ret; cipher_t cipher; uint8_t mac_length = 8; uint8_t nonce[15] = {0}; uint8_t key[16] = {0}; uint8_t nonce_len = nonce_and_len_encoding_size - len_encoding; cipher_init(&cipher, CIPHER_AES_128, key, 16); ret = func(&cipher, NULL, adata_len, mac_length, len_encoding, nonce, nonce_len, input, input_len, data); return ret; }
/******************************************************************************* * Once per lifetime init, retrieve optional functions */ apr_status_t h2_h2_init(apr_pool_t *pool, server_rec *s) { (void)pool; ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, "h2_h2, child_init"); opt_ssl_engine_disable = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable); opt_ssl_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https); opt_ssl_var_lookup = APR_RETRIEVE_OPTIONAL_FN(ssl_var_lookup); if (!opt_ssl_is_https || !opt_ssl_var_lookup) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02951) "mod_ssl does not seem to be enabled"); } cipher_init(pool); return APR_SUCCESS; }
/* * Selects the cipher, and keys if by computing the MD5 checksum of the * passphrase and using the resulting 16 bytes as the key. */ int cipher_set_key_string(struct sshcipher_ctx **ccp, const struct sshcipher *cipher, const char *passphrase, int do_encrypt) { u_char digest[16]; int r = SSH_ERR_INTERNAL_ERROR; if ((r = ssh_digest_memory(SSH_DIGEST_MD5, passphrase, strlen(passphrase), digest, sizeof(digest))) != 0) goto out; r = cipher_init(ccp, cipher, digest, 16, NULL, 0, do_encrypt); out: explicit_bzero(digest, sizeof(digest)); return r; }
/* * Selects the cipher, and keys if by computing the MD5 checksum of the * passphrase and using the resulting 16 bytes as the key. */ int cipher_set_key_string(struct sshcipher_ctx *cc, struct sshcipher *cipher, const char *pphrase, int do_encrypt) { MD5_CTX md; u_char digest[16]; int ret = SSH_ERR_LIBCRYPTO_ERROR; if (MD5_Init(&md) != 1 || MD5_Update(&md, (const u_char *)pphrase, strlen(pphrase)) != 1 || MD5_Final(digest, &md) != 1) goto out; ret = cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); out: memset(digest, 0, sizeof(digest)); memset(&md, 0, sizeof(md)); return ret; }
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; }
void cipher_init_decrypt(struct iked_cipher *encr) { cipher_init(encr, 0); }
void cipher_init_encrypt(struct iked_cipher *encr) { cipher_init(encr, 1); }
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; }
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; }
int ciphers_valid(const char *names) { const Cipher *c; char *cipher_list, *cp; char *p; if (names == NULL || strcmp(names, "") == 0) return 0; cipher_list = cp = xstrdup(names); for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; (p = strsep(&cp, CIPHER_SEP))) { c = cipher_by_name(p); #ifdef NONE_CIPHER_ENABLED if (c == NULL || (c->number != SSH_CIPHER_SSH2 && c->number != SSH_CIPHER_NONE)) { #else if (c == NULL || (c->number != SSH_CIPHER_SSH2)) { #endif debug("bad cipher %s [%s]", p, names); free(cipher_list); return 0; } } debug3("ciphers ok: [%s]", names); free(cipher_list); return 1; } /* * Parses the name of the cipher. Returns the number of the corresponding * cipher, or -1 on error. */ int cipher_number(const char *name) { const Cipher *c; if (name == NULL) return -1; for (c = ciphers; c->name != NULL; c++) if (strcasecmp(c->name, name) == 0) return c->number; return -1; } char * cipher_name(int id) { const Cipher *c = cipher_by_number(id); return (c==NULL) ? "<unknown>" : c->name; } void cipher_init(CipherContext *cc, const Cipher *cipher, const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, int do_encrypt) { static int dowarn = 1; #ifdef SSH_OLD_EVP EVP_CIPHER *type; #else const EVP_CIPHER *type; int klen; #endif u_char *junk, *discard; if (cipher->number == SSH_CIPHER_DES) { if (dowarn) { error("Warning: use of DES is strongly discouraged " "due to cryptographic weaknesses"); dowarn = 0; } if (keylen > 8) keylen = 8; } cc->plaintext = (cipher->number == SSH_CIPHER_NONE); cc->encrypt = do_encrypt; if (keylen < cipher->key_len) fatal("cipher_init: key length %d is insufficient for %s.", keylen, cipher->name); if (iv != NULL && ivlen < cipher_ivlen(cipher)) fatal("cipher_init: iv length %d is insufficient for %s.", ivlen, cipher->name); cc->cipher = cipher; if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { chachapoly_init(&cc->cp_ctx, key, keylen); return; } type = (*cipher->evptype)(); EVP_CIPHER_CTX_init(&cc->evp); #ifdef SSH_OLD_EVP if (type->key_len > 0 && type->key_len != keylen) { debug("cipher_init: set keylen (%d -> %d)", type->key_len, keylen); type->key_len = keylen; } EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv, (do_encrypt == CIPHER_ENCRYPT)); #else if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, (do_encrypt == CIPHER_ENCRYPT)) == 0) fatal("cipher_init: EVP_CipherInit failed for %s", cipher->name); if (cipher_authlen(cipher) && !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, -1, (u_char *)iv)) fatal("cipher_init: EVP_CTRL_GCM_SET_IV_FIXED failed for %s", cipher->name); klen = EVP_CIPHER_CTX_key_length(&cc->evp); if (klen > 0 && keylen != (u_int)klen) { debug2("cipher_init: set keylen (%d -> %d)", klen, keylen); if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) fatal("cipher_init: set keylen failed (%d -> %d)", klen, keylen); } if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) fatal("cipher_init: EVP_CipherInit: set key failed for %s", cipher->name); #endif if (cipher->discard_len > 0) { junk = xmalloc(cipher->discard_len); discard = xmalloc(cipher->discard_len); if (EVP_Cipher(&cc->evp, discard, junk, cipher->discard_len) == 0) fatal("evp_crypt: EVP_Cipher failed during discard"); explicit_bzero(discard, cipher->discard_len); free(junk); free(discard); } } /* * cipher_crypt() operates as following: * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'. * Theses bytes are treated as additional authenticated data for * authenticated encryption modes. * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. * This tag is written on encryption and verified on decryption. * Both 'aadlen' and 'authlen' can be set to 0. * cipher_crypt() returns 0 on success and -1 if the decryption integrity * check fails. */ int cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src, u_int len, u_int aadlen, u_int authlen) { if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len, aadlen, authlen, cc->encrypt); if (authlen) { u_char lastiv[1]; if (authlen != cipher_authlen(cc->cipher)) fatal("%s: authlen mismatch %d", __func__, authlen); /* increment IV */ if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, 1, lastiv)) fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__); /* set tag on decyption */ if (!cc->encrypt && !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG, authlen, (u_char *)src + aadlen + len)) fatal("%s: EVP_CTRL_GCM_SET_TAG", __func__); } if (aadlen) { if (authlen && EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0) fatal("%s: EVP_Cipher(aad) failed", __func__); memcpy(dest, src, aadlen); } if (len % cc->cipher->block_size) fatal("%s: bad plaintext length %d", __func__, len); if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, len) < 0) fatal("%s: EVP_Cipher failed", __func__); if (authlen) { /* compute tag (on encrypt) or verify tag (on decrypt) */ if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) { if (cc->encrypt) fatal("%s: EVP_Cipher(final) failed", __func__); else return -1; } if (cc->encrypt && !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, authlen, dest + aadlen + len)) fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__); } return 0; } /* Extract the packet length, including any decryption necessary beforehand */ int cipher_get_length(CipherContext *cc, u_int *plenp, u_int seqnr, const u_char *cp, u_int len) { if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr, cp, len); if (len < 4) return -1; *plenp = get_u32(cp); return 0; } void cipher_cleanup(CipherContext *cc) { if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed"); } /* * Selects the cipher, and keys if by computing the MD5 checksum of the * passphrase and using the resulting 16 bytes as the key. */ void cipher_set_key_string(CipherContext *cc, const Cipher *cipher, const char *passphrase, int do_encrypt) { u_char digest[16]; if (ssh_digest_memory(SSH_DIGEST_MD5, passphrase, strlen(passphrase), digest, sizeof(digest)) < 0) fatal("%s: md5 failed", __func__); cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); explicit_bzero(digest, sizeof(digest)); }
void BSP_DRV_Init() { #ifdef CONFIG_MODULE_VIC s32 ret = 0; #endif /***********************基础模块初始化***************************/ #ifdef CONFIG_BALONG_CCLK hi6930_clock_init(); #endif #ifdef CONFIG_CCORE_PM bsp_dpm_init(); #endif #ifdef K3_TIMER_FEATURE k3_timer_init(); #endif adp_timer_init(); timer_dpm_init(); if(0 != BSP_UDI_Init()) logMsg("BSP_UDI_Init fail\n",0,0,0,0,0,0); bsp_ipc_init(); bsp_icc_init(); #ifdef CONFIG_K3V3_CLK_CRG /*CONFIG_K3V3_CLK_CRG*/ gps_refclk_icc_read_cb_init(); #endif /* Cshell init if magic number is set to PRT_FLAG_EN_MAGIC_M */ #ifdef CONFIG_CSHELL if(0 != cshell_init()) { logMsg("cshell init fail\n",0,0,0,0,0,0); } #endif #ifdef CONFIG_NVIM if(0 != bsp_nvm_init()) logMsg("nv init fail\n",0,0,0,0,0,0); #endif /* axi monitor监控初始化 */ (void)bsp_amon_init(); /*此初始化必须放置在MSP/OAM/PS初始化之前,请不要随意改动顺序*/ tcxo_init_configure(); if(0 != bsp_rfile_init()) logMsg("rfile init fail\n",0,0,0,0,0,0); /* version inits */ bsp_productinfo_init(); hwspinlock_init(); bsp_hkadc_init(); bsp_version_init(); bsp_lowpower_mntn_init(); #ifdef CONFIG_MODULE_VIC ret = bsp_vic_init(); if(ret != OK) { logMsg("bsp_vic_init error\n", 0, 0, 0, 0, 0, 0); } #endif (void)bsp_softtimer_init(); #ifdef CONFIG_BALONG_EDMA if(0 != bsp_edma_init()) { logMsg("edma init fail \n",0,0,0,0,0,0); } #endif /*C core init ipc module*/ if(0 != socp_init()) logMsg("socp init fail\n",0,0,0,0,0,0); if(0 != bsp_om_server_init()) logMsg("om init fail\n",0,0,0,0,0,0); if(0 != bsp_dual_modem_init()) logMsg("dual modem uart init fail\n",0,0,0,0,0,0); /***********************外设模块初始化***************************/ bsp_dsp_init(); #ifdef CONFIG_BBP_INT bbp_int_init();/*此处需要放在dsp初始化之后,放在pastar/abb之前*/ #endif bsp_spi_init(); bsp_pmu_init(); regulator_init(); #if defined(CONFIG_PMIC_HI6559) if(bsp_pa_rf_init()) /* 依赖于regulator_init */ { logMsg("bsp_pa_rf_init fail\n",0,0,0,0,0,0); } #endif /*init mipi*/ #ifdef CONFIG_MIPI bsp_mipi_init(); #endif #ifdef CONFIG_TUNER bsp_tuner_init(); #endif #ifdef CONFIG_PASTAR /*此函数的位置不可以向后移动,为pastar上电后,提供足够的稳定时间*/ pmu_hi6561_init_phase1(); #endif if(0 != hi6930_wdt_init()) logMsg("wdt init fail\n",0,0,0,0,0,0); #ifdef CONFIG_CCORE_I2C if(0!=bsp_i2c_initial()) logMsg("i2c init fail\n",0,0,0,0,0,0); #endif if(0 != bsp_gpio_init()) logMsg("gpio init fail\n",0,0,0,0,0,0); #ifdef CONFIG_EFUSE if(0 != efuse_init()) { logMsg("efuse init fail \n",0,0,0,0,0,0); } #endif #ifdef CONFIG_LEDS_CCORE if(0 != bsp_led_init()) { logMsg("led init fail\n",0,0,0,0,0,0); } #endif /***********************通信支撑模块初始化***************************/ #ifdef CONFIG_CIPHER if(0 != cipher_init()) { logMsg("cipher init fail \n",0,0,0,0,0,0); } if(0 != bsp_acc_init()) { logMsg("acc init fail \n",0,0,0,0,0,0); } #endif #ifdef CONFIG_IPF if(0 != ipf_init()) logMsg("ipf init fail\n",0,0,0,0,0,0); #endif #ifdef CONFIG_MODULE_BUSSTRESS ipf_ul_stress_test_start(10); #endif #ifdef FEATURE_TLPHY_MAILBOX bsp_mailbox_init(); #endif mailbox_init(); #ifdef CONFIG_ANTEN if(0 != bsp_anten_init()) logMsg("anten init fail.\n",0,0,0,0,0,0); #endif bsp_sci_cfg_init(); bsp_abb_init(); bsp_on_off_init(); cpufreq_init(); /*初始化醒来的时间戳*/ update_awake_time_stamp(); #ifdef CONFIG_CCORE_BALONG_PM balong_pm_init(); #endif #ifdef CONFIG_AUDIO audio_init(); #endif #ifdef CONFIG_BALONG_MODEM_RESET bsp_reset_init(); #endif (void)bsp_rf_rse_init(); #ifdef CONFIG_PASTAR /*勿动!此处需要放置在该函数最后,确保pastar上电后稳定后,进行初始化配置*/ pmu_hi6561_init_phase2(); #endif (void)bsp_antn_sw_init(); }
int sshkey_xmss_encrypt_state(const struct sshkey *k, struct sshbuf *b, struct sshbuf **retp) { struct ssh_xmss_state *state = k->xmss_state; struct sshbuf *encrypted = NULL, *encoded = NULL, *padded = NULL; struct sshcipher_ctx *ciphercontext = NULL; const struct sshcipher *cipher; u_char *cp, *key, *iv = NULL; size_t i, keylen, ivlen, blocksize, authlen, encrypted_len, aadlen; int r = SSH_ERR_INTERNAL_ERROR; if (retp != NULL) *retp = NULL; if (state == NULL || state->enc_keyiv == NULL || state->enc_ciphername == NULL) return SSH_ERR_INTERNAL_ERROR; if ((cipher = cipher_by_name(state->enc_ciphername)) == NULL) { r = SSH_ERR_INTERNAL_ERROR; goto out; } blocksize = cipher_blocksize(cipher); keylen = cipher_keylen(cipher); ivlen = cipher_ivlen(cipher); authlen = cipher_authlen(cipher); if (state->enc_keyiv_len != keylen + ivlen) { r = SSH_ERR_INVALID_FORMAT; goto out; } key = state->enc_keyiv; if ((encrypted = sshbuf_new()) == NULL || (encoded = sshbuf_new()) == NULL || (padded = sshbuf_new()) == NULL || (iv = malloc(ivlen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* replace first 4 bytes of IV with index to ensure uniqueness */ memcpy(iv, key + keylen, ivlen); POKE_U32(iv, state->idx); if ((r = sshbuf_put(encoded, XMSS_MAGIC, sizeof(XMSS_MAGIC))) != 0 || (r = sshbuf_put_u32(encoded, state->idx)) != 0) goto out; /* padded state will be encrypted */ if ((r = sshbuf_putb(padded, b)) != 0) goto out; i = 0; while (sshbuf_len(padded) % blocksize) { if ((r = sshbuf_put_u8(padded, ++i & 0xff)) != 0) goto out; } encrypted_len = sshbuf_len(padded); /* header including the length of state is used as AAD */ if ((r = sshbuf_put_u32(encoded, encrypted_len)) != 0) goto out; aadlen = sshbuf_len(encoded); /* concat header and state */ if ((r = sshbuf_putb(encoded, padded)) != 0) goto out; /* reserve space for encryption of encoded data plus auth tag */ /* encrypt at offset addlen */ if ((r = sshbuf_reserve(encrypted, encrypted_len + aadlen + authlen, &cp)) != 0 || (r = cipher_init(&ciphercontext, cipher, key, keylen, iv, ivlen, 1)) != 0 || (r = cipher_crypt(ciphercontext, 0, cp, sshbuf_ptr(encoded), encrypted_len, aadlen, authlen)) != 0) goto out; /* success */ r = 0; out: if (retp != NULL) { *retp = encrypted; encrypted = NULL; } sshbuf_free(padded); sshbuf_free(encoded); sshbuf_free(encrypted); cipher_free(ciphercontext); free(iv); return r; }
int sshkey_xmss_decrypt_state(const struct sshkey *k, struct sshbuf *encoded, struct sshbuf **retp) { struct ssh_xmss_state *state = k->xmss_state; struct sshbuf *copy = NULL, *decrypted = NULL; struct sshcipher_ctx *ciphercontext = NULL; const struct sshcipher *cipher = NULL; u_char *key, *iv = NULL, *dp; size_t keylen, ivlen, authlen, aadlen; u_int blocksize, encrypted_len, index; int r = SSH_ERR_INTERNAL_ERROR; if (retp != NULL) *retp = NULL; if (state == NULL || state->enc_keyiv == NULL || state->enc_ciphername == NULL) return SSH_ERR_INTERNAL_ERROR; if ((cipher = cipher_by_name(state->enc_ciphername)) == NULL) { r = SSH_ERR_INVALID_FORMAT; goto out; } blocksize = cipher_blocksize(cipher); keylen = cipher_keylen(cipher); ivlen = cipher_ivlen(cipher); authlen = cipher_authlen(cipher); if (state->enc_keyiv_len != keylen + ivlen) { r = SSH_ERR_INTERNAL_ERROR; goto out; } key = state->enc_keyiv; if ((copy = sshbuf_fromb(encoded)) == NULL || (decrypted = sshbuf_new()) == NULL || (iv = malloc(ivlen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* check magic */ if (sshbuf_len(encoded) < sizeof(XMSS_MAGIC) || memcmp(sshbuf_ptr(encoded), XMSS_MAGIC, sizeof(XMSS_MAGIC))) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* parse public portion */ if ((r = sshbuf_consume(encoded, sizeof(XMSS_MAGIC))) != 0 || (r = sshbuf_get_u32(encoded, &index)) != 0 || (r = sshbuf_get_u32(encoded, &encrypted_len)) != 0) goto out; /* check size of encrypted key blob */ if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* check that an appropriate amount of auth data is present */ if (sshbuf_len(encoded) < encrypted_len + authlen) { r = SSH_ERR_INVALID_FORMAT; goto out; } aadlen = sshbuf_len(copy) - sshbuf_len(encoded); /* replace first 4 bytes of IV with index to ensure uniqueness */ memcpy(iv, key + keylen, ivlen); POKE_U32(iv, index); /* decrypt private state of key */ if ((r = sshbuf_reserve(decrypted, aadlen + encrypted_len, &dp)) != 0 || (r = cipher_init(&ciphercontext, cipher, key, keylen, iv, ivlen, 0)) != 0 || (r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(copy), encrypted_len, aadlen, authlen)) != 0) goto out; /* there should be no trailing data */ if ((r = sshbuf_consume(encoded, encrypted_len + authlen)) != 0) goto out; if (sshbuf_len(encoded) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* remove AAD */ if ((r = sshbuf_consume(decrypted, aadlen)) != 0) goto out; /* XXX encrypted includes unchecked padding */ /* success */ r = 0; if (retp != NULL) { *retp = decrypted; decrypted = NULL; } out: cipher_free(ciphercontext); sshbuf_free(copy); sshbuf_free(decrypted); free(iv); return r; }