[libfko] first HMAC-SHA256 implementation (includes test suite support)
authorMichael Rash <mbr@cipherdyne.org>
Mon, 30 Jul 2012 01:34:08 +0000 (21:34 -0400)
committerMichael Rash <mbr@cipherdyne.org>
Mon, 30 Jul 2012 01:34:08 +0000 (21:34 -0400)
lib/cipher_funcs.c
lib/cipher_funcs.h
lib/fko_context.h
lib/fko_encryption.c
lib/fko_hmac.c
lib/fko_util.c
test/conf/fwknoprc_default_hmac_base64_key
test/test-fwknop.pl

index 51d5e3f..1fd1163 100644 (file)
@@ -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***/
index 6bcc4c3..929b4a9 100644 (file)
@@ -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 */
 
index 2d52e76..e1401de 100644 (file)
@@ -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;
index 1df8d3f..79b8687 100644 (file)
@@ -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.
index 13e48e4..85e18a9 100644 (file)
 */
 #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
index 5b1fdd6..23cb3da 100644 (file)
@@ -76,3 +76,5 @@ is_valid_digest_len(const int len)
 
     return(1);
 }
+
+/***EOF***/
index 3aaec5c..9e9043c 100644 (file)
@@ -47,7 +47,7 @@
 #GPG_SIGNER          <signer ID>
 #GPG_RECIPIENT       <recipient ID>
 KEY_BASE64:          wzNP62oPPgEc+kXDPQLHPOayQBuNbYUTPP+QrErNDmg=
-HMAC_KEY_BASE64:     zJgtsaMr5TSCDczX9MHAaePq3ADu0qN1ehlOQFUS0tc=
+HMAC_KEY_BASE64:     Yh+xizBnl6FotC5ec7FanVGClRMlsOAPh2u6eovnerfBVKwaVKzjGoblFMHMc593TNyi0dWn4opLoTIV9q/ttg==
 
 # User-provided named stanzas:
 
index f94a276..2f5bdfd 100755 (executable)
@@ -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
     {