Add password support
diff --git a/keyctl.c b/keyctl.c
index 013bb70..ab43c0a 100644
--- a/keyctl.c
+++ b/keyctl.c
@@ -100,11 +100,11 @@
 	{ act_keyctl_padd,	"padd",		"<type> <desc> <keyring>" },
 	{ act_keyctl_pinstantiate, "pinstantiate","<key> <keyring>" },
 	{ act_keyctl_pipe,	"pipe",		"<key>" },
-	{ act_keyctl_pkey_query, "pkey_query",	"<key> [k=v]*" },
-	{ act_keyctl_pkey_encrypt, "pkey_encrypt", "<key> <datafile> [k=v]*" },
-	{ act_keyctl_pkey_decrypt, "pkey_decrypt", "<key> <datafile> [k=v]*" },
-	{ act_keyctl_pkey_sign, "pkey_sign",	"<key> <datafile> [k=v]*" },
-	{ act_keyctl_pkey_verify, "pkey_verify", "<key> <datafile> <sigfile> [k=v]*" },
+	{ act_keyctl_pkey_query, "pkey_query",	"<key> <pass> [k=v]*" },
+	{ act_keyctl_pkey_encrypt, "pkey_encrypt", "<key> <pass> <datafile> [k=v]*" },
+	{ act_keyctl_pkey_decrypt, "pkey_decrypt", "<key> <pass> <datafile> [k=v]*" },
+	{ act_keyctl_pkey_sign, "pkey_sign",	"<key> <pass> <datafile> [k=v]*" },
+	{ act_keyctl_pkey_verify, "pkey_verify", "<key> <pass> <datafile> <sigfile> [k=v]*" },
 	{ act_keyctl_prequest2,	"prequest2",	"<type> <desc> [<dest_keyring>]" },
 	{ act_keyctl_print,	"print",	"<key>" },
 	{ act_keyctl_pupdate,	"pupdate",	"<key>" },
