[PATCH 03/04] Add encryption ops to the keyctl syscall

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Changes the keyctl syscall to accept six arguments (is it valid to do so?)
and adds encryption as one of the supported ops for in-kernel keys.

Signed-off-by: David Härdeman <[email protected]>

--

Index: vanilla-kernel/include/linux/compat.h
===================================================================
--- vanilla-kernel.orig/include/linux/compat.h	2006-01-15 18:22:51.000000000 +0100
+++ vanilla-kernel/include/linux/compat.h	2006-01-23 18:40:52.000000000 +0100
@@ -132,8 +132,8 @@
 long compat_sys_shmctl(int first, int second, void __user *uptr);
 long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
 		unsigned nsems, const struct compat_timespec __user *timeout);
-asmlinkage long compat_sys_keyctl(u32 option,
-			      u32 arg2, u32 arg3, u32 arg4, u32 arg5);
+asmlinkage long compat_sys_keyctl(u32 option, u32 arg2, u32 arg3, 
+                                  u32 arg4, u32 arg5, u32 arg6);
 
 asmlinkage ssize_t compat_sys_readv(unsigned long fd,
 		const struct compat_iovec __user *vec, unsigned long vlen);
Index: vanilla-kernel/include/linux/key.h
===================================================================
--- vanilla-kernel.orig/include/linux/key.h	2006-01-17 22:49:50.000000000 +0100
+++ vanilla-kernel/include/linux/key.h	2006-01-23 18:40:52.000000000 +0100
@@ -220,6 +220,17 @@
 	 */
 	long (*read)(const struct key *key, char __user *buffer, size_t buflen);
 
+	/* encrypt data using a key (optional)
+	 * - permission checks will be done by the caller
+	 * - the key's semaphore will be readlocked by the caller
+	 * - should return the amount of data that would be returned from the
+         *   encryption even if the buffer is NULL
+         * - expects the output buffer to be able to hold the result
+	 */
+	long (*encrypt)(const struct key *key,
+                        char __user *inbuffer, size_t inbuflen,
+                        char __user *outbuffer, size_t outbuflen);
+
 	/* handle request_key() for this type instead of invoking
 	 * /sbin/request-key (optional)
 	 * - key is the key to instantiate
Index: vanilla-kernel/include/linux/keyctl.h
===================================================================
--- vanilla-kernel.orig/include/linux/keyctl.h	2006-01-17 22:49:50.000000000 +0100
+++ vanilla-kernel/include/linux/keyctl.h	2006-01-23 18:40:52.000000000 +0100
@@ -49,5 +49,6 @@
 #define KEYCTL_SET_REQKEY_KEYRING	14	/* set default request-key keyring */
 #define KEYCTL_SET_TIMEOUT		15	/* set key timeout */
 #define KEYCTL_ASSUME_AUTHORITY		16	/* assume request_key() authorisation */
+#define KEYCTL_ENCRYPT                  17      /* encrypt a chunk of data using key */
 
 #endif /*  _LINUX_KEYCTL_H */
Index: vanilla-kernel/include/linux/syscalls.h
===================================================================
--- vanilla-kernel.orig/include/linux/syscalls.h	2006-01-17 22:49:50.000000000 +0100
+++ vanilla-kernel/include/linux/syscalls.h	2006-01-23 18:40:52.000000000 +0100
@@ -504,8 +504,9 @@
 				const char __user *_callout_info,
 				key_serial_t destringid);
 
-asmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3,
-			   unsigned long arg4, unsigned long arg5);
+asmlinkage long sys_keyctl(int cmd, unsigned long arg2, 
+                           unsigned long arg3, unsigned long arg4, 
+                           unsigned long arg5, unsigned long arg6);
 
 asmlinkage long sys_ioprio_set(int which, int who, int ioprio);
 asmlinkage long sys_ioprio_get(int which, int who);
Index: vanilla-kernel/security/keys/compat.c
===================================================================
--- vanilla-kernel.orig/security/keys/compat.c	2006-01-17 22:49:50.000000000 +0100
+++ vanilla-kernel/security/keys/compat.c	2006-01-23 18:44:01.000000000 +0100
@@ -23,8 +23,8 @@
  *   registers on taking a 32-bit syscall are zero
  * - if you can, you should call sys_keyctl directly
  */
