int main(void) { fko_ctx_t ctx = NULL; int res = 0, i, es = EXIT_SUCCESS; int exec=0, success=0, fail=0; fiu_init(0); for (i=0; i < sizeof(fiu_rvs)/sizeof(int); i++) { exec++; printf("[+] libfiu injection tag: %s\n", fiu_tags[i]); fiu_enable(fiu_tags[i], fiu_rvs[i], NULL, 0); res = fko_new(&ctx); if(strncmp(fiu_tags[i], "fko_set_rand_value_lenval", strlen("fko_set_rand_value_lenval")) == 0) res = fko_set_rand_value(ctx, "asdf1234"); if(strncmp(fiu_tags[i], "fko_set_rand_value_strdup", strlen("fko_set_rand_value_strdup")) == 0) res = fko_set_rand_value(ctx, "asdf1234"); if(strncmp(fiu_tags[i], "fko_set_username_valuser", strlen("fko_set_username_valuser")) == 0) res = fko_set_username(ctx, "BADCHAR="); if(strncmp(fiu_tags[i], "fko_set_username_strdup", strlen("fko_set_username_strdup")) == 0) res = fko_set_username(ctx, "normaluser"); if(res == FKO_SUCCESS) { printf("[-] fko_new(): %s\n", fko_errstr(res)); fail++; es = EXIT_FAILURE; } else { printf("[+] fko_new(): %s\n", fko_errstr(res)); success++; } fko_destroy(ctx); ctx = NULL; fiu_disable(fiu_tags[i]); } printf("fiu_fault_injection() passed/failed/executed: %d/%d/%d\n", success, fail, exec); return es; }
/* set_username */ static PyObject * set_username(PyObject *self, PyObject *args) { fko_ctx_t ctx; char *username; int res; if(!PyArg_ParseTuple(args, "kz", &ctx, &username)) return NULL; res = fko_set_username(ctx, username); if(res != FKO_SUCCESS) { PyErr_SetString(FKOError, fko_errstr(res)); return NULL; } return Py_BuildValue("", NULL); }
static void spa_default_ctx(fko_ctx_t *ctx) { fko_new(ctx); fko_set_rand_value(*ctx, NULL); fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16); fko_set_spa_message(*ctx, "123.123.123.123,tcp/22"); fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16); fko_set_spa_message_type(*ctx, FKO_ACCESS_MSG); fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16); fko_set_username(*ctx, "someuser"); fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16); fko_set_spa_encryption_type(*ctx, FKO_ENCRYPTION_RIJNDAEL); fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16); fko_set_spa_encryption_mode(*ctx, FKO_ENC_MODE_CBC); fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16); fko_set_spa_digest_type(*ctx, FKO_DEFAULT_DIGEST); fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16); fko_set_spa_hmac_type(*ctx, FKO_HMAC_SHA256); fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16); // display_ctx(*ctx); spa_calls += 16; return; }
int main(int argc, char **argv) { fko_ctx_t ctx = NULL; fko_ctx_t ctx2 = NULL; int res; char *spa_data=NULL, *version=NULL; char access_buf[MAX_LINE_LEN] = {0}; char key[MAX_KEY_LEN+1] = {0}; char hmac_key[MAX_KEY_LEN+1] = {0}; int key_len = 0, orig_key_len = 0, hmac_key_len = 0, enc_mode; int tmp_port = 0; char dump_buf[CTX_DUMP_BUFSIZE]; fko_cli_options_t options; memset(&options, 0x0, sizeof(fko_cli_options_t)); /* Initialize the log module */ log_new(); /* Handle command line */ config_init(&options, argc, argv); #if HAVE_LIBFIU /* Set any fault injection points early */ if(! enable_fault_injections(&options)) clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); #endif /* Handle previous execution arguments if required */ if(prev_exec(&options, argc, argv) != 1) clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); if(options.show_last_command) clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_SUCCESS); /* Intialize the context */ res = fko_new(&ctx); if(res != FKO_SUCCESS) { errmsg("fko_new", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } /* Display version info and exit. */ if(options.version) { fko_get_version(ctx, &version); fprintf(stdout, "fwknop client %s, FKO protocol version %s\n", MY_VERSION, version); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_SUCCESS); } /* Set client timeout */ if(options.fw_timeout >= 0) { res = fko_set_spa_client_timeout(ctx, options.fw_timeout); if(res != FKO_SUCCESS) { errmsg("fko_set_spa_client_timeout", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } /* Set the SPA packet message type based on command line options */ res = set_message_type(ctx, &options); if(res != FKO_SUCCESS) { errmsg("fko_set_spa_message_type", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } /* Adjust the SPA timestamp if necessary */ if(options.time_offset_plus > 0) { res = fko_set_timestamp(ctx, options.time_offset_plus); if(res != FKO_SUCCESS) { errmsg("fko_set_timestamp", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } if(options.time_offset_minus > 0) { res = fko_set_timestamp(ctx, -options.time_offset_minus); if(res != FKO_SUCCESS) { errmsg("fko_set_timestamp", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } if(options.server_command[0] != 0x0) { /* Set the access message to a command that the server will * execute */ snprintf(access_buf, MAX_LINE_LEN, "%s%s%s", options.allow_ip_str, ",", options.server_command); } else { /* Resolve the client's public facing IP address if requestesd. * if this fails, consider it fatal. */ if (options.resolve_ip_http_https) { if(options.resolve_http_only) { if(resolve_ip_http(&options) < 0) { clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } else { /* Default to HTTPS */ if(resolve_ip_https(&options) < 0) { clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } } /* Set a message string by combining the allow IP and the * port/protocol. The fwknopd server allows no port/protocol * to be specified as well, so in this case append the string * "none/0" to the allow IP. */ if(set_access_buf(ctx, &options, access_buf) != 1) clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } res = fko_set_spa_message(ctx, access_buf); if(res != FKO_SUCCESS) { errmsg("fko_set_spa_message", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } /* Set NAT access string */ if (options.nat_local || options.nat_access_str[0] != 0x0) { res = set_nat_access(ctx, &options, access_buf); if(res != FKO_SUCCESS) { errmsg("fko_set_nat_access_str", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } /* Set username */ if(options.spoof_user[0] != 0x0) { res = fko_set_username(ctx, options.spoof_user); if(res != FKO_SUCCESS) { errmsg("fko_set_username", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } /* Set up for using GPG if specified. */ if(options.use_gpg) { /* If use-gpg-agent was not specified, then remove the GPG_AGENT_INFO * ENV variable if it exists. */ #ifndef WIN32 if(!options.use_gpg_agent) unsetenv("GPG_AGENT_INFO"); #endif res = fko_set_spa_encryption_type(ctx, FKO_ENCRYPTION_GPG); if(res != FKO_SUCCESS) { errmsg("fko_set_spa_encryption_type", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } /* Set gpg path if necessary */ if(strlen(options.gpg_exe) > 0) { res = fko_set_gpg_exe(ctx, options.gpg_exe); if(res != FKO_SUCCESS) { errmsg("fko_set_gpg_exe", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } /* If a GPG home dir was specified, set it here. Note: Setting * this has to occur before calling any of the other GPG-related * functions. */ if(strlen(options.gpg_home_dir) > 0) { res = fko_set_gpg_home_dir(ctx, options.gpg_home_dir); if(res != FKO_SUCCESS) { errmsg("fko_set_gpg_home_dir", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } res = fko_set_gpg_recipient(ctx, options.gpg_recipient_key); if(res != FKO_SUCCESS) { errmsg("fko_set_gpg_recipient", res); if(IS_GPG_ERROR(res)) log_msg(LOG_VERBOSITY_ERROR, "GPG ERR: %s", fko_gpg_errstr(ctx)); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } if(strlen(options.gpg_signer_key) > 0) { res = fko_set_gpg_signer(ctx, options.gpg_signer_key); if(res != FKO_SUCCESS) { errmsg("fko_set_gpg_signer", res); if(IS_GPG_ERROR(res)) log_msg(LOG_VERBOSITY_ERROR, "GPG ERR: %s", fko_gpg_errstr(ctx)); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } res = fko_set_spa_encryption_mode(ctx, FKO_ENC_MODE_ASYMMETRIC); if(res != FKO_SUCCESS) { errmsg("fko_set_spa_encryption_mode", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } if(options.encryption_mode && !options.use_gpg) { res = fko_set_spa_encryption_mode(ctx, options.encryption_mode); if(res != FKO_SUCCESS) { errmsg("fko_set_spa_encryption_mode", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } /* Set Digest type. */ if(options.digest_type) { res = fko_set_spa_digest_type(ctx, options.digest_type); if(res != FKO_SUCCESS) { errmsg("fko_set_spa_digest_type", res); clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } /* Acquire the necessary encryption/hmac keys */ if(get_keys(ctx, &options, key, &key_len, hmac_key, &hmac_key_len) != 1) clean_exit(ctx, &options, key, &key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); orig_key_len = key_len; if(options.encryption_mode == FKO_ENC_MODE_CBC_LEGACY_IV && key_len > 16) { log_msg(LOG_VERBOSITY_ERROR, "WARNING: Encryption key in '-M legacy' mode must be <= 16 bytes"); log_msg(LOG_VERBOSITY_ERROR, "long - truncating before sending SPA packet. Upgrading remote"); log_msg(LOG_VERBOSITY_ERROR, "fwknopd is recommended."); key_len = 16; } /* Finalize the context data (encrypt and encode the SPA data) */ res = fko_spa_data_final(ctx, key, key_len, hmac_key, hmac_key_len); if(res != FKO_SUCCESS) { errmsg("fko_spa_data_final", res); if(IS_GPG_ERROR(res)) log_msg(LOG_VERBOSITY_ERROR, "GPG ERR: %s", fko_gpg_errstr(ctx)); clean_exit(ctx, &options, key, &orig_key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } /* Display the context data. */ if (options.verbose || options.test) { res = dump_ctx_to_buffer(ctx, dump_buf, sizeof(dump_buf)); if (res == FKO_SUCCESS) log_msg(LOG_VERBOSITY_NORMAL, "%s", dump_buf); else log_msg(LOG_VERBOSITY_WARNING, "Unable to dump FKO context: %s", fko_errstr(res)); } /* Save packet data payload if requested. */ if (options.save_packet_file[0] != 0x0) write_spa_packet_data(ctx, &options); /* SPA packet random destination port handling */ if (options.rand_port) { tmp_port = get_rand_port(ctx); if(tmp_port < 0) clean_exit(ctx, &options, key, &orig_key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); options.spa_dst_port = tmp_port; } /* If we are using one the "raw" modes (normally because * we're going to spoof the SPA packet source IP), then select * a random source port unless the source port is already set */ if ((options.spa_proto == FKO_PROTO_TCP_RAW || options.spa_proto == FKO_PROTO_UDP_RAW || options.spa_proto == FKO_PROTO_ICMP) && !options.spa_src_port) { tmp_port = get_rand_port(ctx); if(tmp_port < 0) clean_exit(ctx, &options, key, &orig_key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); options.spa_src_port = tmp_port; } res = send_spa_packet(ctx, &options); if(res < 0) { log_msg(LOG_VERBOSITY_ERROR, "send_spa_packet: packet not sent."); clean_exit(ctx, &options, key, &orig_key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } else { log_msg(LOG_VERBOSITY_INFO, "send_spa_packet: bytes sent: %i", res); } /* Run through a decode cycle in test mode (--DSS XXX: This test/decode * portion should be moved elsewhere). */ if (options.test) { /************** Decoding now *****************/ /* Now we create a new context based on data from the first one. */ res = fko_get_spa_data(ctx, &spa_data); if(res != FKO_SUCCESS) { errmsg("fko_get_spa_data", res); clean_exit(ctx, &options, key, &orig_key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } /* Pull the encryption mode. */ res = fko_get_spa_encryption_mode(ctx, &enc_mode); if(res != FKO_SUCCESS) { errmsg("fko_get_spa_encryption_mode", res); if(fko_destroy(ctx) == FKO_ERROR_ZERO_OUT_DATA) log_msg(LOG_VERBOSITY_ERROR, "[*] Could not zero out sensitive data buffer."); ctx = NULL; clean_exit(ctx, &options, key, &orig_key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } /* If gpg-home-dir is specified, we have to defer decrypting if we * use the fko_new_with_data() function because we need to set the * gpg home dir after the context is created, but before we attempt * to decrypt the data. Therefore we either pass NULL for the * decryption key to fko_new_with_data() or use fko_new() to create * an empty context, populate it with the encrypted data, set our * options, then decode it. * * This also verifies the HMAC and truncates it if there are no * problems. */ res = fko_new_with_data(&ctx2, spa_data, NULL, 0, enc_mode, hmac_key, hmac_key_len, options.hmac_type); if(res != FKO_SUCCESS) { errmsg("fko_new_with_data", res); if(fko_destroy(ctx2) == FKO_ERROR_ZERO_OUT_DATA) log_msg(LOG_VERBOSITY_ERROR, "[*] Could not zero out sensitive data buffer."); ctx2 = NULL; clean_exit(ctx, &options, key, &orig_key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } res = fko_set_spa_encryption_mode(ctx2, enc_mode); if(res != FKO_SUCCESS) { errmsg("fko_set_spa_encryption_mode", res); if(fko_destroy(ctx2) == FKO_ERROR_ZERO_OUT_DATA) log_msg(LOG_VERBOSITY_ERROR, "[*] Could not zero out sensitive data buffer."); ctx2 = NULL; clean_exit(ctx, &options, key, &orig_key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } /* See if we are using gpg and if we need to set the GPG home dir. */ if(options.use_gpg) { if(strlen(options.gpg_home_dir) > 0) { res = fko_set_gpg_home_dir(ctx2, options.gpg_home_dir); if(res != FKO_SUCCESS) { errmsg("fko_set_gpg_home_dir", res); if(fko_destroy(ctx2) == FKO_ERROR_ZERO_OUT_DATA) log_msg(LOG_VERBOSITY_ERROR, "[*] Could not zero out sensitive data buffer."); ctx2 = NULL; clean_exit(ctx, &options, key, &orig_key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } } } /* Decrypt */ res = fko_decrypt_spa_data(ctx2, key, key_len); if(res != FKO_SUCCESS) { errmsg("fko_decrypt_spa_data", res); if(IS_GPG_ERROR(res)) { /* we most likely could not decrypt the gpg-encrypted data * because we don't have access to the private key associated * with the public key we used for encryption. Since this is * expected, return 0 instead of an error condition (so calling * programs like the fwknop test suite don't interpret this as * an unrecoverable error), but print the error string for * debugging purposes. The test suite does run a series of * tests that use a single key pair for encryption and * authentication, so decryption become possible for these * tests. */ log_msg(LOG_VERBOSITY_ERROR, "GPG ERR: %s\n%s", fko_gpg_errstr(ctx2), "No access to recipient private key?"); } if(fko_destroy(ctx2) == FKO_ERROR_ZERO_OUT_DATA) log_msg(LOG_VERBOSITY_ERROR, "[*] Could not zero out sensitive data buffer."); ctx2 = NULL; clean_exit(ctx, &options, key, &orig_key_len, hmac_key, &hmac_key_len, EXIT_FAILURE); } res = dump_ctx_to_buffer(ctx2, dump_buf, sizeof(dump_buf)); if (res == FKO_SUCCESS) log_msg(LOG_VERBOSITY_NORMAL, "\nDump of the Decoded Data\n%s", dump_buf); else log_msg(LOG_VERBOSITY_WARNING, "Unable to dump FKO context: %s", fko_errstr(res)); if(fko_destroy(ctx2) == FKO_ERROR_ZERO_OUT_DATA) log_msg(LOG_VERBOSITY_ERROR, "[*] Could not zero out sensitive data buffer."); ctx2 = NULL; } clean_exit(ctx, &options, key, &orig_key_len, hmac_key, &hmac_key_len, EXIT_SUCCESS); return EXIT_SUCCESS; /* quiet down a gcc warning */ }
static void test_loop(int new_ctx_flag, int destroy_ctx_flag) { fko_ctx_t ctx = NULL, decrypt_ctx = NULL; int i, j; char *spa_data = NULL, encode_buf[100], decode_buf[100]; printf("[+] test_loop(): %s, %s\n", new_ctx_flag == NEW_CTX ? "NEW_CTX" : "NO_NEW_CTX", destroy_ctx_flag == CTX_DESTROY ? "DESTROY_CTX" : "NO_DESTROY_CTX"); printf("fko_new(): %s\n", fko_errstr(fko_new(&ctx))); fko_destroy(ctx); ctx = NULL; printf("fko_new(): %s\n", fko_errstr(fko_new(&ctx))); spa_func_getset_int(&ctx, "fko_set_spa_client_timeout", &fko_set_spa_client_timeout, "fko_get_spa_client_timeout", &fko_get_spa_client_timeout, -F_INT, F_INT, 10, new_ctx_flag, destroy_ctx_flag); spa_func_getset_short(&ctx, "fko_set_spa_message_type", &fko_set_spa_message_type, "fko_get_spa_message_type", &fko_get_spa_message_type, FKO_COMMAND_MSG-F_INT, FKO_LAST_MSG_TYPE+F_INT, FKO_ACCESS_MSG, NO_DIGEST, new_ctx_flag, destroy_ctx_flag); spa_func_int(&ctx, "fko_set_timestamp", &fko_set_timestamp, -F_INT, F_INT, 10, new_ctx_flag, destroy_ctx_flag); for (i=0; i<FCN_CALLS; i++) { printf("fko_set_spa_message(1.1.1.1,tcp/22): %s\n", fko_errstr(fko_set_spa_message(ctx, "1.1.1.1,tcp/22"))); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, DO_PRINT); } for (i=0; i<FCN_CALLS; i++) { printf("fko_set_spa_nat_access(1.2.3.4,1234): %s\n", fko_errstr(fko_set_spa_nat_access(ctx, "1.2.3.4,1234"))); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, DO_PRINT); } for (i=0; i<FCN_CALLS; i++) { printf("fko_set_username(someuser): %s\n", fko_errstr(fko_set_username(ctx, "someuser"))); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, DO_PRINT); } spa_func_getset_short(&ctx, "fko_set_spa_encryption_type", &fko_set_spa_encryption_type, "fko_get_spa_encryption_type", &fko_get_spa_encryption_type, FKO_ENCRYPTION_INVALID_DATA-F_INT, FKO_LAST_ENCRYPTION_TYPE+F_INT, FKO_ENCRYPTION_RIJNDAEL, NO_DIGEST, new_ctx_flag, destroy_ctx_flag); spa_func_getset_int(&ctx, "fko_set_spa_encryption_mode", &fko_set_spa_encryption_mode, "fko_get_spa_encryption_mode", &fko_get_spa_encryption_mode, FKO_ENC_MODE_UNKNOWN-F_INT, FKO_LAST_ENC_MODE+F_INT, FKO_ENC_MODE_CBC, new_ctx_flag, destroy_ctx_flag); if (ENABLE_GPG_TESTS) { for (i=0; i<FCN_CALLS; i++) { printf("fko_set_spa_encryption_type(FKO_ENCRYPTION_GPG): %s\n", fko_errstr(fko_set_spa_encryption_type(ctx, FKO_ENCRYPTION_GPG))); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, DO_PRINT); } for (i=0; i<FCN_CALLS; i++) { printf("fko_set_gpg_home_dir(/home/mbr/.gnupg): %s\n", fko_errstr(fko_set_gpg_home_dir(ctx, "/home/mbr/.gnupg"))); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, DO_PRINT); } for (i=0; i<FCN_CALLS; i++) { printf("fko_set_gpg_recipient(1234asdf): %s\n", fko_errstr(fko_set_gpg_recipient(ctx, "1234asdf"))); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, DO_PRINT); } } spa_func_getset_short(&ctx, "fko_set_spa_digest_type", &fko_set_spa_digest_type, "fko_get_spa_digest_type", &fko_get_spa_digest_type, FKO_DIGEST_INVALID_DATA-F_INT, FKO_LAST_DIGEST_TYPE+F_INT, FKO_DEFAULT_DIGEST, DO_DIGEST, new_ctx_flag, destroy_ctx_flag); spa_func_getset_short(&ctx, "fko_set_raw_spa_digest_type", &fko_set_spa_digest_type, "fko_get_raw_spa_digest_type", &fko_get_spa_digest_type, FKO_DIGEST_INVALID_DATA-F_INT, FKO_LAST_DIGEST_TYPE+F_INT, FKO_DEFAULT_DIGEST, RAW_DIGEST, new_ctx_flag, destroy_ctx_flag); spa_func_getset_short(&ctx, "fko_set_spa_hmac_type", &fko_set_spa_hmac_type, "fko_get_spa_hmac_type", &fko_get_spa_hmac_type, FKO_HMAC_INVALID_DATA-F_INT, FKO_LAST_HMAC_MODE+F_INT, FKO_HMAC_SHA256, NO_DIGEST, new_ctx_flag, destroy_ctx_flag); printf("Trying encrypt / authenticate step with bogus key lengths...\n"); for (i=-100; i < 200; i += 10) { for (j=-100; j < 200; j += 10) { fko_spa_data_final(ctx, ENC_KEY, i, HMAC_KEY, j); fko_spa_data_final(ctx, NULL, i, HMAC_KEY, j); fko_spa_data_final(ctx, ENC_KEY, i, NULL, j); fko_spa_data_final(ctx, NULL, i, NULL, j); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, NO_PRINT); spa_calls += 4; } } for (i=0; i<FCN_CALLS; i++) { printf("fko_spa_data_final(ENC_KEY, 16, HMAC_KEY, 16): %s\n", fko_errstr(fko_spa_data_final(ctx, ENC_KEY, 16, HMAC_KEY, 16))); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, DO_PRINT); } for (i=0; i<FCN_CALLS; i++) { printf("fko_get_spa_data(): %s\n", fko_errstr(fko_get_spa_data(ctx, &spa_data))); printf(" SPA DATA: %s\n", spa_data == NULL ? "<NULL>" : spa_data); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, DO_PRINT); } printf("fko_new_with_data(): %s (data: %s)\n", fko_errstr(fko_new_with_data(&decrypt_ctx, spa_data, NULL, 0, FKO_ENC_MODE_CBC, NULL, 0, FKO_HMAC_SHA256)), spa_data); /* verify hmac, decrypt, and display ctx all together*/ for (i=0; i<FCN_CALLS; i++) { display_ctx(decrypt_ctx); printf("fko_verify_hmac() (1): %s\n", fko_errstr(fko_verify_hmac(decrypt_ctx, HMAC_KEY, 16))); printf("fko_decrypt_spa_data() (1): %s\n", fko_errstr(fko_decrypt_spa_data(decrypt_ctx, ENC_KEY, 16))); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, DO_PRINT); } /* now, separately verify hmac, decrypt, and display ctx */ for (i=0; i<FCN_CALLS; i++) { printf("fko_verify_hmac() (2): %s\n", fko_errstr(fko_verify_hmac(decrypt_ctx, HMAC_KEY, 16))); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, DO_PRINT); } /* now decrypt */ for (i=0; i<FCN_CALLS; i++) { printf("fko_decrypt_spa_data() (2): %s\n", fko_errstr(fko_decrypt_spa_data(decrypt_ctx, ENC_KEY, 16))); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, DO_PRINT); } for (i=0; i<FCN_CALLS; i++) { display_ctx(decrypt_ctx); ctx_update(&ctx, new_ctx_flag, destroy_ctx_flag, DO_PRINT); } /* NULL tests */ fko_set_rand_value(ctx, NULL); fko_set_rand_value(ctx, NULL); fko_set_username(ctx, NULL); fko_set_username(ctx, NULL); fko_set_spa_message(ctx, NULL); fko_set_spa_message(ctx, NULL); fko_set_spa_nat_access(ctx, NULL); fko_set_spa_nat_access(ctx, NULL); fko_set_spa_server_auth(ctx, NULL); fko_set_spa_server_auth(ctx, NULL); fko_set_spa_data(ctx, NULL); fko_set_spa_data(ctx, NULL); spa_calls += 12; for (i=0; i<FCN_CALLS; i++) { fko_destroy(ctx); ctx = NULL; } for (i=0; i<FCN_CALLS; i++) { fko_destroy(decrypt_ctx); decrypt_ctx = NULL; } /* exercise the base64 encode/decode wrapper */ fko_base64_encode((unsigned char *)ENC_KEY, encode_buf, 16); fko_base64_decode(encode_buf, (unsigned char *)decode_buf); /* call fko_errstr() across valid and invalid values */ for (i=-5; i < FKO_LAST_ERROR+5; i++) { printf("libfko error (%d): %s\n", i, fko_errstr(i)); spa_calls++; } return; }
static void test_loop_compounded(void) { fko_ctx_t ctx = NULL, decrypt_ctx = NULL; char *spa_data = NULL; int i, j, k, l, res; for (i=0; i<FCN_CALLS; i++) { fko_new(&ctx); res = fko_set_spa_client_timeout(ctx, i); if (res != FKO_SUCCESS) printf("fko_set_spa_client_timeout(): %s\n", fko_errstr(res)); for (j=-1; j<FKO_LAST_MSG_TYPE+1; j++) { res = fko_set_spa_message_type(ctx, j); if (res != FKO_SUCCESS) printf("fko_set_spa_message_type(): %s\n", fko_errstr(res)); res = fko_set_timestamp(ctx, 100); if (res != FKO_SUCCESS) printf("fko_set_timestamp(): %s\n", fko_errstr(res)); fko_set_spa_message(ctx, "1.1.1.1,tcp/22"); res = fko_set_spa_message(ctx, "123.123.123.123,tcp/22"); if (res != FKO_SUCCESS) printf("fko_set_spa_message(): %s\n", fko_errstr(res)); res = fko_set_spa_nat_access(ctx, "1.2.3.4,1234"); if (res != FKO_SUCCESS) printf("fko_set_spa_nat_access(): %s\n", fko_errstr(res)); res = fko_set_username(ctx, "someuser"); if (res != FKO_SUCCESS) printf("fko_set_username(): %s\n", fko_errstr(res)); res = fko_set_spa_server_auth(ctx, "passwd"); if (res != FKO_SUCCESS) printf("fko_set_spa_server_auth(): %s\n", fko_errstr(res)); res = fko_set_spa_hmac_type(ctx, FKO_HMAC_SHA256); if (res != FKO_SUCCESS) printf("fko_set_spa_hmac_type(): %s\n", fko_errstr(res)); for (k=-4; k<=16; k+=4) { for (l=-4; l<=16; l+=4) { res = fko_spa_data_final(ctx, ENC_KEY, k, HMAC_KEY, l); if (res == FKO_SUCCESS) { res = fko_get_spa_data(ctx, &spa_data); if (res == FKO_SUCCESS) { res = fko_new_with_data(&decrypt_ctx, spa_data, NULL, 0, FKO_ENC_MODE_CBC, HMAC_KEY, l, FKO_HMAC_SHA256); if (res == FKO_SUCCESS) { res = fko_decrypt_spa_data(decrypt_ctx, ENC_KEY, k); if (res != FKO_SUCCESS) printf("fko_decrypt_spa_data(): %s\n", fko_errstr(res)); fko_destroy(decrypt_ctx); decrypt_ctx = NULL; spa_calls += 13; spa_compounded_calls += 13; } else { printf("fko_new_with_data(): %s\n", fko_errstr(res)); } } else { printf("fko_get_spa_data(): %s\n", fko_errstr(res)); } } else { printf("fko_spa_data_final(): %s\n", fko_errstr(res)); } } } } fko_destroy(ctx); ctx = NULL; spa_calls += 3; spa_compounded_calls += 3; } }
/* Initialize an fko context. */ int fko_new(fko_ctx_t *r_ctx) { fko_ctx_t ctx; int res; char *ver; ctx = calloc(1, sizeof *ctx); if(ctx == NULL) return(FKO_ERROR_MEMORY_ALLOCATION); /* Set default values and state. * * Note: We have to explicitly set the ctx->state to initialized * just before making an fko_xxx function call, then set it * back to zero just afer. During initialization, we need * to make these functions think they are operating on an * initialized context, or else they would fail. */ /* Set the version string. */ ctx->initval = FKO_CTX_INITIALIZED; ver = strdup(FKO_PROTOCOL_VERSION); ctx->initval = 0; if(ver == NULL) { free(ctx); return(FKO_ERROR_MEMORY_ALLOCATION); } ctx->version = ver; /* Rand value. */ ctx->initval = FKO_CTX_INITIALIZED; res = fko_set_rand_value(ctx, NULL); ctx->initval = 0; if(res != FKO_SUCCESS) { fko_destroy(ctx); return res; } /* Username. */ ctx->initval = FKO_CTX_INITIALIZED; res = fko_set_username(ctx, NULL); ctx->initval = 0; if(res != FKO_SUCCESS) { fko_destroy(ctx); return res; } /* Timestamp. */ ctx->initval = FKO_CTX_INITIALIZED; res = fko_set_timestamp(ctx, 0); ctx->initval = 0; if(res != FKO_SUCCESS) { fko_destroy(ctx); return res; } /* Default Digest Type. */ ctx->initval = FKO_CTX_INITIALIZED; res = fko_set_spa_digest_type(ctx, FKO_DEFAULT_DIGEST); ctx->initval = 0; if(res != FKO_SUCCESS) { fko_destroy(ctx); return res; } /* Default Message Type. */ ctx->initval = FKO_CTX_INITIALIZED; res = fko_set_spa_message_type(ctx, FKO_DEFAULT_MSG_TYPE); ctx->initval = 0; if(res != FKO_SUCCESS) { fko_destroy(ctx); return res; } /* Default Encryption Type. */ ctx->initval = FKO_CTX_INITIALIZED; res = fko_set_spa_encryption_type(ctx, FKO_DEFAULT_ENCRYPTION); ctx->initval = 0; if(res != FKO_SUCCESS) { fko_destroy(ctx); return res; } #if HAVE_LIBGPGME /* Set gpg signature verify on. */ ctx->verify_gpg_sigs = 1; #endif /* HAVE_LIBGPGME */ /* Now we mean it. */ ctx->initval = FKO_CTX_INITIALIZED; FKO_SET_CTX_INITIALIZED(ctx); *r_ctx = ctx; return(FKO_SUCCESS); }
/* Initialize an fko context. */ int fko_new(fko_ctx_t *r_ctx) { fko_ctx_t ctx = NULL; int res; char *ver; #if HAVE_LIBFIU fiu_return_on("fko_new_calloc", FKO_ERROR_MEMORY_ALLOCATION); #endif ctx = calloc(1, sizeof *ctx); if(ctx == NULL) return(FKO_ERROR_MEMORY_ALLOCATION); /* Set default values and state. * * Note: We initialize the context early so that the fko_set_xxx * functions can operate properly. If there are any problems during * initialization, then fko_destroy() is called which will clean up * the context. */ ctx->initval = FKO_CTX_INITIALIZED; /* Set the version string. */ ver = strdup(FKO_PROTOCOL_VERSION); if(ver == NULL) { fko_destroy(ctx); ctx = NULL; return(FKO_ERROR_MEMORY_ALLOCATION); } ctx->version = ver; /* Rand value. */ res = fko_set_rand_value(ctx, NULL); if(res != FKO_SUCCESS) { fko_destroy(ctx); ctx = NULL; return res; } /* Username. */ res = fko_set_username(ctx, NULL); if(res != FKO_SUCCESS) { fko_destroy(ctx); ctx = NULL; return res; } /* Timestamp. */ res = fko_set_timestamp(ctx, 0); if(res != FKO_SUCCESS) { fko_destroy(ctx); ctx = NULL; return res; } /* Default Digest Type. */ res = fko_set_spa_digest_type(ctx, FKO_DEFAULT_DIGEST); if(res != FKO_SUCCESS) { fko_destroy(ctx); ctx = NULL; return res; } /* Default Message Type. */ res = fko_set_spa_message_type(ctx, FKO_DEFAULT_MSG_TYPE); if(res != FKO_SUCCESS) { fko_destroy(ctx); ctx = NULL; return res; } /* Default Encryption Type. */ res = fko_set_spa_encryption_type(ctx, FKO_DEFAULT_ENCRYPTION); if(res != FKO_SUCCESS) { fko_destroy(ctx); ctx = NULL; return res; } /* Default is Rijndael in CBC mode */ res = fko_set_spa_encryption_mode(ctx, FKO_DEFAULT_ENC_MODE); if(res != FKO_SUCCESS) { fko_destroy(ctx); ctx = NULL; return res; } #if HAVE_LIBGPGME /* Set gpg signature verify on. */ ctx->verify_gpg_sigs = 1; #endif /* HAVE_LIBGPGME */ FKO_SET_CTX_INITIALIZED(ctx); *r_ctx = ctx; return(FKO_SUCCESS); }