@@ -1891,7 +1891,7 @@
 static void act_keyctl_pkey_query(int argc, char *argv[])
 {
 	struct keyctl_pkey_query result;
-	key_serial_t key;
+	key_serial_t key, password = 0;
 	char info[4096];
 
 	if (argc < 3)
@@ -1899,8 +1899,9 @@
 	pkey_parse_info(argv + 2, info);
 
 	key = get_key_id(argv[1]);
+	password = get_key_id(argv[2]);
 
-	if (keyctl_pkey_query(key, info, &result) < 0)
+	if (keyctl_pkey_query(key, password, info, &result) < 0)
 		error("keyctl_pkey_query");
 
 	printf("key_size=%u\n", result.key_size);
@@ -1921,7 +1922,7 @@
 static void act_keyctl_pkey_encrypt(int argc, char *argv[])
 {
 	struct keyctl_pkey_query result;
-	key_serial_t key;
+	key_serial_t key, password;
 	size_t in_len;
 	long out_len;
 	void *in, *out;
@@ -1932,16 +1933,17 @@
 	pkey_parse_info(argv + 4, info);
 
 	key = get_key_id(argv[1]);
+	password = get_key_id(argv[2]);
 	in = read_file(argv[3], &in_len);
 
-	if (keyctl_pkey_query(key, info, &result) < 0)
+	if (keyctl_pkey_query(key, password, info, &result) < 0)
 		error("keyctl_pkey_query");
 
 	out = malloc(result.max_dec_size);
 	if (!out)
 		error("malloc");
 
-	out_len = keyctl_pkey_encrypt(key, info,
+	out_len = keyctl_pkey_encrypt(key, password, info,
 				      in, in_len, out, result.max_dec_size);
 	if (out_len < 0)
 		error("keyctl_pkey_encrypt");
@@ -1957,7 +1959,7 @@
 static void act_keyctl_pkey_decrypt(int argc, char *argv[])
 {
 	struct keyctl_pkey_query result;
-	key_serial_t key;
+	key_serial_t key, password;
 	size_t in_len;
 	long out_len;
 	void *in, *out;
@@ -1968,16 +1970,17 @@
 	pkey_parse_info(argv + 4, info);
 
 	key = get_key_id(argv[1]);
+	password = get_key_id(argv[2]);
 	in = read_file(argv[3], &in_len);
 
-	if (keyctl_pkey_query(key, info, &result) < 0)
+	if (keyctl_pkey_query(key, password, info, &result) < 0)
 		error("keyctl_pkey_query");
 
 	out = malloc(result.max_enc_size);
 	if (!out)
 		error("malloc");
 
-	out_len = keyctl_pkey_decrypt(key, info,
+	out_len = keyctl_pkey_decrypt(key, password, info,
 				      in, in_len, out, result.max_enc_size);
 	if (out_len < 0)
 		error("keyctl_pkey_decrypt");
@@ -1993,7 +1996,7 @@
 static void act_keyctl_pkey_sign(int argc, char *argv[])
 {
 	struct keyctl_pkey_query result;
-	key_serial_t key;
+	key_serial_t key, password;
 	size_t in_len;
 	long out_len;
 	void *in, *out;
@@ -2004,16 +2007,17 @@
 	pkey_parse_info(argv + 4, info);
 
 	key = get_key_id(argv[1]);
+	password = get_key_id(argv[2]);
 	in = read_file(argv[3], &in_len);
 
-	if (keyctl_pkey_query(key, info, &result) < 0)
+	if (keyctl_pkey_query(key, password, info, &result) < 0)
 		error("keyctl_pkey_query");
 
 	out = malloc(result.max_sig_size);
 	if (!out)
 		error("malloc");
 
-	out_len = keyctl_pkey_sign(key, info,
+	out_len = keyctl_pkey_sign(key, password, info,
 				   in, in_len, out, result.max_sig_size);
 	if (out_len < 0)
 		error("keyctl_pkey_sign");
@@ -2028,7 +2032,7 @@
  */
 static void act_keyctl_pkey_verify(int argc, char *argv[])
 {
-	key_serial_t key;
+	key_serial_t key, password;
 	size_t data_len, sig_len;
 	void *data, *sig;
 	char info[4096];
@@ -2038,10 +2042,11 @@
 	pkey_parse_info(argv + 5, info);
 
 	key = get_key_id(argv[1]);
+	password = get_key_id(argv[2]);
 	data = read_file(argv[3], &data_len);
 	sig = read_file(argv[4], &sig_len);
 
-	if (keyctl_pkey_verify(key, info,
+	if (keyctl_pkey_verify(key, password, info,
 			       data, data_len, sig, sig_len) < 0)
 		error("keyctl_pkey_verify");
 	exit(0);
diff --git a/keyutils.c b/keyutils.c
index e3bf775..fc7dc4d 100644
--- a/keyutils.c
+++ b/keyutils.c
@@ -264,20 +264,21 @@
 	return keyctl(KEYCTL_RESTRICT_KEYRING, keyring, type, restriction);
 }
 
-long keyctl_pkey_query(key_serial_t key_id,
+long keyctl_pkey_query(key_serial_t key_id, key_serial_t password_id,
 		       const char *info,
 		       struct keyctl_pkey_query *result)
 {
-	return keyctl(KEYCTL_PKEY_QUERY, key_id, 0, info, result);
+	return keyctl(KEYCTL_PKEY_QUERY, key_id, password_id, info, result);
 }
 
-long keyctl_pkey_encrypt(key_serial_t key_id,
+long keyctl_pkey_encrypt(key_serial_t key_id, key_serial_t password_id,
 			 const char *info,
 			 const void *data, size_t data_len,
 			 void *enc, size_t enc_len)
 {
 	struct keyctl_pkey_params params = {
 		.key_id		= key_id,
+		.password_id	= password_id,
 		.in_len		= data_len,
 		.out_len	= enc_len,
 	};
@@ -285,13 +286,14 @@
 	return keyctl(KEYCTL_PKEY_ENCRYPT, &params, info, data, enc);
 }
 
-long keyctl_pkey_decrypt(key_serial_t key_id,
+long keyctl_pkey_decrypt(key_serial_t key_id, key_serial_t password_id,
 			 const char *info,
 			 const void *enc, size_t enc_len,
 			 void *data, size_t data_len)
 {
 	struct keyctl_pkey_params params = {
 		.key_id		= key_id,
+		.password_id	= password_id,
 		.in_len		= enc_len,
 		.out_len	= data_len,
 	};
@@ -299,13 +301,14 @@
 	return keyctl(KEYCTL_PKEY_DECRYPT, &params, info, enc, data);
 }
 
-long keyctl_pkey_sign(key_serial_t key_id,
+long keyctl_pkey_sign(key_serial_t key_id, key_serial_t password_id,
 		      const char *info,
 		      const void *data, size_t data_len,
 		      void *sig, size_t sig_len)
 {
 	struct keyctl_pkey_params params = {
 		.key_id		= key_id,
+		.password_id	= password_id,
 		.in_len		= data_len,
 		.out_len	= sig_len,
 	};
@@ -313,13 +316,14 @@
 	return keyctl(KEYCTL_PKEY_SIGN, &params, info, data, sig);
 }
 
-long keyctl_pkey_verify(key_serial_t key_id,
+long keyctl_pkey_verify(key_serial_t key_id, key_serial_t password_id,
 			const char *info,
 			const void *data, size_t data_len,
 			const void *sig, size_t sig_len)
 {
 	struct keyctl_pkey_params params = {
 		.key_id		= key_id,
+		.password_id	= password_id,
 		.in_len		= data_len,
 		.in2_len	= sig_len,
 	};
diff --git a/keyutils.h b/keyutils.h
index 911e93e..5f81c62 100644
--- a/keyutils.h
+++ b/keyutils.h
@@ -143,7 +143,8 @@
 		unsigned int	out_len; /* Output buffer size (encrypt/decrypt/sign) */
 		unsigned int	in2_len; /* Second input data size (verify) */
 	};
-	unsigned int	__spare[7];
+	key_serial_t	password_id;	/* Serial no. of password-containing key to use (or 0) */
+	unsigned int	__spare[6];
 };
 
 /*
@@ -208,22 +209,22 @@
 extern long keyctl_restrict_keyring(key_serial_t keyring, const char *type,
 				    const char *restriction);
 
-extern long keyctl_pkey_query(key_serial_t key_id,
+extern long keyctl_pkey_query(key_serial_t key_id, key_serial_t password_id,
 			      const char *info,
 			      struct keyctl_pkey_query *result);
-extern long keyctl_pkey_encrypt(key_serial_t key_id,
+extern long keyctl_pkey_encrypt(key_serial_t key_id, key_serial_t password_id,
 				const char *info,
 				const void *data, size_t data_len,
 				void *enc, size_t enc_len);
-extern long keyctl_pkey_decrypt(key_serial_t key_id,
+extern long keyctl_pkey_decrypt(key_serial_t key_id, key_serial_t password_id,
 				const char *info,
 				const void *enc, size_t enc_len,
 				void *data, size_t data_len);
-extern long keyctl_pkey_sign(key_serial_t key_id,
+extern long keyctl_pkey_sign(key_serial_t key_id, key_serial_t password_id,
 			     const char *info,
 			     const void *data, size_t data_len,
 			     void *sig, size_t sig_len);
-extern long keyctl_pkey_verify(key_serial_t key_id,
+extern long keyctl_pkey_verify(key_serial_t key_id, key_serial_t password_id,
 			       const char *info,
 			       const void *data, size_t data_len,
 			       const void *sig, size_t sig_len);