[PATCH 12/25] KEYS: PGP data parser
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
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,