diff options
author | David Howells <dhowells@redhat.com> | 2019-08-16 16:04:52 +0100 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2019-08-19 15:42:10 +0100 |
commit | af573e51f2abae3da702204c068043a11018e9a4 (patch) | |
tree | 8ea0280b4ab1af737e12de0bc406fa432375b202 | |
parent | 9a99f28afbabb48d2164ab7819b3fd981c978d46 (diff) | |
download | keyutils-af573e51f2abae3da702204c068043a11018e9a4.tar.gz |
keyctl: Allow add, padd and suchlike to take hex-encoded data
Allow add, padd, update, pupdate, instantiate, pinstantiate and
dh_compute_kdf_oi to take hex-encoded data which is then converted into
binary before being passed to the kernel, e.g.:
$ keyctl add -x user foo 686578 @s
$ echo 686578 | keyctl padd -x user foo @s
This makes it easier to stash data in scripts.
Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r-- | keyctl.c | 137 | ||||
-rw-r--r-- | man/keyctl.1 | 56 | ||||
-rw-r--r-- | tests/keyctl/add/useradd/runtest.sh | 10 | ||||
-rw-r--r-- | tests/keyctl/padd/useradd/runtest.sh | 10 | ||||
-rw-r--r-- | tests/keyctl/pupdate/bad-args/runtest.sh | 6 | ||||
-rw-r--r-- | tests/keyctl/pupdate/userupdate/runtest.sh | 2 | ||||
-rw-r--r-- | tests/keyctl/update/userupdate/runtest.sh | 9 | ||||
-rw-r--r-- | tests/toolbox.inc.sh | 8 |
8 files changed, 202 insertions, 36 deletions
@@ -10,6 +10,7 @@ */ #define _GNU_SOURCE +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> @@ -77,17 +78,17 @@ static nr void act_keyctl_supports(int argc, char *argv[]); static const struct command commands[] = { { act_keyctl___version, "--version", "" }, - { act_keyctl_add, "add", "<type> <desc> <data> <keyring>" }, + { act_keyctl_add, "add", "[-x] <type> <desc> <data> <keyring>" }, { act_keyctl_chgrp, "chgrp", "<key> <gid>" }, { act_keyctl_chown, "chown", "<key> <uid>" }, { act_keyctl_clear, "clear", "<keyring>" }, { act_keyctl_describe, "describe", "<keyring>" }, { act_keyctl_dh_compute, "dh_compute", "<private> <prime> <base>" }, { act_keyctl_dh_compute_kdf, "dh_compute_kdf", "<private> <prime> <base> <len> <hash_name>" }, - { act_keyctl_dh_compute_kdf_oi, "dh_compute_kdf_oi", "<private> <prime> <base> <len> <hash_name>" }, + { act_keyctl_dh_compute_kdf_oi, "dh_compute_kdf_oi", "[-x] <private> <prime> <base> <len> <hash_name>" }, { act_keyctl_get_persistent, "get_persistent", "<keyring> [<uid>]" }, { act_keyctl_id, "id", "<key>" }, - { act_keyctl_instantiate, "instantiate","<key> <data> <keyring>" }, + { act_keyctl_instantiate, "instantiate","[-x] <key> <data> <keyring>" }, { act_keyctl_invalidate,"invalidate", "<key>" }, { act_keyctl_link, "link", "<key> <keyring>" }, { act_keyctl_list, "list", "<keyring>" }, @@ -95,8 +96,8 @@ static const struct command commands[] = { { act_keyctl_negate, "negate", "<key> <timeout> <keyring>" }, { act_keyctl_new_session, "new_session", "[<name>]" }, { act_keyctl_newring, "newring", "<name> <keyring>" }, - { act_keyctl_padd, "padd", "<type> <desc> <keyring>" }, - { act_keyctl_pinstantiate, "pinstantiate","<key> <keyring>" }, + { act_keyctl_padd, "padd", "[-x] <type> <desc> <keyring>" }, + { act_keyctl_pinstantiate, "pinstantiate","[-x] <key> <keyring>" }, { act_keyctl_pipe, "pipe", "<key>" }, { act_keyctl_pkey_query, "pkey_query", "<key> <pass> [k=v]*" }, { act_keyctl_pkey_encrypt, "pkey_encrypt", "<key> <pass> <datafile> [k=v]*" }, @@ -105,7 +106,7 @@ static const struct command commands[] = { { act_keyctl_pkey_verify, "pkey_verify", "<key> <pass> <datafile> <sigfile> [k=v]*" }, { act_keyctl_prequest2, "prequest2", "<type> <desc> [<dest_keyring>]" }, { act_keyctl_print, "print", "<key>" }, - { act_keyctl_pupdate, "pupdate", "<key>" }, + { act_keyctl_pupdate, "pupdate", "[-x] <key>" }, { act_keyctl_purge, "purge", "<type>" }, { NULL, "purge", "[-p] [-i] <type> <desc>" }, { NULL, "purge", "-s <type> <desc>" }, @@ -128,7 +129,7 @@ static const struct command commands[] = { { act_keyctl_supports, "supports", "[<cap> | --raw]" }, { act_keyctl_timeout, "timeout", "<key> <timeout>" }, { act_keyctl_unlink, "unlink", "<key> [<keyring>]" }, - { act_keyctl_update, "update", "<key> <data>" }, + { act_keyctl_update, "update", "[-x] <key> <data>" }, { act_keyctl_test, "--test", "..." }, { NULL, NULL, NULL } }; @@ -290,6 +291,49 @@ static char *grab_stdin(size_t *_size) } /* end grab_stdin() */ /* + * Convert hex to binary if need be. + */ +void hex2bin(void **_data, size_t *_datalen, bool as_hex) +{ + unsigned char *buf, *q, h, l; + char *p, *end; + + if (!as_hex || *_datalen == 0) + return; + + q = buf = malloc(*_datalen / 2 + 2); + if (!buf) + error("malloc"); + + p = *_data; + end = p + *_datalen; + + while (p < end) { + if (isspace(*p)) { + p++; + continue; + } + if (end - p < 2) { + fprintf(stderr, "Short hex doublet\n"); + exit(1); + } + if (!isxdigit(p[0]) || !isxdigit(p[1])) { + fprintf(stderr, "Bad hex doublet\n"); + exit(1); + } + + h = isdigit(p[0]) ? p[0] - '0' : tolower(p[0]) - 'a' + 0xa; + l = isdigit(p[1]) ? p[1] - '0' : tolower(p[1]) - 'a' + 0xa; + p += 2; + *q++ = (h << 4) | l; + } + + *q = 0; + *_data = buf; + *_datalen = q - buf; +} + +/* * Load the groups list and grab the process's UID and GID. */ static void grab_creds(void) @@ -419,14 +463,27 @@ static void act_keyctl_show(int argc, char *argv[]) static void act_keyctl_add(int argc, char *argv[]) { key_serial_t dest; + size_t datalen; + void *data; + bool as_hex = false; int ret; + if (argc > 1 && strcmp(argv[1], "-x") == 0) { + as_hex = true; + argc--; + argv++; + } + if (argc != 5) format(); + data = argv[3]; + datalen = strlen(argv[3]); + hex2bin(&data, &datalen, as_hex); + dest = get_key_id(argv[4]); - ret = add_key(argv[1], argv[2], argv[3], strlen(argv[3]), dest); + ret = add_key(argv[1], argv[2], data, datalen, dest); if (ret < 0) error("add_key"); @@ -445,15 +502,22 @@ static void act_keyctl_padd(int argc, char *argv[]) key_serial_t dest; size_t datalen; void *data; + bool as_hex = false; int ret; + if (argc > 1 && strcmp(argv[1], "-x") == 0) { + as_hex = true; + argc--; + argv++; + } if (argc != 4) format(); - dest = get_key_id(argv[3]); - data = grab_stdin(&datalen); + hex2bin(&data, &datalen, as_hex); + + dest = get_key_id(argv[3]); ret = add_key(argv[1], argv[2], data, datalen, dest); if (ret < 0) @@ -548,13 +612,26 @@ static void act_keyctl_prequest2(int argc, char *argv[]) static void act_keyctl_update(int argc, char *argv[]) { key_serial_t key; + size_t datalen; + void *data; + bool as_hex = false; + + if (argc > 1 && strcmp(argv[1], "-x") == 0) { + as_hex = true; + argc--; + argv++; + } if (argc != 3) format(); + data = argv[2]; + datalen = strlen(argv[2]); + hex2bin(&data, &datalen, as_hex); + key = get_key_id(argv[1]); - if (keyctl_update(key, argv[2], strlen(argv[2])) < 0) + if (keyctl_update(key, data, datalen) < 0) error("keyctl_update"); exit(0); @@ -570,12 +647,20 @@ static void act_keyctl_pupdate(int argc, char *argv[]) key_serial_t key; size_t datalen; void *data; + bool as_hex = false; + + if (argc > 1 && strcmp(argv[1], "-x") == 0) { + as_hex = true; + argc--; + argv++; + } if (argc != 2) format(); key = get_key_id(argv[1]); data = grab_stdin(&datalen); + hex2bin(&data, &datalen, as_hex); if (keyctl_update(key, data, datalen) < 0) error("keyctl_update"); @@ -1223,14 +1308,26 @@ static void act_keyctl_session(int argc, char *argv[]) static void act_keyctl_instantiate(int argc, char *argv[]) { key_serial_t key, dest; + size_t datalen; + void *data; + bool as_hex = false; + + if (argc > 1 && strcmp(argv[1], "-x") == 0) { + as_hex = true; + argc--; + argv++; + } if (argc != 4) format(); key = get_key_id(argv[1]); dest = get_key_id(argv[3]); + data = argv[2]; + datalen = strlen(argv[2]); + hex2bin(&data, &datalen, as_hex); - if (keyctl_instantiate(key, argv[2], strlen(argv[2]), dest) < 0) + if (keyctl_instantiate(key, data, datalen, dest) < 0) error("keyctl_instantiate"); exit(0); @@ -1246,6 +1343,13 @@ static void act_keyctl_pinstantiate(int argc, char *argv[]) key_serial_t key, dest; size_t datalen; void *data; + bool as_hex = false; + + if (argc > 1 && strcmp(argv[1], "-x") == 0) { + as_hex = true; + argc--; + argv++; + } if (argc != 3) format(); @@ -1253,6 +1357,7 @@ static void act_keyctl_pinstantiate(int argc, char *argv[]) key = get_key_id(argv[1]); dest = get_key_id(argv[2]); data = grab_stdin(&datalen); + hex2bin(&data, &datalen, as_hex); if (keyctl_instantiate(key, data, datalen, dest) < 0) error("keyctl_instantiate"); @@ -1798,6 +1903,13 @@ static void act_keyctl_dh_compute_kdf_oi(int argc, char *argv[]) unsigned long buflen = 0; size_t oilen; void *oi; + bool as_hex = false; + + if (argc > 1 && strcmp(argv[1], "-x") == 0) { + as_hex = true; + argc--; + argv++; + } if (argc != 6) format(); @@ -1815,6 +1927,7 @@ static void act_keyctl_dh_compute_kdf_oi(int argc, char *argv[]) error("dh_compute: cannot allocate memory"); oi = grab_stdin(&oilen); + hex2bin(&oi, &oilen, as_hex); ret = keyctl_dh_compute_kdf(private, prime, base, argv[5], oi, oilen, buffer, buflen); diff --git a/man/keyctl.1 b/man/keyctl.1 index dd1f4a5..2f545bd 100644 --- a/man/keyctl.1 +++ b/man/keyctl.1 @@ -19,9 +19,9 @@ keyctl \- key management facility control .br \fBkeyctl\fR show [\-x] [<keyring>] .br -\fBkeyctl\fR add <type> <desc> <data> <keyring> +\fBkeyctl\fR add [\-x] <type> <desc> <data> <keyring> .br -\fBkeyctl\fR padd <type> <desc> <keyring> +\fBkeyctl\fR padd [\-x] <type> <desc> <keyring> .br \fBkeyctl\fR request <type> <desc> [<dest_keyring>] .br @@ -29,9 +29,9 @@ keyctl \- key management facility control .br \fBkeyctl\fR prequest2 <type> <desc> [<dest_keyring>] .br -\fBkeyctl\fR update <key> <data> +\fBkeyctl\fR update [\-x] <key> <data> .br -\fBkeyctl\fR pupdate <key> +\fBkeyctl\fR pupdate [\-x] <key> .br \fBkeyctl\fR newring <name> <keyring> .br @@ -77,9 +77,9 @@ keyctl \- key management facility control .br \fBkeyctl\fR session <name> [<prog> <arg1> <arg2> ...] .br -\fBkeyctl\fR instantiate <key> <data> <keyring> +\fBkeyctl\fR instantiate [\-x] <key> <data> <keyring> .br -\fBkeyctl\fR pinstantiate <key> <keyring> +\fBkeyctl\fR pinstantiate [\-x] <key> <keyring> .br \fBkeyctl\fR negate <key> <timeout> <keyring> .br @@ -103,7 +103,7 @@ keyctl \- key management facility control .br \fBkeyctl\fR dh_compute_kdf <private> <prime> <base> <output_length> <hash_type> .br -\fBkeyctl\fR dh_compute_kdf_oi <private> <prime> <base> <output_length> <hash_type> +\fBkeyctl\fR dh_compute_kdf_oi [\-x] <private> <prime> <base> <output_length> <hash_type> .br \fBkeyctl\fR pkey_query <key> <pass> [k=v]* .br @@ -274,9 +274,9 @@ to and what keys and keyrings they contain. If a keyring is specified then that keyring will be dumped instead. If \fB\-x\fR is specified then the keyring IDs will be dumped in hex instead of decimal. .SS Add a key to a keyring -\fBkeyctl add\fR <type> <desc> <data> <keyring> +\fBkeyctl add\fR [\-x] <type> <desc> <data> <keyring> .br -\fBkeyctl padd\fR <type> <desc> <keyring> +\fBkeyctl padd\fR [\-x] <type> <desc> <keyring> This command creates a key of the specified type and description; instantiates it with the given data and attaches it to the specified keyring. It then prints @@ -298,6 +298,10 @@ $ echo \-n stuff | keyctl padd user mykey @u 26 .fi .RE + +If \fB\-x\fR is given, then the data is hex-decoded with whitespace being +discarded. + .SS Request a key \fBkeyctl request\fR <type> <desc> [<dest_keyring>] .br @@ -339,9 +343,9 @@ $ keyctl request user debug:hello .fi .RE .SS Update a key -\fBkeyctl update\fR <key> <data> +\fBkeyctl update\fR [\-x] <key> <data> .br -\fBkeyctl pupdate\fR <key> +\fBkeyctl pupdate\fR [\-x] <key> This command replaces the data attached to a key with a new set of data. If the type of the key doesn't support update then error "Operation not supported" @@ -359,8 +363,13 @@ taking it from the command line: .RS .nf $ echo \-n zebra | keyctl pupdate 23 +$ echo 616263313233 | keyctl pupdate -x 23 .fi .RE + +If \fB\-x\fR is given, then the data is hex-decoded with whitespace being +discarded. + .SS Create a keyring \fBkeyctl newring\fR <name> <keyring> @@ -666,9 +675,9 @@ keyring;4043;4043;3f1f0000;fish .fi .RE .SS Instantiate a key -\fBkeyctl instantiate\fR <key> <data> <keyring> +\fBkeyctl instantiate\fR [\-x] <key> <data> <keyring> .br -\fBkeyctl pinstantiate\fR <key> <keyring> +\fBkeyctl pinstantiate\fR [\-x] <key> <keyring> .br \fBkeyctl negate\fR <key> <timeout> <keyring> .br @@ -711,6 +720,16 @@ than taking it from the command line: $ echo \-n "Debug $3" | keyctl pinstantiate $1 $4 .fi .RE + +If \fB\-x\fR is given, then the data is hex-decoded with whitespace being +discarded: + +.RS +.nf +$ echo 01 02 03 04 | keyctl pinstantiate -x $1 $4 +.fi +.RE + .SS Set the expiry time on a key \fBkeyctl timeout\fR <key> <timeout> @@ -843,6 +862,9 @@ The result is printed to stdout as a hex dump. $ keyctl dh_compute $1 $2 $3 8 bytes of data in result: 00010203 04050607 +.fi +.RE + .SS Compute a Diffie-Hellman shared secret and derive key material \fBkeyctl\fR dh_compute_kdf <private> <prime> <base> <output_length> <hash_type> @@ -858,15 +880,17 @@ The operation is compliant to the specification of SP800-56A. The result is printed to stdout as hex dump. .SS Compute a Diffie-Hellman shared secret and apply KDF with other input -\fBkeyctl\fR dh_compute_kdf_oi <private> <prime> <base> <output_length> <hash_type> +\fBkeyctl\fR dh_compute_kdf_oi [\-x] <private> <prime> <base> <output_length> <hash_type> This command is identical to the command .IR dh_compute_kdf to generate a Diffie-Hellman shared secret followed by a key derivation operation. This command allows the caller to provide the other input data (OI data) compliant to SP800-56A via stdin. -.fi -.RE + +If \fB\-x\fR is given, then the data passed to stdin is hex-decoded with +whitespace being discarded. + .SS Perform public-key operations with an asymmetric key \fBkeyctl\fR pkey_query <key> <pass> [k=v]* .br diff --git a/tests/keyctl/add/useradd/runtest.sh b/tests/keyctl/add/useradd/runtest.sh index 031241c..e421a89 100644 --- a/tests/keyctl/add/useradd/runtest.sh +++ b/tests/keyctl/add/useradd/runtest.sh @@ -19,6 +19,16 @@ marker "PRINT PAYLOAD" print_key $keyid expect_payload payload "stuff" +# check that we can add a hex-encoded user key to the session keyring +marker "ADD HEX USER KEY" +create_key -x user wibble "73 7475 66 66 " @s +expect_keyid keyid + +# read back what we put in it +marker "PRINT PAYLOAD" +print_key $keyid +expect_payload payload "stuff" + # check that we can update a user key marker "UPDATE USER KEY" create_key user wibble lizard @s diff --git a/tests/keyctl/padd/useradd/runtest.sh b/tests/keyctl/padd/useradd/runtest.sh index 206a163..6bd3c09 100644 --- a/tests/keyctl/padd/useradd/runtest.sh +++ b/tests/keyctl/padd/useradd/runtest.sh @@ -19,6 +19,16 @@ marker "PRINT PAYLOAD" print_key $keyid expect_payload payload "stuff" +# check that we can add a hex-encoded user key to the session keyring +marker "ADD HEX USER KEY" +pcreate_key "73 7475 66 66 " -x user wibble @s +expect_keyid keyid + +# read back what we put in it +marker "PRINT PAYLOAD" +print_key $keyid +expect_payload payload "stuff" + # check that we can update a user key marker "UPDATE USER KEY" pcreate_key lizard user wibble @s diff --git a/tests/keyctl/pupdate/bad-args/runtest.sh b/tests/keyctl/pupdate/bad-args/runtest.sh index bced352..e8bc28f 100644 --- a/tests/keyctl/pupdate/bad-args/runtest.sh +++ b/tests/keyctl/pupdate/bad-args/runtest.sh @@ -11,12 +11,12 @@ echo "++++ BEGINNING TEST" >$OUTPUTFILE # attempt to update the session keyring marker "CHECK UPDATE SESSION KEYRING" -pupdate_key --fail @s a +echo -n "a" | pupdate_key --fail @s expect_error EOPNOTSUPP # attempt to update an invalid key marker "CHECK UPDATE INVALID KEY" -pupdate_key --fail 0 a +echo -n "a" | pupdate_key --fail 0 expect_error EINVAL # add a user key to the session keyring for us to play with @@ -30,7 +30,7 @@ unlink_key --wait $keyid @s # it should fail when we attempt to update it marker "UPDATE UNLINKED KEY" -pupdate_key --fail $keyid @s +echo -n "a" | pupdate_key --fail $keyid expect_error ENOKEY echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE diff --git a/tests/keyctl/pupdate/userupdate/runtest.sh b/tests/keyctl/pupdate/userupdate/runtest.sh index 05a77c1..eada6ff 100644 --- a/tests/keyctl/pupdate/userupdate/runtest.sh +++ b/tests/keyctl/pupdate/userupdate/runtest.sh @@ -21,7 +21,7 @@ expect_payload payload "stuff" # check that we can update a user key marker "PUPDATE USER KEY" -pupdate_key $keyid "lizard" +echo -n "lizard" | pupdate_key $keyid # read back what we changed it to marker "PRINT UPDATED PAYLOAD" diff --git a/tests/keyctl/update/userupdate/runtest.sh b/tests/keyctl/update/userupdate/runtest.sh index ddc7cd4..4a86eb3 100644 --- a/tests/keyctl/update/userupdate/runtest.sh +++ b/tests/keyctl/update/userupdate/runtest.sh @@ -28,6 +28,15 @@ marker "PRINT UPDATED PAYLOAD" print_key $keyid expect_payload payload "lizard" +# check that we can update a user key with hex-encoded data +marker "UPDATE USER KEY HEX" +update_key -x $keyid " 6c 697a 6172 64 78 " + +# read back what we changed it to +marker "PRINT UPDATED PAYLOAD" +print_key $keyid +expect_payload payload "lizardx" + # remove the key we added marker "UNLINK KEY" unlink_key $keyid @s diff --git a/tests/toolbox.inc.sh b/tests/toolbox.inc.sh index 2b432a8..7ee5d92 100644 --- a/tests/toolbox.inc.sh +++ b/tests/toolbox.inc.sh @@ -820,8 +820,8 @@ function update_key () shift fi - echo keyctl update $1 $2 >>$OUTPUTFILE - keyctl update $1 $2 >>$OUTPUTFILE 2>&1 + echo keyctl update "$@" >>$OUTPUTFILE + keyctl update "$@" >>$OUTPUTFILE 2>&1 if [ $? != $my_exitval ] then failed @@ -842,8 +842,8 @@ function pupdate_key () shift fi - echo echo -n $2 \| keyctl pupdate $1 >>$OUTPUTFILE - echo -n $2 | keyctl pupdate $1 >>$OUTPUTFILE 2>&1 + echo keyctl pupdate "$@" >>$OUTPUTFILE + keyctl pupdate "$@" >>$OUTPUTFILE 2>&1 if [ $? != $my_exitval ] then failed |