Skip to content

Commit 00d60fd

Browse files
dhowellsJames Morris
authored andcommitted
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: 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>
1 parent 70025f8 commit 00d60fd

File tree

7 files changed

+541
-0
lines changed

7 files changed

+541
-0
lines changed

Documentation/security/keys/core.rst

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,7 @@ The keyctl syscall functions are:
859859
and either the buffer length or the OtherInfo length exceeds the
860860
allowed length.
861861

862+
862863
* Restrict keyring linkage::
863864

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

892893

894+
* Query an asymmetric key::
895+
896+
long keyctl(KEYCTL_PKEY_QUERY,
897+
key_serial_t key_id, unsigned long reserved,
898+
struct keyctl_pkey_query *info);
899+
900+
Get information about an asymmetric key. The information is returned in
901+
the keyctl_pkey_query struct::
902+
903+
__u32 supported_ops;
904+
__u32 key_size;
905+
__u16 max_data_size;
906+
__u16 max_sig_size;
907+
__u16 max_enc_size;
908+
__u16 max_dec_size;
909+
__u32 __spare[10];
910+
911+
``supported_ops`` contains a bit mask of flags indicating which ops are
912+
supported. This is constructed from a bitwise-OR of::
913+
914+
KEYCTL_SUPPORTS_{ENCRYPT,DECRYPT,SIGN,VERIFY}
915+
916+
``key_size`` indicated the size of the key in bits.
917+
918+
``max_*_size`` indicate the maximum sizes in bytes of a blob of data to be
919+
signed, a signature blob, a blob to be encrypted and a blob to be
920+
decrypted.
921+
922+
``__spare[]`` must be set to 0. This is intended for future use to hand
923+
over one or more passphrases needed unlock a key.
924+
925+
If successful, 0 is returned. If the key is not an asymmetric key,
926+
EOPNOTSUPP is returned.
927+
928+
929+
* Encrypt, decrypt, sign or verify a blob using an asymmetric key::
930+
931+
long keyctl(KEYCTL_PKEY_ENCRYPT,
932+
const struct keyctl_pkey_params *params,
933+
const char *info,
934+
const void *in,
935+
void *out);
936+
937+
long keyctl(KEYCTL_PKEY_DECRYPT,
938+
const struct keyctl_pkey_params *params,
939+
const char *info,
940+
const void *in,
941+
void *out);
942+
943+
long keyctl(KEYCTL_PKEY_SIGN,
944+
const struct keyctl_pkey_params *params,
945+
const char *info,
946+
const void *in,
947+
void *out);
948+
949+
long keyctl(KEYCTL_PKEY_VERIFY,
950+
const struct keyctl_pkey_params *params,
951+
const char *info,
952+
const void *in,
953+
const void *in2);
954+
955+
Use an asymmetric key to perform a public-key cryptographic operation a
956+
blob of data. For encryption and verification, the asymmetric key may
957+
only need the public parts to be available, but for decryption and signing
958+
the private parts are required also.
959+
960+
The parameter block pointed to by params contains a number of integer
961+
values::
962+
963+
__s32 key_id;
964+
__u32 in_len;
965+
__u32 out_len;
966+
__u32 in2_len;
967+
968+
``key_id`` is the ID of the asymmetric key to be used. ``in_len`` and
969+
``in2_len`` indicate the amount of data in the in and in2 buffers and
970+
``out_len`` indicates the size of the out buffer as appropriate for the
971+
above operations.
972+
973+
For a given operation, the in and out buffers are used as follows::
974+
975+
Operation ID in,in_len out,out_len in2,in2_len
976+
======================= =============== =============== ===============
977+
KEYCTL_PKEY_ENCRYPT Raw data Encrypted data -
978+
KEYCTL_PKEY_DECRYPT Encrypted data Raw data -
979+
KEYCTL_PKEY_SIGN Raw data Signature -
980+
KEYCTL_PKEY_VERIFY Raw data - Signature
981+
982+
``info`` is a string of key=value pairs that supply supplementary
983+
information. These include:
984+
985+
``enc=<encoding>`` The encoding of the encrypted/signature blob. This
986+
can be "pkcs1" for RSASSA-PKCS1-v1.5 or
987+
RSAES-PKCS1-v1.5; "pss" for "RSASSA-PSS"; "oaep" for
988+
"RSAES-OAEP". If omitted or is "raw", the raw output
989+
of the encryption function is specified.
990+
991+
``hash=<algo>`` If the data buffer contains the output of a hash
992+
function and the encoding includes some indication of
993+
which hash function was used, the hash function can be
994+
specified with this, eg. "hash=sha256".
995+
996+
The ``__spare[]`` space in the parameter block must be set to 0. This is
997+
intended, amongst other things, to allow the passing of passphrases
998+
required to unlock a key.
999+
1000+
If successful, encrypt, decrypt and sign all return the amount of data
1001+
written into the output buffer. Verification returns 0 on success.
1002+
1003+
8931004
Kernel Services
8941005
===============
8951006

