Skip to content

Commit

Permalink
KEYS: Provide keyctls to drive the new key type ops for asymmetric ke…
Browse files Browse the repository at this point in the history
…ys [ver #2]

Provide five keyctl functions that permit userspace to make use of the new
key type ops for accessing and driving asymmetric keys.

 (*) Query an asymmetric key.

	long keyctl(KEYCTL_PKEY_QUERY,
		    key_serial_t key, unsigned long reserved,
		    struct keyctl_pkey_query *info);

     Get information about an asymmetric key.  The information is returned
     in the keyctl_pkey_query struct:

	__u32	supported_ops;

     A bit mask of flags indicating which ops are supported.  This is
     constructed from a bitwise-OR of:

	KEYCTL_SUPPORTS_{ENCRYPT,DECRYPT,SIGN,VERIFY}

	__u32	key_size;

     The size in bits of the key.

	__u16	max_data_size;
	__u16	max_sig_size;
	__u16	max_enc_size;
	__u16	max_dec_size;

     The maximum sizes in bytes of a blob of data to be signed, a signature
     blob, a blob to be encrypted and a blob to be decrypted.

     reserved must be set to 0.  This is intended for future use to hand
     over one or more passphrases needed unlock a key.

     If successful, 0 is returned.  If the key is not an asymmetric key,
     EOPNOTSUPP is returned.

 (*) Encrypt, decrypt, sign or verify a blob using an asymmetric key.

	long keyctl(KEYCTL_PKEY_ENCRYPT,
		    const struct keyctl_pkey_params *params,
		    const char *info,
		    const void *in,
		    void *out);

	long keyctl(KEYCTL_PKEY_DECRYPT,
		    const struct keyctl_pkey_params *params,
		    const char *info,
		    const void *in,
		    void *out);

	long keyctl(KEYCTL_PKEY_SIGN,
		    const struct keyctl_pkey_params *params,
		    const char *info,
		    const void *in,
		    void *out);

	long keyctl(KEYCTL_PKEY_VERIFY,
		    const struct keyctl_pkey_params *params,
		    const char *info,
		    const void *in,
		    const void *in2);

     Use an asymmetric key to perform a public-key cryptographic operation
     a blob of data.

     The parameter block pointed to by params contains a number of integer
     values:

	__s32		key_id;
	__u32		in_len;
	__u32		out_len;
	__u32		in2_len;

     For a given operation, the in and out buffers are used as follows:

	Operation ID		in,in_len	out,out_len	in2,in2_len
	=======================	===============	===============	===========
	KEYCTL_PKEY_ENCRYPT	Raw data	Encrypted data	-
	KEYCTL_PKEY_DECRYPT	Encrypted data	Raw data	-
	KEYCTL_PKEY_SIGN	Raw data	Signature	-
	KEYCTL_PKEY_VERIFY	Raw data	-		Signature

     info is a string of key=value pairs that supply supplementary
     information.

     The __spare space in the parameter block must be set to 0.  This is
     intended, amongst other things, to allow the passing of passphrases
     required to unlock a key.

     If successful, encrypt, decrypt and sign all return the amount of data
     written into the output buffer.  Verification returns 0 on success.

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>
  • Loading branch information
dhowells authored and James Morris committed Oct 26, 2018
1 parent 70025f8 commit 00d60fd
Show file tree
Hide file tree
Showing 7 changed files with 541 additions and 0 deletions.
111 changes: 111 additions & 0 deletions Documentation/security/keys/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,7 @@ The keyctl syscall functions are:
and either the buffer length or the OtherInfo length exceeds the
allowed length.


* Restrict keyring linkage::

long keyctl(KEYCTL_RESTRICT_KEYRING, key_serial_t keyring,
Expand Down Expand Up @@ -890,6 +891,116 @@ The keyctl syscall functions are:
applicable to the asymmetric key type.


* Query an asymmetric key::

long keyctl(KEYCTL_PKEY_QUERY,
key_serial_t key_id, unsigned long reserved,
struct keyctl_pkey_query *info);
Get information about an asymmetric key. The information is returned in
the keyctl_pkey_query struct::

__u32 supported_ops;
__u32 key_size;
__u16 max_data_size;
__u16 max_sig_size;
__u16 max_enc_size;
__u16 max_dec_size;
__u32 __spare[10];

``supported_ops`` contains a bit mask of flags indicating which ops are
supported. This is constructed from a bitwise-OR of::

KEYCTL_SUPPORTS_{ENCRYPT,DECRYPT,SIGN,VERIFY}

``key_size`` indicated the size of the key in bits.

``max_*_size`` indicate the maximum sizes in bytes of a blob of data to be
signed, a signature blob, a blob to be encrypted and a blob to be
decrypted.

``__spare[]`` must be set to 0. This is intended for future use to hand
over one or more passphrases needed unlock a key.

If successful, 0 is returned. If the key is not an asymmetric key,
EOPNOTSUPP is returned.


* Encrypt, decrypt, sign or verify a blob using an asymmetric key::

long keyctl(KEYCTL_PKEY_ENCRYPT,
const struct keyctl_pkey_params *params,
const char *info,
const void *in,
void *out);
long keyctl(KEYCTL_PKEY_DECRYPT,
const struct keyctl_pkey_params *params,
const char *info,
const void *in,
void *out);
long keyctl(KEYCTL_PKEY_SIGN,
const struct keyctl_pkey_params *params,
const char *info,
const void *in,
void *out);
long keyctl(KEYCTL_PKEY_VERIFY,
const struct keyctl_pkey_params *params,
const char *info,
const void *in,
const void *in2);
Use an asymmetric key to perform a public-key cryptographic operation a
blob of data. For encryption and verification, the asymmetric key may
only need the public parts to be available, but for decryption and signing
the private parts are required also.

The parameter block pointed to by params contains a number of integer
values::

__s32 key_id;
__u32 in_len;
__u32 out_len;
__u32 in2_len;

``key_id`` is the ID of the asymmetric key to be used. ``in_len`` and
``in2_len`` indicate the amount of data in the in and in2 buffers and
``out_len`` indicates the size of the out buffer as appropriate for the
above operations.

For a given operation, the in and out buffers are used as follows::

Operation ID in,in_len out,out_len in2,in2_len
======================= =============== =============== ===============
KEYCTL_PKEY_ENCRYPT Raw data Encrypted data -
KEYCTL_PKEY_DECRYPT Encrypted data Raw data -
KEYCTL_PKEY_SIGN Raw data Signature -
KEYCTL_PKEY_VERIFY Raw data - Signature

``info`` is a string of key=value pairs that supply supplementary
information. These include:

``enc=<encoding>`` The encoding of the encrypted/signature blob. This
can be "pkcs1" for RSASSA-PKCS1-v1.5 or
RSAES-PKCS1-v1.5; "pss" for "RSASSA-PSS"; "oaep" for
"RSAES-OAEP". If omitted or is "raw", the raw output
of the encryption function is specified.

``hash=<algo>`` If the data buffer contains the output of a hash
function and the encoding includes some indication of
which hash function was used, the hash function can be
specified with this, eg. "hash=sha256".

The ``__spare[]`` space in the parameter block must be set to 0. This is
intended, amongst other things, to allow the passing of passphrases
required to unlock a key.

If successful, encrypt, decrypt and sign all return the amount of data
written into the output buffer. Verification returns 0 on success.


Kernel Services
===============

Expand Down
25 changes: 25 additions & 0 deletions include/uapi/linux/keyctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@
#define KEYCTL_INVALIDATE 21 /* invalidate a key */
#define KEYCTL_GET_PERSISTENT 22 /* get a user's persistent keyring */
#define KEYCTL_DH_COMPUTE 23 /* Compute Diffie-Hellman values */
#define KEYCTL_PKEY_QUERY 24 /* Query public key parameters */
#define KEYCTL_PKEY_ENCRYPT 25 /* Encrypt a blob using a public key */
#define KEYCTL_PKEY_DECRYPT 26 /* Decrypt a blob using a public key */
#define KEYCTL_PKEY_SIGN 27 /* Create a public key signature */
#define KEYCTL_PKEY_VERIFY 28 /* Verify a public key signature */
#define KEYCTL_RESTRICT_KEYRING 29 /* Restrict keys allowed to link to a keyring */

/* keyctl structures */
Expand All @@ -87,4 +92,24 @@ struct keyctl_kdf_params {
#define KEYCTL_SUPPORTS_SIGN 0x04
#define KEYCTL_SUPPORTS_VERIFY 0x08

struct keyctl_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 */
__u32 __spare[10];
};

struct keyctl_pkey_params {
__s32 key_id; /* Serial no. of public key to use */
__u32 in_len; /* Input data size */
union {
__u32 out_len; /* Output buffer size (encrypt/decrypt/sign) */
__u32 in2_len; /* 2nd input data size (verify) */
};
__u32 __spare[7];
};

#endif /* _LINUX_KEYCTL_H */
1 change: 1 addition & 0 deletions security/keys/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_SYSCTL) += sysctl.o
obj-$(CONFIG_PERSISTENT_KEYRINGS) += persistent.o
obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o
obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += keyctl_pkey.o

#
# Key types
Expand Down
18 changes: 18 additions & 0 deletions security/keys/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,24 @@ COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
return keyctl_restrict_keyring(arg2, compat_ptr(arg3),
compat_ptr(arg4));

case KEYCTL_PKEY_QUERY:
if (arg3 != 0)
return -EINVAL;
return keyctl_pkey_query(arg2,
compat_ptr(arg4),
compat_ptr(arg5));

case KEYCTL_PKEY_ENCRYPT:
case KEYCTL_PKEY_DECRYPT:
case KEYCTL_PKEY_SIGN:
return keyctl_pkey_e_d_s(option,
compat_ptr(arg2), compat_ptr(arg3),
compat_ptr(arg4), compat_ptr(arg5));

case KEYCTL_PKEY_VERIFY:
return keyctl_pkey_verify(compat_ptr(arg2), compat_ptr(arg3),
compat_ptr(arg4), compat_ptr(arg5));

default:
return -EOPNOTSUPP;
}
Expand Down
39 changes: 39 additions & 0 deletions security/keys/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,45 @@ static inline long compat_keyctl_dh_compute(
#endif
#endif

#ifdef CONFIG_ASYMMETRIC_KEY_TYPE
extern long keyctl_pkey_query(key_serial_t,
const char __user *,
struct keyctl_pkey_query __user *);

extern long keyctl_pkey_verify(const struct keyctl_pkey_params __user *,
const char __user *,
const void __user *, const void __user *);

extern long keyctl_pkey_e_d_s(int,
const struct keyctl_pkey_params __user *,
const char __user *,
const void __user *, void __user *);
#else
static inline long keyctl_pkey_query(key_serial_t id,
const char __user *_info,
struct keyctl_pkey_query __user *_res)
{
return -EOPNOTSUPP;
}

static inline long keyctl_pkey_verify(const struct keyctl_pkey_params __user *params,
const char __user *_info,
const void __user *_in,
const void __user *_in2)
{
return -EOPNOTSUPP;
}

static inline long keyctl_pkey_e_d_s(int op,
const struct keyctl_pkey_params __user *params,
const char __user *_info,
const void __user *_in,
void __user *_out)
{
return -EOPNOTSUPP;
}
#endif

/*
* Debugging key validation
*/
Expand Down
24 changes: 24 additions & 0 deletions security/keys/keyctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1747,6 +1747,30 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
(const char __user *) arg3,
(const char __user *) arg4);

case KEYCTL_PKEY_QUERY:
if (arg3 != 0)
return -EINVAL;
return keyctl_pkey_query((key_serial_t)arg2,
(const char __user *)arg4,
(struct keyctl_pkey_query *)arg5);

case KEYCTL_PKEY_ENCRYPT:
case KEYCTL_PKEY_DECRYPT:
case KEYCTL_PKEY_SIGN:
return keyctl_pkey_e_d_s(
option,
(const struct keyctl_pkey_params __user *)arg2,
(const char __user *)arg3,
(const void __user *)arg4,
(void __user *)arg5);

case KEYCTL_PKEY_VERIFY:
return keyctl_pkey_verify(
(const struct keyctl_pkey_params __user *)arg2,
(const char __user *)arg3,
(const void __user *)arg4,
(const void __user *)arg5);

default:
return -EOPNOTSUPP;
}
Expand Down
Loading

0 comments on commit 00d60fd

Please sign in to comment.