Add support for signing a file hash
authorMimi Zohar <zohar@linux.vnet.ibm.com>
Tue, 18 Feb 2014 21:41:33 +0000 (16:41 -0500)
committerDmitry Kasatkin <d.kasatkin@samsung.com>
Wed, 26 Mar 2014 12:50:20 +0000 (14:50 +0200)
In a number of situations, the file hash has already been calculated.
Instead of reading a file to calculate the file hash, read the file hash
from stdin; and instead of writing the signature as an xattr or creating
a .sig file, output the signature as ascii-hex to stdout.

For example, piping the output of sha256sum <pathname> to evmctl would
display the original sha256 output with the file signature appended.

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
src/evmctl.c

index 74c22ca..0d4c143 100644 (file)
@@ -402,6 +402,23 @@ static int hex2bin(uint8_t *dst, const char *src, size_t count)
        return 0;
 }
 
+#define hex_asc_lo(x)   hex_asc[((x) & 0x0f)]
+#define hex_asc_hi(x)   hex_asc[((x) & 0xf0) >> 4]
+
+const char hex_asc[] = "0123456789abcdef";
+
+/* this is faster than fprintf - makes sense? */
+static void bin2hex(uint8_t *buf, size_t buflen, FILE *stream)
+{
+       char asciihex[2];
+
+       for (; buflen--; buf++) {
+               asciihex[0] = hex_asc_hi(*buf);
+               asciihex[1] = hex_asc_lo(*buf);
+               fwrite(asciihex, 2, 1, stream);
+       }
+}
+
 static int pack_uuid(const char *uuid_str, char *uuid)
 {
        int i;
@@ -751,6 +768,49 @@ static int cmd_sign_ima(struct command *cmd)
        return err;
 }
 
+static int cmd_sign_hash(struct command *cmd)
+{
+       char *key, *token, *line = NULL;
+       int hashlen = 0;
+       size_t line_len;
+       ssize_t len;
+       unsigned char hash[64];
+       unsigned char sig[1024] = "\x03";
+       int siglen;
+
+       key = params.keyfile ? : "/etc/keys/privkey_evm.pem";
+
+       /* support reading hash (eg. output of shasum) */
+       while ((len = getline(&line, &line_len, stdin)) > 0) {
+               /* remove end of line */
+               if (line[len - 1] == '\n')
+                       line[--len] = '\0';
+
+               /* find the end of the hash */
+               token = strpbrk(line, ", \t");
+               hashlen = token ? token - line : strlen(line);
+
+               hex2bin(hash, line, hashlen);
+               siglen = sign_hash(params.hash_algo, hash, hashlen/2,
+                                key, sig + 1);
+               if (siglen <= 1)
+                       return siglen;
+
+               fwrite(line, len, 1, stdout);
+               fprintf(stdout, " ");
+               bin2hex(sig, siglen + 1, stdout);
+               fprintf(stdout, "\n");
+       }
+
+       if (!hashlen) {
+               log_err("Parameters missing\n");
+               print_usage(cmd);
+               return -1;
+       }
+
+       return 0;
+}
+
 static int sign_evm_path(const char *file)
 {
        char *key;
@@ -1599,6 +1659,7 @@ struct command cmds[] = {
        {"ima_hash", cmd_hash_ima, 0, "file", "Make file content hash.\n"},
        {"ima_measurement", cmd_ima_measurement, 0, "file", "Verify measurement list (experimental).\n"},
        {"ima_fix", cmd_ima_fix, 0, "[-t fdsxm] path", "Recursively fix IMA/EVM xattrs in fix mode.\n"},
+       {"sign_hash", cmd_sign_hash, 0, "[--key key] [--pass password]", "Sign hashes from shaXsum output.\n"},
 #ifdef DEBUG
        {"hmac", cmd_hmac_evm, 0, "[--imahash | --imasig ] file", "Sign file metadata with HMAC using symmetric key (for testing purpose).\n"},
 #endif