include/uapi/linux/keyctl.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@
6161
#define KEYCTL_INVALIDATE 21 /* invalidate a key */
6262
#define KEYCTL_GET_PERSISTENT 22 /* get a user's persistent keyring */
6363
#define KEYCTL_DH_COMPUTE 23 /* Compute Diffie-Hellman values */
64+
#define KEYCTL_PKEY_QUERY 24 /* Query public key parameters */
65+
#define KEYCTL_PKEY_ENCRYPT 25 /* Encrypt a blob using a public key */
66+
#define KEYCTL_PKEY_DECRYPT 26 /* Decrypt a blob using a public key */
67+
#define KEYCTL_PKEY_SIGN 27 /* Create a public key signature */
68+
#define KEYCTL_PKEY_VERIFY 28 /* Verify a public key signature */
6469
#define KEYCTL_RESTRICT_KEYRING 29 /* Restrict keys allowed to link to a keyring */
6570

6671
/* keyctl structures */
@@ -87,4 +92,24 @@ struct keyctl_kdf_params {
8792
#define KEYCTL_SUPPORTS_SIGN 0x04
8893
#define KEYCTL_SUPPORTS_VERIFY 0x08
8994

95+
struct keyctl_pkey_query {
96+
__u32 supported_ops; /* Which ops are supported */
97+
__u32 key_size; /* Size of the key in bits */
98+
__u16 max_data_size; /* Maximum size of raw data to sign in bytes */
99+
__u16 max_sig_size; /* Maximum size of signature in bytes */
100+
__u16 max_enc_size; /* Maximum size of encrypted blob in bytes */
101+
__u16 max_dec_size; /* Maximum size of decrypted blob in bytes */
102+
__u32 __spare[10];
103+
};
104+
105+
struct keyctl_pkey_params {
106+
__s32 key_id; /* Serial no. of public key to use */
107+
__u32 in_len; /* Input data size */
108+
union {
109+
__u32 out_len; /* Output buffer size (encrypt/decrypt/sign) */
110+
__u32 in2_len; /* 2nd input data size (verify) */
111+
};
112+
__u32 __spare[7];
113+
};
114+
90115
#endif /* _LINUX_KEYCTL_H */

security/keys/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ obj-$(CONFIG_PROC_FS) += proc.o
2222
obj-$(CONFIG_SYSCTL) += sysctl.o
2323
obj-$(CONFIG_PERSISTENT_KEYRINGS) += persistent.o
2424
obj-$(CONFIG_KEY_DH_OPERATIONS) += dh.o
25+
obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += keyctl_pkey.o
2526

2627
#
2728
# Key types

security/keys/compat.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,24 @@ COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
141141
return keyctl_restrict_keyring(arg2, compat_ptr(arg3),
142142
compat_ptr(arg4));
143143

144+
case KEYCTL_PKEY_QUERY:
145+
if (arg3 != 0)
146+
return -EINVAL;
147+
return keyctl_pkey_query(arg2,
148+
compat_ptr(arg4),
149+
compat_ptr(arg5));
150+
151+
case KEYCTL_PKEY_ENCRYPT:
152+
case KEYCTL_PKEY_DECRYPT:
153+
case KEYCTL_PKEY_SIGN:
154+
return keyctl_pkey_e_d_s(option,
155+
compat_ptr(arg2), compat_ptr(arg3),
156+
compat_ptr(arg4), compat_ptr(arg5));
157+
158+
case KEYCTL_PKEY_VERIFY:
159+
return keyctl_pkey_verify(compat_ptr(arg2), compat_ptr(arg3),
160+
compat_ptr(arg4), compat_ptr(arg5));
161+
144162
default:
145163
return -EOPNOTSUPP;
146164
}

security/keys/internal.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,45 @@ static inline long compat_keyctl_dh_compute(
298298
#endif
299299
#endif
300300

301+
#ifdef CONFIG_ASYMMETRIC_KEY_TYPE
302+
extern long keyctl_pkey_query(key_serial_t,
303+
const char __user *,
304+
struct keyctl_pkey_query __user *);
305+
306+
extern long keyctl_pkey_verify(const struct keyctl_pkey_params __user *,
307+
const char __user *,
308+
const void __user *, const void __user *);
309+
310+
extern long keyctl_pkey_e_d_s(int,
311+
const struct keyctl_pkey_params __user *,
312+
const char __user *,
313+
const void __user *, void __user *);
314+
#else
315+
static inline long keyctl_pkey_query(key_serial_t id,
316+
const char __user *_info,
317+
struct keyctl_pkey_query __user *_res)
318+
{
319+
return -EOPNOTSUPP;
320+
}
321+
322+
static inline long keyctl_pkey_verify(const struct keyctl_pkey_params __user *params,
323+
const char __user *_info,
324+
const void __user *_in,
325+
const void __user *_in2)
326+
{
327+
return -EOPNOTSUPP;
328+
}
329+
330+
static inline long keyctl_pkey_e_d_s(int op,
331+
const struct keyctl_pkey_params __user *params,
332+
const char __user *_info,
333+
const void __user *_in,
334+
void __user *_out)
335+
{
336+
return -EOPNOTSUPP;
337+
}
338+
#endif
339+
301340
/*
302341
* Debugging key validation
303342
*/

security/keys/keyctl.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,30 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
17471747
(const char __user *) arg3,
17481748
(const char __user *) arg4);
17491749

1750+
case KEYCTL_PKEY_QUERY:
1751+
if (arg3 != 0)
1752+
return -EINVAL;
1753+
return keyctl_pkey_query((key_serial_t)arg2,
1754+
(const char __user *)arg4,
1755+
(struct keyctl_pkey_query *)arg5);
1756+
1757+
case KEYCTL_PKEY_ENCRYPT:
1758+
case KEYCTL_PKEY_DECRYPT:
1759+
case KEYCTL_PKEY_SIGN:
1760+
return keyctl_pkey_e_d_s(
1761+
option,
1762+
(const struct keyctl_pkey_params __user *)arg2,
1763+
(const char __user *)arg3,
1764+
(const void __user *)arg4,
1765+
(void __user *)arg5);
1766+
1767+
case KEYCTL_PKEY_VERIFY:
1768+
return keyctl_pkey_verify(
1769+
(const struct keyctl_pkey_params __user *)arg2,
1770+
(const char __user *)arg3,
1771+
(const void __user *)arg4,
1772+
(const void __user *)arg5);
1773+
17501774
default:
17511775
return -EOPNOTSUPP;
17521776
}

0 commit comments

Comments
 (0)