Merge branch 'man_formatting_fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/mtk/keyutils.git

Signed-off-by: David Howells <dhowells@redhat.com>
diff --git a/.gitignore b/.gitignore
index 1caa791..0ac39ed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,7 +4,8 @@
 *.so
 *.a
 *.so.*
-keyctl
-request-key
-key.dns_resolver
-rpmbuild
+/keyctl
+/request-key
+/key.dns_resolver
+/rpmbuild
+test.out
diff --git a/Makefile b/Makefile
index 5395c0b..824bbbf 100644
--- a/Makefile
+++ b/Makefile
@@ -194,6 +194,7 @@
 	$(LNS) keyctl_link.3 $(DESTDIR)$(MAN3)/keyctl_unlink.3
 	$(LNS) keyctl_read.3 $(DESTDIR)$(MAN3)/keyctl_read_alloc.3
 	$(LNS) recursive_key_scan.3 $(DESTDIR)$(MAN3)/recursive_session_key_scan.3
+	$(LNS) keyctl_dh_compute.3 $(DESTDIR)$(MAN3)/keyctl_dh_compute_alloc.3
 	$(INSTALL) -D -m 0644 keyutils.h $(DESTDIR)$(INCLUDEDIR)/keyutils.h
 
 ###############################################################################
@@ -217,7 +218,7 @@
 	$(RM) debugfiles.list debugsources.list
 
 distclean: clean
-	$(RM) -r rpmbuild
+	$(RM) -r rpmbuild $(TARBALL)
 
 ###############################################################################
 #
@@ -226,7 +227,7 @@
 ###############################################################################
 $(ZTARBALL):
 	git archive --prefix=keyutils-$(VERSION)/ --format tar -o $(TARBALL) HEAD
-	bzip2 -9 $(TARBALL)
+	bzip2 -9 <$(TARBALL) >$(ZTARBALL)
 
 tarball: $(ZTARBALL)
 
@@ -236,9 +237,10 @@
 #
 ###############################################################################
 SRCBALL	:= rpmbuild/SOURCES/$(TARBALL)
+ZSRCBALL := rpmbuild/SOURCES/$(ZTARBALL)
 
 BUILDID	:= .local
-dist	:= $(word 2,$(shell grep "%dist" /etc/rpm/macros.dist))
+dist	:= $(word 2,$(shell grep -r "^%dist" /etc/rpm /usr/lib/rpm))
 release	:= $(word 2,$(shell grep ^Release: $(SPECFILE)))
 release	:= $(subst %{?dist},$(dist),$(release))
 release	:= $(subst %{?buildid},$(BUILDID),$(release))
@@ -246,12 +248,12 @@
 SRPM	:= rpmbuild/SRPMS/keyutils-$(rpmver).src.rpm
 
 RPMBUILDDIRS := \
-		--define "_srcrpmdir $(CURDIR)/rpmbuild/SRPMS" \
-		--define "_rpmdir $(CURDIR)/rpmbuild/RPMS" \
-		--define "_sourcedir $(CURDIR)/rpmbuild/SOURCES" \
-		--define "_specdir $(CURDIR)/rpmbuild/SPECS" \
-		--define "_builddir $(CURDIR)/rpmbuild/BUILD" \
-		--define "_buildrootdir $(CURDIR)/rpmbuild/BUILDROOT"
+	--define "_srcrpmdir $(CURDIR)/rpmbuild/SRPMS" \
+	--define "_rpmdir $(CURDIR)/rpmbuild/RPMS" \
+	--define "_sourcedir $(CURDIR)/rpmbuild/SOURCES" \
+	--define "_specdir $(CURDIR)/rpmbuild/SPECS" \
+	--define "_builddir $(CURDIR)/rpmbuild/BUILD" \
+	--define "_buildrootdir $(CURDIR)/rpmbuild/BUILDROOT"
 
 RPMFLAGS := \
 	--define "buildid $(BUILDID)"
@@ -261,8 +263,8 @@
 	chmod ug-s rpmbuild
 	mkdir -p rpmbuild/{SPECS,SOURCES,BUILD,BUILDROOT,RPMS,SRPMS}
 	git archive --prefix=keyutils-$(VERSION)/ --format tar -o $(SRCBALL) HEAD
-	bzip2 -9f $(SRCBALL)
-	rpmbuild -ts $(SRCBALL).bz2 --define "_srcrpmdir rpmbuild/SRPMS" $(RPMFLAGS)
+	bzip2 -9 <$(SRCBALL) >$(ZSRCBALL)
+	rpmbuild -ts $(ZSRCBALL) --define "_srcrpmdir rpmbuild/SRPMS" $(RPMFLAGS)
 	rpmbuild --rebuild $(SRPM) $(RPMBUILDDIRS) $(RPMFLAGS)
 
 rpmlint: rpm
diff --git a/keyctl.c b/keyctl.c
index 7e5ce6f..801a864 100644
--- a/keyctl.c
+++ b/keyctl.c
@@ -66,6 +66,7 @@
 static nr void act_keyctl_purge(int argc, char *argv[]);
 static nr void act_keyctl_invalidate(int argc, char *argv[]);
 static nr void act_keyctl_get_persistent(int argc, char *argv[]);
+static nr void act_keyctl_dh_compute(int argc, char *argv[]);
 
 const struct command commands[] = {
 	{ act_keyctl___version,	"--version",	"" },
@@ -74,6 +75,7 @@
 	{ act_keyctl_chown,	"chown",	"<key> <uid>" },
 	{ act_keyctl_clear,	"clear",	"<keyring>" },
 	{ act_keyctl_describe,	"describe",	"<keyring>" },
+	{ act_keyctl_dh_compute, "dh_compute",	"<private> <prime> <base>" },
 	{ act_keyctl_instantiate, "instantiate","<key> <data> <keyring>" },
 	{ act_keyctl_invalidate,"invalidate",	"<key>" },
 	{ act_keyctl_get_persistent, "get_persistent", "<keyring> [<uid>]" },
@@ -1627,6 +1629,56 @@
 
 /*****************************************************************************/
 /*
+ * Perform Diffie-Hellman computation
+ */
+static void act_keyctl_dh_compute(int argc, char *argv[])
+{
+	key_serial_t priv, prime, base;
+	void *buffer;
+	char *p;
+	int ret, sep, col;
+
+	if (argc != 4)
+		format();
+
+	priv = get_key_id(argv[1]);
+	prime = get_key_id(argv[2]);
+	base = get_key_id(argv[3]);
+
+	ret = keyctl_dh_compute_alloc(priv, prime, base, &buffer);
+	if (ret < 0)
+		error("keyctl_dh_compute_alloc");
+
+	/* hexdump the contents */
+	printf("%u bytes of data in result:\n", ret);
+
+	sep = 0;
+	col = 0;
+	p = buffer;
+
+	do {
+		if (sep) {
+			putchar(sep);
+			sep = 0;
+		}
+
+		printf("%02hhx", *p);
+		p++;
+
+		col++;
+		if (col % 32 == 0)
+			sep = '\n';
+		else if (col % 4 == 0)
+			sep = ' ';
+
+	} while (--ret > 0);
+
+	printf("\n");
+	exit(0);
+}
+
+/*****************************************************************************/
+/*
  * parse a key identifier
  */
 static key_serial_t get_key_id(char *arg)
diff --git a/keyutils.c b/keyutils.c
index 8856c8a..a6325d0 100644
--- a/keyutils.c
+++ b/keyutils.c
@@ -234,6 +234,16 @@
 	return keyctl(KEYCTL_GET_PERSISTENT, uid, id);
 }
 
+long keyctl_dh_compute(key_serial_t priv, key_serial_t prime,
+		       key_serial_t base, char *buffer, size_t buflen)
+{
+	struct keyctl_dh_params params = { .priv = priv,
+					   .prime = prime,
+					   .base = base };
+
+	return keyctl(KEYCTL_DH_COMPUTE, &params, buffer, buflen, 0);
+}
+
 /*****************************************************************************/
 /*
  * fetch key description into an allocated buffer
@@ -343,6 +353,38 @@
 	return ret - 1;
 }
 
+/*****************************************************************************/
+/*
+ * fetch DH computation results into an allocated buffer
+ * - resulting buffer has an extra NUL added to the end
+ * - returns count (not including extraneous NUL)
+ */
+int keyctl_dh_compute_alloc(key_serial_t priv, key_serial_t prime,
+			    key_serial_t base, void **_buffer)
+{
+	char *buf;
+	long buflen, ret;
+
+	ret = keyctl_dh_compute(priv, prime, base, NULL, 0);
+	if (ret < 0)
+		return -1;
+
+	buflen = ret;
+	buf = malloc(buflen + 1);
+	if (!buf)
+		return -1;
+
+	ret = keyctl_dh_compute(priv, prime, base, buf, buflen);
+	if (ret < 0) {
+		free(buf);
+		return -1;
+	}
+
+	buf[ret] = 0;
+	*_buffer = buf;
+	return ret;
+}
+
 /*
  * Depth-first recursively apply a function over a keyring tree
  */
diff --git a/keyutils.h b/keyutils.h
index fc8495d..a69fa7a 100644
--- a/keyutils.h
+++ b/keyutils.h
@@ -99,6 +99,14 @@
 #define KEYCTL_INSTANTIATE_IOV		20	/* instantiate a partially constructed key */
 #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 */
+
+/* keyctl structures */
+struct keyctl_dh_params {
+	key_serial_t priv;
+	key_serial_t prime;
+	key_serial_t base;
+};
 
 /*
  * syscall wrappers
@@ -153,6 +161,8 @@
 				   key_serial_t ringid);
 extern long keyctl_invalidate(key_serial_t id);
 extern long keyctl_get_persistent(uid_t uid, key_serial_t id);
+extern long keyctl_dh_compute(key_serial_t priv, key_serial_t prime,
+			      key_serial_t base, char *buffer, size_t buflen);
 
 /*
  * utilities
@@ -160,6 +170,8 @@
 extern int keyctl_describe_alloc(key_serial_t id, char **_buffer);
 extern int keyctl_read_alloc(key_serial_t id, void **_buffer);
 extern int keyctl_get_security_alloc(key_serial_t id, char **_buffer);
+extern int keyctl_dh_compute_alloc(key_serial_t priv, key_serial_t prime,
+				   key_serial_t base, void **_buffer);
 
 typedef int (*recursive_key_scanner_t)(key_serial_t parent, key_serial_t key,
 				       char *desc, int desc_len, void *data);
diff --git a/keyutils.spec b/keyutils.spec
index 3312f84..895e085 100644
--- a/keyutils.spec
+++ b/keyutils.spec
@@ -2,7 +2,7 @@
 %define verminor 5.9
 %define version %{vermajor}.%{verminor}
 %define libapivermajor 1
-%define libapiversion %{libapivermajor}.5
+%define libapiversion %{libapivermajor}.6
 
 # % define buildid .local
 
diff --git a/man/find_key_by_type_and_name.3 b/man/find_key_by_type_and_name.3
index 88c9880..ad8ae54 100644
--- a/man/find_key_by_type_and_name.3
+++ b/man/find_key_by_type_and_name.3
@@ -58,5 +58,8 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
+.BR request_key (2),
 .BR keyctl (3),
-.BR request_key (3)
+.BR keyrings (7)
diff --git a/man/key.dns_resolver.8 b/man/key.dns_resolver.8
index 71f0980..c737768 100644
--- a/man/key.dns_resolver.8
+++ b/man/key.dns_resolver.8
@@ -27,4 +27,8 @@
 .SH ERRORS
 All errors will be logged to the syslog.
 .SH SEE ALSO
-\fBrequest-key\fR(8), \fBrequest-key.conf\fR(5)
+.ad l
+.nh
+.BR request\-key.conf (5),
+.BR keyrings (7),
+.BR request\-key (8)
diff --git a/man/keyctl.1 b/man/keyctl.1
index 859e340..cd8abf7 100644
--- a/man/keyctl.1
+++ b/man/keyctl.1
@@ -90,6 +90,8 @@
 \fBkeyctl\fR purge \-s <type> <desc>
 .br
 \fBkeyctl\fR get_persistent <keyring> [<uid>]
+.br
+\fBkeyctl\fR dh_compute <private> <prime> <base>
 .SH DESCRIPTION
 This program is used to control the key management facility in various ways
 using a variety of subcommands.
@@ -752,6 +754,31 @@
 If a UID other than the process's real or effective UIDs is specified, then an
 error will be given if the process does not have the CAP_SETUID capability.
 .P
+(*) \fBCompute a Diffie-Hellman shared secret or public key\fR
+.P
+\fBkeyctl\fR dh_compute <private> <prime> <base>
+.P
+This command computes either a Diffie-Hellman shared secret or the
+public key corresponding to the provided private key using the
+payloads of three keys. The computation is:
+.IP
+base ^ private (mod prime)
+.P
+The three inputs must be user keys with read permission. If the
+provided base key contains the shared generator value, the public key
+will be computed.  If the provided base key contains the remote public
+key value, the shared secret will be computed.
+.P
+The result is printed to stdout as a hex dump.
+.P
+.RS
+testbox>keyctl dh_compute $1 $2 $3
+.br
+8 bytes of data in result:
+.br
+00010203 04050607
+.RE
+.P
 .SH ERRORS
 .P
 There are a number of common errors returned by this program:
@@ -765,6 +792,11 @@
 "Key has expired" - an expired key was accessed.
 .P
 "Permission denied" - permission was denied by a UID/GID/mask combination.
+.P
 
 .SH SEE ALSO
-\fBkeyctl\fR(1), \fBrequest-key.conf\fR(5)
+.ad l
+.nh
+.BR keyctl (1),
+.BR request\-key.conf (5),
+.BR keyrings (7)
diff --git a/man/keyctl.3 b/man/keyctl.3
index 6a02443..d9a2f85 100644
--- a/man/keyctl.3
+++ b/man/keyctl.3
@@ -43,6 +43,10 @@
 .br
 .BR keyctl_describe_alloc (3)
 .br
+.BR keyctl_dh_compute (3)
+.br
+.BR keyctl_dh_compute_alloc (3)
+.br
 .BR keyctl_get_keyring_ID (3)
 .br
 .BR keyctl_get_persistent (3)
@@ -93,14 +97,11 @@
 .BR recursive_session_key_scan (3)
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
diff --git a/man/keyctl_chown.3 b/man/keyctl_chown.3
index 8eb79e9..1db72ef 100644
--- a/man/keyctl_chown.3
+++ b/man/keyctl_chown.3
@@ -77,16 +77,12 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
diff --git a/man/keyctl_clear.3 b/man/keyctl_clear.3
index b031fc3..da10fe8 100644
--- a/man/keyctl_clear.3
+++ b/man/keyctl_clear.3
@@ -62,17 +62,13 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
 
diff --git a/man/keyctl_describe.3 b/man/keyctl_describe.3
index 706493e..3db2c20 100644
--- a/man/keyctl_describe.3
+++ b/man/keyctl_describe.3
@@ -101,16 +101,12 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
diff --git a/man/keyctl_dh_compute.3 b/man/keyctl_dh_compute.3
new file mode 100644
index 0000000..9b1e6fe
--- /dev/null
+++ b/man/keyctl_dh_compute.3
@@ -0,0 +1,109 @@
+.\"
+.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+.\" Copyright (C) 2016 Intel Corporation. All rights reserved.
+.\"
+.\" This program is free software; you can redistribute it and/or
+.\" modify it under the terms of the GNU General Public License
+.\" as published by the Free Software Foundation; either version
+.\" 2 of the License, or (at your option) any later version.
+.\"
+.TH KEYCTL_DH_COMPUTE 3 "07 Apr 2016" Linux "Linux Key Management Calls"
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.SH NAME
+keyctl_dh_compute \- Compute a Diffie-Hellman shared secret or public key
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.SH SYNOPSIS
+.nf
+.B #include <keyutils.h>
+.sp
+.BI "long keyctl_dh_compute(key_serial_t " private ", key_serial_t " prime ,
+.BI "key_serial_t " base ", char *" buffer ", size_t " buflen ");"
+.sp
+.BI "long keyctl_dh_compute_alloc(key_serial_t " private,
+.BI "key_serial_t " prime ", key_serial_t " base ", void **" _buffer ");"
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.SH DESCRIPTION
+.BR keyctl_dh_compute ()
+computes a Diffie-Hellman public key or shared secret.  That computation is:
+.IP
+.I base
+^
+.I private
+( mod
+.I prime
+)
+.P
+When
+.I base
+is a key containing the shared generator value, the remote public key is
+computed.  When
+.I base
+is a key containing the remote public key, the shared secret is computed.
+.P
+.IR base ", " private ", and " prime
+must all refer to
+.BR user -type
+keys containing the parameters for the computation.  Each of these keys must
+grant the caller
+.B read
+permission in order for them to be used.
+.P
+.I buffer
+and
+.I buflen
+specify the buffer into which the computed result will be placed.
+.I buflen
+may be zero, in which case the buffer is not used and the minimum buffer length
+is fetched.
+.P
+.BR keyctl_dh_compute_alloc ()
+is similar to
+.BR keyctl_dh_compute ()
+except that it allocates a buffer big enough to hold the payload data and
+places the data in it.  If successful, a pointer to the buffer is placed in
+.IR *_buffer .
+The caller must free the buffer.
+.P
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.SH RETURN VALUE
+On success
+.BR keyctl_dh_compute ()
+returns the amount of data placed into the buffer when
+.I buflen
+is non-zero.  When
+.I buflen
+is zero, the minimum buffer length to hold the data is returned.
+.P
+On success
+.BR keyctl_dh_compute_alloc ()
+returns the amount of data in the buffer.
+.P
+On error, both functions set errno to an appropriate code and return the value
+.BR -1 .
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.SH ERRORS
+.TP
+.B ENOKEY
+One of the keys specified is invalid or not readable.
+.TP
+.B EINVAL
+The buffer pointer is invalid or buflen is too small.
+.TP
+.B EOPNOTSUPP
+One of the keys was not a valid user key.
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.SH LINKING
+This is a library function that can be found in
+.IR libkeyutils .
+When linking,
+.B -lkeyutils
+should be specified to the linker.
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.SH SEE ALSO
+.BR keyctl (1),
+.br
+.BR keyctl (2),
+.br
+.BR keyctl (3),
+.br
+.BR keyutils (7)
diff --git a/man/keyctl_get_keyring_ID.3 b/man/keyctl_get_keyring_ID.3
index 3eeb767..44b07af 100644
--- a/man/keyctl_get_keyring_ID.3
+++ b/man/keyctl_get_keyring_ID.3
@@ -85,16 +85,12 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
diff --git a/man/keyctl_get_persistent.3 b/man/keyctl_get_persistent.3
index 8c2269e..72088f8 100644
--- a/man/keyctl_get_persistent.3
+++ b/man/keyctl_get_persistent.3
@@ -102,18 +102,13 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR persistent-keyring (7),
-.br
+.BR keyrings (7),
 .BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR persistent\-keyring (7),
diff --git a/man/keyctl_get_security.3 b/man/keyctl_get_security.3
index ec815ac..28b1675 100644
--- a/man/keyctl_get_security.3
+++ b/man/keyctl_get_security.3
@@ -91,16 +91,12 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
diff --git a/man/keyctl_instantiate.3 b/man/keyctl_instantiate.3
index 95f4057..da72054 100644
--- a/man/keyctl_instantiate.3
+++ b/man/keyctl_instantiate.3
@@ -179,18 +179,13 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR request-key (8),
-.br
+.BR keyrings (7),
 .BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR request\-key (8)
diff --git a/man/keyctl_invalidate.3 b/man/keyctl_invalidate.3
index 79cf1b2..82ee1df 100644
--- a/man/keyctl_invalidate.3
+++ b/man/keyctl_invalidate.3
@@ -65,16 +65,12 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
diff --git a/man/keyctl_join_session_keyring.3 b/man/keyctl_join_session_keyring.3
index d68a90c..5d7db93 100644
--- a/man/keyctl_join_session_keyring.3
+++ b/man/keyctl_join_session_keyring.3
@@ -71,20 +71,14 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR session-keyring (7),
-.br
-.BR user-session-keyring (7),
-.br
+.BR keyrings (7),
 .BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR session\-keyring (7),
+.BR user\-session-keyring (7)
diff --git a/man/keyctl_link.3 b/man/keyctl_link.3
index fac9257..2f51670 100644
--- a/man/keyctl_link.3
+++ b/man/keyctl_link.3
@@ -96,17 +96,13 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
 
diff --git a/man/keyctl_read.3 b/man/keyctl_read.3
index 6403a19..23d623b 100644
--- a/man/keyctl_read.3
+++ b/man/keyctl_read.3
@@ -101,16 +101,12 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
diff --git a/man/keyctl_revoke.3 b/man/keyctl_revoke.3
index 2f7f646..dd0e152 100644
--- a/man/keyctl_revoke.3
+++ b/man/keyctl_revoke.3
@@ -62,16 +62,12 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
diff --git a/man/keyctl_search.3 b/man/keyctl_search.3
index adc623f..7fb068b 100644
--- a/man/keyctl_search.3
+++ b/man/keyctl_search.3
@@ -127,16 +127,12 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
diff --git a/man/keyctl_session_to_parent.3 b/man/keyctl_session_to_parent.3
index 213964a..343feb9 100644
--- a/man/keyctl_session_to_parent.3
+++ b/man/keyctl_session_to_parent.3
@@ -64,20 +64,14 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR session-keyring (7),
-.br
-.BR user-session-keyring (7),
-.br
+.BR keyrings (7),
 .BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR session\-keyring (7),
+.BR user\-session-keyring (7)
diff --git a/man/keyctl_set_reqkey_keyring.3 b/man/keyctl_set_reqkey_keyring.3
index c7300f2..ed8e9e0 100644
--- a/man/keyctl_set_reqkey_keyring.3
+++ b/man/keyctl_set_reqkey_keyring.3
@@ -89,18 +89,13 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR request-key (8),
-.br
 .BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR request\-key (8)
diff --git a/man/keyctl_set_timeout.3 b/man/keyctl_set_timeout.3
index ef4dc7a..e434ff5 100644
--- a/man/keyctl_set_timeout.3
+++ b/man/keyctl_set_timeout.3
@@ -70,16 +70,12 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
diff --git a/man/keyctl_setperm.3 b/man/keyctl_setperm.3
index fc14d02..6a1bfbd 100644
--- a/man/keyctl_setperm.3
+++ b/man/keyctl_setperm.3
@@ -119,16 +119,12 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
diff --git a/man/keyctl_update.3 b/man/keyctl_update.3
index 58f0993..9823dd8 100644
--- a/man/keyctl_update.3
+++ b/man/keyctl_update.3
@@ -85,16 +85,12 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (1),
-.br
 .BR add_key (2),
-.br
 .BR keyctl (2),
-.br
 .BR request_key (2),
-.br
 .BR keyctl (3),
-.br
-.BR keyutils (7),
-.br
-.BR keyrings (7)
+.BR keyrings (7),
+.BR keyutils (7)
diff --git a/man/keyrings.7 b/man/keyrings.7
deleted file mode 100644
index ed72b68..0000000
--- a/man/keyrings.7
+++ /dev/null
@@ -1,416 +0,0 @@
-.\"
-.\" Copyright (C) 2014 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.
-.\"
-.TH KEYRINGS 7 "21 Feb 2014" Linux "Kernel key management"
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH NAME
-keyrings \- In-kernel key management and retention facility
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH OVERVIEW
-The
-.B keyrings
-facility is primarily a way for drivers to retain or cache security data,
-authentication keys, encryption keys and other data in the kernel.
-.P
-System call interfaces are provided so that userspace programs can manage those
-objects and also use the facility for their own purposes.
-.P
-A library and some userspace utilities are provided to allow access to the
-facility.  See
-.BR keyutils (7)
-manual page for more information.
-.P
-This document contains the following sections:
-.P
-.RS
-- Keys.
-.br
-- Key types.
-.br
-- Keyrings.
-.br
-- Anchoring keys.
-.br
-- Possession.
-.br
-- Access rights.
-.br
-- Searching for keys.
-.br
-- On-demand key creation.
-.br
-- Users.
-.br
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.P
-.SH KEYS
-The facility provides the concept of a '\fBkey\fR', where all of the above
-examples are encapsulated within objects of this type.
-.P
-A 'key' contains the following elements:
-.IP "\fBSerial number\fR"
-This is a unique integer handle by which a key is referred to in system call
-arguments.
-.IP "\fBType\fR"
-This defines what sort of data can be held in the key, how the proposed content
-of the key will be parsed and how the payload will be used.
-.IP
-There are a number of general purpose types available, plus some specialist
-types defined by specific drivers.
-.IP "\fBDescription\fR"
-This is a printable string that is used as the search term for the key (in
-conjunction with the type) as well as a display name.  The description may be
-partially matched or exactly matched.
-.IP "\fBPayload\fR"
-This is the actual content of a key.  This is usually set when a key is
-created, but it is possible for the kernel to upcall to userspace to finish the
-instantiation of a key if that key wasn't already known to the kernel when it
-was requested.
-.IP
-A key's payload can be read and updated if the key type supports it and if
-suitable permission is granted to the caller.
-.IP "\fBAccess rights\fR"
-Each key has an owning user ID, an owning group and a security label - much as
-files do.  They also have a set of permissions, though there are more than for
-a normal UNIX file, and there is an additional category beyond the usual user,
-group and other (see below).
-.IP
-Note that keys are quota controlled since they represent unswappable kernel
-memory and the owning user ID specifies whose quota is to be debited.
-.IP "\fBExpiration time\fR"
-Each key can have an expiration time set.  When that time is reached, the key
-is marked as being expired and accesses to it fail with \fIEKEYEXPIRED\fR.  If
-not deleted, updated or replaced, after a set amount of time, expired keys are
-automatically removed along with all links to them and \fIENOKEY\fR will be
-reported.
-.IP "\fBReference count\fR"
-Each key has a reference count.  Keys are referenced by keyrings, by current
-active users and by a process's credentials.  When the reference count reaches
-zero, the key is scheduled for garbage collection.
-.P
-See the
-.BR keyctl_describe (3)
-manual page for more information.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH KEY TYPES
-.P
-The facility provides several basic types of key:
-.IP "\fBkeyring\fR"
-Keys of this type are special.  The payload consists of a set of links to other
-keys, analogous to a directory holding links to files.  The main purpose of a
-keyring is to prevent other keys from being garbage collected because nothing
-refers to them.
-.IP "\fBuser\fR"
-This is a general purpose key type.  It may be instantiated with an arbitrary
-blob of data of up to about 32KB.  It is kept entirely within kernel memory.
-It may be read and updated by userspace.
-.IP "\fBbig_key\fR"
-This is similar to \fBuser\fR but it may hold data up to 1MB in size.  The data
-may be stored in the swap space rather than in kernel memory if the size
-exceeds the overhead of doing so (a tmpfs file is used - which requires
-filesystem structures to be allocated in the kernel).
-.IP "\fBlogon\fR"
-This is similar to \fBuser\fR but the contents may not be read by userspace.
-.P
-There are more specialised key types available also, but they're not discussed
-here as they're not intended for normal userspace use.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.P
-.SH KEYRINGS
-As previously mentioned, keyrings are a special type of key that contain links
-to other keys (which may include other keyrings).  Keys may be linked to by
-multiple keyrings.  Keyrings may be considered as analogous to UNIX directories
-where each directory contains a set of hard links to files.
-.P
-Several of the syscall functions available may only be applied to keyrings:
-.IP "\fBAdding\fR"
-A key may be added to a keyring by system calls that create keys.  This
-prevents the new key from being immediately deleted when the system call driver
-releases its last reference to the key.
-.IP "\fBLinking\fR"
-A link may be added to a keyring pointing to a key that is already known,
-provided this does not create a self-referential cycle.
-.IP "\fBUnlinking\fR"
-A link may be removed from a keyring.  When the last link to a key is removed,
-that key will be scheduled for deletion by the garbage collector.
-.IP "\fBClearing\fR"
-All the links may be removed from a keyring.
-.IP "\fBSearching\fR"
-A keyring may be considered the root of a tree or subtree in which keyrings
-form the branches and non-keyrings the leaves.  This tree may be searched for a
-leaf matching a particular type and description.
-.P
-See the
-.BR keyctl_clear (3),
-.BR keyctl_link (3),
-.BR keyctl_search (3)
-and
-.BR keyctl_unlink (3)
-manual pages for more information.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH ANCHORING KEYS
-.P
-To prevent a key from being prematurely garbage collected, it must anchored to
-keep its reference count elevated when it is not in active use by the kernel.
-.P
-\fBKeyrings\fR are used to anchor other keys - each link is a reference on a
-key - but whilst keyrings are available to link to keys, keyrings themselves
-are just keys and are also subject to the same anchoring necessity.
-.P
-The kernel makes available a number of anchor keyrings.  Note that some of
-these keyrings will only be created when first accessed.
-.IP "\fBProcess keyrings\fR"
-Process credentials themselves reference keyrings with specific semantics.
-These keyrings are pinned as long as the set of credentials exists - which is
-usually as long as the process does.
-.IP
-There are three keyrings with different inheritance/sharing rules:  The \fBsession
-keyring\fR (inherited and shared by all child processes), the \fBprocess keyring\fR
-(shared by all threads in a process) and the \fBthread keyring\fR (specific to
-a particular thread).
-.IP "\fBUser keyrings\fR"
-Each UID known to the kernel has a record that contains two keyrings: The
-\fBuser keyring\fR and the \fBuser session keyring\fR.  These exist for as long
-as the UID record in the kernel exists.  A link to the user keyring is placed
-in a new session keyring by \fBpam_keyinit\fR when a new login session is
-initiated.
-.IP "\fBPersistent keyrings\fR"
-There is a \fBpersistent keyring\fR available to each UID known to the system.
-It may persist beyond the life of the UID record previously mentioned, but has
-an expiration time set such that it is automatically cleaned up after a set
-time.  This, for example, permits cron scripts to use credentials left when the
-user logs out.
-.IP
-Note that the expiration time is reset every time the persistent key is
-requested.
-.IP "\fBSpecial keyrings\fR"
-There are special keyrings owned by the kernel that can anchor keys for special
-purposes.  An example of this is the \fBsystem keyring\fR used for holding
-encryption keys for module signature verification.
-.IP
-These are usually closed to direct alteration by userspace.
-.P
-See the
-.BR thread-keyring (7),
-.BR process-keyring (7),
-.BR session-keyring (7),
-.BR user-keyring (7),
-.BR user-session-keyring (7),
-and
-.BR persistent-keyring (7)
-manual pages for more information.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH POSSESSION
-.P
-The concept of '\fBpossession\fR' is important to understanding the keyrings
-security model.  Whether a thread possesses a key is determined by the
-following rules:
-.IP (1)
-Any key or keyring that does not grant \fBSearch\fP permission to the caller is
-\fIignored\fP in all the following rules.
-.IP (2)
-A thread \fIpossesses\fR its \fBsession\fR, \fBprocess\fR and \fBthread\fR
-keyrings directly because those are pointed to by its credentials.
-.IP (3)
-If a keyring is possessed, then any key it links to is \fIalso\fR possessed.
-.IP (4)
-If any key a keyring links to is itself a keyring, then rule (3) applies
-\fIrecursively\fP.
-.IP (5)
-If a process is upcalled from the kernel to instantiate a key, then it also
-possess's the \fIrequester's\fP keyrings as in rule (1) as if it were the
-requester.
-.P
-Note that possession is not a fundamental property of a key, but must rather be
-calculated each time it is needed.
-.P
-Possession is designed to allow setuid programs run from, say, a user's shell
-to access the user's keys.  It also allows the prevention of access to keys
-just on the basis of UID and GID matches.
-.P
-When it creates the session keyring, the \fBpam_keyinit\fR module adds a link
-to the user keyring, thus making the user keyring and anything it contains
-possessed by default.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH ACCESS RIGHTS
-.P
-Each key has the following security-related attributes:
-.P
-.RS
-- The owning user ID
-.br
-- The ID of a group that is permitted to access the key
-.br
-- A security label
-.br
-- A permissions mask
-.RE
-.P
-The permissions mask is used to govern the following rights:
-.IP \fBView\fR
-If set, the attributes of a key may be read.  This includes the type,
-description and access rights (excluding the security label).
-.IP \fBRead\fR
-If set, the payload of a key may be read and a list of the serial numbers to
-which a keyring has links may be read.
-.IP \fBWrite\fR
-If set, the payload of a key may be updated, links may be added to or removed
-from a keyring, a keyring may be cleared completely and a key may be revoked.
-.IP \fBSearch\fR
-If set, keyrings and subkeyrings may be searched and keys and keyrings may be
-found by that search.
-.IP \fBLink\fR
-If set, an additional link may be made to a key from a keyring.  The initial
-link to a key when it is created doesn't require this permit.
-.IP \fBSetattr\fR
-If set, the ownership details on a key and its security label may be changed,
-its expiration time may be set and it may be revoked.
-.P
-The permissions mask contains four sets of rights.  The first three sets are
-mutually exclusive.  One and only one will be in force at any one time.  In
-order of descending priority:
-.IP \fBUser\fR
-Used if the key's user ID matches the caller's \fBfsuid\fR.
-.IP \fBGroup\fR
-Used if the user ID didn't match and the key's group ID matches the caller's
-\fBfsgid\fR or one of the caller's supplementary group list.
-.IP \fBOther\fR
-Used if neither the key's user ID nor group ID matched.
-.P
-The fourth set of rights is:
-.IP \fBPossessor\fR
-Used if a key is determined to be \fBpossessed\fR by the caller.
-.P
-The complete set of rights for a key is the set union of whichever of the first
-three sets is selected plus the fourth if the key is possessed.
-.P
-If any right is granted to a thread for a key, then that thread will see the
-key listed in /proc/keys.  If no rights at all are granted, then that thread
-can't even tell that the key exists.
-.P
-In addition to access rights, any active \fBLinux Security Module\fP may
-prevent access to a key if its policy so dictates.  A key may be given a
-security label or other attribute by the LSM which can be retrieved.
-.P
-See the
-.BR keyctl_chown (3),
-.BR keyctl_describe (3),
-.BR keyctl_get_security (3),
-.BR keyctl_setperm (3)
-and
-.BR selinux (8)
-manual pages for more information.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH SEARCHING FOR KEYS
-.P
-One of the key features of this facility is the ability to find a key that it
-is retaining.  The \fBrequest_key\fR() system call is the primary point of
-access for userspace to find a key to use (the kernel has something similar
-available).
-.P
-The search algorithm works as follows:
-.IP (1)
-The three process keyrings are searched in the following order: the thread
-keyring if it exists, the process keyring if it exists and then either the
-session keyring if it exists or the user session keyring if that exists.
-.IP (2)
-If the caller was a process that was invoked by the \fBrequest_key\fR() upcall
-mechanism then the keyrings of the original caller of that \fBrequest_key\fR()
-will be searched as well.
-.IP (3)
-Each keyring is searched first for a match, then the keyrings referred to by
-that keyring are searched.
-.IP (4)
-If a matching key is found that is valid, then the search terminates and that
-key is returned.
-.IP (5)
-If a matching key is found that has an error state attached, that error state
-is noted and the search continues.
-.IP (6)
-If valid matching key is found, then the first noted error state is returned or
-else \fBENOKEY\fR is returned.
-.P
-It is also possible to search a specific keyring, in which case only steps (3)
-to (6) apply.
-.P
-See the
-.BR request_key (2)
-and
-.BR keyctl_search (3)
-manual pages for more information.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH ON-DEMAND KEY CREATION
-.P
-If a key cannot be found, the \fBrequest_key\fR() system call will, if given a
-\fIcallout_info\fR argument, create a new key and then upcall to userspace to
-instantiate the key.  This allows keys to be created on an as-needed basis.
-.P
-Typically, this will involve the kernel forking and exec'ing \fBrequest-key\fR
-program, which will then execute the appopriate handler based on its
-configuration.
-.P
-The handler is passed a special authorisation key that allows it and only it to
-instantiate the new key.  This is also used to permit searches performed by the
-handler program to also search the requester's keyrings.
-.P
-See the
-.BR keyctl_assume_authority (3),
-.BR keyctl_instantiate (3),
-.BR keyctl_negate (3),
-.BR keyctl_reject (3),
-.BR request_key (2),
-.BR request-key (8)
-and
-.BR request-key.conf (5)
-manual pages for more information.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH USERS
-.P
-The facility has a number of users and usages, but is not limited to those
-that already exist.
-.P
-In-kernel users of this facility include:
-.IP "\fBNetwork filesystems - DNS\fR"
-The kernel uses the upcall mechanism provided by the keys to upcall to
-userspace to do DNS lookups and then to cache the results.
-.IP "\fBAF_RXRPC and kAFS - Authentication\fR"
-The AF_RXRPC network protocol and the in-kernel AFS filesystem store the ticket
-needed to do secured or encrypted traffic in keys.  These are then looked up by
-network operations on AF_RXRPC and filesystem operations on kAFS.
-.IP "\fBNFS - User ID mapping\fR"
-The NFS filesystem uses keys to store foreign user ID to local user ID mapping.
-.IP "\fBCIFS - Password\fR"
-The CIFS filesystem uses keys to store passwords for accessing remote shares.
-.IP "\fBModule verification\fR"
-The kernel build process can be made to cryptographically sign modules.  That
-signature is then checked when a module is loaded.
-.P
-Userspace users of this facility include:
-.IP "\fBKerberos key storage\fR"
-The MIT Kerberos 5 facility (libkrb5) can use keys to store authentication
-tokens which can be made to be automatically cleaned up a set time after the
-user last uses them, but until then permits them to hang around after the user
-has logged out so that cron scripts can use them.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH SEE ALSO
-.BR keyutils (7),
-.br
-.BR pam_keyinit (8),
-.br
-.BR thread-keyring (7),
-.br
-.BR process-keyring (7),
-.br
-.BR session-keyring (7),
-.br
-.BR user-keyring (7),
-.br
-.BR user-session-keyring (7),
-.br
-.BR persistent-keyring (7)
diff --git a/man/keyutils.7 b/man/keyutils.7
index a388acf..ab245ce 100644
--- a/man/keyutils.7
+++ b/man/keyutils.7
@@ -92,19 +92,15 @@
 manual pages for more information.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
+.BR keyctl (1),
+.BR keyctl (3),
 .BR keyrings (7),
-.br
-.BR pam_keyinit (8),
-.br
-.BR process-keyring (7),
-.br
-.BR session-keyring (7),
-.br
-.BR thread-keyring (7),
-.br
-.BR user-keyring (7),
-.br
-.BR user-session-keyring (7),
-.br
-.BR persistent-keyring (7)
-
+.BR persistent\-keyring (7),
+.BR process\-keyring (7),
+.BR session\-keyring (7),
+.BR thread\-keyring (7),
+.BR user\-keyring (7),
+.BR user\-session-keyring (7),
+.BR pam_keyinit (8)
diff --git a/man/persistent-keyring.7 b/man/persistent-keyring.7
deleted file mode 100644
index 6e5596c..0000000
--- a/man/persistent-keyring.7
+++ /dev/null
@@ -1,67 +0,0 @@
-.\"
-.\" Copyright (C) 2014 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.
-.\"
-.TH "PERSISTENT KEYRING" 7 "20 Feb 2014" Linux "Kernel key management"
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH NAME
-persistent_keyring \- Per-user persistent keyring
-.SH DESCRIPTION
-The
-.B persistent keyring
-is a keyring used to anchor keys on behalf of a user.  Each UID the kernel
-deals with has its own persistent keyring that is shared between all threads
-owned by that UID.
-.P
-The persistent keyring is created on demand when a thread requests it.  The
-keyring's expiration timer is reset every time it is accessed to the value in:
-.IP
-/proc/sys/kernel/keys/persistent_keyring_expiry
-.P
-The persistent keyring is not searched by \fBrequest_key\fP() unless it is
-referred to by a keyring that is.
-.P
-The persistent keyring may not be accessed directly, even by processes with
-the appropriate UID.  Instead it must be linked to one of a process's keyrings
-first before that keyring can access it by virtue of its possessor permits.
-This is done with \fBkeyctl_get_persistent\fP().
-.P
-Persistent keyrings are independent of clone(), fork(), vfork(), execve() and
-exit().  They persist until their expiration timers trigger - at which point
-they are garbage collected.  This allows them to carry keys beyond the life of
-the kernel's record of the corresponding UID (the destruction of which results
-in the destruction of the user and user session keyrings).
-.P
-If a persistent keyring does not exist when it is accessed, it will be
-created.
-.SH SPECIAL OPERATIONS
-The keyutils library provides a special operation for manipulating persistent
-keyrings:
-.IP \fBkeyctl_get_persistent\fP()
-This operation allows the caller to get the persistent keyring corresponding
-to their own UID or, if they have \fBCAP_SETUID\fR, the persistent keyring
-corresponding to some other UID in the same user namespace.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH SEE ALSO
-.BR keyctl (1),
-.br
-.BR keyctl (3),
-.br
-.BR keyctl_get_persistent (3),
-.br
-.BR keyrings (7),
-.br
-.BR process-keyring (7),
-.br
-.BR session-keyring (7),
-.br
-.BR thread-keyring (7),
-.br
-.BR user-keyring (7),
-.br
-.BR user-session-keyring (7)
diff --git a/man/process-keyring.7 b/man/process-keyring.7
deleted file mode 100644
index bacd3cf..0000000
--- a/man/process-keyring.7
+++ /dev/null
@@ -1,53 +0,0 @@
-.\"
-.\" Copyright (C) 2014 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.
-.\"
-.TH "PROCESS KEYRING" 7 "19 Feb 2014" Linux "Kernel key management"
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH NAME
-process_keyring \- Per-process shared keyring
-.SH DESCRIPTION
-The
-.B process keyring
-is a keyring used to anchor keys on behalf of a process.  It is only created
-when a process requests it.
-.P
-A special serial number value, \fBKEY_SPEC_PROCESS_KEYRING\fP, is defined that
-can be used in lieu of the calling process's process keyring's actual serial
-number.
-.P
-From the keyctl utility, '\fB@p\fP' can be used instead of a numeric key ID in
-much the same way, but as keyctl is a program run after forking, this is of no
-utility.
-.P
-A process's process keyring is inherited across clone() with CLONE_THREAD and
-is cleared by execve().  The process keyring will be destroyed when the last
-thread that refers to it exits.
-.P
-If a process doesn't have a process keyring when it is accessed, then the
-process keyring will be created if the keyring is to be modified, otherwise
-error ENOKEY will be issued.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH SEE ALSO
-.BR keyctl (1),
-.br
-.BR keyctl (3),
-.br
-.BR keyrings (7),
-.br
-.BR thread-keyring (7),
-.br
-.BR process-keyring (7),
-.br
-.BR session-keyring (7),
-.br
-.BR user-keyring (7),
-.br
-.BR user-session-keyring (7),
-.br
-.BR persistent-keyring (7)
diff --git a/man/recursive_key_scan.3 b/man/recursive_key_scan.3
index e46c5b5..689ff7a 100644
--- a/man/recursive_key_scan.3
+++ b/man/recursive_key_scan.3
@@ -83,5 +83,8 @@
 should be specified to the linker.
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .SH SEE ALSO
+.ad l
+.nh
 .BR keyctl (3),
-.BR keyctl_describe_alloc (3)
+.BR keyctl_describe_alloc (3),
+.BR keyrings (7)
diff --git a/man/request-key.8 b/man/request-key.8
index 01a70d9..45cdeb1 100644
--- a/man/request-key.8
+++ b/man/request-key.8
@@ -31,4 +31,8 @@
 .ul 0
 Keytype specific configuration file.
 .SH SEE ALSO
-\fBkeyctl\fR(1), \fBrequest-key.conf\fR(5)
+.ad l
+.nh
+.BR keyctl (1),
+.BR request\-key.conf (5),
+.BR keyrings (7)
diff --git a/man/session-keyring.7 b/man/session-keyring.7
deleted file mode 100644
index 9dc4cdf..0000000
--- a/man/session-keyring.7
+++ /dev/null
@@ -1,85 +0,0 @@
-.\"
-.\" Copyright (C) 2014 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.
-.\"
-.TH "SESSION KEYRING" 7 "19 Feb 2014" Linux "Kernel key management"
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH NAME
-session_keyring \- Session shared process keyring
-.SH DESCRIPTION
-The
-.B session keyring
-is a keyring used to anchor keys on behalf of a process.  It is typically
-created by the \fBpam_keyinit\fP module when a user logs in and a link will be
-added that refers to the \fBuser keyring\fP.
-.P
-A special serial number value, \fBKEY_SPEC_SESSION_KEYRING\fP, is defined that
-can be used in lieu of the calling process's session keyring's actual serial
-number.
-.P
-From the keyctl utility, '\fB@s\fP' can be used instead of a numeric key ID in
-much the same way.
-.P
-A process's session keyring is inherited across clone(), fork() and vfork() and
-is retained across execve() - even when the target executable is setuid or
-setgid.  The session keyring will be destroyed when the last process that
-refers to it exits.
-.P
-If a process doesn't have a session keyring when it is accessed, then, under
-certain circumstances, the \fBuser session keyring\fR will be attached as the
-session keyring and under others a new session keyring will be created.
-.SH SPECIAL OPERATIONS
-The keyutils library provides a number of special operations for manipulating
-session keyrings:
-.IP \fBkeyctl_join_session_keyring\fP()
-This operation allows the caller to change their session keyring.  The caller
-can join an existing keyring by name, create a new keyring of the name given or
-ask the kernel to create a new session keyring with the name "_ses".
-.IP \fBkeyctl_session_to_parent\fP()
-This operation allows the caller to set the parent process's session keyring to
-the same as their own.  For this to succeed, the parent process must have
-identical security attributes and must be single threaded.
-.P
-These operations are also exposed through the keyctl utility as:
-.P
-.RS
-\fBkeyctl\fP session
-.br
-\fBkeyctl\fP session - [<prog> <arg1> <arg2> ...]
-.br
-\fBkeyctl\fP session <name> [<prog> <arg1> <arg2> ...]
-.RE
-.P
-and:
-.P
-.RS
-\fBkeyctl\fP new_session
-.RE
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH SEE ALSO
-.BR keyctl (1),
-.br
-.BR keyctl (3),
-.br
-.BR keyctl_join_session_keyring (3),
-.br
-.BR keyctl_session_to_parent (3),
-.br
-.BR pam_keyinit (8),
-.br
-.BR keyrings (7),
-.br
-.BR thread-keyring (7),
-.br
-.BR process-keyring (7),
-.br
-.BR user-keyring (7),
-.br
-.BR user-session-keyring (7)
-.br
-.BR persistent-keyring (7)
diff --git a/man/thread-keyring.7 b/man/thread-keyring.7
deleted file mode 100644
index 5644fc7..0000000
--- a/man/thread-keyring.7
+++ /dev/null
@@ -1,50 +0,0 @@
-.\"
-.\" Copyright (C) 2014 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.
-.\"
-.TH "THREAD KEYRING" 7 "20 Feb 2014" Linux "Kernel key management"
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH NAME
-thread_keyring \- Per-thread keyring
-.SH DESCRIPTION
-The
-.B thread keyring
-is a keyring used to anchor keys on behalf of a process.  It is only created
-when a thread requests it.
-.P
-A special serial number value, \fBKEY_SPEC_THREAD_KEYRING\fP, is defined that
-can be used in lieu of the calling thread's thread keyring's actual serial
-number.
-.P
-From the keyctl utility, '\fB@t\fP' can be used instead of a numeric key ID in
-much the same way, but as keyctl is a program run after forking, this is of no
-utility.
-.P
-Thread keyrings are not inherited across clone() and are cleared by execve().
-A thread keyring is destroyed when the thread that refers to it exits.
-.P
-If a thread doesn't have a thread keyring when it is accessed, then the thread
-keyring will be created if the keyring is to be modified, otherwise error
-ENOKEY will be issued.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH SEE ALSO
-.BR keyctl (1),
-.br
-.BR keyctl (3),
-.br
-.BR keyrings (7),
-.br
-.BR process-keyring (7),
-.br
-.BR session-keyring (7),
-.br
-.BR user-keyring (7),
-.br
-.BR user-session-keyring (7)
-.br
-.BR persistent-keyring (7)
diff --git a/man/user-keyring.7 b/man/user-keyring.7
deleted file mode 100644
index db562a2..0000000
--- a/man/user-keyring.7
+++ /dev/null
@@ -1,63 +0,0 @@
-.\"
-.\" Copyright (C) 2014 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.
-.\"
-.TH "USER KEYRING" 7 "20 Feb 2014" Linux "Kernel key management"
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH NAME
-user_keyring \- Per-user keyring
-.SH DESCRIPTION
-The
-.B user keyring
-is a keyring used to anchor keys on behalf of a user.  Each UID the kernel
-deals with has its own user keyring.  This keyring is associated with the
-record that the kernel maintains for the UID and, once created, is retained as
-long as that record persists.  It is shared amongst all processes of that UID.
-.P
-The user keyring is created on demand when a thread requests it.  Normally,
-this happens when \fBpam_keyinit\fP is invoked when a user logs in.
-.P
-The user keyring is not searched by default by \fBrequest_key\fP().  When the
-pam_keyinit module creates a session keyring, it adds to it a link to the user
-keyring so that the user keyring will be searched when the session keyring is.
-.P
-A special serial number value, \fBKEY_SPEC_USER_KEYRING\fP, is defined that
-can be used in lieu of the calling process's user keyring's actual serial
-number.
-.P
-From the keyctl utility, '\fB@u\fP' can be used instead of a numeric key ID in
-much the same way.
-.P
-User keyrings are independent of clone(), fork(), vfork(), execve() and exit()
-excepting that the keyring is destroyed when the UID record is destroyed when
-the last process pinning it exits.
-.P
-If it necessary to for a key associated with a user to exist beyond the UID
-record being garbage collected - for example for use by a cron script - then
-the \fBpersistent keyring\fP should be used instead.
-.P
-If a user keyring does not exist when it is accessed, it will be created.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH SEE ALSO
-.BR keyctl (1),
-.br
-.BR keyctl (3),
-.br
-.BR keyrings (7),
-.br
-.BR pam_keyinit (8),
-.br
-.BR process-keyring (7),
-.br
-.BR session-keyring (7),
-.br
-.BR thread-keyring (7),
-.br
-.BR user-session-keyring (7),
-.br
-.BR persistent-keyring (7)
diff --git a/man/user-session-keyring.7 b/man/user-session-keyring.7
deleted file mode 100644
index 8253557..0000000
--- a/man/user-session-keyring.7
+++ /dev/null
@@ -1,65 +0,0 @@
-.\"
-.\" Copyright (C) 2014 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.
-.\"
-.TH "USER-SESSION KEYRING" 7 "20 Feb 2014" Linux "Kernel key management"
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH NAME
-user_session_keyring \- Per-user default session keyring
-.SH DESCRIPTION
-The
-.B user session keyring
-is a keyring used to anchor keys on behalf of a user.  Each UID the kernel
-deals with has its own user session keyring.  This keyring is associated with
-the record that the kernel maintains for the UID and, once created, is retained
-as long as that record persists.  It is shared amongst all processes of that
-UID.
-.P
-The user session keyring is created on demand when a thread requests it or when
-a thread asks for its \fBsession keyring\fP and that doesn't exist.  In the
-latter case, a user session keyring will be created and, if the session keyring
-wasn't to be created, the user session keyring will be set as the process's
-actual session keyring.
-.P
-The user session keyring is searched by \fBrequest_key\fP() if the actual
-session keyring does not exist and is ignored otherwise.
-.P
-A special serial number value, \fBKEY_SPEC_USER_SESSION_KEYRING\fP, is defined
-that can be used in lieu of the calling process's user session keyring's actual
-serial number.
-.P
-From the keyctl utility, '\fB@us\fP' can be used instead of a numeric key ID in
-much the same way.
-.P
-User session keyrings are independent of clone(), fork(), vfork(), execve() and
-exit() excepting that the keyring is destroyed when the UID record is destroyed
-when the last process pinning it exits.
-.P
-If a user session keyring does not exist when it is accessed, it will be
-created.
-.P
-It is strongly recommended that a \fBsession keyring\fP be set explicitly, for
-example by \fBpam_keyinit\fP, rather than relying on the user session keyring -
-particularly if a process is running as root.
-.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
-.SH SEE ALSO
-.BR keyctl (1),
-.br
-.BR keyctl (3),
-.br
-.BR keyrings (7),
-.br
-.BR process-keyring (7),
-.br
-.BR session-keyring (7),
-.br
-.BR thread-keyring (7),
-.br
-.BR user-keyring (7),
-.br
-.BR persistent-keyring (7)
diff --git a/tests/keyctl/dh_compute/bad-args/runtest.sh b/tests/keyctl/dh_compute/bad-args/runtest.sh
new file mode 100644
index 0000000..7e8828b
--- /dev/null
+++ b/tests/keyctl/dh_compute/bad-args/runtest.sh
@@ -0,0 +1,89 @@
+#!/bin/bash
+
+. ../../../prepare.inc.sh
+. ../../../toolbox.inc.sh
+
+
+# ---- do the actual testing ----
+
+if [ $have_dh_compute = 0 ]
+then
+    toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF DIFFIE-HELLMAN"
+    exit 0
+fi
+
+result=PASS
+echo "++++ BEGINNING TEST" >$OUTPUTFILE
+
+# Prime, generator, and key values created with:
+#   openssl dhparam 2048 -check -out dh.pem
+#   openssl genpkey -paramfile dh.pem -text
+prime="\x00\xb6\x89\x4d\x8f\xf7\xaf\x56\xd4\x46\xc9\x50\xc7\xe9\x1d"
+prime+="\x29\x8a\x07\x8d\xae\xa7\x79\x66\xf1\x1f\xc1\x6f\x22\x92\x11"
+prime+="\x73\x7f\x1f\x39\xce\xf3\xda\xd7\x87\x2a\x53\x8f\x6c\x8f\x9a"
+prime+="\x27\x6a\x7c\xf7\x7b\xb2\xd6\x3a\x87\x2a\x4d\xb9\xed\x12\xae"
+prime+="\x0f\x1c\x69\xaf\x9b\xf2\xf2\xe3\x69\x1d\x36\x15\xa1\xd7\xd5"
+prime+="\x77\xa8\x7d\x1c\xb4\xab\xa0\x49\x4b\xae\x0c\x24\x9b\x0c\xce"
+prime+="\xef\x6b\x7a\xb9\xa7\xbe\x70\xb5\xb4\x5e\x4c\xf7\xcb\x71\xad"
+prime+="\x8f\xeb\x7a\x4d\x6c\x7c\xcb\x96\xd5\x29\x8f\x0f\xee\xb4\x78"
+prime+="\x77\x60\x5e\x80\xa0\x33\x86\x91\xe3\x58\x62\xf0\xf4\xcb\xb2"
+prime+="\x09\xe1\x7d\xd9\xfe\xbc\xce\x4c\x21\x57\x70\x06\xce\xb1\x15"
+prime+="\x7b\x18\x15\x92\xd2\xf7\x84\xba\x44\xe0\x06\xc3\x14\xdf\x53"
+prime+="\x06\xbd\xbb\x17\xa0\x10\xb3\x66\x0d\x47\x93\x56\xd8\xd5\x2c"
+prime+="\x5a\xf0\x14\x53\x6c\x20\x89\x7e\x76\x53\x21\x8e\x2c\x7a\x65"
+prime+="\x0a\x73\xdc\x27\x58\x45\x98\xde\x92\xde\x5c\x62\x70\x67\x71"
+prime+="\xfa\x2d\x67\xf6\x25\x44\x1d\x91\x1c\xa0\x3f\x21\x49\xb6\xd4"
+prime+="\xc7\x6b\x5e\xcd\x98\x96\xe9\xd7\x99\xa3\xa5\x00\xec\xec\xc5"
+prime+="\x19\xe3\x1b\x71\x15\x4d\x7b\x36\x1b\xd0\xdd\x15\xf7\xce\x8d"
+prime+="\xfc\x63"
+
+generator="\x02"
+
+private="\x40\x94\x9d\xa2\xca\x2b\x7c\x35\x3d\xe3\x8f\xef\xb0\x6d\xdd"
+private+="\x0d\x67\x47\x9a\x63\x61\xc8\x9e\x77\xb9\x80\xd2\x48\x6c\x4d"
+private+="\x31\x97\x1e\xb8\x8f\x65\x72\x06\x99\x73\xe3\xae\x5a\x43\xce"
+private+="\x76\xbc\xcb\x35\xea\x05\xac\x65\x38\xeb\x0e\xa6\xad\xee\x49"
+private+="\x37\x60\x04\x35\xdd\x79\x40\x88\x5d\x2e\x3f\x78\xc7\x28\x08"
+private+="\x34\xf8\x78\xd3\xd5\x50\xcc\x93\x05\x33\x0b\xb8\xf0\x20\x85"
+private+="\xee\x6c\x23\x0d\x42\xd8\x4e\xb6\x7a\x24\x5b\x92\x81\x7f\xd1"
+private+="\x54\xbc\xb1\x39\x4a\x28\x9d\x11\xaf\xb5\xa1\xe5\x0e\x13\x95"
+private+="\x09\x08\xaf\x70\x75\x67\x04\xe9\xbf\x03\xdf\xf0\xe5\xd4\x90"
+private+="\x74\x38\x41\xc5\x34\xcb\x7e\x2c\xf4\xb9\xf0\x49\x3a\x73\x0b"
+private+="\x0d\x71\x09\x6a\x16\xbd\xc0\xe8\x52\xf1\x75\x75\x51\x34\xb2"
+private+="\xb4\x11\x12\x28\x0a\x88\x21\x27\x28\xaf\xbe\x16\xd4\x17\xf3"
+private+="\x18\x93\xcb\xe4\x42\xe0\x6d\x21\x2d\x8e\xfe\x22\x7a\xa0\x03"
+private+="\x9a\x65\xce\x99\x81\x07\xfa\xe2\x78\x51\x1c\x6b\xf4\xd5\x99"
+private+="\x32\x53\x4a\xe9\xfc\x39\xdb\x80\x63\x51\x63\xc0\x54\x66\x57"
+private+="\x50\x08\x66\xd5\x46\x1c\x5f\xa3\x54\x02\x38\x32\x4a\x29\xf3"
+private+="\x16\xe0\x68\xf3\xba\x17\x37\xd0\x42\xcb\x51\xa8\x97\x1b\xc7"
+private+="\xa2"
+
+pcreate_key "-e $prime" user dh:prime @s
+expect_keyid primeid
+
+pcreate_key "-e $generator" user dh:generator @s
+expect_keyid generatorid
+
+pcreate_key "-e $private" user dh:private @s
+expect_keyid privateid
+
+pcreate_key "-e \x00" logon dh:logon @s
+expect_keyid logonid
+
+marker "CHECK WRONG KEY TYPE"
+dh_compute --fail $privateid $primeid $logonid
+expect_error ENOKEY
+dh_compute --fail $privateid $primeid @s
+expect_error EOPNOTSUPP
+
+marker "CHECK MISSING KEY"
+dh_compute --fail $privateid $primeid 0
+expect_error ENOKEY
+unlink_key --wait $generatorid @s
+dh_compute --fail $privateid $primeid $generatorid
+expect_error ENOKEY
+
+echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE
+
+# --- then report the results in the database ---
+toolbox_report_result $TEST $result
diff --git a/tests/keyctl/dh_compute/noargs/runtest.sh b/tests/keyctl/dh_compute/noargs/runtest.sh
new file mode 100644
index 0000000..e761f6b
--- /dev/null
+++ b/tests/keyctl/dh_compute/noargs/runtest.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+. ../../../prepare.inc.sh
+. ../../../toolbox.inc.sh
+
+
+# ---- do the actual testing ----
+
+if [ $have_dh_compute = 0 ]
+then
+    toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF DIFFIE-HELLMAN"
+    exit 0
+fi
+
+result=PASS
+echo "++++ BEGINNING TEST" >$OUTPUTFILE
+
+marker "NO ARGS"
+expect_args_error keyctl dh_compute
+
+marker "TWO ARGS"
+expect_args_error keyctl dh_compute 0 0
+
+marker "FOUR ARGS"
+expect_args_error keyctl dh_compute 0 0 0 0
+
+echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE
+
+# --- then report the results in the database ---
+toolbox_report_result $TEST $result
diff --git a/tests/keyctl/dh_compute/valid/runtest.sh b/tests/keyctl/dh_compute/valid/runtest.sh
new file mode 100644
index 0000000..f2aace6
--- /dev/null
+++ b/tests/keyctl/dh_compute/valid/runtest.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+
+. ../../../prepare.inc.sh
+. ../../../toolbox.inc.sh
+
+
+# ---- do the actual testing ----
+
+if [ $have_dh_compute = 0 ]
+then
+    toolbox_skip_test $TEST "SKIPPING DUE TO LACK OF DIFFIE-HELLMAN"
+    exit 0
+fi
+
+result=PASS
+echo "++++ BEGINNING TEST" >$OUTPUTFILE
+
+# Prime, generator, and key values created with:
+#   openssl dhparam 2048 -check -out dh.pem
+#   openssl genpkey -paramfile dh.pem -text
+prime="\x00\xb6\x89\x4d\x8f\xf7\xaf\x56\xd4\x46\xc9\x50\xc7\xe9\x1d"
+prime+="\x29\x8a\x07\x8d\xae\xa7\x79\x66\xf1\x1f\xc1\x6f\x22\x92\x11"
+prime+="\x73\x7f\x1f\x39\xce\xf3\xda\xd7\x87\x2a\x53\x8f\x6c\x8f\x9a"
+prime+="\x27\x6a\x7c\xf7\x7b\xb2\xd6\x3a\x87\x2a\x4d\xb9\xed\x12\xae"
+prime+="\x0f\x1c\x69\xaf\x9b\xf2\xf2\xe3\x69\x1d\x36\x15\xa1\xd7\xd5"
+prime+="\x77\xa8\x7d\x1c\xb4\xab\xa0\x49\x4b\xae\x0c\x24\x9b\x0c\xce"
+prime+="\xef\x6b\x7a\xb9\xa7\xbe\x70\xb5\xb4\x5e\x4c\xf7\xcb\x71\xad"
+prime+="\x8f\xeb\x7a\x4d\x6c\x7c\xcb\x96\xd5\x29\x8f\x0f\xee\xb4\x78"
+prime+="\x77\x60\x5e\x80\xa0\x33\x86\x91\xe3\x58\x62\xf0\xf4\xcb\xb2"
+prime+="\x09\xe1\x7d\xd9\xfe\xbc\xce\x4c\x21\x57\x70\x06\xce\xb1\x15"
+prime+="\x7b\x18\x15\x92\xd2\xf7\x84\xba\x44\xe0\x06\xc3\x14\xdf\x53"
+prime+="\x06\xbd\xbb\x17\xa0\x10\xb3\x66\x0d\x47\x93\x56\xd8\xd5\x2c"
+prime+="\x5a\xf0\x14\x53\x6c\x20\x89\x7e\x76\x53\x21\x8e\x2c\x7a\x65"
+prime+="\x0a\x73\xdc\x27\x58\x45\x98\xde\x92\xde\x5c\x62\x70\x67\x71"
+prime+="\xfa\x2d\x67\xf6\x25\x44\x1d\x91\x1c\xa0\x3f\x21\x49\xb6\xd4"
+prime+="\xc7\x6b\x5e\xcd\x98\x96\xe9\xd7\x99\xa3\xa5\x00\xec\xec\xc5"
+prime+="\x19\xe3\x1b\x71\x15\x4d\x7b\x36\x1b\xd0\xdd\x15\xf7\xce\x8d"
+prime+="\xfc\x63"
+
+generator="\x02"
+
+private="\x40\x94\x9d\xa2\xca\x2b\x7c\x35\x3d\xe3\x8f\xef\xb0\x6d\xdd"
+private+="\x0d\x67\x47\x9a\x63\x61\xc8\x9e\x77\xb9\x80\xd2\x48\x6c\x4d"
+private+="\x31\x97\x1e\xb8\x8f\x65\x72\x06\x99\x73\xe3\xae\x5a\x43\xce"
+private+="\x76\xbc\xcb\x35\xea\x05\xac\x65\x38\xeb\x0e\xa6\xad\xee\x49"
+private+="\x37\x60\x04\x35\xdd\x79\x40\x88\x5d\x2e\x3f\x78\xc7\x28\x08"
+private+="\x34\xf8\x78\xd3\xd5\x50\xcc\x93\x05\x33\x0b\xb8\xf0\x20\x85"
+private+="\xee\x6c\x23\x0d\x42\xd8\x4e\xb6\x7a\x24\x5b\x92\x81\x7f\xd1"
+private+="\x54\xbc\xb1\x39\x4a\x28\x9d\x11\xaf\xb5\xa1\xe5\x0e\x13\x95"
+private+="\x09\x08\xaf\x70\x75\x67\x04\xe9\xbf\x03\xdf\xf0\xe5\xd4\x90"
+private+="\x74\x38\x41\xc5\x34\xcb\x7e\x2c\xf4\xb9\xf0\x49\x3a\x73\x0b"
+private+="\x0d\x71\x09\x6a\x16\xbd\xc0\xe8\x52\xf1\x75\x75\x51\x34\xb2"
+private+="\xb4\x11\x12\x28\x0a\x88\x21\x27\x28\xaf\xbe\x16\xd4\x17\xf3"
+private+="\x18\x93\xcb\xe4\x42\xe0\x6d\x21\x2d\x8e\xfe\x22\x7a\xa0\x03"
+private+="\x9a\x65\xce\x99\x81\x07\xfa\xe2\x78\x51\x1c\x6b\xf4\xd5\x99"
+private+="\x32\x53\x4a\xe9\xfc\x39\xdb\x80\x63\x51\x63\xc0\x54\x66\x57"
+private+="\x50\x08\x66\xd5\x46\x1c\x5f\xa3\x54\x02\x38\x32\x4a\x29\xf3"
+private+="\x16\xe0\x68\xf3\xba\x17\x37\xd0\x42\xcb\x51\xa8\x97\x1b\xc7"
+private+="\xa2"
+
+read -d '' public <<"EOF"
+a4cf1f93 95fce03f d02aaece da1f86bd d8d77b69 29039fcc bd138c98 2483bf9c
+7e4406c1 4f3cea24 6cafb29e 95095d0c 6768f13b 31babb24 6c590d92 6c343e69
+59dbd47f 65982a3b b1baa7a3 05a72054 89b6cd0d 78397962 fc834fc9 3ec0517e
+c218396f 9cff860e 29078aee 6b8598b6 79325014 bb84597d f031e149 edbe1c5a
+2a55fe4e bbc64a52 6da59e71 1c7ae5e0 954ba23b 9d58c423 17d84841 815708c8
+b9059987 48773eac 2244b286 cd118277 48b7ed3a 5af5cc0f 8f254190 5e16f998
+a328e894 acc343f4 66a95281 86cea6a3 93eb4fee f83c0e2e f4a00ce6 fcc9ef81
+cc4624d5 ba659411 d1ba7b5f 14a3e286 d42e6ac8 afa9f846 41cb7cb5 66965725
+EOF
+
+pcreate_key "-e $prime" user dh:prime @s
+expect_keyid primeid
+
+pcreate_key "-e $generator" user dh:generator @s
+expect_keyid generatorid
+
+pcreate_key "-e $private" user dh:private @s
+expect_keyid privateid
+
+marker "COMPUTE DH PUBLIC KEY"
+dh_compute $privateid $primeid $generatorid
+expect_multiline payload "$public"
+
+echo "++++ FINISHED TEST: $result" >>$OUTPUTFILE
+
+# --- then report the results in the database ---
+toolbox_report_result $TEST $result
diff --git a/tests/prepare.inc.sh b/tests/prepare.inc.sh
index a2793d4..9a663c0 100644
--- a/tests/prepare.inc.sh
+++ b/tests/prepare.inc.sh
@@ -93,6 +93,15 @@
 fi
 
 #
+# Work out whether Diffie-Hellman is supported by the kernel
+#
+have_dh_compute=0
+if keyutils_at_or_later_than 1.5.10 && kernel_at_or_later_than 4.7-rc1
+then
+    have_dh_compute=1
+fi
+
+#
 # Check if skipping of tests requiring root was requested
 #
 skip_root_required=0
diff --git a/tests/toolbox.inc.sh b/tests/toolbox.inc.sh
index 5ac23ff..7f19a02 100644
--- a/tests/toolbox.inc.sh
+++ b/tests/toolbox.inc.sh
@@ -672,6 +672,25 @@
 
 ###############################################################################
 #
+# extract multiline output from the log file
+#
+###############################################################################
+function expect_multiline ()
+{
+    my_varname=$1
+    my_linecount="`echo \"$2\" | wc -l`"
+
+    my_payload=$(tail -$my_linecount $OUTPUTFILE)
+    eval $my_varname="\"$my_payload\""
+
+    if [ $# != 2 -o "x$my_payload" != "x$2" ]
+    then
+	failed
+    fi
+}
+
+###############################################################################
+#
 # revoke a key
 #
 ###############################################################################
@@ -1065,6 +1084,28 @@
 
 ###############################################################################
 #
+# Do a DH computation
+#
+###############################################################################
+function dh_compute ()
+{
+    my_exitval=0
+    if [ "x$1" = "x--fail" ]
+    then
+	my_exitval=1
+	shift
+    fi
+
+    echo keyctl dh_compute $@ >>$OUTPUTFILE
+    keyctl dh_compute $@ >>$OUTPUTFILE 2>&1
+    if [ $? != $my_exitval ]
+    then
+	failed
+    fi
+}
+
+###############################################################################
+#
 # Make sure we sleep at least N seconds
 #
 ###############################################################################
diff --git a/version.lds b/version.lds
index 5f07463..2bfed13 100644
--- a/version.lds
+++ b/version.lds
@@ -23,7 +23,7 @@
 	keyctl_set_reqkey_keyring;
 	keyctl_unlink;
 	keyctl_update;
-	 
+
 };
 
 KEYUTILS_1.0 {
@@ -61,3 +61,10 @@
 	find_key_by_type_and_desc;
 
 } KEYUTILS_1.4;
+
+KEYUTILS_1.6 {
+	/* management functions */
+	keyctl_dh_compute;
+	keyctl_dh_compute_alloc;
+
+} KEYUTILS_1.5;