-asmlinkage long compat_sys_keyctl(u32 option,
-				  u32 arg2, u32 arg3, u32 arg4, u32 arg5)
+asmlinkage long compat_sys_keyctl(u32 option, u32 arg2, u32 arg3, 
+				  u32 arg4, u32 arg5, u32 arg6)
 {
 	switch (option) {
 	case KEYCTL_GET_KEYRING_ID:
@@ -80,6 +80,11 @@
 	case KEYCTL_ASSUME_AUTHORITY:
 		return keyctl_assume_authority(arg2);
 
+	case KEYCTL_ENCRYPT:
+		return keyctl_encrypt_with_key(arg2,
+					       compat_ptr(arg3), arg4,
+					       compat_ptr(arg5), arg6);
+
 	default:
 		return -EOPNOTSUPP;
 	}
Index: vanilla-kernel/security/keys/keyctl.c
===================================================================
--- vanilla-kernel.orig/security/keys/keyctl.c	2006-01-17 22:49:50.000000000 +0100
+++ vanilla-kernel/security/keys/keyctl.c	2006-01-23 18:44:02.000000000 +0100
@@ -1066,10 +1066,71 @@
 
 /*****************************************************************************/
 /*
+ * encrypt a chunk of data using a specified key
+ * - implements keyctl(KEYCTL_ENCRYPT)
+ */
+long keyctl_encrypt_with_key(key_serial_t keyid,
+			     const void __user *data,
+			     size_t dlen,
+			     const void __user *result,
+			     size_t rlen)
+{
+	struct key *key;
+	key_ref_t key_ref;
+	long ret;
+
+	/* find the key first */
+	key_ref = lookup_user_key(NULL, keyid, 0, 0, 0);
+	if (IS_ERR(key_ref)) {
+		ret = -ENOKEY;
+		goto error;
+	}
+
+	key = key_ref_to_ptr(key_ref);
+
+	/* see if we can read it directly */
+	ret = key_permission(key_ref, KEY_READ);
+	if (ret == 0)
+		goto can_read_key;
+	if (ret != -EACCES)
+		goto error;
+
+	/* we can't; see if it's searchable from this process's keyrings
+	 * - we automatically take account of the fact that it may be
+	 *   dangling off an instantiation key
+	 */
+	if (!is_key_possessed(key_ref)) {
+		ret = -EACCES;
+		goto error2;
+	}
+
+	/* the key is probably readable - now try to read it */
+ can_read_key:
+	ret = key_validate(key);
+	if (ret == 0) {
+		ret = -EOPNOTSUPP;
+		if (key->type->encrypt) {
+			/* encrypt the data with the semaphore held (since we
+			 * might sleep) */
+			down_read(&key->sem);
+			ret = key->type->encrypt(key, data, dlen, result, rlen);
+			up_read(&key->sem);
+		}
+	}
+
+ error2:
+	key_put(key);
+ error:
+	return ret;
+} /* end keyctl_encrypt_with_key() */
+
+/*****************************************************************************/
+/*
  * the key control system call
  */
-asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
-			   unsigned long arg4, unsigned long arg5)
+asmlinkage long sys_keyctl(int option, unsigned long arg2, 
+			   unsigned long arg3, unsigned long arg4, 
+			   unsigned long arg5, unsigned long arg6)
 {
 	switch (option) {
 	case KEYCTL_GET_KEYRING_ID:
@@ -1144,6 +1205,13 @@
 	case KEYCTL_ASSUME_AUTHORITY:
 		return keyctl_assume_authority((key_serial_t) arg2);
 
+	case KEYCTL_ENCRYPT:
+		return keyctl_encrypt_with_key((key_serial_t) arg2,
+					       (const char __user *) arg3,
+					       (size_t) arg4,
+					       (const char __user *) arg5,
+					       (size_t) arg6);
+
 	default:
 		return -EOPNOTSUPP;
 	}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux