[PATCH 12/25] KEYS: PGP data parser

2012-08-15 Thread David Howells
Implement a PGP data parser for the crypto key type to use when instantiating a
key.

This parser attempts to parse the instantiation data as a PGP packet sequence
(RFC 4880) and if it parses okay, attempts to extract a public-key algorithm
key or subkey from it.

If it finds such a key, it will set up a public_key subtype payload with
appropriate handler routines (DSA or RSA) and attach it to the key.

Thanks to Tetsuo Handa  for pointing out
some errors.

Signed-off-by: David Howells 
---

 security/keys/crypto/Kconfig  |   12 +
 security/keys/crypto/Makefile |4 
 security/keys/crypto/pgp_parser.h |   23 ++
 security/keys/crypto/pgp_public_key.c |  344 +
 4 files changed, 383 insertions(+)
 create mode 100644 security/keys/crypto/pgp_parser.h
 create mode 100644 security/keys/crypto/pgp_public_key.c


diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
index 88ce0e2..1c2ae55 100644
--- a/security/keys/crypto/Kconfig
+++ b/security/keys/crypto/Kconfig
@@ -28,3 +28,15 @@ config PGP_LIBRARY
help
  This option enables a library that provides a number of simple
  utility functions for parsing PGP (RFC 4880) packet-based messages.
+
+config CRYPTO_KEY_PGP_PARSER
+   tristate "PGP key blob parser"
+   depends on CRYPTO_KEY_TYPE
+   select CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
+   select PGP_LIBRARY
+   select MD5 # V3 fingerprint generation
+   select SHA1 # V4 fingerprint generation
+   help
+ This option provides support for parsing PGP (RFC 4880) format blobs
+ for key data and provides the ability to instantiate a crypto key
+ from a public key packet found inside the blob.
diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
index 5fbe54e..35733fc 100644
--- a/security/keys/crypto/Makefile
+++ b/security/keys/crypto/Makefile
@@ -8,3 +8,7 @@ crypto_keys-y := crypto_type.o crypto_verify.o
 obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
 obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
 obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
+
+obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_key_parser.o
+pgp_key_parser-y := \
+   pgp_public_key.o
diff --git a/security/keys/crypto/pgp_parser.h 
b/security/keys/crypto/pgp_parser.h
new file mode 100644
index 000..1cda231
--- /dev/null
+++ b/security/keys/crypto/pgp_parser.h
@@ -0,0 +1,23 @@
+/* PGP crypto data parser internal definitions
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@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.
+ */
+
+#include 
+
+#define kenter(FMT, ...) \
+   pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+#define kleave(FMT, ...) \
+   pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+
+/*
+ * pgp_key_parser.c
+ */
+extern const
+struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST];
diff --git a/security/keys/crypto/pgp_public_key.c 
b/security/keys/crypto/pgp_public_key.c
new file mode 100644
index 000..c260e02
--- /dev/null
+++ b/security/keys/crypto/pgp_public_key.c
@@ -0,0 +1,344 @@
+/* Instantiate a public key crypto key from PGP format data [RFC 4880]
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@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.
+ */
+
+#define pr_fmt(fmt) "PGP: "fmt
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "public_key.h"
+#include "pgp_parser.h"
+
+MODULE_LICENSE("GPL");
+
+const
+struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST] = {
+#if defined(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) || \
+   defined(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA_MODULE)
+   [PGP_PUBKEY_RSA_ENC_OR_SIG] = _public_key_algorithm,
+   [PGP_PUBKEY_RSA_ENC_ONLY]   = _public_key_algorithm,
+   [PGP_PUBKEY_RSA_SIG_ONLY]   = _public_key_algorithm,
+#endif
+   [PGP_PUBKEY_ELGAMAL]= NULL,
+   [PGP_PUBKEY_DSA]= NULL,
+};
+
+static const u8 pgp_public_key_capabilities[PGP_PUBKEY__LAST] = {
+   [PGP_PUBKEY_RSA_ENC_OR_SIG] = PKEY_CAN_ENCDEC | PKEY_CAN_SIGVER,
+   [PGP_PUBKEY_RSA_ENC_ONLY]   = PKEY_CAN_ENCDEC,
+   [PGP_PUBKEY_RSA_SIG_ONLY]   = PKEY_CAN_SIGVER,
+   [PGP_PUBKEY_ELGAMAL]= 0,
+   [PGP_PUBKEY_DSA]= 0,
+};
+
+static inline void digest_putc(struct shash_desc *digest, uint8_t ch)
+{
+   

[PATCH 12/25] KEYS: PGP data parser

2012-08-15 Thread David Howells
Implement a PGP data parser for the crypto key type to use when instantiating a
key.

This parser attempts to parse the instantiation data as a PGP packet sequence
(RFC 4880) and if it parses okay, attempts to extract a public-key algorithm
key or subkey from it.

If it finds such a key, it will set up a public_key subtype payload with
appropriate handler routines (DSA or RSA) and attach it to the key.

Thanks to Tetsuo Handa penguin-ker...@i-love.sakura.ne.jp for pointing out
some errors.

Signed-off-by: David Howells dhowe...@redhat.com
---

 security/keys/crypto/Kconfig  |   12 +
 security/keys/crypto/Makefile |4 
 security/keys/crypto/pgp_parser.h |   23 ++
 security/keys/crypto/pgp_public_key.c |  344 +
 4 files changed, 383 insertions(+)
 create mode 100644 security/keys/crypto/pgp_parser.h
 create mode 100644 security/keys/crypto/pgp_public_key.c


diff --git a/security/keys/crypto/Kconfig b/security/keys/crypto/Kconfig
index 88ce0e2..1c2ae55 100644
--- a/security/keys/crypto/Kconfig
+++ b/security/keys/crypto/Kconfig
@@ -28,3 +28,15 @@ config PGP_LIBRARY
help
  This option enables a library that provides a number of simple
  utility functions for parsing PGP (RFC 4880) packet-based messages.
+
+config CRYPTO_KEY_PGP_PARSER
+   tristate PGP key blob parser
+   depends on CRYPTO_KEY_TYPE
+   select CRYPTO_KEY_PUBLIC_KEY_SUBTYPE
+   select PGP_LIBRARY
+   select MD5 # V3 fingerprint generation
+   select SHA1 # V4 fingerprint generation
+   help
+ This option provides support for parsing PGP (RFC 4880) format blobs
+ for key data and provides the ability to instantiate a crypto key
+ from a public key packet found inside the blob.
diff --git a/security/keys/crypto/Makefile b/security/keys/crypto/Makefile
index 5fbe54e..35733fc 100644
--- a/security/keys/crypto/Makefile
+++ b/security/keys/crypto/Makefile
@@ -8,3 +8,7 @@ crypto_keys-y := crypto_type.o crypto_verify.o
 obj-$(CONFIG_CRYPTO_KEY_PUBLIC_KEY_SUBTYPE) += public_key.o
 obj-$(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) += crypto_rsa.o
 obj-$(CONFIG_PGP_LIBRARY) += pgp_library.o
+
+obj-$(CONFIG_CRYPTO_KEY_PGP_PARSER) += pgp_key_parser.o
+pgp_key_parser-y := \
+   pgp_public_key.o
diff --git a/security/keys/crypto/pgp_parser.h 
b/security/keys/crypto/pgp_parser.h
new file mode 100644
index 000..1cda231
--- /dev/null
+++ b/security/keys/crypto/pgp_parser.h
@@ -0,0 +1,23 @@
+/* PGP crypto data parser internal definitions
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@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.
+ */
+
+#include linux/pgp.h
+
+#define kenter(FMT, ...) \
+   pr_devel(== %s(FMT)\n, __func__, ##__VA_ARGS__)
+#define kleave(FMT, ...) \
+   pr_devel(== %s()FMT\n, __func__, ##__VA_ARGS__)
+
+/*
+ * pgp_key_parser.c
+ */
+extern const
+struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST];
diff --git a/security/keys/crypto/pgp_public_key.c 
b/security/keys/crypto/pgp_public_key.c
new file mode 100644
index 000..c260e02
--- /dev/null
+++ b/security/keys/crypto/pgp_public_key.c
@@ -0,0 +1,344 @@
+/* Instantiate a public key crypto key from PGP format data [RFC 4880]
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@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.
+ */
+
+#define pr_fmt(fmt) PGP: fmt
+#include keys/crypto-subtype.h
+#include linux/module.h
+#include linux/kernel.h
+#include linux/slab.h
+#include linux/mpi.h
+#include linux/pgplib.h
+#include crypto/hash.h
+#include public_key.h
+#include pgp_parser.h
+
+MODULE_LICENSE(GPL);
+
+const
+struct public_key_algorithm *pgp_public_key_algorithms[PGP_PUBKEY__LAST] = {
+#if defined(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA) || \
+   defined(CONFIG_CRYPTO_KEY_PKEY_ALGO_RSA_MODULE)
+   [PGP_PUBKEY_RSA_ENC_OR_SIG] = RSA_public_key_algorithm,
+   [PGP_PUBKEY_RSA_ENC_ONLY]   = RSA_public_key_algorithm,
+   [PGP_PUBKEY_RSA_SIG_ONLY]   = RSA_public_key_algorithm,
+#endif
+   [PGP_PUBKEY_ELGAMAL]= NULL,
+   [PGP_PUBKEY_DSA]= NULL,
+};
+
+static const u8 pgp_public_key_capabilities[PGP_PUBKEY__LAST] = {
+   [PGP_PUBKEY_RSA_ENC_OR_SIG] = PKEY_CAN_ENCDEC | PKEY_CAN_SIGVER,
+   [PGP_PUBKEY_RSA_ENC_ONLY]   = PKEY_CAN_ENCDEC,
+   [PGP_PUBKEY_RSA_SIG_ONLY]   = PKEY_CAN_SIGVER,
+   [PGP_PUBKEY_ELGAMAL]= 0,