From: Denis Kenzior <denkenz@gmail.com>
To: ell@lists.01.org
Subject: Re: [PATCH 3/4] key: Add key-based asymmetric crypto operations
Date: Fri, 22 Jul 2016 14:35:09 -0500 [thread overview]
Message-ID: <5792756D.8090103@gmail.com> (raw)
In-Reply-To: <20160720221928.24488-3-mathew.j.martineau@linux.intel.com>
[-- Attachment #1: Type: text/plain, Size: 9340 bytes --]
Hi Mat,
On 07/20/2016 05:19 PM, Mat Martineau wrote:
> The kernel (as of v4.8) has asymmetric crypto methods available using
> the keyctl API which make use of the kernel keyrings. The main
> advantage of this API over AF_ALG is that typical asymmetric
> operations involve fewer system calls.
> ---
> ell/key.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ell/key.h | 21 +++++++
> 2 files changed, 221 insertions(+)
>
> diff --git a/ell/key.c b/ell/key.c
> index 60602f9..85e461f 100644
> --- a/ell/key.c
> +++ b/ell/key.c
> @@ -29,10 +29,12 @@
> #include <stdint.h>
> #include <sys/syscall.h>
> #include <linux/keyctl.h>
> +#include <errno.h>
>
> #include "private.h"
> #include "util.h"
> #include "key.h"
> +#include "string.h"
>
> #ifndef KEYCTL_DH_COMPUTE
> #define KEYCTL_DH_COMPUTE 23
> @@ -44,11 +46,47 @@ struct keyctl_dh_params {
> };
> #endif
>
> +#ifndef KEYCTL_PKEY_QUERY
> +#define KEYCTL_PKEY_QUERY 24
> +#define KEYCTL_PKEY_ENCRYPT 25
> +#define KEYCTL_PKEY_DECRYPT 26
> +#define KEYCTL_PKEY_SIGN 27
> +#define KEYCTL_PKEY_VERIFY 28
> +
> +#define KEYCTL_SUPPORTS_ENCRYPT 0x01
> +#define KEYCTL_SUPPORTS_DECRYPT 0x02
> +#define KEYCTL_SUPPORTS_SIGN 0x04
> +#define KEYCTL_SUPPORTS_VERIFY 0x08
> +
> +struct keyctl_pkey_query {
> + uint32_t supported_ops;
> + uint32_t key_size;
> + uint16_t max_data_size;
> + uint16_t max_sig_size;
> + uint16_t max_enc_size;
> + uint16_t max_dec_size;
> +
> + uint32_t __spare[10];
> +};
> +
> +struct keyctl_pkey_params {
> + int32_t key_id;
> + uint32_t in_len;
> + union {
> + uint32_t out_len;
> + uint32_t in2_len;
> + };
> + uint32_t __spare[7];
> +};
> +#endif
> +
> static int32_t internal_keyring;
>
> struct l_key {
> int type;
> int32_t serial;
> + char *encoding;
> + char *hash;
Should these be const char?
> };
>
> struct l_keyring {
> @@ -117,6 +155,43 @@ static long kernel_unlink_key(int32_t key_serial, int32_t ring_serial)
> return result >= 0 ? result : -errno;
> }
>
> +static char *format_key_info(const char *encoding, const char *hash)
> +{
> + struct l_string *info;
> +
> + if (!encoding && !hash)
> + return NULL;
> +
> + info = l_string_new(0);
> +
> + if (encoding)
> + l_string_append_printf(info, "enc=%s ", encoding);
> +
> + if (hash)
> + l_string_append_printf(info, "hash=%s", hash);
> +
> + return l_string_free(info, false);
> +}
> +
> +static long kernel_query_key(int32_t key_serial, size_t *size, bool *public,
> + const char *encoding, const char *hash)
> +{
> + long result;
> + struct keyctl_pkey_query query;
> + char *info = format_key_info(encoding, hash);
> +
> + result = syscall(__NR_keyctl, KEYCTL_PKEY_QUERY, key_serial, 0,
> + info ?: "", &query);
> + if (result == 0) {
> + *size = query.key_size;
> + *public = ((query.supported_ops & KEYCTL_SUPPORTS_ENCRYPT) &&
> + !(query.supported_ops & KEYCTL_SUPPORTS_DECRYPT));
> + }
> + l_free(info);
> +
> + return result >= 0 ? result : -errno;
> +}
> +
> static long kernel_dh_compute(int32_t private, int32_t prime, int32_t base,
> void *payload, size_t len)
> {
> @@ -132,6 +207,40 @@ static long kernel_dh_compute(int32_t private, int32_t prime, int32_t base,
> return result >= 0 ? result : -errno;
> }
>
> +static long kernel_key_eds(int op, int32_t serial, const char *encoding,
> + const char *hash, const void *in, void *out,
> + size_t len_in, size_t len_out)
> +{
> + long result;
> + struct keyctl_pkey_params params = { .key_id = serial,
> + .in_len = len_in,
> + .out_len = len_out };
> + char *info = format_key_info(encoding, hash);
> +
> + result = syscall(__NR_keyctl, op, ¶ms, info ?: "", in, out);
> + l_free(info);
> +
> + return result >= 0 ? result : -errno;
> +}
> +
> +static long kernel_key_verify(int32_t serial, const char *encoding,
> + const char *hash, const void *data,
> + const void *sig, size_t len_data,
> + size_t len_sig)
> +{
> + long result;
> + struct keyctl_pkey_params params = { .key_id = serial,
> + .in_len = len_data,
> + .in2_len = len_sig };
> + char *info = format_key_info(encoding, hash);
> +
> + result = syscall(__NR_keyctl, KEYCTL_PKEY_VERIFY, ¶ms, info ?: "",
> + data, sig);
> + l_free(info);
> +
> + return result >= 0 ? result : -errno;
> +}
> +
> static bool setup_internal_keyring(void)
> {
> internal_keyring = kernel_add_key("keyring", "ell-internal", NULL, 0,
> @@ -220,6 +329,12 @@ LIB_EXPORT ssize_t l_key_get_size(struct l_key *key)
> return kernel_read_key(key->serial, NULL, 0);
> }
>
> +bool l_key_get_info(struct l_key *key, size_t *bits, bool *public)
> +{
> + return !kernel_query_key(key->serial, bits, public, key->encoding,
> + key->hash);
> +}
> +
How is this related to l_key_get_size()?
We might want to start documenting the l_key methods...
> static bool compute_common(struct l_key *base,
> struct l_key *private,
> struct l_key *prime,
> @@ -255,6 +370,91 @@ LIB_EXPORT bool l_key_compute_dh_secret(struct l_key *other_public,
> return compute_common(other_public, private, prime, payload, len);
> }
>
> +LIB_EXPORT bool l_key_set_cipher(struct l_key *key,
> + enum l_asymmetric_cipher_type cipher)
> +{
> + if (unlikely(!key))
> + return false;
> +
> + switch (cipher) {
> + case L_CIPHER_RSA_PKCS1_V1_5:
> + key->encoding = "pkcs1";
> + break;
> + }
> +
> + return true;
> +}
> +
> +LIB_EXPORT bool l_key_set_checksum_info(struct l_key *key,
> + enum l_checksum_type checksum)
> +{
> + if (unlikely(!key))
> + return false;
> +
> + switch (checksum) {
> + case L_CHECKSUM_MD5:
> + key->hash = "md5";
> + break;
> + case L_CHECKSUM_SHA1:
> + key->hash = "sha1";
> + break;
> + case L_CHECKSUM_SHA256:
> + key->hash = "sha256";
> + break;
> + case L_CHECKSUM_SHA384:
> + key->hash = "sha384";
> + break;
> + case L_CHECKSUM_SHA512:
> + key->hash = "sha512";
> + break;
> + }
> +
> + return true;
> +}
> +
> +static ssize_t eds_common(struct l_key *key, const void *in, void *out,
> + size_t len_in, size_t len_out, int op)
Whats eds stand for?
> +{
> + if (unlikely(!key))
> + return -EINVAL;
> +
> + return kernel_key_eds(op, key->serial, key->encoding, key->hash, in,
> + out, len_in, len_out);
> +}
> +
> +LIB_EXPORT ssize_t l_key_encrypt(struct l_key *key, const void *in, void *out,
> + size_t len_in, size_t len_out)
> +{
> + return eds_common(key, in, out, len_in, len_out, KEYCTL_PKEY_ENCRYPT);
> +}
> +
> +LIB_EXPORT ssize_t l_key_decrypt(struct l_key *key, const void *in, void *out,
> + size_t len_in, size_t len_out)
> +{
> + return eds_common(key, in, out, len_in, len_out, KEYCTL_PKEY_DECRYPT);
> +}
> +
> +LIB_EXPORT ssize_t l_key_sign(struct l_key *key, const void *in, void *out,
> + size_t len_in, size_t len_out)
> +{
> + return eds_common(key, in, out, len_in, len_out, KEYCTL_PKEY_SIGN);
> +}
> +
> +LIB_EXPORT bool l_key_verify(struct l_key *key, const void *data,
> + const void *sig, size_t len_data,
> + size_t len_sig)
> +{
> + long result;
> +
> + if (unlikely(!key))
> + return false;
> +
> + result = kernel_key_verify(key->serial, key->encoding, key->hash,
> + data, sig, len_data, len_sig);
> +
> + return result == 0;
> +}
> +
> LIB_EXPORT struct l_keyring *l_keyring_new(enum l_keyring_type type,
> const struct l_keyring *trusted)
> {
> diff --git a/ell/key.h b/ell/key.h
> index 5d981f1..f5176d1 100644
> --- a/ell/key.h
> +++ b/ell/key.h
> @@ -30,6 +30,9 @@ extern "C" {
> #include <stddef.h>
> #include <stdbool.h>
>
> +#include <ell/checksum.h>
> +#include <ell/cipher.h>
> +
> struct l_key;
> struct l_keyring;
>
> @@ -54,12 +57,30 @@ bool l_key_extract(struct l_key *key, void *payload, size_t *len);
>
> ssize_t l_key_get_size(struct l_key *key);
>
> +bool l_key_get_info(struct l_key *key, size_t *bits, bool *public);
> +
> bool l_key_compute_dh_public(struct l_key *generator, struct l_key *private,
> struct l_key *prime, void *payload, size_t *len);
>
> bool l_key_compute_dh_secret(struct l_key *other_public, struct l_key *private,
> struct l_key *prime, void *payload, size_t *len);
>
> +bool l_key_set_cipher(struct l_key *key, enum l_asymmetric_cipher_type cipher);
> +
> +bool l_key_set_checksum_info(struct l_key *key, enum l_checksum_type checksum);
> +
Why not make these parameters into encrypt / decrypt / sign / verify
operation?
> +ssize_t l_key_encrypt(struct l_key *key, const void *in, void *out,
> + size_t len_in, size_t len_out);
> +
> +ssize_t l_key_decrypt(struct l_key *key, const void *in, void *out,
> + size_t len_in, size_t len_out);
> +
> +ssize_t l_key_sign(struct l_key *key, const void *in, void *out,
> + size_t len_in, size_t len_out);
> +
> +bool l_key_verify(struct l_key *key, const void *data, const void *sig,
> + size_t len_data, size_t len_sig);
> +
> struct l_keyring *l_keyring_new(enum l_keyring_type type,
> const struct l_keyring *trust);
>
>
Regards,
-Denis
next prev parent reply other threads:[~2016-07-22 19:35 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-07-20 22:19 [PATCH 1/4] key: Update restrict method name Mat Martineau
2016-07-20 22:19 ` [PATCH 2/4] key: Consistently return errno from syscall wrappers Mat Martineau
2016-07-21 20:19 ` Denis Kenzior
2016-07-21 21:23 ` Mat Martineau
2016-07-20 22:19 ` [PATCH 3/4] key: Add key-based asymmetric crypto operations Mat Martineau
2016-07-22 19:35 ` Denis Kenzior [this message]
2016-07-22 21:55 ` Mat Martineau
2016-07-20 22:19 ` [PATCH 4/4] unit: Add tests for key-based asymmetric crypto Mat Martineau
2016-07-21 20:19 ` [PATCH 1/4] key: Update restrict method name Denis Kenzior
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5792756D.8090103@gmail.com \
--to=denkenz@gmail.com \
--cc=ell@lists.01.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.