aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-08-16 16:04:52 +0100
committerDavid Howells <dhowells@redhat.com>2019-08-19 15:42:10 +0100
commitaf573e51f2abae3da702204c068043a11018e9a4 (patch)
tree8ea0280b4ab1af737e12de0bc406fa432375b202
parent9a99f28afbabb48d2164ab7819b3fd981c978d46 (diff)
downloadkeyutils-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.c137
-rw-r--r--man/keyctl.156
-rw-r--r--tests/keyctl/add/useradd/runtest.sh10
-rw-r--r--tests/keyctl/padd/useradd/runtest.sh10
-rw-r--r--tests/keyctl/pupdate/bad-args/runtest.sh6
-rw-r--r--tests/keyctl/pupdate/userupdate/runtest.sh2
-rw-r--r--tests/keyctl/update/userupdate/runtest.sh9
-rw-r--r--tests/toolbox.inc.sh8
8 files changed, 202 insertions, 36 deletions
diff --git a/keyctl.c b/keyctl.c
index 8fa7420..988994b 100644
--- a/keyctl.c
+++ b/keyctl.c
@@ -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