Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 00d60fd3 authored by David Howells's avatar David Howells Committed by James Morris
Browse files

KEYS: Provide keyctls to drive the new key type ops for asymmetric keys [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: default avatarDavid Howells <dhowells@redhat.com>
Tested-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Reviewed-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Reviewed-by: default avatarDenis Kenzior <denkenz@gmail.com>
Tested-by: default avatarDenis Kenzior <denkenz@gmail.com>
Signed-off-by: default avatarJames Morris <james.morris@microsoft.com>
parent 70025f84
Loading
Loading
Loading
Loading
+111 −0
Original line number Diff line number Diff line
@@ -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,
@@ -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
===============

+25 −0
Original line number Diff line number Diff line
@@ -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 */
@@ -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 −0
Original line number Diff line number Diff line
@@ -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
+18 −0
Original line number Diff line number Diff line
@@ -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;
	}
+39 −0
Original line number Diff line number Diff line
@@ -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
 */
Loading