diff --git a/lib/cipher_funcs.c b/lib/cipher_funcs.c index 51d5e3f9..1fd1163c 100644 --- a/lib/cipher_funcs.c +++ b/lib/cipher_funcs.c @@ -282,4 +282,41 @@ rij_decrypt(unsigned char *in, size_t in_len, return(ondx - out); } +/* See if we need to add the "Salted__" string to the front of the + * encrypted data. +*/ +int +add_salted_str(fko_ctx_t ctx) +{ + char *tbuf; + + if(strncmp(ctx->encrypted_msg, + B64_RIJNDAEL_SALT, B64_RIJNDAEL_SALT_STR_LEN)) + { + /* We need to realloc space for the salt. + */ + tbuf = realloc(ctx->encrypted_msg, ctx->encrypted_msg_len + + B64_RIJNDAEL_SALT_STR_LEN+1); + if(tbuf == NULL) + return(FKO_ERROR_MEMORY_ALLOCATION); + + memmove(tbuf+B64_RIJNDAEL_SALT_STR_LEN, tbuf, ctx->encrypted_msg_len); + + ctx->encrypted_msg = memcpy(tbuf, + B64_RIJNDAEL_SALT, B64_RIJNDAEL_SALT_STR_LEN); + + /* Adjust the encoded msg len for added SALT value and Make sure we + * are still a properly NULL-terminated string (Ubuntu was one system + * for which this was an issue). + */ + ctx->encrypted_msg_len += B64_RIJNDAEL_SALT_STR_LEN; + tbuf[ctx->encrypted_msg_len] = '\0'; + + ctx->added_salted_str = 1; + } + + return(FKO_SUCCESS); +} + + /***EOF***/ diff --git a/lib/cipher_funcs.h b/lib/cipher_funcs.h index 6bcc4c36..929b4a9c 100644 --- a/lib/cipher_funcs.h +++ b/lib/cipher_funcs.h @@ -57,6 +57,7 @@ size_t rij_encrypt(unsigned char *in, size_t len, size_t rij_decrypt(unsigned char *in, size_t len, const char *key, const int key_len, unsigned char *out, int encryption_mode); +int add_salted_str(fko_ctx_t ctx); #endif /* CIPHER_FUNCS_H */ diff --git a/lib/fko_context.h b/lib/fko_context.h index 2d52e763..e1401dec 100644 --- a/lib/fko_context.h +++ b/lib/fko_context.h @@ -86,6 +86,7 @@ struct fko_context { int encrypted_msg_len; char *msg_hmac; int msg_hmac_len; + int added_salted_str; /* State info */ unsigned short state; diff --git a/lib/fko_encryption.c b/lib/fko_encryption.c index 1df8d3f1..79b86879 100644 --- a/lib/fko_encryption.c +++ b/lib/fko_encryption.c @@ -117,7 +117,6 @@ static int _rijndael_decrypt(fko_ctx_t ctx, const char *dec_key, const int key_len, int encryption_mode) { - char *tbuf; unsigned char *ndx; unsigned char *cipher; int cipher_len, pt_len, i, err = 0; @@ -125,25 +124,8 @@ _rijndael_decrypt(fko_ctx_t ctx, /* Now see if we need to add the "Salted__" string to the front of the * encrypted data. */ - if(strncmp(ctx->encrypted_msg, B64_RIJNDAEL_SALT, B64_RIJNDAEL_SALT_STR_LEN)) - { - /* We need to realloc space for the salt. - */ - tbuf = realloc(ctx->encrypted_msg, ctx->encrypted_msg_len + B64_RIJNDAEL_SALT_STR_LEN+1); - if(tbuf == NULL) - return(FKO_ERROR_MEMORY_ALLOCATION); - - memmove(tbuf+B64_RIJNDAEL_SALT_STR_LEN, tbuf, ctx->encrypted_msg_len); - - ctx->encrypted_msg = memcpy(tbuf, B64_RIJNDAEL_SALT, B64_RIJNDAEL_SALT_STR_LEN); - - /* Adjust the encoded msg len for added SALT value and Make sure we are still - * a properly NULL-terminated string (Ubuntu was one system for which this was - * an issue). - */ - ctx->encrypted_msg_len += B64_RIJNDAEL_SALT_STR_LEN; - tbuf[ctx->encrypted_msg_len] = '\0'; - } + if(! ctx->added_salted_str) + add_salted_str(ctx); /* Create a bucket for the (base64) decoded encrypted data and get the * raw cipher data. diff --git a/lib/fko_hmac.c b/lib/fko_hmac.c index 13e48e40..85e18a98 100644 --- a/lib/fko_hmac.c +++ b/lib/fko_hmac.c @@ -30,20 +30,72 @@ */ #include "fko_common.h" #include "fko.h" +#include "cipher_funcs.h" #include "hmac.h" #include "base64.h" int fko_verify_hmac(fko_ctx_t ctx, const char *hmac_key, const int hmac_key_len) { + char *hmac_digest_from_data = NULL; + char *tbuf = NULL; + int res = FKO_SUCCESS; + /* Must be initialized */ if(!CTX_INITIALIZED(ctx)) - { return(FKO_ERROR_CTX_NOT_INITIALIZED); + + if (! is_valid_encoded_msg_len(ctx->encrypted_msg_len)) + return(FKO_ERROR_INVALID_DATA); + + /* Get digest value + */ + hmac_digest_from_data = strndup((ctx->encrypted_msg + + ctx->encrypted_msg_len - SHA256_B64_LENGTH), SHA256_B64_LENGTH); + + if(hmac_digest_from_data == NULL) + return(FKO_ERROR_MEMORY_ALLOCATION); + + /* Now we chop the HMAC digest off of the encrypted msg + */ + tbuf = strndup(ctx->encrypted_msg, ctx->encrypted_msg_len - SHA256_B64_LENGTH); + if(tbuf == NULL) + return(FKO_ERROR_MEMORY_ALLOCATION); + + free(ctx->encrypted_msg); + + ctx->encrypted_msg = tbuf; + ctx->encrypted_msg_len -= SHA256_B64_LENGTH; + + /* See if we need to add the "Salted__" string to the front of the + * encrypted data. + */ + if(! ctx->added_salted_str) + res = add_salted_str(ctx); + + if (res != FKO_SUCCESS) + return(res); + + /* Calculate the HMAC from the encrypted data and then + * compare + */ + res = fko_set_hmac_mode(ctx, FKO_HMAC_SHA256); + if(res == FKO_SUCCESS) + { + res = fko_calculate_hmac(ctx, hmac_key, hmac_key_len); + + if(res == FKO_SUCCESS) + { + if(strncmp(hmac_digest_from_data, + ctx->msg_hmac, SHA256_B64_LENGTH) != 0) + { + res = FKO_ERROR_INVALID_DATA; + } + } } - return FKO_SUCCESS; + return(res); } /* Return the fko HMAC data diff --git a/lib/fko_util.c b/lib/fko_util.c index 5b1fdd6c..23cb3da9 100644 --- a/lib/fko_util.c +++ b/lib/fko_util.c @@ -76,3 +76,5 @@ is_valid_digest_len(const int len) return(1); } + +/***EOF***/ diff --git a/test/conf/fwknoprc_default_hmac_base64_key b/test/conf/fwknoprc_default_hmac_base64_key index 3aaec5c2..9e9043cb 100644 --- a/test/conf/fwknoprc_default_hmac_base64_key +++ b/test/conf/fwknoprc_default_hmac_base64_key @@ -47,7 +47,7 @@ #GPG_SIGNER #GPG_RECIPIENT KEY_BASE64: wzNP62oPPgEc+kXDPQLHPOayQBuNbYUTPP+QrErNDmg= -HMAC_KEY_BASE64: zJgtsaMr5TSCDczX9MHAaePq3ADu0qN1ehlOQFUS0tc= +HMAC_KEY_BASE64: Yh+xizBnl6FotC5ec7FanVGClRMlsOAPh2u6eovnerfBVKwaVKzjGoblFMHMc593TNyi0dWn4opLoTIV9q/ttg== # User-provided named stanzas: diff --git a/test/test-fwknop.pl b/test/test-fwknop.pl index f94a2763..2f5bdfdb 100755 --- a/test/test-fwknop.pl +++ b/test/test-fwknop.pl @@ -24,6 +24,7 @@ my %cf = ( 'nat' => "$conf_dir/nat_fwknopd.conf", 'def' => "$conf_dir/default_fwknopd.conf", 'def_access' => "$conf_dir/default_access.conf", + 'hmac_access' => "$conf_dir/hmac_access.conf", 'exp_access' => "$conf_dir/expired_stanza_access.conf", 'future_exp_access' => "$conf_dir/future_expired_stanza_access.conf", 'exp_epoch_access' => "$conf_dir/expired_epoch_stanza_access.conf", @@ -664,7 +665,7 @@ my @tests = ( { 'category' => 'Rijndael SPA', 'subcategory' => 'client+server', - 'detail' => 'complete cycle sha1 (tcp/22 ssh)', + 'detail' => 'complete cycle SHA1 (tcp/22 ssh)', 'err_msg' => 'could not complete SPA cycle', 'function' => \&spa_cycle, 'cmdline' => "$default_client_args -m sha1", @@ -677,7 +678,7 @@ my @tests = ( { 'category' => 'Rijndael SPA', 'subcategory' => 'client+server', - 'detail' => 'complete cycle sha256 (tcp/22 ssh)', + 'detail' => 'complete cycle SHA256 (tcp/22 ssh)', 'err_msg' => 'could not complete SPA cycle', 'function' => \&spa_cycle, 'cmdline' => "$default_client_args -m sha256", @@ -690,7 +691,7 @@ my @tests = ( { 'category' => 'Rijndael SPA', 'subcategory' => 'client+server', - 'detail' => 'complete cycle sha384 (tcp/22 ssh)', + 'detail' => 'complete cycle SHA384 (tcp/22 ssh)', 'err_msg' => 'could not complete SPA cycle', 'function' => \&spa_cycle, 'cmdline' => "$default_client_args -m sha384", @@ -703,7 +704,7 @@ my @tests = ( { 'category' => 'Rijndael SPA', 'subcategory' => 'client+server', - 'detail' => 'complete cycle sha512 (tcp/22 ssh)', + 'detail' => 'complete cycle SHA512 (tcp/22 ssh)', 'err_msg' => 'could not complete SPA cycle', 'function' => \&spa_cycle, 'cmdline' => "$default_client_args -m sha512", @@ -810,13 +811,28 @@ my @tests = ( { 'category' => 'Rijndael SPA', 'subcategory' => 'client', - 'detail' => 'rc file hmac base64 key (tcp/22 ssh)', + 'detail' => 'rc file HMAC base64 key (tcp/22 ssh)', 'err_msg' => 'SPA packet not generated', 'function' => \&generic_exec, 'cmdline' => "$default_client_args_no_get_key " . "--rc-file $cf{'rc_file_hmac_b64_key'}", 'fatal' => $NO }, + { + 'category' => 'Rijndael SPA', + 'subcategory' => 'client+server', + 'detail' => 'complete cycle + HMAC (tcp/22 ssh)', + 'err_msg' => 'could not complete SPA cycle', + 'function' => \&spa_cycle, + 'cmdline' => "$default_client_args_no_get_key " . + "--rc-file $cf{'rc_file_hmac_b64_key'}", + 'fwknopd_cmdline' => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " . + "$fwknopdCmd -c $cf{'def'} -a $cf{'hmac_access'} " . + "-d $default_digest_file -p $default_pid_file $intf_str", + 'fw_rule_created' => $NEW_RULE_REQUIRED, + 'fw_rule_removed' => $NEW_RULE_REMOVED, + 'fatal' => $NO + }, ### --key-gen tests {