KEYS: Provide key type operations for asymmetric key ops [ver #2]
authorDavid Howells <dhowells@redhat.com>
Tue, 9 Oct 2018 16:46:51 +0000 (17:46 +0100)
committerJames Morris <james.morris@microsoft.com>
Fri, 26 Oct 2018 08:30:46 +0000 (09:30 +0100)
Provide five new operations in the key_type struct that can be used to
provide access to asymmetric key operations.  These will be implemented for
the asymmetric key type in a later patch and may refer to a key retained in
RAM by the kernel or a key retained in crypto hardware.

     int (*asym_query)(const struct kernel_pkey_params *params,
       struct kernel_pkey_query *info);
     int (*asym_eds_op)(struct kernel_pkey_params *params,
const void *in, void *out);
     int (*asym_verify_signature)(struct kernel_pkey_params *params,
          const void *in, const void *in2);

Since encrypt, decrypt and sign are identical in their interfaces, they're
rolled together in the asym_eds_op() operation and there's an operation ID
in the params argument to distinguish them.

Verify is different in that we supply the data and the signature instead
and get an error value (or 0) as the only result on the expectation that
this may well be how a hardware crypto device may work.

Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Marcel Holtmann <marcel@holtmann.org>
Reviewed-by: Marcel Holtmann <marcel@holtmann.org>
Reviewed-by: Denis Kenzior <denkenz@gmail.com>
Tested-by: Denis Kenzior <denkenz@gmail.com>
Signed-off-by: James Morris <james.morris@microsoft.com>
Documentation/security/keys/core.rst
include/linux/key-type.h
include/linux/keyctl.h [new file with mode: 0644]
include/uapi/linux/keyctl.h

index 9ce7256c6edba8b605e9928a42159d717f6d7cf5..c144978479d589fe68f3c5f63aa2439f2ad445eb 100644 (file)
@@ -1483,6 +1483,112 @@ The structure has a number of fields, some of which are mandatory:
      attempted key link operation. If there is no match, -EINVAL is returned.
 
 
+  *  ``int (*asym_eds_op)(struct kernel_pkey_params *params,
+                         const void *in, void *out);``
+     ``int (*asym_verify_signature)(struct kernel_pkey_params *params,
+                                   const void *in, const void *in2);``
+
+     These methods are optional.  If provided the first allows a key to be
+     used to encrypt, decrypt or sign a blob of data, and the second allows a
+     key to verify a signature.
+
+     In all cases, the following information is provided in the params block::
+
+       struct kernel_pkey_params {
+               struct key      *key;
+               const char      *encoding;
+               const char      *hash_algo;
+               char            *info;
+               __u32           in_len;
+               union {
+                       __u32   out_len;
+                       __u32   in2_len;
+               };
+               enum kernel_pkey_operation op : 8;
+       };
+
+     This includes the key to be used; a string indicating the encoding to use
+     (for instance, "pkcs1" may be used with an RSA key to indicate
+     RSASSA-PKCS1-v1.5 or RSAES-PKCS1-v1.5 encoding or "raw" if no encoding);
+     the name of the hash algorithm used to generate the data for a signature
+     (if appropriate); the sizes of the input and output (or second input)
+     buffers; and the ID of the operation to be performed.
+
+     For a given operation ID, the input and output buffers are used as
+     follows::
+
+       Operation ID            in,in_len       out,out_len     in2,in2_len
+       ======================= =============== =============== ===============
+       kernel_pkey_encrypt     Raw data        Encrypted data  -
+       kernel_pkey_decrypt     Encrypted data  Raw data        -
+       kernel_pkey_sign        Raw data        Signature       -
+       kernel_pkey_verify      Raw data        -               Signature
+
+     asym_eds_op() deals with encryption, decryption and signature creation as
+     specified by params->op.  Note that params->op is also set for
+     asym_verify_signature().
+
+     Encrypting and signature creation both take raw data in the input buffer
+     and return the encrypted result in the output buffer.  Padding may have
+     been added if an encoding was set.  In the case of signature creation,
+     depending on the encoding, the padding created may need to indicate the
+     digest algorithm - the name of which should be supplied in hash_algo.
+
+     Decryption takes encrypted data in the input buffer and returns the raw
+     data in the output buffer.  Padding will get checked and stripped off if
+     an encoding was set.
+
+     Verification takes raw data in the input buffer and the signature in the
+     second input buffer and checks that the one matches the other.  Padding
+     will be validated.  Depending on the encoding, the digest algorithm used
+     to generate the raw data may need to be indicated in hash_algo.
+
+     If successful, asym_eds_op() should return the number of bytes written
+     into the output buffer.  asym_verify_signature() should return 0.
+
+     A variety of errors may be returned, including EOPNOTSUPP if the operation
+     is not supported; EKEYREJECTED if verification fails; ENOPKG if the
+     required crypto isn't available.
+
+
+  *  ``int (*asym_query)(const struct kernel_pkey_params *params,
+                        struct kernel_pkey_query *info);``
+
+     This method is optional.  If provided it allows information about the
+     public or asymmetric key held in the key to be determined.
+
+     The parameter block is as for asym_eds_op() and co. but in_len and out_len
+     are unused.  The encoding and hash_algo fields should be used to reduce
+     the returned buffer/data sizes as appropriate.
+
+     If successful, the following information is filled in::
+
+       struct kernel_pkey_query {
+               __u32           supported_ops;
+               __u32           key_size;
+               __u16           max_data_size;
+               __u16           max_sig_size;
+               __u16           max_enc_size;
+               __u16           max_dec_size;
+       };
+
+     The supported_ops field will contain a bitmask indicating what operations
+     are supported by the key, including encryption of a blob, decryption of a
+     blob, signing a blob and verifying the signature on a blob.  The following
+     constants are defined for this::
+
+       KEYCTL_SUPPORTS_{ENCRYPT,DECRYPT,SIGN,VERIFY}
+
+     The key_size field is the size of the key in bits.  max_data_size and
+     max_sig_size are the maximum raw data and signature sizes for creation and
+     verification of a signature; max_enc_size and max_dec_size are the maximum
+     raw data and signature sizes for encryption and decryption.  The
+     max_*_size fields are measured in bytes.
+
+     If successful, 0 will be returned.  If the key doesn't support this,
+     EOPNOTSUPP will be returned.
+
+
 Request-Key Callback Service
 ============================
 
index 05d8fb5a06c491076889f57872a1388690e40438..bc9af551fc83821e5bec98e5cbc582b2fe0be07a 100644 (file)
@@ -17,6 +17,9 @@
 
 #ifdef CONFIG_KEYS
 
+struct kernel_pkey_query;
+struct kernel_pkey_params;
+
 /*
  * key under-construction record
  * - passed to the request_key actor if supplied
@@ -155,6 +158,14 @@ struct key_type {
         */
        struct key_restriction *(*lookup_restriction)(const char *params);
 
+       /* Asymmetric key accessor functions. */
+       int (*asym_query)(const struct kernel_pkey_params *params,
+                         struct kernel_pkey_query *info);
+       int (*asym_eds_op)(struct kernel_pkey_params *params,
+                          const void *in, void *out);
+       int (*asym_verify_signature)(struct kernel_pkey_params *params,
+                                    const void *in, const void *in2);
+
        /* internal fields */
        struct list_head        link;           /* link in types list */
        struct lock_class_key   lock_class;     /* key->sem lock class */
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
new file mode 100644 (file)
index 0000000..c7c48c7
--- /dev/null
@@ -0,0 +1,46 @@
+/* keyctl kernel bits
+ *
+ * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef __LINUX_KEYCTL_H
+#define __LINUX_KEYCTL_H
+
+#include <uapi/linux/keyctl.h>
+
+struct kernel_pkey_query {
+       __u32           supported_ops;  /* Which ops are supported */
+       __u32           key_size;       /* Size of the key in bits */
+       __u16           max_data_size;  /* Maximum size of raw data to sign in bytes */
+       __u16           max_sig_size;   /* Maximum size of signature in bytes */
+       __u16           max_enc_size;   /* Maximum size of encrypted blob in bytes */
+       __u16           max_dec_size;   /* Maximum size of decrypted blob in bytes */
+};
+
+enum kernel_pkey_operation {
+       kernel_pkey_encrypt,
+       kernel_pkey_decrypt,
+       kernel_pkey_sign,
+       kernel_pkey_verify,
+};
+
+struct kernel_pkey_params {
+       struct key      *key;
+       const char      *encoding;      /* Encoding (eg. "oaep" or "raw" for none) */
+       const char      *hash_algo;     /* Digest algorithm used (eg. "sha1") or NULL if N/A */
+       char            *info;          /* Modified info string to be released later */
+       __u32           in_len;         /* Input data size */
+       union {
+               __u32   out_len;        /* Output buffer size (enc/dec/sign) */
+               __u32   in2_len;        /* 2nd input data size (verify) */
+       };
+       enum kernel_pkey_operation op : 8;
+};
+
+#endif /* __LINUX_KEYCTL_H */
index 0f3cb13db8e93efe9d6319395f21849e896f7a02..1d1e9f2877afb2ec7deab2cb496f6aad912225b3 100644 (file)
@@ -82,4 +82,9 @@ struct keyctl_kdf_params {
        __u32 __spare[8];
 };
 
+#define KEYCTL_SUPPORTS_ENCRYPT                0x01
+#define KEYCTL_SUPPORTS_DECRYPT                0x02
+#define KEYCTL_SUPPORTS_SIGN           0x04
+#define KEYCTL_SUPPORTS_VERIFY         0x08
+
 #endif /*  _LINUX_KEYCTL_H */