diff --git a/perl/FKO/FKO.xs b/perl/FKO/FKO.xs index 9b1654d5..7549a6e4 100644 --- a/perl/FKO/FKO.xs +++ b/perl/FKO/FKO.xs @@ -189,6 +189,16 @@ _set_hmac_type(ctx, hmac_type) OUTPUT: RETVAL +int +_get_hmac_type(ctx, hmac_type) + INPUT: + fko_ctx_t ctx; + short hmac_type; + CODE: + RETVAL = fko_get_spa_hmac_type(ctx, hmac_type); + OUTPUT: + RETVAL + int _set_rand_value(ctx, rand_val) INPUT: @@ -377,6 +387,17 @@ _get_spa_digest(ctx, val) val RETVAL +int +_get_spa_hmac(ctx, val) + INPUT: + fko_ctx_t ctx; + char *val; + CODE: + RETVAL = fko_get_hmac_data(ctx, &val); + OUTPUT: + val + RETVAL + int _set_spa_data(ctx, spa_data) INPUT: @@ -606,6 +627,28 @@ _decrypt_spa_data(ctx, dec_key, dec_key_len) OUTPUT: RETVAL +int +_verify_hmac(ctx, hmac_key, hmac_key_len) + INPUT: + fko_ctx_t ctx; + char* hmac_key; + int hmac_key_len; + CODE: + RETVAL = fko_verify_hmac(ctx, hmac_key, hmac_key_len); + OUTPUT: + RETVAL + +int +_calculate_hmac(ctx, hmac_key, hmac_key_len) + INPUT: + fko_ctx_t ctx; + char* hmac_key; + int hmac_key_len; + CODE: + RETVAL = fko_calculate_hmac(ctx, hmac_key, hmac_key_len); + OUTPUT: + RETVAL + int _encrypt_spa_data(ctx, enc_key, enc_key_len) INPUT: diff --git a/perl/FKO/lib/FKO.pm b/perl/FKO/lib/FKO.pm index c941f985..0cddf279 100644 --- a/perl/FKO/lib/FKO.pm +++ b/perl/FKO/lib/FKO.pm @@ -73,6 +73,10 @@ sub new { my $data = shift; my $dc_pw = shift; my $dc_pw_len = shift; + my $enc_mode = shift; + my $hmac_pw = shift; + my $hmac_pw_len = shift; + my $hmac_type = shift; my $res; my $ctx; @@ -82,7 +86,8 @@ sub new { # if($data) { if(defined($dc_pw)) { - $ctx = _init_ctx_with_data($data, $dc_pw, $dc_pw_len); + $ctx = _init_ctx_with_data($data, $dc_pw, $dc_pw_len, + $enc_mode, $hmac_pw, $hmac_pw_len, $hmac_type); } else { $ctx = _init_ctx_with_data_only($data); } @@ -166,6 +171,19 @@ sub digest_type { return($self->_check_return_val($val)); } +sub hmac_type { + my $self = shift; + my $val = shift; + + return FKO::_set_hmac_type($self->{_ctx}, $val) + if(defined($val)); + + $val = -1; + $self->{_err} = FKO::_get_hmac_type($self->{_ctx}, $val); + + return($self->_check_return_val($val)); +} + sub encryption_type { my $self = shift; my $val = shift; @@ -297,6 +315,22 @@ sub spa_digest { return($self->_check_return_val($val)); } +sub spa_hmac { + my $self = shift; + my $recompute = shift || 0; + my $hmac_key = shift || ''; + my $hmac_key_len = shift || 0; + + my $val = ''; + + return FKO::_calculate_hmac($self->{_ctx}) + if($recompute and $hmac_key and $hmac_key_len); + + $self->{_err} = FKO::_get_spa_hmac($self->{_ctx}, $val); + + return($self->_check_return_val($val)); +} + sub spa_data { my $self = shift; my $val = shift; @@ -476,6 +510,22 @@ sub decode_spa_data { return FKO::_decode_spa_data($self->{_ctx}); } +sub verify_hmac { + my $self = shift; + my $hmac_key = shift || ''; + my $hmac_key_len = shift || 0; + + return FKO::_verify_hmac($self->{_ctx}, $hmac_key, $hmac_key_len) +} + +sub calculate_hmac { + my $self = shift; + my $hmac_key = shift || ''; + my $hmac_key_len = shift || 0; + + return FKO::_calculate_hmac($self->{_ctx}, $hmac_key, $hmac_key_len) +} + sub DESTROY { my $self = shift; FKO::_destroy_ctx($self->{_ctx}) if($self->{_ctx}); @@ -545,7 +595,7 @@ FKO - Perl module wrapper for libfko } elsif($digest_type == FKO::FKO_DIGEST_MD5) { # do something else } - + =head1 DESCRIPTION This module is essentially a Perl wrapper for the I diff --git a/test/test-fwknop.pl b/test/test-fwknop.pl index 65ef49c7..63170a40 100755 --- a/test/test-fwknop.pl +++ b/test/test-fwknop.pl @@ -1832,15 +1832,19 @@ sub fuzzing_usernames() { sub valid_encryption_keys() { my @keys = ( + '!@#$%', + 'asdfasdfsafsdafasdfasdfsafsdaf', +# 'asdfasdfsafsdafasdfasdfsafsdaffdjskalfjdskl' . +# 'afjsldkafjdsajdkajsklfdafsklfjjdkljdsafjdjd' . +# 'sklfjsfdsafjdslfdkjdljsajdskjdskafjdldsljdk' . +# afdsljdslafdslaldldajdskajlddslajsl', + '$', + 'asdfasdfsafsdaf', 'testtest', '12341234', '1', '1234', 'a', - '$', - '!@#$%', - 'asdfasdfsafsdaf', - 'asdfasdfsafsdafasdfasdfsafsdaf', ); return \@keys; } @@ -1856,6 +1860,34 @@ sub valid_spa_digest_types() { return \@types; } +sub valid_spa_hmac_types() { + my @types = ( + FKO->FKO_HMAC_MD5, + FKO->FKO_HMAC_SHA1, + FKO->FKO_HMAC_SHA256, + FKO->FKO_HMAC_SHA384, + FKO->FKO_HMAC_SHA512 + ); + return \@types; +} + +sub hmac_type_to_str() { + my $hmac_type = shift; + + if ($hmac_type == FKO->FKO_HMAC_MD5) { + return 'md5'; + } elsif ($hmac_type == FKO->FKO_HMAC_SHA1) { + return 'sha1'; + } elsif ($hmac_type == FKO->FKO_HMAC_SHA256) { + return 'sha256'; + } elsif ($hmac_type == FKO->FKO_HMAC_SHA384) { + return 'sha384'; + } elsif ($hmac_type == FKO->FKO_HMAC_SHA512) { + return 'sha512'; + } + return 'Unknown'; +} + sub fuzzing_spa_digest_types() { my @types = ( -1, @@ -2116,6 +2148,115 @@ sub perl_fko_module_rijndael_truncated_keys() { return $rv; } +sub perl_fko_module_complete_cycle_hmac() { + my $test_hr = shift; + + my $rv = 1; + + for my $msg (@{valid_access_messages()}) { + for my $user (@{valid_usernames()}) { + for my $digest_type (@{valid_spa_digest_types()}) { + for my $hmac_type (@{valid_spa_hmac_types()}) { + my $key_ctr = 0; + KEY: for my $key (@{valid_encryption_keys()}) { + $key_ctr++; + last KEY if $key_ctr >= 2; + if ($test_hr->{'set_legacy_iv'} eq $YES + and (length($key) > 16)) { + &write_test_file("[.] Legacy IV mode is set, " . + "skipping long key '$key'.\n", + $curr_test_file); + next KEY; + } + + my $hmac_key_ctr = 0; + HMAC_KEY: for my $hmac_key (@{valid_encryption_keys()}) { + $hmac_key_ctr++; + last HMAC_KEY if $hmac_key_ctr >= 4; + + if ($test_hr->{'set_legacy_iv'} eq $YES + and (length($hmac_key) > 16)) { + &write_test_file("[.] Legacy IV mode is set, " . + "skipping long key '$hmac_key'.\n", + $curr_test_file); + next HMAC_KEY; + } + + &write_test_file("[+] msg: $msg, user: $user, " . + "digest type: $digest_type, hmac digest type: " . + "$hmac_type, key: $key, hmac_key: $hmac_key\n", + $curr_test_file); + + $fko_obj = FKO->new(); + unless ($fko_obj) { + &write_test_file("[-] error FKO->new(): " . FKO::error_str() . "\n", + $curr_test_file); + return 0; + } + $fko_obj->spa_message($msg); + $fko_obj->username($user); + $fko_obj->spa_message_type(FKO->FKO_ACCESS_MSG); + $fko_obj->digest_type($digest_type); + $fko_obj->hmac_type($hmac_type); + + my $enc_mode = FKO->FKO_ENC_MODE_CBC; + $enc_mode = FKO->FKO_ENC_MODE_CBC_LEGACY_IV + if $test_hr->{'set_legacy_iv'} eq $YES; + $fko_obj->encryption_mode($enc_mode); + + $fko_obj->spa_data_final($key, length($key), $hmac_key, length($hmac_key)); + + my $encrypted_msg = $fko_obj->spa_data(); + + $fko_obj->destroy(); + + ### now get new object for decryption + $fko_obj = FKO->new($encrypted_msg, $key, length($key), + $enc_mode, $hmac_key, length($hmac_key), $hmac_type); + unless ($fko_obj) { + &write_test_file("[-] error FKO->new(): " . FKO::error_str() . "\n", + $curr_test_file); + return 0; + } + $fko_obj->spa_data($encrypted_msg); + $fko_obj->hmac_type($hmac_type); + $fko_obj->encryption_mode($enc_mode); + my $hmac_digest = $fko_obj->spa_hmac(); + + $fko_obj->decrypt_spa_data($key, length($key), $hmac_key, length($hmac_key)); + + if ($msg ne $fko_obj->spa_message()) { + &write_test_file("[-] $msg encrypt/decrypt mismatch\n", + $curr_test_file); + $rv = 0; + } + + $fko_obj->destroy(); + + if ($enable_openssl_compatibility_tests) { + unless (&openssl_hmac_verification($encrypted_msg, + '', $msg, $hmac_key, 0, $hmac_digest, + &hmac_type_to_str($hmac_type))) { + $rv = 0; + } + +# my $flag = $REQUIRE_SUCCESS; +# $flag = $REQUIRE_FAILURE if $test_hr->{'set_legacy_iv'} eq $YES; +# unless (&openssl_enc_verification($encrypted_msg, +# '', $msg, $key, 0, $flag)) { +# $rv = 0; +# } + } + } + } + } + } + } + } + + return $rv; +} + sub perl_fko_module_complete_cycle() { my $test_hr = shift; diff --git a/test/tests/perl_FKO_module.pl b/test/tests/perl_FKO_module.pl index 032319d9..bed00b37 100644 --- a/test/tests/perl_FKO_module.pl +++ b/test/tests/perl_FKO_module.pl @@ -115,6 +115,15 @@ 'set_legacy_iv' => $YES, 'fatal' => $NO }, + { + 'category' => 'perl FKO module', + 'subcategory' => 'HMAC encrypt/decrypt', + 'detail' => 'libfko complete cycle', + 'function' => \&perl_fko_module_complete_cycle_hmac, + 'set_legacy_iv' => $NO, + 'fatal' => $NO + }, + { 'category' => 'perl FKO module', 'subcategory' => 'encrypt/decrypt',